Graphics Refactor Initial
This commit is contained in:
parent
87d8ce84dc
commit
bb5cbfdfe2
14 changed files with 378 additions and 555 deletions
|
|
@ -12,31 +12,32 @@
|
|||
#include <nanovg_gl.h>
|
||||
|
||||
namespace tp {
|
||||
class Graphics::Canvas::Context {
|
||||
class Canvas::Context {
|
||||
public:
|
||||
NVGcontext* vg;
|
||||
NVGcontext* vg {};
|
||||
Window* window {};
|
||||
};
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::Canvas::Canvas() { mContext = new Context(); }
|
||||
Canvas::Canvas(Window* window) {
|
||||
mContext = new Context();
|
||||
mContext->window = window;
|
||||
|
||||
Graphics::Canvas::~Canvas() { delete mContext; }
|
||||
|
||||
void Graphics::Canvas::init() {
|
||||
mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||
|
||||
if (nvgCreateFont(mContext->vg, "default", "Font.ttf") == -1) {
|
||||
// TODO
|
||||
ASSERT(!"Cant create NVG font")
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::Canvas::deinit() { nvgDeleteGL3(mContext->vg); }
|
||||
Canvas::~Canvas() {
|
||||
nvgDeleteGL3(mContext->vg);
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
RectF Graphics::Canvas::getAvaliableArea() { return { (halnf) 0, (halnf) 0, mWidth, mHeight }; }
|
||||
|
||||
void Graphics::Canvas::rect(const RectF& rec, const RGBA& col, halnf round) {
|
||||
void Canvas::rect(const RectF& rec, const RGBA& col, halnf round) {
|
||||
nvgBeginPath(mContext->vg);
|
||||
|
||||
if (round == 0) {
|
||||
|
|
@ -49,7 +50,7 @@ void Graphics::Canvas::rect(const RectF& rec, const RGBA& col, halnf round) {
|
|||
nvgFill(mContext->vg);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::pushClamp(const RectF& rec) {
|
||||
void Canvas::pushClamp(const RectF& rec) {
|
||||
RectF intersection = rec;
|
||||
if (mScissors.size()) {
|
||||
mScissors.last().calcIntersection(rec, intersection);
|
||||
|
|
@ -58,7 +59,7 @@ void Graphics::Canvas::pushClamp(const RectF& rec) {
|
|||
mScissors.append(rec);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::popClamp() {
|
||||
void Canvas::popClamp() {
|
||||
DEBUG_ASSERT(mScissors.size());
|
||||
mIsClamping = false;
|
||||
mScissors.pop();
|
||||
|
|
@ -70,7 +71,7 @@ void Graphics::Canvas::popClamp() {
|
|||
}
|
||||
}
|
||||
|
||||
void Graphics::Canvas::text(
|
||||
void Canvas::text(
|
||||
const char* string, const RectF& aRec, halnf size, Align align, halnf marging, const RGBA& col
|
||||
) {
|
||||
RectF rec = { aRec.x + marging, aRec.y + marging, aRec.z - marging * 2, aRec.w - marging * 2 };
|
||||
|
|
@ -112,7 +113,7 @@ void Graphics::Canvas::text(
|
|||
popClamp();
|
||||
}
|
||||
|
||||
void Graphics::Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
|
||||
void Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
|
||||
auto imgPaint = nvgImagePattern(mContext->vg, rec.x, rec.y, rec.z, rec.w, angle, image->id, alpha);
|
||||
nvgBeginPath(mContext->vg);
|
||||
nvgRoundedRect(mContext->vg, rec.x, rec.y, rec.z, rec.w, rounding);
|
||||
|
|
@ -120,7 +121,7 @@ void Graphics::Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf ang
|
|||
nvgFill(mContext->vg);
|
||||
}
|
||||
|
||||
Graphics::Canvas::ImageHandle Graphics::Canvas::createImageFromTextId(ualni id, Vec2F size) {
|
||||
Canvas::ImageHandle Canvas::createImageFromTextId(ualni id, Vec2F size) {
|
||||
#ifdef ENV_OS_ANDROID
|
||||
return { (ualni) nvglCreateImageFromHandleGLES3(mContext->vg, id, size.x, size.y, 0) };
|
||||
#else
|
||||
|
|
@ -128,12 +129,17 @@ void Graphics::Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf ang
|
|||
#endif
|
||||
}
|
||||
|
||||
void Graphics::Canvas::deleteImageHandle(ImageHandle image) {
|
||||
void Canvas::deleteImageHandle(ImageHandle image) {
|
||||
if (image.id) {
|
||||
nvgDeleteImage(mContext->vg, image.id);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::Canvas::proc() { nvgBeginFrame(mContext->vg, mWidth, mHeight, 1.0); }
|
||||
void Canvas::proc() {
|
||||
const auto size = mContext->window->getSize();
|
||||
nvgBeginFrame(mContext->vg, size.x, size.y, 1.0);
|
||||
}
|
||||
|
||||
void Graphics::Canvas::draw() { nvgEndFrame(mContext->vg); }
|
||||
void Canvas::draw() {
|
||||
nvgEndFrame(mContext->vg);
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
#include "Graphics.hpp"
|
||||
|
||||
// -------- Debug UI -------- //
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
|
|
@ -9,7 +10,7 @@
|
|||
#include <imgui_internal.h>
|
||||
|
||||
namespace tp {
|
||||
class Graphics::GUI::Context {
|
||||
class DebugGUI::Context {
|
||||
public:
|
||||
ImGuiIO* io{};
|
||||
ImGuiContext* ctx{};
|
||||
|
|
@ -18,11 +19,9 @@ namespace tp {
|
|||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::GUI::GUI() { mContext = new Context(); }
|
||||
DebugGUI::DebugGUI(Window* window) {
|
||||
mContext = new Context();
|
||||
|
||||
Graphics::GUI::~GUI() { delete mContext; }
|
||||
|
||||
void Graphics::GUI::init(Window* window) {
|
||||
IMGUI_CHECKVERSION();
|
||||
mContext->ctx = ImGui::CreateContext();
|
||||
mContext->io = &ImGui::GetIO();
|
||||
|
|
@ -38,13 +37,15 @@ void Graphics::GUI::init(Window* window) {
|
|||
io.Fonts->AddFontFromFileTTF("Font.ttf", 20.f);
|
||||
}
|
||||
|
||||
void Graphics::GUI::deinit() {
|
||||
DebugGUI::~DebugGUI() {
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void Graphics::GUI::proc() {
|
||||
void DebugGUI::proc() {
|
||||
tp::HeapAllocGlobal::startIgnore();
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
|
@ -54,7 +55,7 @@ void Graphics::GUI::proc() {
|
|||
tp::HeapAllocGlobal::stopIgnore();
|
||||
}
|
||||
|
||||
void Graphics::GUI::draw() {
|
||||
void DebugGUI::draw() {
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
2
Graphics/private/EventHandler.cpp
Normal file
2
Graphics/private/EventHandler.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "EventHandler.hpp"
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#include "GraphicsCommon.hpp"
|
||||
#include "MathCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
static ModuleManifest* deps[] = { &gModuleAllocators, nullptr };
|
||||
ModuleManifest gModuleGraphics = ModuleManifest("Graphics", nullptr, nullptr, deps);
|
||||
}
|
||||
151
Graphics/private/Window.cpp
Normal file
151
Graphics/private/Window.cpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#include "Window.hpp"
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
// -------- OpenGL -------- //
|
||||
#include <GL/glew.h>
|
||||
|
||||
// -------- Window Context -------- //
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#ifdef ENV_OS_WINDOWS
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef ENV_OS_LINUX
|
||||
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
#endif
|
||||
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
|
||||
namespace tp {
|
||||
static ModuleManifest* deps[] = { &gModuleAllocators, nullptr };
|
||||
ModuleManifest gModuleGraphics = ModuleManifest("Graphics", nullptr, nullptr, deps);
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
static void scrollCallback(GLFWwindow* window, double xOffset, double yOffset);
|
||||
|
||||
Window::Window(Vec2F size, const String& title) {
|
||||
mContext = new Context();
|
||||
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, 1);
|
||||
|
||||
// Create a window and OpenGL context
|
||||
mContext->window = glfwCreateWindow((int) size.x, (int) size.y, title.read(), nullptr, nullptr);
|
||||
if (!mContext->window) {
|
||||
printf("Failed to create GLFW window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(mContext->window);
|
||||
|
||||
// Initialize GLEW
|
||||
if (glewInit() != GLEW_OK) {
|
||||
printf("Failed to initialize GLEW\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// set event bindings
|
||||
glfwSetWindowUserPointer(mContext->window, this);
|
||||
glfwSetKeyCallback(mContext->window, keyCallback);
|
||||
glfwSetMouseButtonCallback(mContext->window, mouseButtonCallback);
|
||||
glfwSetScrollCallback(mContext->window, scrollCallback);
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
glfwDestroyWindow(mContext->window);
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
Window* Window::createWindow(Vec2F size, const String& title) {
|
||||
HeapAllocGlobal::startIgnore();
|
||||
|
||||
static int count = 1;
|
||||
if (!count) {
|
||||
printf("Window class is a singleton\n");
|
||||
return nullptr;
|
||||
}
|
||||
count--;
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit()) {
|
||||
printf("Failed to initialize GLFW\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set the GLFW error callback
|
||||
glfwSetErrorCallback([](int error, const char* description) { printf("GLFW Error: %i %s\n", error, description); });
|
||||
|
||||
auto out = new Window(size, title);
|
||||
|
||||
HeapAllocGlobal::stopIgnore();
|
||||
return out;
|
||||
}
|
||||
|
||||
void Window::destroyWindow(Window* window) {
|
||||
delete window;
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
void Window::draw() {
|
||||
glfwSwapBuffers(mContext->window);
|
||||
}
|
||||
|
||||
const Vec2F& Window::getSize() const { return mSize; }
|
||||
|
||||
Window::Context* Window::getContext() { return mContext; }
|
||||
|
||||
void Window::setEventHandler(EventHandler* eventHandler) { mEventHandler = eventHandler; }
|
||||
EventHandler* Window::getEventHandler() { return mEventHandler; }
|
||||
|
||||
|
||||
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
|
||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
if (!self) return;
|
||||
|
||||
EventHandler* eventHandler = self->getEventHandler();
|
||||
if (!eventHandler) return;
|
||||
|
||||
// post key event
|
||||
/*
|
||||
if (action == GLFW_PRESS) {
|
||||
inputManager->keyStates[key] = GLFW_PRESS;
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
inputManager->keyStates[key] = GLFW_RELEASE;
|
||||
}
|
||||
inputManager->isEvent = true;
|
||||
*/
|
||||
}
|
||||
|
||||
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
|
||||
auto* self = static_cast<Window*>(glfwGetWindowUserPointer(window));
|
||||
if (!self) return;
|
||||
|
||||
EventHandler* eventHandler = self->getEventHandler();
|
||||
if (!eventHandler) return;
|
||||
|
||||
// post mouse button event
|
||||
// inputManager->mouseButtonStates[button] = action;
|
||||
// inputManager->isEvent = true;
|
||||
}
|
||||
|
||||
static void scrollCallback(GLFWwindow* window, double xOffset, double yOffset) {
|
||||
// ignore for now
|
||||
}
|
||||
14
Graphics/private/WindowContext.hpp
Normal file
14
Graphics/private/WindowContext.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "Window.hpp"
|
||||
|
||||
class GLFWwindow;
|
||||
|
||||
namespace tp {
|
||||
|
||||
class Window::Context {
|
||||
public:
|
||||
Context() = default;
|
||||
GLFWwindow* window = nullptr;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
// -------- OpenGL -------- //
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "WindowContext.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
// #define EASYTAB_IMPLEMENTATION
|
||||
// #include "easytab.h"
|
||||
|
||||
namespace tp {
|
||||
class Graphics::GL::Context {
|
||||
public:
|
||||
// Showoff data
|
||||
GLuint vao{};
|
||||
GLuint vbo{};
|
||||
GLfloat vertices[9] = {
|
||||
-0.0f, -0.0f, 0.0f, // Left vertex
|
||||
1.0f, 0.0f, 0.0f, // Right vertex
|
||||
0.5f, 1.0f, 0.0f // Top vertex
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Graphics::GL::GL() { mContext = new Context(); }
|
||||
|
||||
Graphics::GL::~GL() { delete mContext; }
|
||||
|
||||
void Graphics::GL::init() {
|
||||
// Create a Vertex Array Object (VAO)
|
||||
glGenVertexArrays(1, &mContext->vao);
|
||||
glBindVertexArray(mContext->vao);
|
||||
|
||||
// Create a Vertex Buffer Object (VBO)
|
||||
glGenBuffers(1, &mContext->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mContext->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(mContext->vertices), mContext->vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Set up vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*) nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
void Graphics::GL::deinit() {
|
||||
glDeleteBuffers(1, &mContext->vbo);
|
||||
glDeleteVertexArrays(1, &mContext->vao);
|
||||
}
|
||||
|
||||
void Graphics::GL::proc() {}
|
||||
|
||||
void Graphics::GL::draw() {
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, mWidth, mHeight);
|
||||
// glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
void Graphics::init(Window* window) {
|
||||
mGl.init();
|
||||
mGui.init(window);
|
||||
mCanvas.init();
|
||||
}
|
||||
|
||||
void Graphics::deinit() {
|
||||
mCanvas.deinit();
|
||||
mGui.deinit();
|
||||
mGl.deinit();
|
||||
}
|
||||
|
||||
void Graphics::proc() {
|
||||
mGl.proc();
|
||||
mCanvas.proc();
|
||||
mGui.proc();
|
||||
}
|
||||
|
||||
void Graphics::draw() {
|
||||
mGl.draw();
|
||||
mCanvas.draw();
|
||||
mGui.draw();
|
||||
}
|
||||
|
||||
tp::Window::Window(int width, int height, const char* title) {
|
||||
mContext = new Context();
|
||||
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, 1);
|
||||
|
||||
// Create a window and OpenGL context
|
||||
mContext->window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||
if (!mContext->window) {
|
||||
printf("Failed to create GLFW window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(mContext->window);
|
||||
|
||||
// Initialize GLEW
|
||||
if (glewInit() != GLEW_OK) {
|
||||
printf("Failed to initialize GLEW\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->inputManager.init(mContext->window);
|
||||
|
||||
mGraphics.init(this);
|
||||
|
||||
mEvents.mContext = mContext;
|
||||
|
||||
#ifdef ENV_OS_WINDOWS
|
||||
// EasyTab_Load(glfwGetWin32Window(mContext->window));
|
||||
#endif
|
||||
}
|
||||
|
||||
tp::Window::~Window() {
|
||||
#ifdef ENV_OS_WINDOWS
|
||||
// EasyTab_Unload();
|
||||
#endif
|
||||
|
||||
mGraphics.deinit();
|
||||
glfwDestroyWindow(mContext->window);
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
tp::Window* tp::Window::createWindow(int width, int height, const char* title) {
|
||||
tp::HeapAllocGlobal::startIgnore();
|
||||
|
||||
static int count = 1;
|
||||
if (!count) {
|
||||
printf("Window class is a singleton\n");
|
||||
return nullptr;
|
||||
}
|
||||
count--;
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit()) {
|
||||
printf("Failed to initialize GLFW\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set the GLFW error callback
|
||||
glfwSetErrorCallback([](int error, const char* description) { printf("GLFW Error: %i %s\n", error, description); });
|
||||
|
||||
auto out = new Window(width, height, title);
|
||||
|
||||
tp::HeapAllocGlobal::stopIgnore();
|
||||
return out;
|
||||
}
|
||||
|
||||
void tp::Window::destroyWindow(Window* window) {
|
||||
delete window;
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool tp::Window::shouldClose() const { return glfwWindowShouldClose(mContext->window); }
|
||||
|
||||
void tp::Window::processEvents() {
|
||||
mContext->inputManager.isEvent = false;
|
||||
|
||||
#ifdef ENV_OS_WINDOWS
|
||||
// HWND w32window = glfwGetWin32Window(mContext->window);
|
||||
// MSG msg;
|
||||
// if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||
// if (EasyTab_HandleEvent(msg.hwnd, msg.message, msg.lParam, msg.wParam) == EASYTAB_OK)
|
||||
// mEvents.pressure = EasyTab->Pressure;
|
||||
// }
|
||||
#endif
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
int w, h;
|
||||
glfwGetWindowSize(mContext->window, &w, &h);
|
||||
|
||||
mGraphics.mCanvas.mWidth = w;
|
||||
mGraphics.mCanvas.mHeight = h;
|
||||
|
||||
mGraphics.mGl.mWidth = w;
|
||||
mGraphics.mGl.mHeight = h;
|
||||
|
||||
mGraphics.proc();
|
||||
|
||||
mContext->inputManager.update();
|
||||
|
||||
if (mEvents.isPressed()) {
|
||||
mEvents.pressure = 1.f;
|
||||
} else if (mEvents.isReleased()) {
|
||||
mEvents.pressure = 0.f;
|
||||
}
|
||||
|
||||
get_time();
|
||||
}
|
||||
|
||||
void tp::Window::draw() {
|
||||
mGraphics.draw();
|
||||
glfwSwapBuffers(mContext->window);
|
||||
mContext->inputManager.resetScroll();
|
||||
}
|
||||
|
||||
auto tp::Window::getContext() -> Context* { return mContext; }
|
||||
Graphics::Canvas& tp::Window::getCanvas() { return mGraphics.mCanvas; }
|
||||
const tp::Window::Events& tp::Window::getEvents() { return mEvents; }
|
||||
|
||||
const Vec2F& tp::Window::Events::getPos() const { return mContext->inputManager.getPos(); }
|
||||
|
||||
bool tp::Window::Events::isPressed() const { return mContext->inputManager.isPressed(); }
|
||||
|
||||
bool tp::Window::Events::isReleased() const { return mContext->inputManager.isReleased(); }
|
||||
|
||||
bool tp::Window::Events::isDown() const { return mContext->inputManager.isDown(); }
|
||||
|
||||
halnf tp::Window::Events::getScrollY() const { return mContext->inputManager.getScrollY(); }
|
||||
|
||||
bool tp::Window::Events::isEvent() const { return mContext->inputManager.isEvents(); }
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Environment.hpp"
|
||||
|
||||
// -------- Window Context -------- //
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#ifdef ENV_OS_WINDOWS
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef ENV_OS_LINUX
|
||||
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
#endif
|
||||
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace tp {
|
||||
|
||||
class Window;
|
||||
|
||||
class InputManager {
|
||||
public:
|
||||
InputManager() = default;
|
||||
|
||||
void init(GLFWwindow* aWindow) {
|
||||
window = aWindow;
|
||||
// Set up key and mouse button callbacks
|
||||
|
||||
glfwSetWindowUserPointer(window, this);
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetMouseButtonCallback(window, mouseButtonCallback);
|
||||
glfwSetScrollCallback(window, scrollCallback);
|
||||
}
|
||||
|
||||
const Vec2F& getPos() const { return mousePos; }
|
||||
|
||||
bool isKeyPressed(int key) const { return keyStates[key] == GLFW_PRESS; }
|
||||
|
||||
bool isKeyDown(int key) const { return keyStates[key] == GLFW_REPEAT || keyStates[key] == GLFW_PRESS; }
|
||||
|
||||
bool isPressed() const { return mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_PRESS; }
|
||||
|
||||
bool isReleased() const { return mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_RELEASE; }
|
||||
|
||||
bool isDown() const { return mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_REPEAT || mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] == GLFW_PRESS; }
|
||||
|
||||
bool isEvents() const { return isEvent; }
|
||||
|
||||
double getScrollY() const { return scrollY; }
|
||||
|
||||
// bool isScrollDown() const { return scrollY < 0.0; }
|
||||
|
||||
private:
|
||||
friend Window;
|
||||
|
||||
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (!inputManager) {
|
||||
// Update key state
|
||||
if (action == GLFW_PRESS) {
|
||||
inputManager->keyStates[key] = GLFW_PRESS;
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
inputManager->keyStates[key] = GLFW_RELEASE;
|
||||
}
|
||||
inputManager->isEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
|
||||
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (inputManager) {
|
||||
// Update mouse button state
|
||||
inputManager->mouseButtonStates[button] = action;
|
||||
inputManager->isEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||
InputManager* inputManager = static_cast<InputManager*>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (inputManager) {
|
||||
// Update scroll state
|
||||
inputManager->scrollX = xoffset;
|
||||
inputManager->scrollY = yoffset;
|
||||
inputManager->isEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
void update() {
|
||||
double x, y;
|
||||
glfwGetCursorPos(window, &x, &y);
|
||||
mousePosPrev = mousePos;
|
||||
mousePos = { x, y };
|
||||
|
||||
if ((mousePosPrev - mousePos).length2()) {
|
||||
isEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
void resetScroll() {
|
||||
scrollX = 0.0;
|
||||
scrollY = 0.0;
|
||||
mouseButtonStates[GLFW_MOUSE_BUTTON_LEFT] = GLFW_REPEAT;
|
||||
}
|
||||
|
||||
bool isEvent = false;
|
||||
double scrollX = 0.0;
|
||||
double scrollY = 0.0;
|
||||
GLFWwindow* window;
|
||||
Vec2F mousePos;
|
||||
Vec2F mousePosPrev;
|
||||
std::array<int, GLFW_KEY_LAST + 1> keyStates = { GLFW_RELEASE };
|
||||
std::array<int, GLFW_MOUSE_BUTTON_LAST + 1> mouseButtonStates = { GLFW_RELEASE };
|
||||
};
|
||||
|
||||
class Window::Context {
|
||||
friend Graphics::GL;
|
||||
friend Graphics::GUI;
|
||||
friend Graphics::Canvas;
|
||||
|
||||
public:
|
||||
GLFWwindow* window;
|
||||
InputManager inputManager;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue