diff options
author | LaG1924 <12997935+LaG1924@users.noreply.github.com> | 2017-08-29 17:25:30 +0200 |
---|---|---|
committer | LaG1924 <12997935+LaG1924@users.noreply.github.com> | 2018-01-13 03:39:31 +0100 |
commit | a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1 (patch) | |
tree | 7bf54f8141c513650130e8d3cc6bd8ce3f71b1fe /src | |
parent | 2017-08-27 (diff) | |
download | AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar.gz AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar.bz2 AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar.lz AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar.xz AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.tar.zst AltCraft-a0d5862d99186f317a0f7364e8b6cd3cfeccfdf1.zip |
Diffstat (limited to 'src')
-rw-r--r-- | src/DebugInfo.cpp | 6 | ||||
-rw-r--r-- | src/DebugInfo.hpp | 10 | ||||
-rw-r--r-- | src/Event.hpp | 6 | ||||
-rw-r--r-- | src/Render.cpp | 272 | ||||
-rw-r--r-- | src/Render.hpp | 24 | ||||
-rw-r--r-- | src/RendererWorld.cpp | 4 | ||||
-rw-r--r-- | src/Socket.hpp | 2 | ||||
-rw-r--r-- | src/Texture.cpp | 76 | ||||
-rw-r--r-- | src/Texture.hpp | 1 | ||||
-rw-r--r-- | src/ThreadGame.cpp | 64 | ||||
-rw-r--r-- | src/World.cpp | 2 | ||||
-rw-r--r-- | src/imgui_impl_sdl_gl3.cpp | 395 | ||||
-rw-r--r-- | src/imgui_impl_sdl_gl3.h | 19 |
13 files changed, 751 insertions, 130 deletions
diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp new file mode 100644 index 0000000..309c7aa --- /dev/null +++ b/src/DebugInfo.cpp @@ -0,0 +1,6 @@ +#include "DebugInfo.hpp" + +std::atomic_int DebugInfo::totalSections = 0; +std::atomic_int DebugInfo::renderSections = 0; +std::atomic_int DebugInfo::readyRenderer = 0; +std::atomic_int DebugInfo::gameThreadTime = 0;
\ No newline at end of file diff --git a/src/DebugInfo.hpp b/src/DebugInfo.hpp new file mode 100644 index 0000000..a29a056 --- /dev/null +++ b/src/DebugInfo.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include <atomic> + +struct DebugInfo { + static std::atomic_int totalSections; + static std::atomic_int renderSections; + static std::atomic_int readyRenderer; + static std::atomic_int gameThreadTime; +};
\ No newline at end of file diff --git a/src/Event.hpp b/src/Event.hpp index b137a85..569be00 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -9,7 +9,7 @@ #include <variant> #include <functional> -#include <SFML/Window.hpp> +#include <SDL.h> #include "Vector.hpp" #include "Packet.hpp" @@ -119,11 +119,11 @@ struct MouseMovedData { }; struct KeyPressedData { - sf::Keyboard::Key key; + SDL_Scancode key; }; struct KeyReleasedData { - sf::Keyboard::Key key; + SDL_Scancode key; }; struct InitalizeSectionRenderData { diff --git a/src/Render.cpp b/src/Render.cpp index c739b77..19e89f6 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -4,6 +4,10 @@ #include "Shader.hpp" #include "AssetManager.hpp" #include "Event.hpp" +#include "DebugInfo.hpp" + +#include <imgui.h> +#include "imgui_impl_sdl_gl3.h" Render::Render(unsigned int windowWidth, unsigned int windowHeight, std::string windowTitle) : timer(std::chrono::milliseconds(0)) { InitSfml(windowWidth, windowHeight, windowTitle); @@ -15,21 +19,31 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight, std::string } Render::~Render() { - delete window; + ImGui_ImplSdlGL3_Shutdown(); + SDL_GL_DeleteContext(glContext); + SDL_DestroyWindow(window); + SDL_Quit(); } void Render::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string WinTitle) { LOG(INFO) << "Creating window: " << WinWidth << "x" << WinHeight << " \"" << WinTitle << "\""; - sf::ContextSettings contextSetting; - contextSetting.majorVersion = 3; - contextSetting.minorVersion = 3; - contextSetting.attributeFlags = contextSetting.Core; - contextSetting.depthBits = 24; - window = new sf::Window(sf::VideoMode(WinWidth, WinHeight), WinTitle, sf::Style::Default, contextSetting); - glCheckError(); - window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2, - sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2)); - window->setKeyRepeatEnabled(false); + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + throw std::runtime_error("SDL initalization failed: " + std::string(SDL_GetError())); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + + window = SDL_CreateWindow(WinTitle.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WinWidth, WinHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + if (!window) + throw std::runtime_error("Window creation failed: " + std::string(SDL_GetError())); + + glContext = SDL_GL_CreateContext(window); + if (!glContext) + throw std::runtime_error("OpenGl context creation failed: " + std::string(SDL_GetError())); + SetMouseCapture(false); renderState.WindowWidth = WinWidth; renderState.WindowHeight = WinHeight; @@ -43,7 +57,9 @@ void Render::InitGlew() { if (glewStatus != GLEW_OK) { LOG(FATAL) << "Failed to initialize GLEW: " << glewGetErrorString(glewStatus); } - glViewport(0, 0, window->getSize().x, window->getSize().y); + int width, height; + SDL_GL_GetDrawableSize(window, &width, &height); + glViewport(0, 0, width, height); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -58,12 +74,18 @@ void Render::PrepareToRendering() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas()); AssetManager::Instance().GetTextureAtlasIndexes(); + + ImGui_ImplSdlGL3_Init(window); } void Render::UpdateKeyboard() { - sf::Keyboard::Key toUpdate[] = { sf::Keyboard::A,sf::Keyboard::W,sf::Keyboard::S,sf::Keyboard::D,sf::Keyboard::Space }; + if (ImGui::GetIO().WantCaptureKeyboard) + return; + + SDL_Scancode toUpdate[] = { SDL_SCANCODE_A,SDL_SCANCODE_W,SDL_SCANCODE_S,SDL_SCANCODE_D,SDL_SCANCODE_SPACE }; + const Uint8 *kbState = SDL_GetKeyboardState(0); for (auto key : toUpdate) { - bool isPressed = sf::Keyboard::isKeyPressed(key); + bool isPressed = kbState[key]; if (!isKeyPressed[key] && isPressed) { EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ key }); } @@ -81,6 +103,7 @@ void Render::RenderFrame() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (renderWorld) world->Render(renderState); @@ -88,62 +111,67 @@ void Render::RenderFrame() { world->Update(timer.RemainTimeMs()); } - window->display(); + RenderGui(); + + SDL_GL_SwapWindow(window); } void Render::HandleEvents() { - sf::Event event; - while (window->pollEvent(event)) { + SDL_PumpEvents(); + SDL_Event event; + while (SDL_PollEvent(&event)) { + ImGui_ImplSdlGL3_ProcessEvent(&event); + switch (event.type) { - case sf::Event::Closed: + case SDL_QUIT: LOG(INFO) << "Received close event by window closing"; isRunning = false; break; - case sf::Event::Resized: - glViewport(0, 0, window->getSize().x, window->getSize().y); - renderState.WindowWidth = window->getSize().x; - renderState.WindowHeight = window->getSize().y; - break; - case sf::Event::KeyPressed: - if (!window->hasFocus()) break; - switch (event.key.code) { - case sf::Keyboard::Escape: - LOG(INFO) << "Received close event by esc"; - isRunning = false; - break; - case sf::Keyboard::T: - SetMouseCapture(!isMouseCaptured); + case SDL_WINDOWEVENT: { + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: { + int width, height; + SDL_GL_GetDrawableSize(window, &width, &height); + glViewport(0, 0, width, height); + renderState.WindowWidth = width; + renderState.WindowHeight = height; break; - case sf::Keyboard::U: - EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{ "10.1.1.2", 25565 }); + } + case SDL_WINDOWEVENT_FOCUS_GAINED: + HasFocus = true; break; - case sf::Keyboard::I: - EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ "Manual disconnect" }); + case SDL_WINDOWEVENT_FOCUS_LOST: + HasFocus = false; + SetMouseCapture(false); break; - case sf::Keyboard::K: - if (renderWorld) { - world->MaxRenderingDistance--; - if (world->MaxRenderingDistance <= 0) - world->MaxRenderingDistance = 1; - LOG(INFO) << "Decreased rendering distance: " << world->MaxRenderingDistance; - EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + } + break; + } + case SDL_KEYDOWN: + switch (event.key.keysym.scancode) { + case SDL_SCANCODE_ESCAPE: + if (state == GlobalState::Playing) { + state = GlobalState::Paused; + SetMouseCapture(false); } - break; - case sf::Keyboard::L: - if (renderWorld) { - world->MaxRenderingDistance++; - LOG(INFO) << "Increased rendering distance: " << world->MaxRenderingDistance; - EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + else if (state == GlobalState::Paused) { + state = GlobalState::Playing; + SetMouseCapture(true); + } + else if (state == GlobalState::MainMenu) { + LOG(INFO) << "Received close event by esc"; + isRunning = false; } - break; - default: break; } - case sf::Event::KeyReleased: - if (!window->hasFocus()) break; - switch (event.key.code) { - default: - break; + break; + case SDL_MOUSEMOTION: + if (isMouseCaptured) { + double deltaX = event.motion.xrel; + double deltaY = event.motion.yrel; + deltaX *= sensetivity; + deltaY *= sensetivity * -1; + EventAgregator::DirectEventCall(EventType::MouseMoved, MouseMovedData{ deltaX,deltaY }); } default: break; @@ -151,20 +179,24 @@ void Render::HandleEvents() { } } -void Render::HandleMouseCapture() { - sf::Vector2i mousePos = sf::Mouse::getPosition(*window); - sf::Vector2i center = sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2); - sf::Mouse::setPosition(center, *window); - mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y; - const float Sensetivity = 0.7f; - EventAgregator::DirectEventCall(EventType::MouseMoved, MouseMovedData{ mouseXDelta * Sensetivity, mouseYDelta * Sensetivity}); +void Render::HandleMouseCapture() { } void Render::SetMouseCapture(bool IsCaptured) { - window->setMouseCursorVisible(!isMouseCaptured); - sf::Mouse::setPosition(sf::Vector2i(window->getSize().x / 2, window->getSize().y / 2), *window); - isMouseCaptured = IsCaptured; - window->setMouseCursorVisible(!IsCaptured); + if (IsCaptured == isMouseCaptured) + return; + isMouseCaptured = IsCaptured; + + if (isMouseCaptured) { + SDL_GetGlobalMouseState(&prevMouseX, &prevMouseY); + } + + SDL_CaptureMouse(IsCaptured ? SDL_TRUE : SDL_FALSE); + SDL_SetRelativeMouseMode(IsCaptured ? SDL_TRUE : SDL_FALSE); + + if (!isMouseCaptured) { + SDL_WarpMouseGlobal(prevMouseX, prevMouseY); + } } void Render::ExecuteRenderLoop() { @@ -172,49 +204,135 @@ void Render::ExecuteRenderLoop() { listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) { auto data = std::get<ConnectionSuccessfullData>(eventData); - window->setTitle("Logging in..."); + stateString = "Logging in..."; }); listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) { auto data = std::get<PlayerConnectedData>(eventData); - window->setTitle("Loading terrain..."); + stateString = "Loading terrain..."; world = std::make_unique<RendererWorld>(data.ptr); }); listener.RegisterHandler(EventType::RemoveLoadingScreen, [this](EventData eventData) { - window->setTitle("Playing"); + stateString = "Playing"; renderWorld = true; + state = GlobalState::Playing; + SetMouseCapture(true); }); listener.RegisterHandler(EventType::ConnectionFailed, [this](EventData eventData) { - window->setTitle("Connection failed: " + std::get<ConnectionFailedData>(eventData).reason); + stateString = "Connection failed: " + std::get<ConnectionFailedData>(eventData).reason; renderWorld = false; world.reset(); + state = GlobalState::MainMenu; }); listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) { - window->setTitle("Disconnected: " + std::get<DisconnectedData>(eventData).reason); + stateString = "Disconnected: " + std::get<DisconnectedData>(eventData).reason; renderWorld = false; world.reset(); + state = GlobalState::MainMenu; }); listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) { - window->setTitle("Connecting to the server..."); + stateString = "Connecting to the server..."; + state = GlobalState::Loading; }); + + state = GlobalState::MainMenu; while (isRunning) { HandleEvents(); - if (window->hasFocus()) UpdateKeyboard(); + if (HasFocus) UpdateKeyboard(); if (isMouseCaptured) HandleMouseCapture(); glCheckError(); RenderFrame(); while (listener.IsEventsQueueIsNotEmpty()) listener.HandleEvent(); - if (renderWorld) { - window->setTitle("FPS: " + std::to_string(1.0 / timer.GetRealDeltaS())); - } timer.Update(); } EventAgregator::PushEvent(EventType::Exit, ExitData{}); } + +void Render::RenderGui() { + ImGui_ImplSdlGL3_NewFrame(window); + + if (isMouseCaptured) { + auto& io = ImGui::GetIO(); + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + } + const ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings; + + //ImGui::ShowTestWindow(); + + ImGui::SetNextWindowPos(ImVec2(10, 10)); + ImGui::Begin("DebugInfo", 0, ImVec2(0, 0), 0.4f, windowFlags); + ImGui::Text("Debug Info:"); + ImGui::Separator(); + ImGui::Text("State: %s", stateString.c_str()); + ImGui::Text("FPS: %.1f (%.3fms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate); + float gameTime = DebugInfo::gameThreadTime / 100.0f; + ImGui::Text("TPS: %.1f (%.2fms)", 1000.0f/gameTime, gameTime); + ImGui::Text("Sections loaded: %d", (int)DebugInfo::totalSections); + ImGui::Text("SectionsRenderer: %d (%d)", (int)DebugInfo::renderSections, (int)DebugInfo::readyRenderer); + ImGui::End(); + + + switch (state) { + case GlobalState::MainMenu: { + ImGui::SetNextWindowPosCenter(); + ImGui::Begin("Menu",0, windowFlags); + static char buff[512] = "127.0.0.1"; + static int port = 25565; + if (ImGui::Button("Connect")) { + EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{ buff, (unsigned short)port }); + } + ImGui::InputText("Address", buff, 512); + ImGui::InputInt("Port", &port); + ImGui::Separator(); + if (ImGui::Button("Exit")) + isRunning = false; + ImGui::End(); + break; + } + case GlobalState::Loading: + break; + case GlobalState::Playing: + break; + case GlobalState::Paused: { + ImGui::SetNextWindowPosCenter(); + ImGui::Begin("Pause Menu", 0, windowFlags); + if (ImGui::Button("Continue")) { + state = GlobalState::Playing; + SetMouseCapture(true); + } + ImGui::Separator(); + static float distance = world->MaxRenderingDistance; + ImGui::SliderFloat("Render distance", &distance, 1.0f, 16.0f); + + static float sense = sensetivity; + ImGui::SliderFloat("Sensetivity", &sense, 0.01f, 1.0f); + + if (ImGui::Button("Apply settings")) { + if (distance != world->MaxRenderingDistance) { + world->MaxRenderingDistance = distance; + EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); + } + if (sense != sensetivity) + sensetivity = sense; + } + ImGui::Separator(); + + if (ImGui::Button("Disconnect")) { + EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ "Disconnected by user" }); + } + ImGui::End(); + break; + } + case GlobalState::InitialLoading: + break; + } + + ImGui::Render(); +}
\ No newline at end of file diff --git a/src/Render.hpp b/src/Render.hpp index b7d12d0..0b67218 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -1,21 +1,35 @@ #pragma once -#include <SFML/Window.hpp> +#include <SDL.h> #include "Shader.hpp" #include "RendererWorld.hpp" -#include "RendererWidget.hpp" class Render { - sf::Window *window; + SDL_Window *window; + SDL_GLContext glContext; + + bool renderGui = false; bool isRunning = true; bool isMouseCaptured = false; + int prevMouseX, prevMouseY; float mouseXDelta, mouseYDelta; std::unique_ptr<RendererWorld> world; bool renderWorld = false; RenderState renderState; LoopExecutionTimeController timer; - std::map<sf::Keyboard::Key, bool> isKeyPressed; + std::map<SDL_Scancode, bool> isKeyPressed; + bool HasFocus=true; + float sensetivity = 0.1f; + + enum GlobalState { + InitialLoading, + MainMenu, + Loading, + Playing, + Paused, + } state = InitialLoading; + std::string stateString; void SetMouseCapture(bool IsCaptured); @@ -32,6 +46,8 @@ class Render { void PrepareToRendering(); void UpdateKeyboard(); + + void RenderGui(); public: Render(unsigned int windowWidth, unsigned int windowHeight, std::string windowTitle); ~Render(); diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index 7262583..c90e1fb 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -1,4 +1,5 @@ #include "RendererWorld.hpp" +#include "DebugInfo.hpp" void RendererWorld::WorkerFunction(size_t workerId) { EventListener tasksListener; @@ -357,4 +358,7 @@ void RendererWorld::Update(double timeToUpdate) { EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{}); timeSincePreviousUpdate = std::chrono::steady_clock::now(); } + + DebugInfo::readyRenderer = this->renderData.size(); + DebugInfo::renderSections = this->sections.size(); } diff --git a/src/Socket.hpp b/src/Socket.hpp index 16825f0..3d9e1a2 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -2,8 +2,6 @@ #include <string> -#include <SFML/Network.hpp> - #include <SDL_net.h> /** diff --git a/src/Texture.cpp b/src/Texture.cpp index 5c7ebf7..d39585f 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -1,5 +1,11 @@ #include "Texture.hpp" +#include <SDL.h> +#include <SDL_image.h> + + +bool IsImgInitialized = false; + Texture::Texture(std::string filename, GLenum textureWrapping, GLenum textureFiltering) { glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); @@ -12,25 +18,71 @@ Texture::Texture(std::string filename, GLenum textureWrapping, GLenum textureFil glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //Image load - sf::Image image; - if (!image.loadFromFile(filename)) { - LOG(ERROR) << "Can't open image " << filename; - throw 201; + //Initialize SDL2_image + if (!IsImgInitialized) { + IsImgInitialized = true; + int imgFlags = IMG_INIT_PNG; + if (!(IMG_Init(imgFlags) & imgFlags)) + { + throw std::runtime_error("IMG Not initialized: " + std::string(IMG_GetError())); + } } - if (image.getPixelsPtr() == nullptr) { - LOG(ERROR) << "Image data is corrupted!"; - throw 202; - } - image.flipVertically(); + //Load image + SDL_Surface *image = IMG_Load(filename.c_str()); + if (!image) + throw std::runtime_error("Image not loaded: " + std::string(IMG_GetError())); + + if (image->format->BytesPerPixel != 4) + throw std::runtime_error("PNG format is not RGBA"); + + //Flip surface + SDL_LockSurface(image); + + { + int pitch = image->pitch; + int height = image->h; + void* image_pixels = image->pixels; + + int index; + void* temp_row; + int height_div_2; + + temp_row = (void *)malloc(pitch); + if (!temp_row) + throw std::runtime_error("Not enough memory for texture flipping"); + + height_div_2 = (int)(height * .5); + for (index = 0; index < height_div_2; index++) { + memcpy((Uint8 *)temp_row, + (Uint8 *)(image_pixels)+ + pitch * index, + pitch); + + memcpy( + (Uint8 *)(image_pixels)+ + pitch * index, + (Uint8 *)(image_pixels)+ + pitch * (height - index - 1), + pitch); + memcpy( + (Uint8 *)(image_pixels)+ + pitch * (height - index - 1), + temp_row, + pitch); + } + free(temp_row); + } //Creating texture - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, - (GLvoid *) image.getPixelsPtr()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w,image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, + (GLvoid *) image->pixels); + SDL_UnlockSurface(image); + //glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); + SDL_FreeSurface(image); } Texture::~Texture() { diff --git a/src/Texture.hpp b/src/Texture.hpp index 5b2afcf..6b024d4 100644 --- a/src/Texture.hpp +++ b/src/Texture.hpp @@ -2,7 +2,6 @@ #include <easylogging++.h> #include <GL/glew.h> -#include <SFML/Graphics.hpp> class Texture { Texture(Texture&); diff --git a/src/ThreadGame.cpp b/src/ThreadGame.cpp index 5e1d710..f425747 100644 --- a/src/ThreadGame.cpp +++ b/src/ThreadGame.cpp @@ -1,5 +1,6 @@ #include "ThreadGame.hpp" +#include "DebugInfo.hpp" ThreadGame::ThreadGame() { @@ -35,21 +36,21 @@ void ThreadGame::Execute() { if (!gs) return; switch (std::get<KeyPressedData>(eventData).key) { - case sf::Keyboard::W: - isMoving[GameState::FORWARD] = true; - break; - case sf::Keyboard::A: - isMoving[GameState::LEFT] = true; - break; - case sf::Keyboard::S: - isMoving[GameState::BACKWARD] = true; - break; - case sf::Keyboard::D: - isMoving[GameState::RIGHT] = true; - break; - case sf::Keyboard::Space: - isMoving[GameState::JUMP] = true; - break; + case SDL_SCANCODE_W: + isMoving[GameState::FORWARD] = true; + break; + case SDL_SCANCODE_A: + isMoving[GameState::LEFT] = true; + break; + case SDL_SCANCODE_S: + isMoving[GameState::BACKWARD] = true; + break; + case SDL_SCANCODE_D: + isMoving[GameState::RIGHT] = true; + break; + case SDL_SCANCODE_SPACE: + isMoving[GameState::JUMP] = true; + break; } }); @@ -57,21 +58,21 @@ void ThreadGame::Execute() { if (!gs) return; switch (std::get<KeyReleasedData>(eventData).key) { - case sf::Keyboard::W: - isMoving[GameState::FORWARD] = false; - break; - case sf::Keyboard::A: - isMoving[GameState::LEFT] = false; - break; - case sf::Keyboard::S: - isMoving[GameState::BACKWARD] = false; - break; - case sf::Keyboard::D: - isMoving[GameState::RIGHT] = false; - break; - case sf::Keyboard::Space: - isMoving[GameState::JUMP] = false; - break; + case SDL_SCANCODE_W: + isMoving[GameState::FORWARD] = false; + break; + case SDL_SCANCODE_A: + isMoving[GameState::LEFT] = false; + break; + case SDL_SCANCODE_S: + isMoving[GameState::BACKWARD] = false; + break; + case SDL_SCANCODE_D: + isMoving[GameState::RIGHT] = false; + break; + case SDL_SCANCODE_SPACE: + isMoving[GameState::JUMP] = false; + break; } }); @@ -85,6 +86,7 @@ void ThreadGame::Execute() { LoopExecutionTimeController timer(std::chrono::milliseconds(int(1.0f / 60.0f * 1000.0f))); while (isRunning) { + DebugInfo::gameThreadTime = timer.GetRealDeltaS() * 1000'00.0f; if (gs != nullptr) gs->Update(timer.GetRealDeltaS()); listener.HandleEvent(); @@ -101,7 +103,7 @@ void ThreadGame::Execute() { if (isMoving[GameState::JUMP]) gs->HandleMovement(GameState::JUMP, timer.GetRealDeltaS()); } - timer.Update(); + timer.Update(); } gs.reset(); } diff --git a/src/World.cpp b/src/World.cpp index 1a0e0fa..8f6bb5c 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1,5 +1,6 @@ #include "World.hpp" #include "Event.hpp" +#include "DebugInfo.hpp" void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) { StreamBuffer chunkData(packet->Data.data(), packet->Data.size()); @@ -137,6 +138,7 @@ void World::UpdatePhysics(float delta) it.pos = it.pos + it.vel * delta; } entitiesMutex.unlock(); + DebugInfo::totalSections = sections.size(); } Entity & World::GetEntity(unsigned int EntityId) diff --git a/src/imgui_impl_sdl_gl3.cpp b/src/imgui_impl_sdl_gl3.cpp new file mode 100644 index 0000000..63d7033 --- /dev/null +++ b/src/imgui_impl_sdl_gl3.cpp @@ -0,0 +1,395 @@ +// ImGui SDL2 binding with OpenGL3 +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include "imgui.h" +#include "imgui_impl_sdl_gl3.h" + +// SDL,GL3W +#include <SDL.h> +#include <SDL_syswm.h> +#include <GL/glew.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. + +// Data +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + ImGuiIO& io = ImGui::GetIO(); + int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); + int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); + if (fb_width == 0 || fb_height == 0) + return; + draw_data->ScaleClipRects(io.DisplayFramebufferScale); + + // Backup GL state + GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); + glActiveTexture(GL_TEXTURE0); + GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); + GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); + GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); + GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); + GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); + GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); + GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); + GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); + GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); + GLboolean last_enable_blend = glIsEnabled(GL_BLEND); + GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); + GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); + GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + + // Setup viewport, orthographic projection matrix + glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); + const float ortho_projection[4][4] = + { + { 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + {-1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + const ImDrawIdx* idx_buffer_offset = 0; + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); + + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); + } + idx_buffer_offset += pcmd->ElemCount; + } + } + + // Restore modified GL state + glUseProgram(last_program); + glBindTexture(GL_TEXTURE_2D, last_texture); + glActiveTexture(last_active_texture); + glBindVertexArray(last_vertex_array); + glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); + glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); + glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); + if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); + if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); + if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); + glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); + glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); +} + +static const char* ImGui_ImplSdlGL3_GetClipboardText(void*) +{ + return SDL_GetClipboardText(); +} + +static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text) +{ + SDL_SetClipboardText(text); +} + +bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) +{ + ImGuiIO& io = ImGui::GetIO(); + switch (event->type) + { + case SDL_MOUSEWHEEL: + { + if (event->wheel.y > 0) + g_MouseWheel = 1; + if (event->wheel.y < 0) + g_MouseWheel = -1; + return true; + } + case SDL_MOUSEBUTTONDOWN: + { + if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true; + if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true; + if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true; + return true; + } + case SDL_TEXTINPUT: + { + io.AddInputCharactersUTF8(event->text.text); + return true; + } + case SDL_KEYDOWN: + case SDL_KEYUP: + { + int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK; + io.KeysDown[key] = (event->type == SDL_KEYDOWN); + io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); + io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); + io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); + io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); + return true; + } + } + return false; +} + +void ImGui_ImplSdlGL3_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplSdlGL3_CreateDeviceObjects() +{ + // Backup GL state + GLint last_texture, last_array_buffer, last_vertex_array; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); + + const GLchar *vertex_shader = + "#version 330\n" + "uniform mat4 ProjMtx;\n" + "in vec2 Position;\n" + "in vec2 UV;\n" + "in vec4 Color;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "#version 330\n" + "uniform sampler2D Texture;\n" + "in vec2 Frag_UV;\n" + "in vec4 Frag_Color;\n" + "out vec4 Out_Color;\n" + "void main()\n" + "{\n" + " Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + glCompileShader(g_FragHandle); + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + glGenBuffers(1, &g_ElementsHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + + ImGui_ImplSdlGL3_CreateFontsTexture(); + + // Restore modified GL state + glBindTexture(GL_TEXTURE_2D, last_texture); + glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); + glBindVertexArray(last_vertex_array); + + return true; +} + +void ImGui_ImplSdlGL3_InvalidateDeviceObjects() +{ + if (g_VaoHandle) glDeleteVertexArrays(1, &g_VaoHandle); + if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); + if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); + g_VaoHandle = g_VboHandle = g_ElementsHandle = 0; + + if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); + if (g_VertHandle) glDeleteShader(g_VertHandle); + g_VertHandle = 0; + + if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); + if (g_FragHandle) glDeleteShader(g_FragHandle); + g_FragHandle = 0; + + if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); + g_ShaderHandle = 0; + + if (g_FontTexture) + { + glDeleteTextures(1, &g_FontTexture); + ImGui::GetIO().Fonts->TexID = 0; + g_FontTexture = 0; + } +} + +bool ImGui_ImplSdlGL3_Init(SDL_Window* window) +{ + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; + io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; + io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP; + io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; + io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; + io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; + io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; + io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; + io.KeyMap[ImGuiKey_A] = SDLK_a; + io.KeyMap[ImGuiKey_C] = SDLK_c; + io.KeyMap[ImGuiKey_V] = SDLK_v; + io.KeyMap[ImGuiKey_X] = SDLK_x; + io.KeyMap[ImGuiKey_Y] = SDLK_y; + io.KeyMap[ImGuiKey_Z] = SDLK_z; + + io.RenderDrawListsFn = ImGui_ImplSdlGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplSdlGL3_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText; + io.ClipboardUserData = NULL; + +#ifdef _WIN32 + SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + SDL_GetWindowWMInfo(window, &wmInfo); + io.ImeWindowHandle = wmInfo.info.win.window; +#else + (void)window; +#endif + + return true; +} + +void ImGui_ImplSdlGL3_Shutdown() +{ + ImGui_ImplSdlGL3_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) +{ + if (!g_FontTexture) + ImGui_ImplSdlGL3_CreateDeviceObjects(); + + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + SDL_GetWindowSize(window, &w, &h); + SDL_GL_GetDrawableSize(window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + Uint32 time = SDL_GetTicks(); + double current_time = time / 1000.0; + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) + int mx, my; + Uint32 mouseMask = SDL_GetMouseState(&mx, &my); + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) + io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + else + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + + io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; + io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; + g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); + + // Start the frame + ImGui::NewFrame(); +} diff --git a/src/imgui_impl_sdl_gl3.h b/src/imgui_impl_sdl_gl3.h new file mode 100644 index 0000000..99abd40 --- /dev/null +++ b/src/imgui_impl_sdl_gl3.h @@ -0,0 +1,19 @@ +// ImGui SDL2 binding with OpenGL3 +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct SDL_Window; +typedef union SDL_Event SDL_Event; + +IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window); +IMGUI_API void ImGui_ImplSdlGL3_Shutdown(); +IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window); +IMGUI_API bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplSdlGL3_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplSdlGL3_CreateDeviceObjects(); |