From 4570c971c0add3d3aab27a5f89a46f8d8cfc062a Mon Sep 17 00:00:00 2001 From: Irlan <-> Date: Fri, 13 Apr 2018 14:18:02 -0300 Subject: [PATCH] use mvvm Switch the Testbed GUI architecture pattern to MVVM (Model-View-ModelView). --- examples/testbed/framework/main.cpp | 26 ++- examples/testbed/framework/model.cpp | 90 +++++++--- examples/testbed/framework/model.h | 176 +++----------------- examples/testbed/framework/presenter.cpp | 143 ---------------- examples/testbed/framework/presenter.h | 47 ------ examples/testbed/framework/test.cpp | 5 +- examples/testbed/framework/test.h | 45 +---- examples/testbed/framework/view.cpp | 102 +++++------- examples/testbed/framework/view.h | 22 +-- examples/testbed/framework/view_model.cpp | 192 ++++++++++++++++++++++ examples/testbed/framework/view_model.h | 127 ++++++++++++++ premake5.lua | 4 +- 12 files changed, 475 insertions(+), 504 deletions(-) delete mode 100644 examples/testbed/framework/presenter.cpp delete mode 100644 examples/testbed/framework/presenter.h create mode 100644 examples/testbed/framework/view_model.cpp create mode 100644 examples/testbed/framework/view_model.h diff --git a/examples/testbed/framework/main.cpp b/examples/testbed/framework/main.cpp index 4b3f632..c338850 100644 --- a/examples/testbed/framework/main.cpp +++ b/examples/testbed/framework/main.cpp @@ -24,15 +24,19 @@ // error #endif +#include + #include #include +#include // -GLFWwindow* g_window; +static GLFWwindow* g_window; // -Model* g_model; -View* g_view; +static Model* g_model; +static View* g_view; +static ViewModel* g_viewModel; static void WindowSize(GLFWwindow* ww, int w, int h) { @@ -103,9 +107,9 @@ static void Run() g_profiler->PushEvent("Frame"); - g_view->Command_PreDraw(); + g_view->BeginInterface(); - if (g_settings->pause) + if (g_model->IsPaused()) { g_draw->DrawString(b3Color_white, "*PAUSED*"); } @@ -124,11 +128,11 @@ static void Run() } } - g_view->Command_Draw(); + g_view->Interface(); - g_model->Command_Step(); + g_model->Update(); - g_view->Command_PostDraw(); + g_view->EndInterface(); g_profiler->PopEvent(); @@ -183,12 +187,16 @@ int main(int argc, char** args) // g_model = new Model(); - g_view = new View(g_window, g_model); + g_view = new View(g_window); + g_viewModel = new ViewModel(g_model, g_view); // Run Run(); // + delete g_viewModel; + g_viewModel = nullptr; + delete g_view; g_view = nullptr; diff --git a/examples/testbed/framework/model.cpp b/examples/testbed/framework/model.cpp index b4f1131..6127e10 100644 --- a/examples/testbed/framework/model.cpp +++ b/examples/testbed/framework/model.cpp @@ -17,13 +17,12 @@ */ #include - -Settings* g_settings = nullptr; +#include +#include Model::Model() { - g_settings = &m_settings; - g_testSettings = &m_testSettings; + m_viewModel = nullptr; g_draw = &m_draw; g_camera = &m_camera; g_profiler = &m_profiler; @@ -42,43 +41,80 @@ Model::Model() glClearColor(0.3f, 0.3f, 0.3f, 1.0f); glClearDepth(1.0f); - Action_DefaultCamera(); + Action_ResetCamera(); + + m_setTest = true; + m_pause = true; + m_singlePlay = false; } Model::~Model() { - g_testSettings = nullptr; g_draw = nullptr; g_camera = nullptr; g_profiler = nullptr; g_profilerRecorder = nullptr; g_profilerListener = nullptr; - g_testSettings = nullptr; delete m_test; } -void Model::Command_Step() +void Model::Action_SaveTest() +{ + m_test->Save(); +} + +void Model::Command_Press_Key(int button) +{ + m_test->KeyDown(button); +} + +void Model::Command_Release_Key(int button) +{ + m_test->KeyUp(button); +} + +void Model::Command_Press_Mouse_Left(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseLeftDown(pw); +} + +void Model::Command_Release_Mouse_Left(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseLeftUp(pw); +} + +void Model::Command_Move_Cursor(const b3Vec2& ps) +{ + Ray3 pw = m_camera.ConvertScreenToWorld(ps); + + m_test->MouseMove(pw); +} + +void Model::Update() { g_drawFlags = 0; - g_drawFlags += m_settings.drawPoints * DrawFlags::e_pointsFlag; - g_drawFlags += m_settings.drawLines * DrawFlags::e_linesFlag; - g_drawFlags += m_settings.drawTriangles * DrawFlags::e_trianglesFlag; + g_drawFlags += g_settings->drawPoints * DrawFlags::e_pointsFlag; + g_drawFlags += g_settings->drawLines * DrawFlags::e_linesFlag; + g_drawFlags += g_settings->drawTriangles * DrawFlags::e_trianglesFlag; glViewport(0, 0, GLsizei(m_camera.m_width), GLsizei(m_camera.m_height)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if (m_settings.testID != m_settings.lastTestID) + if (m_setTest) { delete m_test; - m_settings.lastTestID = m_settings.testID; - m_test = g_tests[m_settings.testID].create(); - - m_settings.pause = true; - Action_DefaultCamera(); + m_test = g_tests[g_settings->testID].create(); + m_setTest = false; + m_pause = true; + Action_ResetCamera(); } - if (m_settings.drawGrid) + if (g_settings->drawGrid) { b3Color color(0.2f, 0.2f, 0.2f, 1.0f); @@ -114,19 +150,25 @@ void Model::Command_Step() } // - m_testSettings.inv_hertz = m_testSettings.hertz != 0.0f ? 1.0f / m_testSettings.hertz : 0.0f; - - if (m_settings.pause) + if (m_pause) { - if (m_settings.singleStep) + if (m_singlePlay) { - m_settings.singleStep = false; + // ! + g_testSettings->inv_hertz = g_testSettings->hertz > 0.0f ? 1.0f / g_testSettings->hertz : 0.0f; + m_singlePlay = false; } else { - m_testSettings.inv_hertz = 0.0f; + // ! + g_testSettings->inv_hertz = 0.0f; } } + else + { + // ! + g_testSettings->inv_hertz = g_testSettings->hertz > 0.0f ? 1.0f / g_testSettings->hertz : 0.0f; + } m_test->Step(); diff --git a/examples/testbed/framework/model.h b/examples/testbed/framework/model.h index 3a10625..e41d97b 100644 --- a/examples/testbed/framework/model.h +++ b/examples/testbed/framework/model.h @@ -21,40 +21,10 @@ #include #include -#include -struct Settings -{ - Settings() - { - lastTestID = -1; - testID = 0; - pause = false; - singleStep = false; - drawPoints = true; - drawLines = true; - drawTriangles = true; - drawGrid = true; - drawProfile = false; - drawStats = false; - } +class Test; - int lastTestID; - int testID; - - bool pause; - bool singleStep; - - bool drawPoints; - bool drawLines; - bool drawTriangles; - bool drawGrid; - bool drawProfile; - bool drawStats; -}; - -// -extern Settings* g_settings; +class ViewModel; class Model { @@ -64,88 +34,59 @@ public: ~Model(); void Action_SaveTest(); - - void Action_SelectTest(int selection); - void Action_RestartTest(); - void Action_PreviousTest(); - void Action_NextTest(); + void Action_SetTest(); void Action_PlayPause(); - void Action_SingleStep(); - void Action_DefaultCamera(); - void Action_LeftCamera(); - void Action_RightCamera(); - void Action_BottomCamera(); - void Action_TopCamera(); - void Action_BackCamera(); - void Action_FrontCamera(); + void Action_SinglePlay(); + void Action_ResetCamera(); - void Command_Step(); void Command_Press_Key(int button); void Command_Release_Key(int button); void Command_Press_Mouse_Left(const b3Vec2& ps); void Command_Release_Mouse_Left(const b3Vec2& ps); void Command_Move_Cursor(const b3Vec2& ps); + void Command_ResizeCamera(float32 w, float32 h); void Command_RotateCameraX(float32 angle); void Command_RotateCameraY(float32 angle); void Command_TranslateCameraX(float32 d); void Command_TranslateCameraY(float32 d); void Command_ZoomCamera(float32 d); + + void Update(); + + bool IsPaused() const { return m_pause; } private: - friend class View; + friend class ViewModel; - // UI State - Settings m_settings; - TestSettings m_testSettings; + ViewModel* m_viewModel; - // App State Draw m_draw; Camera m_camera; Profiler m_profiler; TestbedListener m_profilerListener; Test* m_test; + bool m_setTest; + bool m_pause; + bool m_singlePlay; }; -inline void Model::Action_SelectTest(int selection) +inline void Model::Action_SetTest() { - m_settings.testID = selection; - m_settings.lastTestID = -1; -} - -inline void Model::Action_RestartTest() -{ - m_settings.lastTestID = -1; -} - -inline void Model::Action_PreviousTest() -{ - m_settings.testID = b3Clamp(m_settings.testID - 1, 0, int(g_testCount) - 1); - m_settings.lastTestID = -1; -} - -inline void Model::Action_NextTest() -{ - m_settings.testID = b3Clamp(m_settings.testID + 1, 0, int(g_testCount) - 1); - m_settings.lastTestID = -1; -} - -inline void Model::Action_SaveTest() -{ - m_test->Save(); + m_setTest = true; } inline void Model::Action_PlayPause() { - m_settings.pause = !m_settings.pause; + m_pause = !m_pause; } -inline void Model::Action_SingleStep() +inline void Model::Action_SinglePlay() { - m_settings.pause = true; - m_settings.singleStep = true; + m_pause = true; + m_singlePlay = true; } -inline void Model::Action_DefaultCamera() +inline void Model::Action_ResetCamera() { m_camera.m_q = b3QuatRotationX(-0.125f * B3_PI); @@ -157,79 +98,6 @@ inline void Model::Action_DefaultCamera() m_camera.m_zoom = 50.0f; } -inline void Model::Action_LeftCamera() -{ - m_camera.m_q = b3QuatRotationX(0.5f * B3_PI); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Action_RightCamera() -{ - m_camera.m_q = b3QuatRotationX(-0.5f * B3_PI); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Action_BottomCamera() -{ - m_camera.m_q = b3QuatRotationX(0.5f * B3_PI); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Action_TopCamera() -{ - m_camera.m_q = b3QuatRotationX(-0.5f * B3_PI); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Action_BackCamera() -{ - m_camera.m_q = b3QuatRotationX(-B3_PI); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Action_FrontCamera() -{ - m_camera.m_q.SetIdentity(); - m_camera.m_center.SetZero(); - m_camera.m_zoom = 50.0f; -} - -inline void Model::Command_Press_Key(int button) -{ - m_test->KeyDown(button); -} - -inline void Model::Command_Release_Key(int button) -{ - m_test->KeyUp(button); -} - -inline void Model::Command_Press_Mouse_Left(const b3Vec2& ps) -{ - Ray3 pw = m_camera.ConvertScreenToWorld(ps); - - m_test->MouseLeftDown(pw); -} - -inline void Model::Command_Release_Mouse_Left(const b3Vec2& ps) -{ - Ray3 pw = m_camera.ConvertScreenToWorld(ps); - - m_test->MouseLeftUp(pw); -} - -inline void Model::Command_Move_Cursor(const b3Vec2& ps) -{ - Ray3 pw = m_camera.ConvertScreenToWorld(ps); - - m_test->MouseMove(pw); -} - inline void Model::Command_ResizeCamera(float32 w, float32 h) { m_camera.m_width = w; diff --git a/examples/testbed/framework/presenter.cpp b/examples/testbed/framework/presenter.cpp deleted file mode 100644 index 8ab33ca..0000000 --- a/examples/testbed/framework/presenter.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* -* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* 3. This notice may not be removed or altered from any source distribution. -*/ - -#include -#include -#include - -// ! -static inline b3Vec2 GetCursorPosition() -{ - extern GLFWwindow* g_window; - - double x, y; - glfwGetCursorPos(g_window, &x, &y); - - return b3Vec2(float32(x), float32(y)); -} - -Presenter::Presenter(Model* model, View* view) -{ - m_model = model; - m_view = view; -} - -Presenter::~Presenter() -{ - -} - -void Presenter::Event_SetWindowSize(float w, float h) -{ - m_model->Command_ResizeCamera(w, h); -} - -void Presenter::Event_Press_Key(int button) -{ - if (m_view->m_shiftDown) - { - if (button == GLFW_KEY_DOWN) - { - m_model->Command_ZoomCamera(1.0f); - } - - if (button == GLFW_KEY_UP) - { - m_model->Command_ZoomCamera(-1.0f); - } - } - else - { - m_model->Command_Press_Key(button); - } -} - -void Presenter::Event_Release_Key(int button) -{ - if (!m_view->m_shiftDown) - { - m_model->Command_Release_Key(button); - } -} - -void Presenter::Event_Press_Mouse(int button) -{ - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - if (!m_view->m_shiftDown) - { - m_model->Command_Press_Mouse_Left(GetCursorPosition()); - } - } -} - -void Presenter::Event_Release_Mouse(int button) -{ - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - if (!m_view->m_shiftDown) - { - m_model->Command_Release_Mouse_Left(GetCursorPosition()); - } - } -} - -void Presenter::Event_Move_Cursor(float x, float y) -{ - b3Vec2 ps; - ps.Set(x, y); - - b3Vec2 dp = ps - m_view->m_ps0; - - float32 ndx = b3Clamp(dp.x, -1.0f, 1.0f); - float32 ndy = b3Clamp(dp.y, -1.0f, 1.0f); - - if (m_view->m_shiftDown) - { - if (m_view->m_leftDown) - { - float32 ax = -0.005f * B3_PI * ndx; - float32 ay = -0.005f * B3_PI * ndy; - - m_model->Command_RotateCameraY(ax); - m_model->Command_RotateCameraX(ay); - } - - if (m_view->m_rightDown) - { - float32 tx = 0.2f * ndx; - float32 ty = -0.2f * ndy; - - m_model->Command_TranslateCameraX(tx); - m_model->Command_TranslateCameraY(ty); - } - } - else - { - m_model->Command_Move_Cursor(GetCursorPosition()); - } -} - -void Presenter::Event_Scroll(float dx, float dy) -{ - if (m_view->m_shiftDown) - { - float32 ny = b3Clamp(dy, -1.0f, 1.0f); - m_model->Command_ZoomCamera(1.0f * ny); - } -} diff --git a/examples/testbed/framework/presenter.h b/examples/testbed/framework/presenter.h deleted file mode 100644 index 31053be..0000000 --- a/examples/testbed/framework/presenter.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef PRESENTER_H -#define PRESENTER_H - -class Model; -class View; - -class Presenter -{ -public: - Presenter(Model* model, View* view); - - ~Presenter(); - - void Event_SetWindowSize(float w, float h); - void Event_Press_Key(int button); - void Event_Release_Key(int button); - void Event_Press_Mouse(int button); - void Event_Release_Mouse(int button); - void Event_Move_Cursor(float x, float y); - void Event_Scroll(float dx, float dy); -private: - friend class Model; - friend class View; - - Model* m_model; - View* m_view; -}; - -#endif \ No newline at end of file diff --git a/examples/testbed/framework/test.cpp b/examples/testbed/framework/test.cpp index cbbe645..c3602c7 100644 --- a/examples/testbed/framework/test.cpp +++ b/examples/testbed/framework/test.cpp @@ -17,7 +17,8 @@ */ #include -#include +#include +#include extern u32 b3_allocCalls, b3_maxAllocCalls; extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters; @@ -34,8 +35,6 @@ void b3PopProfileScope() g_profiler->PopEvent(); } -TestSettings* g_testSettings = nullptr; - Test::Test() : m_bodyDragger(&m_bodyRay, &m_world) { b3_allocCalls = 0; diff --git a/examples/testbed/framework/test.h b/examples/testbed/framework/test.h index d945f01..8261be0 100644 --- a/examples/testbed/framework/test.h +++ b/examples/testbed/framework/test.h @@ -20,13 +20,10 @@ #define TEST_H #include -#include - #include #include -#include -#include +#include inline float32 RandomFloat(float32 a, float32 b) { @@ -36,46 +33,6 @@ inline float32 RandomFloat(float32 a, float32 b) return a + r; } -struct TestSettings -{ - TestSettings() - { - hertz = 60.0f; - inv_hertz = 1.0f / hertz; - velocityIterations = 8; - positionIterations = 2; - sleep = false; - warmStart = true; - convexCache = true; - drawCenterOfMasses = true; - drawShapes = true; - drawBounds = false; - drawJoints = true; - drawContactPoints = true; - drawContactNormals = false; - drawContactTangents = false; - drawContactPolygons = false; - } - - float hertz, inv_hertz; - int velocityIterations; - int positionIterations; - bool sleep; - bool warmStart; - bool convexCache; - - bool drawCenterOfMasses; - bool drawBounds; - bool drawShapes; - bool drawJoints; - bool drawContactPoints; - bool drawContactNormals; - bool drawContactTangents; - bool drawContactPolygons; -}; - -extern TestSettings* g_testSettings; - class RayCastListener : public b3RayCastListener { public: diff --git a/examples/testbed/framework/view.cpp b/examples/testbed/framework/view.cpp index 6412895..7173102 100644 --- a/examples/testbed/framework/view.cpp +++ b/examples/testbed/framework/view.cpp @@ -17,8 +17,10 @@ */ #include -#include +#include +#include +#include #if defined (U_OPENGL_2) #include #elif defined (U_OPENGL_4) @@ -28,7 +30,7 @@ #include -static bool GetTestName(void* userData, int idx, const char** name) +static inline bool GetTestName(void* userData, int idx, const char** name) { assert(u32(idx) < g_testCount); *name = g_tests[idx].name; @@ -111,8 +113,9 @@ static inline void ImGui_GLFW_GL_RenderDrawData(ImDrawData* draw_data) } -View::View(GLFWwindow* window, Model* model) : m_presenter(model, this) +View::View(GLFWwindow* window) { + m_viewModel = nullptr; m_window = window; // Create UI @@ -127,9 +130,6 @@ View::View(GLFWwindow* window, Model* model) : m_presenter(model, this) ImGui::StyleColorsDark(); - m_leftDown = false; - m_rightDown = false; - m_shiftDown = false; m_ps0.SetZero(); } @@ -141,88 +141,60 @@ View::~View() ImGui::DestroyContext(); } +b3Vec2 View::GetCursorPosition() const +{ + double x, y; + glfwGetCursorPos(m_window, &x, &y); + return b3Vec2(float32(x), float32(y)); +} + void View::Event_SetWindowSize(int w, int h) { - m_presenter.Event_SetWindowSize(float32(w), float32(h)); + m_viewModel->Event_SetWindowSize(w, h); } void View::Event_Press_Key(int button) { - if (button == GLFW_KEY_LEFT_SHIFT) - { - m_shiftDown = true; - } - - m_presenter.Event_Press_Key(button); + m_viewModel->Event_Press_Key(button); } void View::Event_Release_Key(int button) { - if (button == GLFW_KEY_LEFT_SHIFT) - { - m_shiftDown = false; - } - - m_presenter.Event_Release_Key(button); + m_viewModel->Event_Release_Key(button); } void View::Event_Press_Mouse(int button) { - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - m_leftDown = true; - } - - if (button == GLFW_MOUSE_BUTTON_RIGHT) - { - m_rightDown = true; - } - - m_presenter.Event_Press_Mouse(button); + m_viewModel->Event_Press_Mouse(button); } void View::Event_Release_Mouse(int button) { - if (button == GLFW_MOUSE_BUTTON_LEFT) - { - m_leftDown = false; - } - - if (button == GLFW_MOUSE_BUTTON_RIGHT) - { - m_rightDown = false; - } - - m_presenter.Event_Release_Mouse(button); + m_viewModel->Event_Release_Mouse(button); } void View::Event_Move_Cursor(float x, float y) { - b3Vec2 ps(x, y); - - m_presenter.Event_Move_Cursor(ps.x, ps.y); - - m_ps0 = ps; + m_viewModel->Event_Move_Cursor(x, y); + m_ps0.Set(x, y); } void View::Event_Scroll(float dx, float dy) { - m_presenter.Event_Scroll(dx, dy); + m_viewModel->Event_Scroll(dx, dy); } -void View::Command_PreDraw() +void View::BeginInterface() { ImGui_GLFW_GL_NewFrame(); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); } -void View::Command_Draw() +void View::Interface() { - Model* model = m_presenter.m_model; - Settings& settings = model->m_settings; - TestSettings& testSettings = model->m_testSettings; - Camera& camera = model->m_camera; + Settings& settings = m_viewModel->m_settings; + TestSettings& testSettings = m_viewModel->m_testSettings; bool openControls = false; bool openAbout = false; @@ -232,7 +204,7 @@ void View::Command_Draw() { if (ImGui::MenuItem("Save")) { - model->Action_SaveTest(); + m_viewModel->Action_SaveTest(); } ImGui::Separator(); @@ -354,7 +326,7 @@ void View::Command_Draw() if (ImGui::Combo("##Test", &settings.testID, GetTestName, NULL, g_testCount, g_testCount)) { - model->Action_SelectTest(settings.testID); + m_viewModel->Action_SetTest(); } ImGui::PopItemWidth(); @@ -365,38 +337,38 @@ void View::Command_Draw() if (ImGui::Button("Previous", menuButtonSize)) { - model->Action_PreviousTest(); + m_viewModel->Action_PreviousTest(); } if (ImGui::Button("Next", menuButtonSize)) { - model->Action_NextTest(); + m_viewModel->Action_NextTest(); } ImGui::Separator(); if (ImGui::Button("Play/Pause", menuButtonSize)) { - model->Action_PlayPause(); + m_viewModel->Action_PlayPause(); } - if (ImGui::Button("Single Step", menuButtonSize)) + if (ImGui::Button("Single Play", menuButtonSize)) { - model->Action_SingleStep(); + m_viewModel->Action_SinglePlay(); } ImGui::Separator(); if (ImGui::Button("Restart", menuButtonSize)) { - model->Action_RestartTest(); + m_viewModel->Action_SetTest(); } ImGui::Separator(); if (ImGui::Button("Reset Camera", menuButtonSize)) { - model->Action_DefaultCamera(); + m_viewModel->Action_ResetCamera(); } ImGui::EndMenuBar(); @@ -406,8 +378,8 @@ void View::Command_Draw() ImGui::PopStyleVar(); - ImGui::SetNextWindowPos(ImVec2(camera.m_width - 250.0f, 40.0f)); - ImGui::SetNextWindowSize(ImVec2(250.0f, camera.m_height - 40.0f)); + ImGui::SetNextWindowPos(ImVec2(g_camera->m_width - 250.0f, 40.0f)); + ImGui::SetNextWindowSize(ImVec2(250.0f, g_camera->m_height - 40.0f)); ImGui::Begin("Test Settings", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); ImGui::PushItemWidth(-1.0f); @@ -430,7 +402,7 @@ void View::Command_Draw() ImGui::End(); } -void View::Command_PostDraw() +void View::EndInterface() { ImGui::PopStyleVar(); diff --git a/examples/testbed/framework/view.h b/examples/testbed/framework/view.h index 5e30239..26c4e57 100644 --- a/examples/testbed/framework/view.h +++ b/examples/testbed/framework/view.h @@ -20,17 +20,15 @@ #define VIEW_H #include -#include struct GLFWwindow; -class Model; +class ViewModel; class View { public: - View(GLFWwindow* window, Model* model); - + View(GLFWwindow* window); ~View(); void Event_SetWindowSize(int w, int h); @@ -41,20 +39,18 @@ public: void Event_Move_Cursor(float x, float y); void Event_Scroll(float dx, float dy); - void Command_PreDraw(); - void Command_Draw(); - void Command_PostDraw(); + void BeginInterface(); + void Interface(); + void EndInterface(); private: - friend class Presenter; + friend class ViewModel; - Presenter m_presenter; + b3Vec2 GetCursorPosition() const; + + ViewModel* m_viewModel; GLFWwindow* m_window; - bool m_leftDown; - bool m_rightDown; - bool m_shiftDown; b3Vec2 m_ps0; - // Ray3 m_ray0; }; #endif \ No newline at end of file diff --git a/examples/testbed/framework/view_model.cpp b/examples/testbed/framework/view_model.cpp new file mode 100644 index 0000000..370a231 --- /dev/null +++ b/examples/testbed/framework/view_model.cpp @@ -0,0 +1,192 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include +#include +#include +#include +#include + +TestSettings* g_testSettings = nullptr; +Settings* g_settings = nullptr; + +ViewModel::ViewModel(Model* model, View* view) +{ + m_model = model; + assert(m_model->m_viewModel == nullptr); + m_model->m_viewModel = this; + + m_view = view; + assert(m_view->m_viewModel == nullptr); + m_view->m_viewModel = this; + + g_settings = &m_settings; + g_testSettings = &m_testSettings; +} + +ViewModel::~ViewModel() +{ + g_settings = nullptr; + g_testSettings = nullptr; +} + +void ViewModel::Action_SaveTest() +{ + m_model->Action_SaveTest(); +} + +void ViewModel::Action_SetTest() +{ + m_model->Action_SetTest(); +} + +void ViewModel::Action_PreviousTest() +{ + m_settings.testID = b3Clamp(m_settings.testID - 1, 0, int(g_testCount) - 1); + m_model->Action_SetTest(); +} + +void ViewModel::Action_NextTest() +{ + m_settings.testID = b3Clamp(m_settings.testID + 1, 0, int(g_testCount) - 1); + m_model->Action_SetTest(); +} + +void ViewModel::Action_PlayPause() +{ + m_model->Action_PlayPause(); +} + +void ViewModel::Action_SinglePlay() +{ + m_model->Action_SinglePlay(); +} + +void ViewModel::Action_ResetCamera() +{ + m_model->Action_ResetCamera(); +} + +void ViewModel::Event_SetWindowSize(int w, int h) +{ + m_model->Command_ResizeCamera(float32(w), float32(h)); +} + +void ViewModel::Event_Press_Key(int button) +{ + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + if (shiftDown) + { + if (button == GLFW_KEY_DOWN) + { + m_model->Command_ZoomCamera(1.0f); + } + + if (button == GLFW_KEY_UP) + { + m_model->Command_ZoomCamera(-1.0f); + } + } + else + { + m_model->Command_Press_Key(button); + } +} + +void ViewModel::Event_Release_Key(int button) +{ + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + if (!shiftDown) + { + m_model->Command_Release_Key(button); + } +} + +void ViewModel::Event_Press_Mouse(int button) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + if (!shiftDown) + { + m_model->Command_Press_Mouse_Left(m_view->GetCursorPosition()); + } + } +} + +void ViewModel::Event_Release_Mouse(int button) +{ + if (button == GLFW_MOUSE_BUTTON_LEFT) + { + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + if (!shiftDown) + { + m_model->Command_Release_Mouse_Left(m_view->GetCursorPosition()); + } + } +} + +void ViewModel::Event_Move_Cursor(float x, float y) +{ + b3Vec2 ps; + ps.Set(x, y); + + b3Vec2 dp = ps - m_view->m_ps0; + + float32 ndx = b3Clamp(dp.x, -1.0f, 1.0f); + float32 ndy = b3Clamp(dp.y, -1.0f, 1.0f); + + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + bool leftDown = glfwGetMouseButton(m_view->m_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; + bool rightDown = glfwGetMouseButton(m_view->m_window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS; + + if (shiftDown) + { + if (leftDown) + { + float32 ax = -0.005f * B3_PI * ndx; + float32 ay = -0.005f * B3_PI * ndy; + + m_model->Command_RotateCameraY(ax); + m_model->Command_RotateCameraX(ay); + } + + if (rightDown) + { + float32 tx = 0.2f * ndx; + float32 ty = -0.2f * ndy; + + m_model->Command_TranslateCameraX(tx); + m_model->Command_TranslateCameraY(ty); + } + } + else + { + m_model->Command_Move_Cursor(m_view->GetCursorPosition()); + } +} + +void ViewModel::Event_Scroll(float dx, float dy) +{ + bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS; + if (shiftDown) + { + float32 ny = b3Clamp(dy, -1.0f, 1.0f); + m_model->Command_ZoomCamera(1.0f * ny); + } +} diff --git a/examples/testbed/framework/view_model.h b/examples/testbed/framework/view_model.h new file mode 100644 index 0000000..7d5925f --- /dev/null +++ b/examples/testbed/framework/view_model.h @@ -0,0 +1,127 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef VIEW_MODEL_H +#define VIEW_MODEL_H + +class Model; +class View; + +// +struct Settings +{ + Settings() + { + testID = 0; + drawPoints = true; + drawLines = true; + drawTriangles = true; + drawGrid = true; + drawProfile = false; + drawStats = false; + } + + int testID; + + bool drawPoints; + bool drawLines; + bool drawTriangles; + bool drawGrid; + bool drawProfile; + bool drawStats; +}; + +// +extern Settings* g_settings; + +// +struct TestSettings +{ + TestSettings() + { + hertz = 60.0f; + inv_hertz = 1.0f / hertz; + velocityIterations = 8; + positionIterations = 2; + sleep = false; + warmStart = true; + convexCache = true; + drawCenterOfMasses = true; + drawShapes = true; + drawBounds = false; + drawJoints = true; + drawContactPoints = true; + drawContactNormals = false; + drawContactTangents = false; + drawContactPolygons = false; + } + + float hertz, inv_hertz; + int velocityIterations; + int positionIterations; + bool sleep; + bool warmStart; + bool convexCache; + + bool drawCenterOfMasses; + bool drawBounds; + bool drawShapes; + bool drawJoints; + bool drawContactPoints; + bool drawContactNormals; + bool drawContactTangents; + bool drawContactPolygons; +}; + +// +extern TestSettings* g_testSettings; + +class ViewModel +{ +public: + ViewModel(Model* model, View* view); + + ~ViewModel(); + + void Action_SaveTest(); + void Action_SetTest(); + void Action_PreviousTest(); + void Action_NextTest(); + void Action_PlayPause(); + void Action_SinglePlay(); + void Action_ResetCamera(); + + void Event_SetWindowSize(int w, int h); + void Event_Press_Key(int button); + void Event_Release_Key(int button); + void Event_Press_Mouse(int button); + void Event_Release_Mouse(int button); + void Event_Move_Cursor(float x, float y); + void Event_Scroll(float dx, float dy); +private: + friend class Model; + friend class View; + + Settings m_settings; + TestSettings m_testSettings; + + Model* m_model; + View* m_view; +}; + +#endif \ No newline at end of file diff --git a/premake5.lua b/premake5.lua index 05c3d35..890c167 100644 --- a/premake5.lua +++ b/premake5.lua @@ -269,7 +269,7 @@ solution (solution_name) examples_inc_dir .. "/testbed/framework/model.h", examples_inc_dir .. "/testbed/framework/view.h", - examples_inc_dir .. "/testbed/framework/presenter.h", + examples_inc_dir .. "/testbed/framework/view_model.h", examples_src_dir .. "/testbed/framework/test.h", @@ -282,7 +282,7 @@ solution (solution_name) examples_inc_dir .. "/testbed/framework/model.cpp", examples_inc_dir .. "/testbed/framework/view.cpp", - examples_inc_dir .. "/testbed/framework/presenter.cpp", + examples_inc_dir .. "/testbed/framework/view_model.cpp", examples_src_dir .. "/testbed/framework/test.cpp", examples_src_dir .. "/testbed/framework/test_entries.cpp",