From 1686a01b6ae7467e71eac247078248de4a3b3423 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 13 Dec 2021 23:47:30 +0000 Subject: Refactor to start splitting out UI components --- ui/gameMainWindow.cpp | 43 +++++++++++++++++++++++++++ ui/gameMainWindow.h | 27 +++++++++++++++++ ui/inputHandler.h | 18 ++++++++++++ ui/manualCameraController.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++ ui/manualCameraController.h | 26 +++++++++++++++++ ui/window.cpp | 42 +++++++++++++++++++++++++++ ui/window.h | 38 ++++++++++++++++++++++++ 7 files changed, 261 insertions(+) create mode 100644 ui/gameMainWindow.cpp create mode 100644 ui/gameMainWindow.h create mode 100644 ui/inputHandler.h create mode 100644 ui/manualCameraController.cpp create mode 100644 ui/manualCameraController.h create mode 100644 ui/window.cpp create mode 100644 ui/window.h (limited to 'ui') diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp new file mode 100644 index 0000000..4421098 --- /dev/null +++ b/ui/gameMainWindow.cpp @@ -0,0 +1,43 @@ +#include "gameMainWindow.h" +#include "collection.hpp" +#include "gfx/camera_controller.h" +#include "manualCameraController.h" +#include "ui/window.h" +#include +#include +#include +#include // IWYU pragma: keep +#include +#include +#include +#include + +GameMainWindow::GameMainWindow(size_t w, size_t h) : + Window {static_cast(w), static_cast(h), "I Like Trains"}, uiShader {w, h}, camera {{-1250.0F, -1250.0F, + 35.0F}, + 70.0F, rdiv(w, h), + 0.1F, 10000.0F} +{ + inputStack.create(glm::vec2 {-1150, -1150}); + + shader.setUniform("lightDirection", glm::normalize(glm::vec3 {1, 0, -1})); + shader.setUniform("lightColor", {.6, .6, .6}); + shader.setUniform("ambientColor", {0.5, 0.5, 0.5}); +} + +void +GameMainWindow::tick(TickDuration) +{ + inputStack.apply(&CameraController::updateCamera, &camera); + shader.setView(camera.GetViewProjection()); +} + +void +GameMainWindow::Refresh(const GameState * gameState) const +{ + SDL_GL_MakeCurrent(m_window, m_glContext); + glEnable(GL_DEPTH_TEST); + gameState->world.apply(&Renderable::render, shader); + glDisable(GL_DEPTH_TEST); + // do ui bits +} diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h new file mode 100644 index 0000000..affb389 --- /dev/null +++ b/ui/gameMainWindow.h @@ -0,0 +1,27 @@ +#ifndef UI_GAMEMAINWINDOW_H +#define UI_GAMEMAINWINDOW_H + +#include "chronology.hpp" +#include "gfx/gl/camera.h" +#include "gfx/gl/shader.h" +#include "gfx/gl/uiShader.h" +#include "window.h" +#include + +class GameState; + +class GameMainWindow : public Window { +public: + GameMainWindow(size_t w, size_t h); + + void tick(TickDuration) override; + + void Refresh(const GameState * gameState) const override; + +private: + UIShader uiShader; + Shader shader; + Camera camera; +}; + +#endif diff --git a/ui/inputHandler.h b/ui/inputHandler.h new file mode 100644 index 0000000..aac323b --- /dev/null +++ b/ui/inputHandler.h @@ -0,0 +1,18 @@ +#ifndef INPUT_HANDLER_H +#define INPUT_HANDLER_H + +#include + +union SDL_Event; + +class InputHandler { +public: + InputHandler() = default; + virtual ~InputHandler() = default; + + DEFAULT_MOVE_COPY(InputHandler); + + virtual bool handleInput(const SDL_Event &) = 0; +}; + +#endif diff --git a/ui/manualCameraController.cpp b/ui/manualCameraController.cpp new file mode 100644 index 0000000..1d3a067 --- /dev/null +++ b/ui/manualCameraController.cpp @@ -0,0 +1,67 @@ +#include "manualCameraController.h" +#include +#include +#include +#include + +bool +ManualCameraController::handleInput(const SDL_Event & e) +{ + switch (e.type) { + case SDL_KEYDOWN: + switch (e.key.keysym.sym) { + case SDLK_LCTRL: + case SDLK_RCTRL: + ctrl = true; + return true; + } + break; + case SDL_KEYUP: + switch (e.key.keysym.sym) { + case SDLK_LCTRL: + case SDLK_RCTRL: + ctrl = false; + return true; + } + break; + case SDL_MOUSEBUTTONDOWN: + switch (e.button.button) { + case SDL_BUTTON_RIGHT: + SDL_SetRelativeMouseMode(SDL_TRUE); + mrb = true; + return true; + } + break; + case SDL_MOUSEBUTTONUP: + switch (e.button.button) { + case SDL_BUTTON_RIGHT: + SDL_SetRelativeMouseMode(SDL_FALSE); + mrb = false; + return true; + } + break; + case SDL_MOUSEMOTION: + if (mrb) { + if (ctrl) { + direction -= 0.01F * static_cast(e.motion.xrel); + pitch = std::clamp(pitch - 0.01F * static_cast(e.motion.yrel), 0.1F, half_pi); + } + else { + focus += rotate_flat(-direction) * glm::vec2 {-e.motion.xrel, e.motion.yrel}; + } + } + return true; + case SDL_MOUSEWHEEL: + dist = std::clamp(dist - static_cast(e.wheel.y) * 4.F, 5.F, 200.F); + break; + } + return false; +} + +void +ManualCameraController::updateCamera(Camera * camera) const +{ + camera->forward = glm::normalize(sincosf(direction) ^ -sin(pitch)); + camera->pos = !focus + up * 3.F - (camera->forward * std::pow(dist, 1.3F)); + camera->up = up; +} diff --git a/ui/manualCameraController.h b/ui/manualCameraController.h new file mode 100644 index 0000000..ceff9ac --- /dev/null +++ b/ui/manualCameraController.h @@ -0,0 +1,26 @@ +#ifndef MANUAL_CAMERA_CONTROLLER_H +#define MANUAL_CAMERA_CONTROLLER_H + +#include "inputHandler.h" +#include +#include +#include +#include + +class Camera; + +class ManualCameraController : public CameraController, public InputHandler { +public: + explicit ManualCameraController(glm::vec2 f) : focus {f} { } + + bool handleInput(const SDL_Event & e) override; + + void updateCamera(Camera * camera) const override; + +private: + bool ctrl {false}, mrb {false}; + glm::vec2 focus; + float direction {quarter_pi}; + float dist {40}, pitch {quarter_pi}; +}; +#endif diff --git a/ui/window.cpp b/ui/window.cpp new file mode 100644 index 0000000..c451367 --- /dev/null +++ b/ui/window.cpp @@ -0,0 +1,42 @@ +#include "window.h" +#include "ui/inputHandler.h" +#include +#include + +Window::Window(int width, int height, const std::string & title) : + m_window {title.c_str(), static_cast(SDL_WINDOWPOS_CENTERED), static_cast(SDL_WINDOWPOS_CENTERED), width, + height, static_cast(SDL_WINDOW_OPENGL)}, + m_glContext {m_window} +{ + if (glewInit() != GLEW_OK) { + throw std::runtime_error {"Glew failed to initialize!"}; + } + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +void +Window::Clear(float r, float g, float b, float a) const +{ + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void +Window::SwapBuffers() const +{ + SDL_GL_SwapWindow(m_window); +} + +bool +Window::handleInput(const SDL_Event & e) +{ + if (SDL_GetWindowID(m_window) == e.window.windowID) { + inputStack.applyOne(&InputHandler::handleInput, e); + return true; + } + return false; +} diff --git a/ui/window.h b/ui/window.h new file mode 100644 index 0000000..f6279e2 --- /dev/null +++ b/ui/window.h @@ -0,0 +1,38 @@ +#ifndef DISPLAY_INCLUDED_H +#define DISPLAY_INCLUDED_H + +#include "chronology.hpp" +#include "collection.hpp" +#include "inputHandler.h" // IWYU pragma: keep +#include "ptr.hpp" +#include +#include +#include +#include + +class GameState; + +class Window { +public: + Window(int width, int height, const std::string & title); + virtual ~Window() = default; + + NO_COPY(Window); + NO_MOVE(Window); + + void Clear(float r, float g, float b, float a) const; + void SwapBuffers() const; + virtual void tick(TickDuration elapsed) = 0; + virtual void Refresh(const GameState *) const = 0; + bool handleInput(const SDL_Event & e); + +protected: + using GL_Context = std::remove_pointer_t; + using SDL_WindowPtr = wrapped_ptrt; + using SDL_GLContextPtr = wrapped_ptrt; + SDL_WindowPtr m_window; + SDL_GLContextPtr m_glContext; + Collection inputStack; +}; + +#endif -- cgit v1.2.3