new event and window abstraction, preparing for multiple windows
This commit is contained in:
@@ -2,19 +2,24 @@
|
||||
#include "Event.h"
|
||||
#include "Layer.h"
|
||||
#include "Log.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_main.h"
|
||||
#include "SDL3/SDL_render.h"
|
||||
#include "SDL3/SDL_stdinc.h"
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include "imguiinit.h"
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
|
||||
#define SDL_MAIN_HANDLED 1
|
||||
|
||||
namespace SakuraVNE {
|
||||
Application *Application::s_Instance = nullptr;
|
||||
|
||||
Application::Application(const AppData &appdata) : m_Window(nullptr), m_Renderer(nullptr), m_Surface(nullptr), m_isRunning(false), m_AppData(appdata) {
|
||||
Application::Application(const AppData &appdata) : m_Window(), m_Renderer(nullptr), m_Surface(nullptr), m_isRunning(false), m_AppData(appdata) {
|
||||
SDL_SetMainReady();
|
||||
m_initResult = Init();
|
||||
}
|
||||
@@ -37,34 +42,21 @@ bool Application::Init() {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
m_Window = SDL_CreateWindow(GetAppData().windowdata.title.c_str(), GetAppData().windowdata.width, GetAppData().windowdata.height, windowFlags);
|
||||
|
||||
if (!m_Window) {
|
||||
LOG_ERROR("SDL window could not be created! {0}", SDL_GetError());
|
||||
Shutdown();
|
||||
|
||||
return false;
|
||||
} else {
|
||||
LOG_INFO("SDl window created");
|
||||
}
|
||||
|
||||
if (GetAppData().windowdata.pos_x != -1 && GetAppData().windowdata.pos_y != -1) {
|
||||
if (!SDL_SetWindowPosition(m_Window, GetAppData().windowdata.pos_x, GetAppData().windowdata.pos_y)) {
|
||||
LOG_ERROR("Failed to set SDL_Window position {0}", SDL_GetError());
|
||||
} else {
|
||||
LOG_INFO("SDL window position set to the initial value: x {0}, y {1}", GetAppData().windowdata.pos_x, GetAppData().windowdata.pos_y);
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("SDL window position not set. Will not attempt to set window position.");
|
||||
}
|
||||
|
||||
LOG_INFO("Available renderer drivers:");
|
||||
for (int i = 0; i < SDL_GetNumRenderDrivers(); i++) {
|
||||
LOG_INFO("{0}. {1}", i + 1, SDL_GetRenderDriver(i));
|
||||
}
|
||||
|
||||
m_Renderer = SDL_CreateRenderer(m_Window, nullptr);
|
||||
// TODO: check here if m_Window is not null otherwise shutdown procedure
|
||||
if (m_AppData.windowdata.title.empty()) {
|
||||
m_AppData.windowdata.title = m_AppData.name;
|
||||
}
|
||||
|
||||
m_AppData.windowdata.eventCallback = [this](Event &event) { RaiseEvent(event); };
|
||||
m_Window.push_back(std::make_shared<Window>(m_AppData.windowdata));
|
||||
m_Window[0]->Create();
|
||||
|
||||
m_Renderer = SDL_CreateRenderer(GetSDLWindow(), nullptr);
|
||||
if (!m_Renderer) {
|
||||
LOG_ERROR("Renderer could not be created! {0}", SDL_GetError());
|
||||
} else {
|
||||
@@ -72,7 +64,7 @@ bool Application::Init() {
|
||||
LOG_INFO("Renderer: {0}", SDL_GetRendererName(m_Renderer));
|
||||
}
|
||||
|
||||
SDL_SetRenderVSync(m_Renderer, 1);
|
||||
SDL_SetRenderVSync(m_Renderer, m_AppData.windowdata.isVsync);
|
||||
|
||||
m_ImGui = new SakuraVNE::ImGuiInit();
|
||||
|
||||
@@ -100,7 +92,6 @@ void Application::Run() {
|
||||
}
|
||||
|
||||
// Events
|
||||
// TODO: can i connect my events to sdl events and use their dispatcher?
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
@@ -111,31 +102,53 @@ void Application::Run() {
|
||||
LOG_INFO("Running state: {0}", GetRunningState());
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(GetSDLWindow())) {
|
||||
SetRunningState(false);
|
||||
SDL_WindowID targetWindowID = 0;
|
||||
|
||||
if (event.type >= SDL_EVENT_WINDOW_FIRST && event.type <= SDL_EVENT_WINDOW_LAST) {
|
||||
targetWindowID = event.window.windowID;
|
||||
} else if (event.type >= SDL_EVENT_KEY_DOWN && event.type <= SDL_EVENT_KEY_UP) {
|
||||
targetWindowID = event.key.windowID;
|
||||
} else if (event.type >= SDL_EVENT_MOUSE_MOTION && event.type <= SDL_EVENT_MOUSE_WHEEL) {
|
||||
targetWindowID = event.motion.windowID;
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
SDL_GetWindowSize(GetSDLWindow(), &GetAppData().windowdata.width, &GetAppData().windowdata.height);
|
||||
if (targetWindowID != 0) {
|
||||
for (auto it = m_Window.begin(); it != m_Window.end();) {
|
||||
|
||||
SetSDLWindowSurface(SDL_GetWindowSurface(GetSDLWindow()));
|
||||
if (SDL_GetWindowID((*it)->GetHandle()) == targetWindowID) {
|
||||
(*it)->ProcessEvent(event);
|
||||
|
||||
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||
it = m_Window.erase(it);
|
||||
|
||||
if (m_Window.empty()) {
|
||||
SetRunningState(false);
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering
|
||||
m_ImGui->Begin();
|
||||
|
||||
SDL_SetRenderScale(m_Renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColor(m_Renderer, (Uint8)111, (Uint8)232, (Uint8)168, (Uint8)0);
|
||||
SDL_RenderClear(m_Renderer);
|
||||
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnImGuiRender();
|
||||
}
|
||||
|
||||
m_ImGui->End();
|
||||
|
||||
SDL_RenderPresent(m_Renderer);
|
||||
}
|
||||
|
||||
// Rendering
|
||||
m_ImGui->Begin();
|
||||
|
||||
SDL_SetRenderScale(m_Renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColor(m_Renderer, (Uint8)111, (Uint8)232, (Uint8)168, (Uint8)0);
|
||||
SDL_RenderClear(m_Renderer);
|
||||
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnImGuiRender();
|
||||
}
|
||||
|
||||
m_ImGui->End();
|
||||
|
||||
SDL_RenderPresent(m_Renderer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +157,19 @@ void Application::Shutdown() {
|
||||
|
||||
SDL_DestroyRenderer(m_Renderer);
|
||||
|
||||
SDL_DestroyWindow(m_Window);
|
||||
m_Window.clear();
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
s_Instance = nullptr;
|
||||
}
|
||||
|
||||
void Application::RaiseEvent(Event &event) {
|
||||
for (auto &layer : std::views::reverse(m_LayerStack)) {
|
||||
layer->OnEvent(event);
|
||||
if (event.Handled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerStack.h"
|
||||
#include "SDL3/SDL_render.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "Window.h"
|
||||
#include "imguiinit.h"
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
struct WindowData {
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
int pos_x = -1;
|
||||
int pos_y = -1;
|
||||
std::string title = "Window Title";
|
||||
};
|
||||
namespace SakuraVNE {
|
||||
|
||||
struct AppData {
|
||||
std::string name = "Application";
|
||||
@@ -29,12 +26,13 @@ public:
|
||||
bool Init();
|
||||
void Run();
|
||||
void Shutdown();
|
||||
void RaiseEvent(Event &e);
|
||||
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<SakuraVNE::Layer, TLayer>)
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
void PushLayer() {
|
||||
auto newLayer = std::make_unique<TLayer>();
|
||||
SakuraVNE::Layer *layer = newLayer.get();
|
||||
Layer *layer = newLayer.get();
|
||||
|
||||
m_LayerStack.PushLayer(std::move(newLayer));
|
||||
|
||||
@@ -42,7 +40,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<SakuraVNE::Layer, TLayer>)
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
TLayer *GetLayer() {
|
||||
for (const auto &layer : m_LayerStack) {
|
||||
if (auto casted = dynamic_cast<TLayer *>(layer.get())) {
|
||||
@@ -53,7 +51,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<SakuraVNE::Layer, TLayer>)
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
TLayer *GetLayer(const std::string &layerName) {
|
||||
for (const auto &layer : m_LayerStack) {
|
||||
if (auto casted = dynamic_cast<TLayer *>(layer.get()) && layer->GetName() == layerName) {
|
||||
@@ -64,10 +62,10 @@ public:
|
||||
}
|
||||
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<SakuraVNE::Layer, TLayer>)
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
void PushOverlay() {
|
||||
auto newOverlay = std::make_unique<TLayer>();
|
||||
SakuraVNE::Layer *layer = newOverlay.get();
|
||||
Layer *layer = newOverlay.get();
|
||||
|
||||
m_LayerStack.PushOverLay(std::move(newOverlay));
|
||||
|
||||
@@ -75,11 +73,13 @@ public:
|
||||
}
|
||||
|
||||
inline AppData &GetAppData() { return m_AppData; }
|
||||
inline SDL_Window *GetSDLWindow() { return m_Window; }
|
||||
inline SDL_Window *GetSDLWindow(const int index = 0) { return m_Window[index]->GetHandle(); }
|
||||
inline SDL_Renderer *GetSDLRenderer() { return m_Renderer; }
|
||||
inline SDL_Surface *GetSDLWindowSurface() { return m_Surface; }
|
||||
inline void SetSDLWindowSurface(SDL_Surface *newSurface) { m_Surface = newSurface; }
|
||||
|
||||
std::shared_ptr<Window> GetWindow(const int index = 0) const { return m_Window[index]; }
|
||||
|
||||
bool &GetRunningState() { return m_isRunning; }
|
||||
void SetRunningState(bool isRunning) { m_isRunning = isRunning; }
|
||||
|
||||
@@ -89,16 +89,17 @@ private:
|
||||
bool m_isRunning;
|
||||
bool m_initResult;
|
||||
|
||||
SDL_Window *m_Window;
|
||||
SDL_Surface *m_Surface;
|
||||
SDL_Renderer *m_Renderer;
|
||||
|
||||
AppData m_AppData;
|
||||
std::vector<std::shared_ptr<Window>> m_Window;
|
||||
|
||||
SakuraVNE::LayerStack m_LayerStack;
|
||||
SakuraVNE::ImGuiInit *m_ImGui;
|
||||
LayerStack m_LayerStack;
|
||||
ImGuiInit *m_ImGui;
|
||||
|
||||
static Application *s_Instance;
|
||||
|
||||
friend class SakuraVNE::Layer;
|
||||
friend class Layer;
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
#include "Event.h"
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
#include "SDL3/SDL.h"
|
||||
|
||||
void SakuraVNE::ProcessEvents() {}
|
||||
|
||||
@@ -1,3 +1,51 @@
|
||||
namespace SakuraVNE{
|
||||
void ProcessEvents();
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
enum class EventType {
|
||||
None = 0,
|
||||
WindowClose,
|
||||
WindowResize,
|
||||
KeyPressed,
|
||||
KeyReleased,
|
||||
MouseButtonPressed,
|
||||
MouseButtonReleased,
|
||||
MouseMoved,
|
||||
MouseScrolled,
|
||||
};
|
||||
|
||||
#define EVENT_CLASS_TYPE(type) \
|
||||
static EventType GetStaticType() { return EventType::type; } \
|
||||
virtual EventType GetEventType() const override { return GetStaticType(); } \
|
||||
virtual const char *GetName() const override { return #type; }
|
||||
|
||||
class Event {
|
||||
public:
|
||||
bool Handled = false;
|
||||
|
||||
virtual ~Event() {}
|
||||
virtual EventType GetEventType() const = 0;
|
||||
virtual const char *GetName() const = 0;
|
||||
virtual std::string ToString() const { return GetName(); }
|
||||
};
|
||||
|
||||
class EventDispatcher {
|
||||
template <typename T> using EventFn = std::function<bool(T &)>;
|
||||
|
||||
public:
|
||||
EventDispatcher(Event &event) : m_Event(event) {}
|
||||
|
||||
template <typename T> bool Dispatch(EventFn<T> func) {
|
||||
if (m_Event.GetEventType() == T::GetStaticType() && !m_Event.Handled) {
|
||||
m_Event.Handled = func(*(T *)&m_Event);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Event &m_Event;
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
|
||||
94
SakuraCore/src/InputEvents.h
Normal file
94
SakuraCore/src/InputEvents.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#include <format>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
// Key events
|
||||
class KeyEvent : public Event {
|
||||
public:
|
||||
inline int GetKeyCode() const { return m_KeyCode; }
|
||||
|
||||
protected:
|
||||
KeyEvent(int keycode) : m_KeyCode(keycode) {}
|
||||
int m_KeyCode;
|
||||
};
|
||||
|
||||
class KeyPressedEvent : public KeyEvent {
|
||||
public:
|
||||
KeyPressedEvent(int keycode, bool isRepeat) : KeyEvent(keycode), m_IsRepeat(isRepeat) {}
|
||||
inline bool IsRepeat() const { return m_IsRepeat; }
|
||||
std::string ToString() const override { return std::format("KeyPressedEvent: {} (repeat={})", m_KeyCode, m_IsRepeat); }
|
||||
EVENT_CLASS_TYPE(KeyPressed)
|
||||
|
||||
private:
|
||||
bool m_IsRepeat;
|
||||
};
|
||||
|
||||
class KeyReleasedEvent : public KeyEvent {
|
||||
public:
|
||||
KeyReleasedEvent(int keycode) : KeyEvent(keycode) {}
|
||||
std::string ToString() const override { return std::format("KeyReleasedEvent: {}", m_KeyCode); }
|
||||
|
||||
EVENT_CLASS_TYPE(KeyReleased)
|
||||
};
|
||||
|
||||
// Mouse events
|
||||
class MouseMovedEvent : public Event {
|
||||
public:
|
||||
MouseMovedEvent(double x, double y) : m_MouseX(x), m_MouseY(y) {}
|
||||
|
||||
inline double GetX() const { return m_MouseX; }
|
||||
inline double GetY() const { return m_MouseY; }
|
||||
|
||||
std::string ToString() { return std::format("MouseMovedEvent: {}, {}", m_MouseX, m_MouseY); }
|
||||
|
||||
EVENT_CLASS_TYPE(MouseMoved)
|
||||
private:
|
||||
double m_MouseX, m_MouseY;
|
||||
};
|
||||
|
||||
class MouseScrolledEvent : public Event {
|
||||
public:
|
||||
MouseScrolledEvent(double xOffset, double yOffset) : m_XOffset(xOffset), m_YOffset(yOffset) {}
|
||||
|
||||
inline double GetXOffset() const { return m_XOffset; }
|
||||
inline double GetYOffset() const { return m_YOffset; }
|
||||
|
||||
std::string ToString() const override { return std::format("MouseScrolledEvent: {}, {}", m_XOffset, m_YOffset); }
|
||||
|
||||
EVENT_CLASS_TYPE(MouseScrolled)
|
||||
private:
|
||||
double m_XOffset, m_YOffset;
|
||||
};
|
||||
|
||||
class MouseButtonEvent : public Event {
|
||||
public:
|
||||
inline int GetMouseButton() const { return m_Button; }
|
||||
|
||||
protected:
|
||||
MouseButtonEvent(int button) : m_Button(button) {}
|
||||
|
||||
int m_Button;
|
||||
};
|
||||
|
||||
class MouseButtonPressedEvent : public MouseButtonEvent {
|
||||
public:
|
||||
MouseButtonPressedEvent(int button) : MouseButtonEvent(button) {}
|
||||
|
||||
std::string ToString() const override { return std::format("MouseButtonPressedEvent: {}", m_Button); }
|
||||
|
||||
EVENT_CLASS_TYPE(MouseButtonPressed)
|
||||
};
|
||||
|
||||
class MouseButtonReleasedEvent : public MouseButtonEvent {
|
||||
public:
|
||||
MouseButtonReleasedEvent(int button) : MouseButtonEvent(button) {}
|
||||
|
||||
std::string ToString() const override { return std::format("MouseButtonReleasedEvent: {}", m_Button); }
|
||||
|
||||
EVENT_CLASS_TYPE(MouseButtonReleased)
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "SDL3/SDL_stdinc.h"
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
@@ -12,7 +13,7 @@ public:
|
||||
virtual ~Layer() = default;
|
||||
|
||||
virtual void OnFrame(Uint64 timestamp) {}
|
||||
virtual void OnEvent(/*Event &e*/) {}
|
||||
virtual void OnEvent(Event &e) {}
|
||||
virtual void OnAttach() {}
|
||||
virtual void OnDetach() {}
|
||||
virtual void OnImGuiRender() {}
|
||||
|
||||
127
SakuraCore/src/Window.cpp
Normal file
127
SakuraCore/src/Window.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "Window.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "InputEvents.h"
|
||||
#include "Log.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_mouse.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "WindowEvents.h"
|
||||
|
||||
namespace SakuraVNE {
|
||||
Window::Window(const WindowData &data) : m_Data(data) {}
|
||||
Window::~Window() { Destroy(); }
|
||||
|
||||
void Window::Create() {
|
||||
// TODO: maybe get an unknow amount of parameters / an array of window flags? or just provide a seperate function for it
|
||||
SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
m_Handle = SDL_CreateWindow(m_Data.title.c_str(), m_Data.width, m_Data.height, windowFlags);
|
||||
|
||||
if (!m_Handle) {
|
||||
LOG_ERROR("SDL window could not be created! {0}", SDL_GetError());
|
||||
// FIX: there has to be a better way to shutdown this cannot be correct, because i just quit the sdl stuff but the init continues
|
||||
Application::Get().Shutdown();
|
||||
return;
|
||||
} else {
|
||||
LOG_INFO("SDl window created");
|
||||
}
|
||||
|
||||
if (m_Data.pos_x != -1 && m_Data.pos_y != -1) {
|
||||
if (!SDL_SetWindowPosition(m_Handle, m_Data.pos_x, m_Data.pos_y)) {
|
||||
LOG_ERROR("Failed to set SDL_Window position {0}", SDL_GetError());
|
||||
} else {
|
||||
LOG_INFO("SDL window position set to the initial value: x {0}, y {1}", m_Data.pos_x, m_Data.pos_y);
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("SDL window position not set. Will not attempt to set window position.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add the window callbacks here as seperate functions because sdl functions that way
|
||||
// each of them will get a function which will receive a window event filled in with the window's data (id (i guess))
|
||||
// and then they will dispatch it to the event system using the same raise event
|
||||
|
||||
void Window::ProcessEvent(const SDL_Event &event) {
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: {
|
||||
WindowClosedEvent e;
|
||||
RaiseEvent(e);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_WINDOW_RESIZED: {
|
||||
WindowResizeEvent e((uint32_t)event.window.data1, (uint32_t)event.window.data2);
|
||||
RaiseEvent(e);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
bool isRepeat = event.key.repeat != 0;
|
||||
if (event.type == SDL_EVENT_KEY_DOWN) {
|
||||
KeyPressedEvent e(event.key.key, isRepeat);
|
||||
RaiseEvent(e);
|
||||
} else {
|
||||
KeyReleasedEvent e(event.key.key);
|
||||
RaiseEvent(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||
MouseButtonPressedEvent e(event.button.button);
|
||||
RaiseEvent(e);
|
||||
} else {
|
||||
MouseButtonReleasedEvent e(event.button.button);
|
||||
RaiseEvent(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_MOTION: {
|
||||
MouseMovedEvent e(event.motion.x, event.motion.y);
|
||||
RaiseEvent(e);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_WHEEL: {
|
||||
MouseScrolledEvent e(event.wheel.x, event.wheel.y);
|
||||
RaiseEvent(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::Resize() {
|
||||
SDL_GetWindowSize(m_Handle, &m_Data.width, &m_Data.height);
|
||||
SDL_SetWindowSize(m_Handle, m_Data.width, m_Data.height);
|
||||
}
|
||||
|
||||
void Window::Destroy() {
|
||||
if (m_Handle) {
|
||||
SDL_DestroyWindow(m_Handle);
|
||||
}
|
||||
m_Handle = nullptr;
|
||||
}
|
||||
|
||||
void Window::RaiseEvent(Event &event) {
|
||||
if (m_Data.eventCallback) {
|
||||
m_Data.eventCallback(event);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this need testing because i am really not sure this is correct
|
||||
// should this be static or go somewhere else | probably in application?
|
||||
auto Window::GetMousePos() const {
|
||||
struct result {
|
||||
float *x;
|
||||
float *y;
|
||||
};
|
||||
|
||||
SDL_GetMouseState(m_MouseXPos, m_MouseYPos);
|
||||
|
||||
return result{m_MouseXPos, m_MouseYPos};
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
50
SakuraCore/src/Window.h
Normal file
50
SakuraCore/src/Window.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
struct WindowData {
|
||||
std::string title = "Window Title";
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
int pos_x = -1;
|
||||
int pos_y = -1;
|
||||
bool isResizable = true;
|
||||
bool isVsync = true;
|
||||
|
||||
using EventCallbackFn = std::function<void(Event &)>;
|
||||
EventCallbackFn eventCallback;
|
||||
};
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window(const WindowData &data = WindowData());
|
||||
~Window();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
|
||||
void Update();
|
||||
void Resize();
|
||||
void ProcessEvent(const SDL_Event &event);
|
||||
|
||||
void RaiseEvent(Event &event);
|
||||
|
||||
bool ShouldClose() const;
|
||||
auto GetMousePos() const;
|
||||
|
||||
SDL_Window *GetHandle() const { return m_Handle; }
|
||||
|
||||
private:
|
||||
WindowData m_Data;
|
||||
SDL_Window *m_Handle = nullptr;
|
||||
float *m_MouseXPos = nullptr;
|
||||
float *m_MouseYPos = nullptr;
|
||||
};
|
||||
|
||||
} // namespace SakuraVNE
|
||||
29
SakuraCore/src/WindowEvents.h
Normal file
29
SakuraCore/src/WindowEvents.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
class WindowClosedEvent : public Event {
|
||||
public:
|
||||
WindowClosedEvent() {}
|
||||
EVENT_CLASS_TYPE(WindowClose)
|
||||
};
|
||||
|
||||
class WindowResizeEvent : public Event {
|
||||
public:
|
||||
WindowResizeEvent(uint32_t width, uint32_t height) : m_Width(width), m_Height(height) {}
|
||||
|
||||
// TODO: chech if uint32_t works with sdl3 windows
|
||||
inline uint32_t GetWidth() const { return m_Width; }
|
||||
inline uint32_t GetHeight() const { return m_Height; }
|
||||
|
||||
std::string ToString() const override { return std::format("WindowResizeEvent: {}, {}", m_Width, m_Height); }
|
||||
EVENT_CLASS_TYPE(WindowResize)
|
||||
private:
|
||||
uint32_t m_Width, m_Height;
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
Reference in New Issue
Block a user