Refactor the rendering of GUI and other improvements of testbed application

This commit is contained in:
Daniel Chappuis 2021-10-26 17:01:50 +02:00
parent 7ff7b129e9
commit 1b7cadc245
7 changed files with 330 additions and 135 deletions

View File

@ -55,7 +55,12 @@ Gui::~Gui() {
}
/// Initialize the GUI
void Gui::init() {
void Gui::init(GLFWwindow* window) {
mWindow = window;
mScreen = new Screen();
mScreen->initialize(window, true);
// Create the Simulation panel
createSimulationPanel();
@ -66,12 +71,31 @@ void Gui::init() {
// Create the Profiling panel
createProfilingPanel();
mApp->set_visible(true);
mApp->perform_layout();
mScreen->set_visible(true);
mScreen->perform_layout();
mTimeSinceLastProfilingDisplay = glfwGetTime();
}
void Gui::drawAll() {
mScreen->clear();
mScreen->draw_all();
}
void Gui::draw() {
mScreen->draw_setup();
mScreen->clear();
mScreen->draw_contents();
}
void Gui::drawTearDown() {
mScreen->draw_widgets();
mScreen->draw_teardown();
}
// Update the GUI values with the engine settings from the current scene
void Gui::resetWithValuesFromCurrentScene() {
@ -126,7 +150,7 @@ void Gui::update() {
void Gui::createSimulationPanel() {
mSimulationPanel = new Window(mApp, "Simulation");
mSimulationPanel = new Window(mScreen, "Simulation");
mSimulationPanel->set_position(Vector2i(15, 15));
mSimulationPanel->set_layout(new GroupLayout(10, 5, 10 , 20));
//mSimulationPanel->setId("SimulationPanel");
@ -164,17 +188,16 @@ void Gui::createSimulationPanel() {
scenesNames.push_back(scenes[i]->getName().c_str());
}
new Label(mSimulationPanel, "Scene","sans-bold");
ComboBox* comboBoxScenes = new ComboBox(mSimulationPanel, scenesNames);
comboBoxScenes->set_fixed_width(150);
comboBoxScenes->popup()->child_at(0)->set_fixed_height(800);
comboBoxScenes->set_callback([&, scenes](int index) {
mComboBoxScenes = new ComboBox(mSimulationPanel, scenesNames);
mComboBoxScenes->set_callback([&, scenes](int index) {
mApp->switchScene(scenes[index]);
});
}
void Gui::createSettingsPanel() {
mSettingsPanel = new Window(mApp, "Settings");
mSettingsPanel = new Window(mScreen, "Settings");
mSettingsPanel->set_position(Vector2i(15, 180));
mSettingsPanel->set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle, 10, 5));
//mSettingsPanel->setId("SettingsPanel");
@ -189,14 +212,14 @@ void Gui::createSettingsPanel() {
buttonPhysics->set_change_callback([&](bool state) {
mPhysicsPanel->set_visible(true);
mRenderingPanel->set_visible(false);
mApp->perform_layout();
mScreen->perform_layout();
});
Button* buttonRendering = new Button(buttonsPanel, "Rendering");
buttonRendering->set_flags(Button::RadioButton);
buttonRendering->set_change_callback([&](bool state) {
mRenderingPanel->set_visible(true);
mPhysicsPanel->set_visible(false);
mApp->perform_layout();
mScreen->perform_layout();
});
// ---------- Physics Panel ----------
@ -509,7 +532,7 @@ void Gui::createSettingsPanel() {
void Gui::createProfilingPanel() {
Widget* profilingPanel = new Window(mApp, "Profiling");
Widget* profilingPanel = new Window(mScreen, "Profiling");
profilingPanel->set_position(Vector2i(15, 525));
profilingPanel->set_layout(new BoxLayout(Orientation::Vertical, Alignment::Fill, 10, 5));
//profilingPanel->setId("SettingsPanel");
@ -530,3 +553,33 @@ void Gui::createProfilingPanel() {
profilingPanel->set_visible(true);
}
void Gui::onWindowResizeEvent(int width, int height) {
mScreen->resize_callback_event(width, height);
}
void Gui::onMouseMotionEvent(double x, double y) {
mScreen->cursor_pos_callback_event(x, y);
}
bool Gui::onScrollEvent(double x, double y) {
double xMouse, yMouse;
glfwGetCursorPos(mWindow, &xMouse, &yMouse);
// If the mouse cursor is over the scenes choice scrolling menu
const float pixelRatio = mScreen->pixel_ratio();
if (mComboBoxScenes->visible() && mComboBoxScenes->popup()->contains(Vector2i(xMouse, yMouse) / pixelRatio)) {
mScreen->scroll_callback_event(x, y);
return true;
}
return false;
}
void Gui::onMouseButtonEvent(int button, int action, int modifiers) {
mScreen->mouse_button_callback_event(button, action, modifiers);
}
void Gui::onKeyboardEvent(int key, int scancode, int action, int modifiers) {
mScreen->key_callback_event(key, scancode, action, modifiers);
}

View File

@ -56,6 +56,11 @@ class Gui {
// Pointer to the application
TestbedApplication* mApp;
// Screen
Screen* mScreen;
GLFWwindow* mWindow;
static double mScrollX, mScrollY;
// Simulation panel
@ -81,7 +86,11 @@ class Gui {
TextBox* mTextboxSleepLinearVel;
TextBox* mTextboxSleepAngularVel;
ToolButton* mButtonPause;
Widget* mPanelControls;
std::vector<CheckBox*> mCheckboxesScenes;
ComboBox* mComboBoxScenes;
// -------------------- Methods -------------------- //
@ -124,18 +133,31 @@ class Gui {
~Gui();
/// Initialize the GUI
void init();
void init(GLFWwindow* window);
/// Update the GUI
void update();
/// Display the GUI
void render();
void drawAll();
void draw();
void drawTearDown();
/// Update the GUI values with the engine settings from the current scene
void resetWithValuesFromCurrentScene();
static void setScroll(double scrollX, double scrollY);
void onWindowResizeEvent(int width, int height);
void onMouseMotionEvent(double x, double y);
bool onScrollEvent(double x, double y);
void onMouseButtonEvent(int button, int action, int modifiers);
void onKeyboardEvent(int key, int scancode, int action, int modifiers);
};
inline void Gui::resetScroll() {

View File

@ -26,39 +26,35 @@
// Libraries
#include "TestbedApplication.h"
#include "nanogui/nanogui.h"
#include <GLFW/glfw3.h>
using namespace nanogui;
// GLFW
//
#if defined(NANOGUI_USE_OPENGL)
# if defined(NANOGUI_GLAD)
# if defined(NANOGUI_SHARED) && !defined(GLAD_GLAPI_EXPORT)
# define GLAD_GLAPI_EXPORT
# endif
# include <glad/glad.h>
# else
# if defined(__APPLE__)
# define GLFW_INCLUDE_GLCOREARB
# else
# define GL_GLEXT_PROTOTYPES
# endif
# endif
#elif defined(NANOGUI_USE_GLES)
# define GLFW_INCLUDE_ES2
#endif
// Main function
int main(int /*argc*/, char** /*argv*/) {
nanogui::init();
{
bool isFullscreen = false;
// Get the primary monitor
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
// Window size
int windowWidth = mode->width;
int windowHeight = mode->height;
if (!isFullscreen) {
windowWidth *= 0.9;
windowHeight *= 0.9;
}
// Create and start the testbed application
nanogui::ref<TestbedApplication> application = new TestbedApplication(isFullscreen, windowWidth, windowHeight);
application->set_visible(true);
nanogui::mainloop(10);
}
nanogui::shutdown();
// Create and start the testbed application
TestbedApplication application;
application.start();
return 0;
}

View File

@ -31,7 +31,8 @@ using namespace openglframework;
// Constructor
Scene::Scene(const std::string& name, EngineSettings& engineSettings, bool isShadowMappingEnabled)
: mName(name), mEngineSettings(engineSettings), mLastMouseX(0), mLastMouseY(0), mInterpolationFactor(0.0f), mViewportX(0), mViewportY(0),
: mName(name), mEngineSettings(engineSettings), mLastMouseX(0), mLastMouseY(0), mInterpolationFactor(0.0f),
mCurrentCameraVerticalAngle(0.0), mViewportX(0), mViewportY(0),
mViewportWidth(0), mViewportHeight(0), mIsShadowMappingEnabled(isShadowMappingEnabled),
mAreContactPointsDisplayed(true), mAreContactNormalsDisplayed(false), mAreBroadPhaseAABBsDisplayed(false),
mAreCollidersAABBsDisplayed(false), mAreCollisionShapesDisplayed(false), mIsWireframeEnabled(false) {
@ -97,10 +98,6 @@ bool Scene::mouseButtonEvent(int button, bool down, int mods, double mousePosX,
if (down) {
mLastMouseX = mousePosX;
mLastMouseY = mousePosY;
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(mousePosX, mousePosY, mLastPointOnSphere);
}
else { // If the mouse button is released
mIsLastPointOnSphereValid = false;
}
return true;
@ -133,7 +130,6 @@ bool Scene::mouseMotionEvent(double xMouse, double yMouse, int leftButtonState,
// Remember the mouse position
mLastMouseX = xMouse;
mLastMouseY = yMouse;
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(xMouse, yMouse, mLastPointOnSphere);
return true;
}
@ -165,23 +161,25 @@ void Scene::translate(int xMouse, int yMouse) {
// Rotate the camera
void Scene::rotate(int xMouse, int yMouse) {
if (mIsLastPointOnSphereValid) {
const double deltaXMouse = mLastMouseX - xMouse;
const double deltaYMouse = mLastMouseY - yMouse;
Vector3 newPoint3D;
bool isNewPointOK = mapMouseCoordinatesToSphere(xMouse, yMouse, newPoint3D);
double deltaHorizRotationAngle = deltaXMouse / mWindowWidth * MOUSE_CAMERA_ROTATION_SCALING_FACTOR * M_PI;
double deltaVertRotationAngle = deltaYMouse / mWindowHeight * MOUSE_CAMERA_ROTATION_SCALING_FACTOR * M_PI;
if (isNewPointOK) {
Vector3 axis = mLastPointOnSphere.cross(newPoint3D);
float cosAngle = mLastPointOnSphere.dot(newPoint3D);
const double newVerticalAngle = mCurrentCameraVerticalAngle + deltaVertRotationAngle;
float epsilon = std::numeric_limits<float>::epsilon();
if (std::abs(cosAngle) < 1.0f && axis.length() > epsilon) {
axis.normalize();
float angle = 2.0f * std::acos(cosAngle);
// Rotate the camera around the center of the scene
mCamera.rotateAroundLocalPoint(axis, -angle, mCenterScene);
}
}
// Limit Vertical angle
constexpr double piOver2 = M_PI * 0.5f;
if (newVerticalAngle > piOver2 || newVerticalAngle < -piOver2) {
deltaVertRotationAngle = 0;
}
Vector3 localVertAxis = mCamera.getTransformMatrix().getUpperLeft3x3Matrix().getInverse() * Vector3(0, 1, 0);
mCamera.rotateAroundLocalPoint(Vector3(1, 0, 0), deltaVertRotationAngle, mCenterScene);
mCamera.rotateAroundLocalPoint(localVertAxis, deltaHorizRotationAngle, mCenterScene);
mCurrentCameraVerticalAngle += deltaVertRotationAngle;
std::cout << "Delta angle: " << deltaVertRotationAngle << std::endl;
std::cout << "Horizon angle: " << mCurrentCameraVerticalAngle << std::endl;
}

View File

@ -95,6 +95,10 @@ class Scene : public rp3d::EventListener {
protected:
// -------------------- Constants -------------------- //
static constexpr float MOUSE_CAMERA_ROTATION_SCALING_FACTOR = 1.0f;
// -------------------- Attributes -------------------- //
/// Scene name
@ -118,12 +122,12 @@ class Scene : public rp3d::EventListener {
/// Last point computed on a sphere (for camera rotation)
openglframework::Vector3 mLastPointOnSphere;
/// True if the last point computed on a sphere (for camera rotation) is valid
bool mIsLastPointOnSphereValid;
/// Interpolation factor for the bodies in the current frame
float mInterpolationFactor;
/// Current camera vertical angle around the horizontal axis (in radians)
double mCurrentCameraVerticalAngle;
/// Viewport x,y, width and height values
int mViewportX, mViewportY, mViewportWidth, mViewportHeight;

View File

@ -76,13 +76,11 @@ using namespace ropescene;
const float TestbedApplication::SCROLL_SENSITIVITY = 0.08f;
// Constructor
TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight)
: Screen(Vector2i(windowWidth, windowHeight), "Testbed ReactPhysics3D v" + rp3d::RP3D_VERSION, true, isFullscreen, true, true, false, 4, 1),
mIsInitialized(false), mGui(this), mCurrentScene(nullptr),
TestbedApplication::TestbedApplication()
: mIsInitialized(false), mGui(this), mCurrentScene(nullptr),
mDefaultEngineSettings(EngineSettings::defaultSettings()),
mFPS(0), mNbFrames(0), mPreviousTime(0),
mLastTimeComputedFPS(0), mFrameTime(0), mTotalPhysicsTime(0), mPhysicsStepTime(0),
mWidth(windowWidth), mHeight(windowHeight),
mSinglePhysicsStepEnabled(false), mSinglePhysicsStepDone(false),
mWindowToFramebufferRatio(Vector2(1, 1)), mIsShadowMappingEnabled(true),
mAreContactPointsDisplayed(false), mAreContactNormalsDisplayed(false),
@ -91,8 +89,6 @@ TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int w
mIsVSyncEnabled(false), mIsDebugRendererEnabled(false) {
init();
resize_event(Vector2i(0, 0));
}
// Destructor
@ -103,7 +99,62 @@ TestbedApplication::~TestbedApplication() {
}
// Initialize the viewer
void TestbedApplication::init() {
void TestbedApplication::start() {
glfwInit();
glfwSetTime(0);
// Get the primary monitor
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
// Window size
mWidth = mode->width;
mHeight = mode->height;
#if defined(NANOGUI_USE_OPENGL)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#elif defined(NANOGUI_USE_GLES)
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
#elif defined(NANOGUI_USE_METAL)
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
metal_init();
#endif
glfwWindowHint(GLFW_SAMPLES, 0);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_STENCIL_BITS, 8);
glfwWindowHint(GLFW_DEPTH_BITS, 24);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
// Create a the GLFW window object
std::string title = "Testbed - ReactPhysics3D v" + rp3d::RP3D_VERSION;
mWindow = glfwCreateWindow(mWidth, mHeight, title.c_str(), IS_FULLSCREEN ? monitor : nullptr, nullptr);
if (mWindow == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
}
glfwMakeContextCurrent(mWindow);
#if defined(NANOGUI_GLAD)
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress))
throw std::runtime_error("Could not initialize GLAD!");
glGetError(); // pull and ignore unhandled errors like GL_INVALID_ENUM
#endif
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Logger
rp3d::PhysicsCommon::setLogger(&mLogger);
@ -112,12 +163,22 @@ void TestbedApplication::init() {
createScenes();
// Initialize the GUI
mGui.init();
mGui.init(mWindow);
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
int width, height;
glfwGetFramebufferSize(mWindow, &width, &height);
glViewport(0, 0, width, height);
glfwSwapInterval(0);
glfwSwapBuffers(mWindow);
#endif
// Select the initial scene
const int firstSceneIndex = 0;
switchScene(mScenes[firstSceneIndex]);
mGui.drawAll();
mTimer.start();
int glMajorVersion, glMinorVersion;
@ -134,7 +195,68 @@ void TestbedApplication::init() {
}
#endif
glfwSetWindowUserPointer(mWindow, this);
glfwSetCursorPosCallback(mWindow, [](GLFWwindow* window, double x, double y) {
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
app->mouse_motion_event(x, y);
}
);
glfwSetMouseButtonCallback(mWindow, [](GLFWwindow* window, int button, int action, int modifiers) {
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
app->mouse_button_event(button, action, modifiers);
}
);
glfwSetKeyCallback(mWindow, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
app->keyboard_event(key, scancode, action, mods);
}
);
glfwSetScrollCallback(mWindow, [](GLFWwindow* window, double x, double y) {
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
app->scroll_event(x, y);
}
);
glfwSetFramebufferSizeCallback(mWindow, [](GLFWwindow* window, int width, int height) {
TestbedApplication* app = static_cast<TestbedApplication*>(glfwGetWindowUserPointer(window));
app->onWindowResized(width, height);
}
);
mCurrentScene->reshape(mWidth, mHeight);
mCurrentScene->setWindowDimension(mWidth, mHeight);
mIsInitialized = true;
// Game loop
while (!glfwWindowShouldClose(mWindow)) {
// Check if any events have been activated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
update();
mGui.update();
// Draw nanogui
mGui.draw();
render();
mGui.drawTearDown();
}
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
#if defined(NANOGUI_USE_METAL)
metal_shutdown();
#endif
}
// Create all the scenes
@ -357,44 +479,39 @@ void TestbedApplication::update() {
// Update the scene
mCurrentScene->update();
// Compute the current framerate
computeFPS();
}
void TestbedApplication::draw_contents() {
update();
void TestbedApplication::render() {
int bufferWidth, bufferHeight;
glfwMakeContextCurrent(m_glfw_window);
glfwGetFramebufferSize(m_glfw_window, &bufferWidth, &bufferHeight);
glfwMakeContextCurrent(mWindow);
glfwGetFramebufferSize(mWindow, &bufferWidth, &bufferHeight);
// Set the viewport of the scene
mCurrentScene->setViewport(0, 0, bufferWidth, bufferHeight);
// Render the scene
mCurrentScene->render();
mGui.update();
// Compute the current framerate
computeFPS();
}
/// Window resize event handler
bool TestbedApplication::resize_event(const Vector2i &size) {
bool TestbedApplication::onWindowResized(int width, int height) {
if (!mIsInitialized) return false;
// Get the framebuffer dimension
int width, height;
glfwGetFramebufferSize(m_glfw_window, &width, &height);
mGui.onWindowResizeEvent(width, height);
// Resize the camera viewport
mCurrentScene->reshape(width, height);
// Update the window size of the scene
int windowWidth, windowHeight;
glfwGetWindowSize(m_glfw_window, &windowWidth, &windowHeight);
mCurrentScene->setWindowDimension(windowWidth, windowHeight);
mCurrentScene->setWindowDimension(width, height);
mWidth = width;
mHeight = height;
return true;
}
@ -408,13 +525,18 @@ void TestbedApplication::switchScene(Scene* newScene) {
mTimer.reset();
// Resize the camera viewport
mCurrentScene->reshape(mWidth, mHeight);
// Update the window size of the scene
mCurrentScene->setWindowDimension(mWidth, mHeight);
// Reset the scene
mCurrentScene->reset();
mGui.resetWithValuesFromCurrentScene();
mCurrentScene->updateEngineSettings();
resize_event(Vector2i(0, 0));
mGui.resetWithValuesFromCurrentScene();
}
// Notify that the engine settings have changed
@ -472,16 +594,14 @@ void TestbedApplication::computeFPS() {
mPreviousTime = mCurrentTime;
}
bool TestbedApplication::keyboard_event(int key, int scancode, int action, int modifiers) {
void TestbedApplication::keyboard_event(int key, int scancode, int action, int modifiers) {
if (Screen::keyboard_event(key, scancode, action, modifiers)) {
return true;
}
mGui.onKeyboardEvent(key, scancode, action, modifiers);
// Close application on escape key
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(m_glfw_window, GL_TRUE);
return true;
glfwSetWindowShouldClose(mWindow, GL_TRUE);
return;
}
// Close application on escape key
@ -494,48 +614,45 @@ bool TestbedApplication::keyboard_event(int key, int scancode, int action, int m
playSimulation();
}
return true;
return;
}
return mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
}
// Handle a mouse button event (default implementation: propagate to children)
bool TestbedApplication::mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) {
void TestbedApplication::mouse_button_event(int button, int action, int modifiers) {
if (Screen::mouse_button_event(p, button, down, modifiers)) {
return true;
}
mGui.onMouseButtonEvent(button, action, modifiers);
// Get the mouse cursor position
double x, y;
glfwGetCursorPos(m_glfw_window, &x, &y);
glfwGetCursorPos(mWindow, &x, &y);
return mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y);
bool down = action == GLFW_PRESS;
mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y);
}
// Handle a mouse motion event (default implementation: propagate to children)
bool TestbedApplication::mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) {
void TestbedApplication::mouse_motion_event(double x, double y) {
if (Screen::mouse_motion_event(p, rel, button, modifiers)) {
return true;
}
mGui.onMouseMotionEvent(x, y);
int leftButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_LEFT);
int rightButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_RIGHT);
int middleButtonState = glfwGetMouseButton(m_glfw_window, GLFW_MOUSE_BUTTON_MIDDLE);
int altKeyState = glfwGetKey(m_glfw_window, GLFW_KEY_LEFT_ALT);
int leftButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_LEFT);
int rightButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_RIGHT);
int middleButtonState = glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_MIDDLE);
int altKeyState = glfwGetKey(mWindow, GLFW_KEY_LEFT_ALT);
return mCurrentScene->mouseMotionEvent(p[0], p[1], leftButtonState, rightButtonState,
middleButtonState, altKeyState);
mCurrentScene->mouseMotionEvent(x, y, leftButtonState, rightButtonState, middleButtonState, altKeyState);
}
// Handle a mouse scroll event (default implementation: propagate to children)
bool TestbedApplication::scroll_event(const Vector2i &p, const Vector2f &rel) {
// Handle a mouse scroll event
void TestbedApplication::scroll_event(double x, double y) {
if (Screen::scroll_event(p, rel)) {
return true;
}
if (mGui.onScrollEvent(x, y)) {
return;
};
return mCurrentScene->scrollingEvent(rel[0], rel[1], SCROLL_SENSITIVITY);
mCurrentScene->scrollingEvent(x, y, SCROLL_SENSITIVITY);
}

View File

@ -36,22 +36,27 @@
using namespace nanogui;
// Macro for OpenGL errors
#define checkOpenGLErrors() checkOpenGLErrorsInternal(__FILE__,__LINE__)
/// Class TestbedApplication
class TestbedApplication : public Screen {
class TestbedApplication {
private :
// -------------------- Constants -------------------- //
static const float SCROLL_SENSITIVITY;
static constexpr bool IS_FULLSCREEN = false;
// -------------------- Attributes -------------------- //
bool mIsInitialized;
GLFWwindow* mWindow;
Screen* mScreen;
Gui mGui;
/// Timer
@ -186,31 +191,31 @@ class TestbedApplication : public Screen {
// -------------------- Methods -------------------- //
/// Private constructor (for the singleton class)
TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight);
TestbedApplication();
/// Destructor
virtual ~TestbedApplication() override;
~TestbedApplication();
/// Render the content of the application
virtual void draw_contents() override;
void render();
/// Window resize event handler
virtual bool resize_event(const Vector2i& size) override;
bool onWindowResized(int width, int height);
/// Default keyboard event handler
virtual bool keyboard_event(int key, int scancode, int action, int modifiers) override;
void keyboard_event(int key, int scancode, int action, int modifiers);
/// Handle a mouse button event (default implementation: propagate to children)
virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override;
void mouse_button_event(int button, int action, int modifiers);
/// Handle a mouse motion event (default implementation: propagate to children)
virtual bool mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
void mouse_motion_event(double x, double y);
/// Handle a mouse scroll event (default implementation: propagate to children)
virtual bool scroll_event(const Vector2i &p, const Vector2f &rel) override;
/// Handle a mouse scroll event
void scroll_event(double x, double y);
/// Initialize the application
void init();
/// Start the application
void start();
/// Change the current scene
void switchScene(Scene* newScene);