diff --git a/Graphics/examples/Example.cpp b/Graphics/examples/Example.cpp index 489a08b..15d7297 100644 --- a/Graphics/examples/Example.cpp +++ b/Graphics/examples/Example.cpp @@ -1,129 +1,27 @@ -#include "Window.hpp" -#include "Graphics.hpp" - -#include "Timing.hpp" +#include "GraphicApplication.hpp" #include "imgui.h" using namespace tp; -class Application { +class ExampleApplication : public Application { public: - Application() : - mApplicaitonModule("Application", nullptr, nullptr, mModuleDeps) { - mInitialized = mApplicaitonModule.initialize(); - if (!mInitialized) return; + ExampleApplication() = default; - mWindow = Window::createWindow(); - - mDrawTimer.setDuration(1000.f / mDrawPerSecond); - mProcTimer.setDuration(1000.f / mProcPerSecond); - mPerSecondTimer.setDuration(1000.f); + void processFrame(EventHandler* eventHandler) override { + // example } - void run() { - Graphics graphics(mWindow); - auto eventHandler = new EventHandler(); - - mWindow->setEventHandler(eventHandler); - - mDrawTimer.reset(); - mProcTimer.reset(); - mPerSecondTimer.reset(); - - bool redrawNeeded = false; - - while (!mWindow->shouldClose()) { - if (mProcTimer.isTimeout()) { - - mWindow->processEvents(); - - while (eventHandler->isEvents()) { - eventHandler->processEvent(); - processFrame(eventHandler); - - redrawNeeded = true; - mFramesProcessed++; - } - - // graphics.procBegin(); - // graphics.procEnd(); - redrawNeeded = true; - mFramesProcessed++; - - mProcTimer.wait(); - mProcTimer.reset(); - } - - if (mDrawTimer.isTimeout()) { - mDrawTimer.reset(); - - if (redrawNeeded) { - graphics.drawBegin(); - - drawFrame(graphics.getCanvas()); - - graphics.drawEnd(); - - mWindow->draw(); - - redrawNeeded = false; - mFramesDrawn++; - } - } - - if (mPerSecondTimer.isTimeout()) { - mPerSecondTimer.reset(); - - mFramesProcessedPerSecond = mFramesProcessed; - mFramesDrawnPerSecond = mFramesDrawn; - - mFramesDrawn = 0; - mFramesProcessed = 0; - } - } - - delete eventHandler; + virtual void drawFrame(Canvas* canvas) override { + ImGui::Text("Frames processed per second: %f", this->mFramesProcessedPerSecond); + ImGui::Text("Frames drawn per second: %f", this->mFramesDrawnPerSecond); } - virtual void processFrame(EventHandler* eventHandler) { - } - - virtual void drawFrame(Canvas* canvas) { - ImGui::Text("Frames processed per second: %f", mFramesProcessedPerSecond); - ImGui::Text("Frames drawn per second: %f", mFramesDrawnPerSecond); - } - - ~Application() { - if (!mInitialized) return; - Window::destroyWindow(mWindow); - mApplicaitonModule.deinitialize(); - } - -private: - ModuleManifest* mModuleDeps[2] = { &gModuleGraphics, nullptr }; - ModuleManifest mApplicaitonModule; - - Window* mWindow = nullptr; - - bool mInitialized = false; - - ualni mDrawPerSecond = 60; - ualni mProcPerSecond = 1000; - - Timer mDrawTimer; - Timer mProcTimer; - Timer mPerSecondTimer; - - halnf mFramesProcessedPerSecond = 0; - halnf mFramesDrawnPerSecond = 0; - - halnf mFramesProcessed = 0; - halnf mFramesDrawn = 0; + virtual ~ExampleApplication() = default; }; int main() { - Application app; + ExampleApplication app; app.run(); } diff --git a/Graphics/private/GraphicApplication.cpp b/Graphics/private/GraphicApplication.cpp new file mode 100644 index 0000000..0fb2e43 --- /dev/null +++ b/Graphics/private/GraphicApplication.cpp @@ -0,0 +1,89 @@ + +#include "GraphicApplication.hpp" + +using namespace tp; + +Application::Application() : + mApplicationModule("Application", nullptr, nullptr, mModuleDeps) { + mInitialized = mApplicationModule.initialize(); + if (!mInitialized) return; + + mWindow = Window::createWindow(); + + mDrawTimer.setDuration(1000.f / mDrawPerSecond); + mProcTimer.setDuration(1000.f / mProcPerSecond); + mPerSecondTimer.setDuration(1000.f); +} + +void Application::run() { + Graphics graphics(mWindow); + auto eventHandler = new EventHandler(); + + mWindow->setEventHandler(eventHandler); + + mDrawTimer.reset(); + mProcTimer.reset(); + mPerSecondTimer.reset(); + + bool redrawNeeded = false; + + while (!mWindow->shouldClose()) { + if (mProcTimer.isTimeout()) { + + mWindow->processEvents(); + + while (eventHandler->isEvents()) { + eventHandler->processEvent(); + processFrame(eventHandler); + + redrawNeeded = true; + mFramesProcessed++; + } + + mProcTimer.wait(); + mProcTimer.reset(); + } + + if (mDrawTimer.isTimeout()) { + mDrawTimer.reset(); + + if (redrawNeeded) { + graphics.drawBegin(); + + drawFrame(graphics.getCanvas()); + + graphics.drawEnd(); + + mWindow->draw(); + + redrawNeeded = false; + mFramesDrawn++; + } + } + + if (mPerSecondTimer.isTimeout()) { + mPerSecondTimer.reset(); + + mFramesProcessedPerSecond = mFramesProcessed; + mFramesDrawnPerSecond = mFramesDrawn; + + mFramesDrawn = 0; + mFramesProcessed = 0; + } + } + + delete eventHandler; +} + +void Application::processFrame(EventHandler* eventHandler) {} + +void Application::drawFrame(Canvas* canvas) { + // ImGui::Text("Frames processed per second: %f", mFramesProcessedPerSecond); + // ImGui::Text("Frames drawn per second: %f", mFramesDrawnPerSecond); +} + +Application::~Application() { + if (!mInitialized) return; + Window::destroyWindow(mWindow); + mApplicationModule.deinitialize(); +} \ No newline at end of file diff --git a/Graphics/private/Window.cpp b/Graphics/private/Window.cpp index 3c0bdf1..baea6d9 100644 --- a/Graphics/private/Window.cpp +++ b/Graphics/private/Window.cpp @@ -3,6 +3,8 @@ #include "WindowContext.hpp" #include "Allocators.hpp" +#include "Rect.hpp" + #include #ifdef ENV_OS_WINDOWS @@ -92,11 +94,8 @@ void Window::destroyWindow(Window* window) { bool Window::shouldClose() const { return glfwWindowShouldClose(mContext->window); } void Window::processEvents() { - glfwPollEvents(); - - int w, h; - glfwGetWindowSize(mContext->window, &w, &h); - mSize = { (halnf) w, (halnf) h }; + glfwWaitEvents(); + checkAxisUpdates(); } void Window::draw() { @@ -111,6 +110,35 @@ void Window::setEventHandler(EventHandler* eventHandler) { mEventHandler = event EventHandler* Window::getEventHandler() { return mEventHandler; } +void Window::checkAxisUpdates() { + if (!mEventHandler) return; + + int w, h; + glfwGetWindowSize(mContext->window, &w, &h); + + if (mSize != Vec2F((halnf) w, (halnf) h)) { + mSize = { (halnf) w, (halnf) h }; + mEventHandler->postEvent(InputID::WINDOW_RESIZE, {}); + } + + double x, y; + glfwGetCursorPos(mContext->window, &x, &y); + + int posX, posY; + glfwGetWindowPos(mContext->window, &posX, &posY); + + if (mPointerPos != Vec2F{ (halnf) x, (halnf) y }) { + mPointerPos = { (halnf) x, (halnf) y }; + + auto pos = Vec2F{ (halnf) posX, (halnf) posY }; + RectF windowRec = { { 0, 0 }, mSize }; + + if (windowRec.isInside(mPointerPos)) { + mEventHandler->postEvent(InputID::MOUSE1, { {}, {}, mPointerPos }); + } + } +} + static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { auto* self = static_cast(glfwGetWindowUserPointer(window)); @@ -119,6 +147,8 @@ static void keyCallback(GLFWwindow* window, int key, int scancode, int action, i EventHandler* eventHandler = self->getEventHandler(); if (!eventHandler) return; + self->checkAxisUpdates(); + // post key event /* if (action == GLFW_PRESS) { @@ -137,6 +167,8 @@ static void mouseButtonCallback(GLFWwindow* window, int button, int action, int EventHandler* eventHandler = self->getEventHandler(); if (!eventHandler) return; + self->checkAxisUpdates(); + // post mouse button event // inputManager->mouseButtonStates[button] = action; // inputManager->isEvent = true; diff --git a/Graphics/public/EventHandler.hpp b/Graphics/public/EventHandler.hpp index 78f8f5f..a0468f4 100644 --- a/Graphics/public/EventHandler.hpp +++ b/Graphics/public/EventHandler.hpp @@ -60,11 +60,27 @@ namespace tp { ~EventHandler(); public: // Event Poster Interface - void postEvent(InputID inputID, InputEvent inputEvent); // Record event + + // Record event + void postEvent(InputID inputID, InputEvent inputEvent) { + mMutex.lock(); + mEventQueue.pushBack({ inputID, inputEvent }); + mMutex.unlock(); + } public: // User interface - bool isEvents() { return false; } - void processEvent() {} + bool isEvents() { + mMutex.lock(); + auto res = mEventQueue.length(); + mMutex.unlock(); + return res; + } + + void processEvent() { + mMutex.lock(); + mEventQueue.popFront(); + mMutex.unlock(); + } const Vec2F& getPointer() const; @@ -78,7 +94,7 @@ namespace tp { std::mutex mMutex = {}; // Store thread protected queue of posted events - List mEventQueue; + List> mEventQueue; // input states Vec2F mPointer; diff --git a/Graphics/public/GraphicApplication.hpp b/Graphics/public/GraphicApplication.hpp new file mode 100644 index 0000000..28e9fee --- /dev/null +++ b/Graphics/public/GraphicApplication.hpp @@ -0,0 +1,41 @@ + +#pragma once + +#include "Window.hpp" +#include "Graphics.hpp" +#include "Timing.hpp" + +namespace tp { + class Application { + public: + Application(); + + void run(); + + virtual void processFrame(EventHandler* eventHandler); + virtual void drawFrame(Canvas* canvas); + + virtual ~Application(); + + protected: + ModuleManifest* mModuleDeps[2] = { &gModuleGraphics, nullptr }; + ModuleManifest mApplicationModule; + + Window* mWindow = nullptr; + + bool mInitialized = false; + + ualni mDrawPerSecond = 60; + ualni mProcPerSecond = 160; + + Timer mDrawTimer; + Timer mProcTimer; + Timer mPerSecondTimer; + + halnf mFramesProcessedPerSecond = 0; + halnf mFramesDrawnPerSecond = 0; + + halnf mFramesProcessed = 0; + halnf mFramesDrawn = 0; + }; +} \ No newline at end of file diff --git a/Graphics/public/InputCodes.hpp b/Graphics/public/InputCodes.hpp index 889b151..8bab778 100644 --- a/Graphics/public/InputCodes.hpp +++ b/Graphics/public/InputCodes.hpp @@ -146,5 +146,7 @@ namespace tp { MOUSE_DOWN = 507, LAST_KEY_CODE = 508, + + WINDOW_RESIZE = 1000, }; } \ No newline at end of file diff --git a/Graphics/public/Window.hpp b/Graphics/public/Window.hpp index 2815271..43694ff 100644 --- a/Graphics/public/Window.hpp +++ b/Graphics/public/Window.hpp @@ -29,8 +29,12 @@ namespace tp { [[nodiscard]] bool shouldClose() const; [[nodiscard]] const Vec2F& getSize() const; + void checkAxisUpdates(); + private: Vec2F mSize; + Vec2F mPointerPos; + Context* mContext; EventHandler* mEventHandler = nullptr; };