Compare commits
47 Commits
370e0f9c5a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fe522ffbe | |||
| 4cd1528343 | |||
| 31f57eddf7 | |||
| e9808fb47f | |||
| fa05feceb8 | |||
| 4b89548102 | |||
| 99d508c5ed | |||
| fb9e93d9cf | |||
| e64fc16d6a | |||
| 73db13dcc2 | |||
| ec5d5af43e | |||
| ccbc79d496 | |||
| 7ff93e58ea | |||
| e57149e9db | |||
| 796769c6a4 | |||
| daefc73de7 | |||
| d28dbc1083 | |||
| 7e5317fdc0 | |||
| 0dbb8bc642 | |||
| 96c19efaea | |||
| b964c2257b | |||
| e46225eda9 | |||
| 5dd3cc1b73 | |||
| b98f46f425 | |||
| 60f6c9281b | |||
| fd319405e5 | |||
| 5b40377d04 | |||
| 9974471b66 | |||
| 3925ccc520 | |||
| 8b91c7ab76 | |||
| d58ddf6c35 | |||
| da3ad2ed61 | |||
| 53ef776d4c | |||
| abe57222a8 | |||
| 5f2dc0d66e | |||
| 5613e3824a | |||
| 5aa1e39cdd | |||
| fe265c6994 | |||
| fb06a38c83 | |||
| cc3f592c67 | |||
| a9d3910ab3 | |||
| ea1d6252ba | |||
| 51cfab26f2 | |||
| a6ccb37b10 | |||
| b05badcf90 | |||
| 9b64e0b065 | |||
| fed67c7baa |
@@ -2,17 +2,23 @@
|
||||
#include "Event.h"
|
||||
#include "Layer.h"
|
||||
#include "Log.h"
|
||||
#include "SDL3/SDL_main.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_hints.h"
|
||||
#include "SDL3/SDL_init.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 "imgui_impl_sdlrenderer3.h"
|
||||
|
||||
#define SDL_MAIN_HANDLED 1
|
||||
#include "imguiinit.h"
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
|
||||
namespace SakuraVNE {
|
||||
Application *Application::s_Instance = nullptr;
|
||||
|
||||
Application::Application() : m_Window(nullptr), m_Renderer(nullptr), m_Surface(nullptr), m_isRunning(false) { SDL_SetMainReady(); }
|
||||
Application::Application(const AppData &appdata) : m_Window(), m_Renderer(nullptr), m_Surface(nullptr), m_isRunning(false), m_AppData(appdata) { m_initResult = Init(); }
|
||||
Application::~Application() { Shutdown(); }
|
||||
|
||||
bool Application::Init() {
|
||||
@@ -23,7 +29,7 @@ bool Application::Init() {
|
||||
SakuraVNE::Log::Init();
|
||||
LOG_INFO("Initialized logger library");
|
||||
|
||||
LOG_INFO("window width: {0}, height: {1}", GetWindowData().width, GetWindowData().height);
|
||||
LOG_INFO("window width: {0}, height: {1}", GetAppData().windowdata.width, GetAppData().windowdata.height);
|
||||
|
||||
// Init sdl
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == 0) {
|
||||
@@ -32,34 +38,25 @@ bool Application::Init() {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE);
|
||||
m_Window = SDL_CreateWindow(GetWindowData().title, GetWindowData().width, GetWindowData().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 (GetWindowData().pos_x != -1 && GetWindowData().pos_y != -1) {
|
||||
if (!SDL_SetWindowPosition(m_Window, GetWindowData().pos_x, GetWindowData().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}", GetWindowData().pos_x, GetWindowData().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));
|
||||
bool isSuccessful = m_Window[0]->Create({m_AppData.windowdata.windowFlags});
|
||||
if (!isSuccessful) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Renderer = SDL_CreateRenderer(GetSDLWindow(), nullptr);
|
||||
if (!m_Renderer) {
|
||||
LOG_ERROR("Renderer could not be created! {0}", SDL_GetError());
|
||||
} else {
|
||||
@@ -67,25 +64,34 @@ 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_ImGuiLayer = new SakuraVNE::ImGuiLayer();
|
||||
PushOverlay(m_ImGuiLayer);
|
||||
m_ImGui = new SakuraVNE::ImGuiInit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Run() {
|
||||
if (!m_initResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
Uint64 oldTime = SDL_GetTicks();
|
||||
|
||||
while (GetRunningState()) {
|
||||
|
||||
float time = 0;
|
||||
Uint64 currentTime = SDL_GetTicks();
|
||||
Uint64 time = currentTime - oldTime;
|
||||
oldTime = currentTime;
|
||||
|
||||
for (auto layer : m_LayerStack) {
|
||||
// Update functions before rendereing
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnFrame(time);
|
||||
}
|
||||
|
||||
// Events
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
@@ -96,24 +102,69 @@ 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(), &GetWindowData().width, &GetWindowData().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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
if (!m_isRunning) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnRender();
|
||||
}
|
||||
|
||||
m_ImGui->Begin();
|
||||
|
||||
SDL_SetRenderScale(m_Renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
|
||||
SDL_SetRenderDrawColor(m_Renderer, (Uint8)255, (Uint8)255, (Uint8)255, (Uint8)255);
|
||||
SDL_SetRenderDrawColor(m_Renderer, (Uint8)111, (Uint8)232, (Uint8)168, (Uint8)255);
|
||||
SDL_RenderClear(m_Renderer);
|
||||
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), m_Renderer);
|
||||
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnImGuiRender();
|
||||
}
|
||||
|
||||
m_ImGui->End();
|
||||
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
}
|
||||
|
||||
SDL_RenderPresent(m_Renderer);
|
||||
|
||||
// handle layercommands here after each frame
|
||||
m_LayerStack.ProcessCommands();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,18 +173,19 @@ void Application::Shutdown() {
|
||||
|
||||
SDL_DestroyRenderer(m_Renderer);
|
||||
|
||||
// Destroy window
|
||||
SDL_DestroyWindow(m_Window);
|
||||
m_Window.clear();
|
||||
|
||||
// Quit SDL subsystems
|
||||
SDL_Quit();
|
||||
|
||||
s_Instance = nullptr;
|
||||
}
|
||||
|
||||
void Application::PushLayer(SakuraVNE::Layer *layer) {
|
||||
m_LayerStack.PushLayer(layer);
|
||||
layer->OnAttach();
|
||||
}
|
||||
void Application::PushOverlay(SakuraVNE::Layer *layer) {
|
||||
m_LayerStack.PushOverLay(layer);
|
||||
layer->OnAttach();
|
||||
void Application::RaiseEvent(Event &event) {
|
||||
for (auto &layer : std::views::reverse(m_LayerStack)) {
|
||||
layer->OnEvent(event);
|
||||
if (event.Handled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
|
||||
@@ -1,54 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "Layer.h"
|
||||
#include "LayerStack.h"
|
||||
#include "SDL3/SDL.h"
|
||||
#include "imguilayer.h"
|
||||
#include "SDL3/SDL_render.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "Window.h"
|
||||
#include "imguiinit.h"
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
// TODO: Move this out to its own class(?) so it can be defined by the application
|
||||
// maybe this could be used as a fallback if the app did not define one
|
||||
struct WindowData {
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
int pos_x = -1;
|
||||
int pos_y = -1;
|
||||
const char *title = "Sakura Visual Novel Engine";
|
||||
namespace SakuraVNE {
|
||||
|
||||
struct AppData {
|
||||
std::string name = "Application";
|
||||
WindowData windowdata;
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
Application(const AppData &appdata = AppData());
|
||||
~Application();
|
||||
|
||||
bool Init();
|
||||
void Run();
|
||||
void Shutdown();
|
||||
void RaiseEvent(Event &e);
|
||||
|
||||
void PushLayer(SakuraVNE::Layer *);
|
||||
void PushOverlay(SakuraVNE::Layer *);
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
void PushLayer() {
|
||||
auto newLayer = std::make_unique<TLayer>();
|
||||
Layer *layer = newLayer.get();
|
||||
|
||||
inline WindowData &GetWindowData() { return m_WindowData; }
|
||||
inline SDL_Window *GetSDLWindow() { return m_Window; }
|
||||
m_LayerStack.PushLayer(std::move(newLayer));
|
||||
|
||||
layer->OnAttach();
|
||||
}
|
||||
|
||||
template <typename 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())) {
|
||||
return casted;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename 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) {
|
||||
return casted;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename TLayer>
|
||||
requires(std::is_base_of_v<Layer, TLayer>)
|
||||
void PushOverlay() {
|
||||
auto newOverlay = std::make_unique<TLayer>();
|
||||
Layer *layer = newOverlay.get();
|
||||
|
||||
m_LayerStack.PushOverLay(std::move(newOverlay));
|
||||
|
||||
layer->OnAttach();
|
||||
}
|
||||
|
||||
inline AppData &GetAppData() { return m_AppData; }
|
||||
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; }
|
||||
|
||||
static Application &Get() { return *s_Instance; }
|
||||
inline LayerStack &GetLayerStack() { return m_LayerStack; }
|
||||
|
||||
private:
|
||||
SDL_Window *m_Window;
|
||||
bool m_isRunning;
|
||||
bool m_initResult;
|
||||
|
||||
SDL_Surface *m_Surface;
|
||||
SDL_Renderer *m_Renderer;
|
||||
|
||||
WindowData m_WindowData;
|
||||
AppData m_AppData;
|
||||
std::vector<std::shared_ptr<Window>> m_Window;
|
||||
|
||||
bool m_isRunning;
|
||||
|
||||
SakuraVNE::LayerStack m_LayerStack;
|
||||
LayerStack m_LayerStack;
|
||||
ImGuiInit *m_ImGui;
|
||||
|
||||
static Application *s_Instance;
|
||||
SakuraVNE::ImGuiLayer *m_ImGuiLayer;
|
||||
|
||||
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,6 +1,20 @@
|
||||
#include "Layer.h"
|
||||
#include "Application.h"
|
||||
#include "LayerStack.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
Layer::Layer(const std::string &name) : m_LayerName(name) {}
|
||||
Layer::Layer(const std::string &name, bool isActive) : m_LayerName(name), m_isActive(isActive) {}
|
||||
|
||||
void Layer::QueueTransition(std::unique_ptr<Layer> toLayer) {
|
||||
auto &layerStack = Application::Get().GetLayerStack();
|
||||
|
||||
LayerCommand command;
|
||||
command.action = LayerAction::Transition;
|
||||
command.targetLayer = this;
|
||||
command.newLayer = std::move(toLayer);
|
||||
|
||||
layerStack.SubmitCommand(std::move(command));
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
|
||||
@@ -1,23 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "SDL3/SDL_stdinc.h"
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
class Layer {
|
||||
public:
|
||||
Layer(const std::string &name = "Layer");
|
||||
Layer(const std::string &name = "Layer", bool isActive = true);
|
||||
virtual ~Layer() = default;
|
||||
|
||||
virtual void OnStart() {}
|
||||
virtual void OnFrame(float timestamp) {}
|
||||
virtual void OnEnd() {}
|
||||
virtual void OnEvent() {}
|
||||
virtual void OnFrame(Uint64 timestamp) {}
|
||||
virtual void OnEvent(Event &e) {}
|
||||
virtual void OnAttach() {}
|
||||
virtual void OnDetach() {}
|
||||
virtual void OnImGuiRender() {}
|
||||
virtual void OnRender() {}
|
||||
virtual void Suspend() { m_isActive = false; }
|
||||
virtual void Activate() { m_isActive = true; }
|
||||
|
||||
template <std::derived_from<Layer> T, typename... Args> void TransitionTo(Args &&...args) { QueueTransition(std::move(std::make_unique<T>(std::forward<Args>(args)...))); }
|
||||
|
||||
const std::string &GetName() const { return m_LayerName; }
|
||||
|
||||
protected:
|
||||
std::string m_LayerName;
|
||||
bool m_isActive = true;
|
||||
|
||||
private:
|
||||
void QueueTransition(std::unique_ptr<Layer> layer);
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
|
||||
@@ -1,22 +1,59 @@
|
||||
#include "LayerStack.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace SakuraVNE {
|
||||
|
||||
LayerStack::LayerStack() {
|
||||
m_LayerStack.reserve(3);
|
||||
m_CommandQueue.reserve(10);
|
||||
}
|
||||
|
||||
LayerStack::~LayerStack() {
|
||||
for (Layer *layer : m_LayerStack) {
|
||||
for (auto &layer : m_LayerStack) {
|
||||
layer->OnDetach();
|
||||
delete layer;
|
||||
}
|
||||
}
|
||||
|
||||
void LayerStack::PushLayer(Layer *layer) {
|
||||
m_LayerStack.emplace(m_LayerStack.begin() + m_LayerIndex, layer);
|
||||
void LayerStack::SubmitCommand(LayerCommand command) { m_CommandQueue.push_back(std::move(command)); }
|
||||
|
||||
void LayerStack::ProcessCommands() {
|
||||
if (m_CommandQueue.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &command : m_CommandQueue) {
|
||||
switch (command.action) {
|
||||
case LayerAction::Pop:
|
||||
PopLayer(command.targetLayer);
|
||||
break;
|
||||
case LayerAction::Push:
|
||||
PushLayer(std::move(command.newLayer));
|
||||
break;
|
||||
case LayerAction::Transition:
|
||||
auto it = std::find_if(m_LayerStack.begin(), m_LayerStack.end(), [&](const std::unique_ptr<Layer> &layer) { return layer.get() == command.targetLayer; });
|
||||
|
||||
if (it != m_LayerStack.end()) {
|
||||
(*it)->OnDetach();
|
||||
command.newLayer->OnAttach();
|
||||
|
||||
*it = std::move(command.newLayer);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_CommandQueue.clear();
|
||||
}
|
||||
|
||||
void LayerStack::PushLayer(std::unique_ptr<Layer> layer) {
|
||||
m_LayerStack.emplace(m_LayerStack.begin() + m_LayerIndex, std::move(layer));
|
||||
m_LayerIndex++;
|
||||
}
|
||||
|
||||
void LayerStack::PopLayer(Layer *layer) {
|
||||
auto match = std::find(m_LayerStack.begin(), m_LayerStack.begin() + m_LayerIndex, layer);
|
||||
auto match = std::find_if(m_LayerStack.begin(), m_LayerStack.begin() + m_LayerIndex, [layer](const std::unique_ptr<Layer> &ptr) { return ptr.get() == layer; });
|
||||
if (match != m_LayerStack.begin() + m_LayerIndex) {
|
||||
layer->OnDetach();
|
||||
m_LayerStack.erase(match);
|
||||
@@ -24,10 +61,10 @@ void LayerStack::PopLayer(Layer *layer) {
|
||||
}
|
||||
}
|
||||
|
||||
void LayerStack::PushOverLay(Layer *layer) { m_LayerStack.emplace_back(layer); }
|
||||
void LayerStack::PushOverLay(std::unique_ptr<Layer> layer) { m_LayerStack.emplace_back(std::move(layer)); }
|
||||
|
||||
void LayerStack::PopOverlay(Layer *layer) {
|
||||
auto match = std::find(m_LayerStack.begin() + m_LayerIndex, m_LayerStack.end(), layer);
|
||||
auto match = std::find_if(m_LayerStack.begin() + m_LayerIndex, m_LayerStack.end(), [layer](const std::unique_ptr<Layer> &ptr) { return ptr.get() == layer; });
|
||||
|
||||
if (match != m_LayerStack.end()) {
|
||||
layer->OnDetach();
|
||||
|
||||
@@ -2,35 +2,48 @@
|
||||
|
||||
#include "Layer.h"
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace SakuraVNE {
|
||||
enum class LayerAction { Push, Pop, Transition };
|
||||
|
||||
struct LayerCommand {
|
||||
LayerAction action;
|
||||
Layer *targetLayer;
|
||||
std::unique_ptr<Layer> newLayer;
|
||||
};
|
||||
|
||||
class LayerStack {
|
||||
public:
|
||||
LayerStack() = default;
|
||||
LayerStack();
|
||||
~LayerStack();
|
||||
|
||||
void PushLayer(Layer *layer);
|
||||
void PushLayer(std::unique_ptr<Layer> layer);
|
||||
void PopLayer(Layer *layer);
|
||||
void PushOverLay(Layer *layer);
|
||||
void PushOverLay(std::unique_ptr<Layer> layer);
|
||||
void PopOverlay(Layer *layer);
|
||||
|
||||
std::vector<Layer *>::iterator begin() { return m_LayerStack.begin(); }
|
||||
std::vector<Layer *>::iterator end() { return m_LayerStack.end(); }
|
||||
std::vector<Layer *>::reverse_iterator rbegin() { return m_LayerStack.rbegin(); }
|
||||
std::vector<Layer *>::reverse_iterator rend() { return m_LayerStack.rend(); }
|
||||
std::vector<std::unique_ptr<Layer>>::iterator begin() { return m_LayerStack.begin(); }
|
||||
std::vector<std::unique_ptr<Layer>>::iterator end() { return m_LayerStack.end(); }
|
||||
std::vector<std::unique_ptr<Layer>>::reverse_iterator rbegin() { return m_LayerStack.rbegin(); }
|
||||
std::vector<std::unique_ptr<Layer>>::reverse_iterator rend() { return m_LayerStack.rend(); }
|
||||
|
||||
std::vector<Layer *>::const_iterator begin() const { return m_LayerStack.begin(); }
|
||||
std::vector<Layer *>::const_iterator end() const { return m_LayerStack.end(); }
|
||||
std::vector<Layer *>::const_reverse_iterator rbegin() const { return m_LayerStack.rbegin(); }
|
||||
std::vector<Layer *>::const_reverse_iterator rend() const { return m_LayerStack.rend(); }
|
||||
std::vector<std::unique_ptr<Layer>>::const_iterator begin() const { return m_LayerStack.begin(); }
|
||||
std::vector<std::unique_ptr<Layer>>::const_iterator end() const { return m_LayerStack.end(); }
|
||||
std::vector<std::unique_ptr<Layer>>::const_reverse_iterator rbegin() const { return m_LayerStack.rbegin(); }
|
||||
std::vector<std::unique_ptr<Layer>>::const_reverse_iterator rend() const { return m_LayerStack.rend(); }
|
||||
|
||||
void SubmitCommand(LayerCommand command);
|
||||
void ProcessCommands();
|
||||
|
||||
#ifdef DEBUG
|
||||
// this is only used for the tests for now, so it will be taken out of the release build
|
||||
inline const std::vector<Layer *> &GetLayers() const { return m_LayerStack; }
|
||||
inline const std::vector<std::unique_ptr<Layer>> &GetLayers() const { return m_LayerStack; }
|
||||
#endif
|
||||
private:
|
||||
std::vector<Layer *> m_LayerStack;
|
||||
std::vector<LayerCommand> m_CommandQueue;
|
||||
std::vector<std::unique_ptr<Layer>> m_LayerStack;
|
||||
unsigned int m_LayerIndex = 0;
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
|
||||
222
SakuraCore/src/Window.cpp
Normal file
222
SakuraCore/src/Window.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "Window.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"
|
||||
#include <span>
|
||||
|
||||
namespace SakuraVNE {
|
||||
Window::Window(const WindowData &data) : m_Data(data), m_Flags(0) {}
|
||||
Window::~Window() { Destroy(); }
|
||||
|
||||
bool Window::Create(const SDL_WindowFlags flags) {
|
||||
m_Flags |= flags;
|
||||
|
||||
m_Handle = SDL_CreateWindow(m_Data.title.c_str(), m_Data.width, m_Data.height, m_Flags);
|
||||
|
||||
if (!m_Handle) {
|
||||
LOG_ERROR("SDL window could not be created! {0}", SDL_GetError());
|
||||
return false;
|
||||
} 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.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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::AddFlags(std::span<const SDL_WindowFlags> flags) {
|
||||
for (auto &flag : flags) {
|
||||
switch (flag) {
|
||||
case SDL_WINDOW_FULLSCREEN:
|
||||
SDL_SetWindowFullscreen(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_HIDDEN:
|
||||
SDL_ShowWindow(m_Handle);
|
||||
break;
|
||||
case SDL_WINDOW_BORDERLESS:
|
||||
SDL_SetWindowBordered(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_RESIZABLE:
|
||||
SDL_SetWindowResizable(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_MINIMIZED:
|
||||
SDL_MinimizeWindow(m_Handle);
|
||||
break;
|
||||
case SDL_WINDOW_MAXIMIZED:
|
||||
SDL_MaximizeWindow(m_Handle);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_GRABBED:
|
||||
SDL_SetWindowMouseGrab(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_CAPTURE:
|
||||
SDL_SetWindowMouseGrab(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_RELATIVE_MODE:
|
||||
SDL_SetWindowRelativeMouseMode(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_MODAL:
|
||||
SDL_SetWindowModal(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_ALWAYS_ON_TOP:
|
||||
SDL_SetWindowAlwaysOnTop(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_KEYBOARD_GRABBED:
|
||||
SDL_SetWindowKeyboardGrab(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_NOT_FOCUSABLE:
|
||||
SDL_SetWindowFocusable(m_Handle, false);
|
||||
break;
|
||||
default:
|
||||
LOG_WARN("You can only use this when creating a window or the flag is readonly");
|
||||
break;
|
||||
}
|
||||
|
||||
m_Flags |= flag;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::RemoveFlags(std::span<const SDL_WindowFlags> flags) {
|
||||
for (auto &flag : flags) {
|
||||
switch (flag) {
|
||||
case SDL_WINDOW_FULLSCREEN:
|
||||
SDL_SetWindowFullscreen(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_HIDDEN:
|
||||
SDL_HideWindow(m_Handle);
|
||||
break;
|
||||
case SDL_WINDOW_BORDERLESS:
|
||||
SDL_SetWindowBordered(m_Handle, true);
|
||||
break;
|
||||
case SDL_WINDOW_RESIZABLE:
|
||||
SDL_SetWindowResizable(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_MINIMIZED:
|
||||
case SDL_WINDOW_MAXIMIZED:
|
||||
SDL_RestoreWindow(m_Handle);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_GRABBED:
|
||||
SDL_SetWindowMouseGrab(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_CAPTURE:
|
||||
SDL_SetWindowMouseGrab(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_MOUSE_RELATIVE_MODE:
|
||||
SDL_SetWindowRelativeMouseMode(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_MODAL:
|
||||
SDL_SetWindowModal(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_ALWAYS_ON_TOP:
|
||||
SDL_SetWindowAlwaysOnTop(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_KEYBOARD_GRABBED:
|
||||
SDL_SetWindowKeyboardGrab(m_Handle, false);
|
||||
break;
|
||||
case SDL_WINDOW_NOT_FOCUSABLE:
|
||||
SDL_SetWindowFocusable(m_Handle, true);
|
||||
break;
|
||||
default:
|
||||
LOG_WARN("You can only use this when creating a window or the flag is readonly");
|
||||
break;
|
||||
}
|
||||
|
||||
m_Flags &= flag;
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
struct result {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
SDL_GetMouseState(&m_MouseXPos, &m_MouseYPos);
|
||||
|
||||
return result{m_MouseXPos, m_MouseYPos};
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
54
SakuraCore/src/Window.h
Normal file
54
SakuraCore/src/Window.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "Event.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include <functional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
namespace SakuraVNE {
|
||||
struct WindowData {
|
||||
SDL_WindowFlags windowFlags = 0;
|
||||
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();
|
||||
|
||||
bool Create(const SDL_WindowFlags flags = 0);
|
||||
void Destroy();
|
||||
|
||||
void Update();
|
||||
void AddFlags(std::span<const SDL_WindowFlags> flags = {});
|
||||
void RemoveFlags(std::span<const SDL_WindowFlags> flags = {});
|
||||
void Resize();
|
||||
void ProcessEvent(const SDL_Event &event);
|
||||
|
||||
void RaiseEvent(Event &event);
|
||||
|
||||
bool ShouldClose() const;
|
||||
auto GetMousePos();
|
||||
|
||||
SDL_Window *GetHandle() const { return m_Handle; }
|
||||
|
||||
private:
|
||||
WindowData m_Data;
|
||||
SDL_Window *m_Handle = nullptr;
|
||||
SDL_WindowFlags m_Flags;
|
||||
float m_MouseXPos;
|
||||
float m_MouseYPos;
|
||||
};
|
||||
|
||||
} // 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
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "imguilayer.h"
|
||||
#include "imguiinit.h"
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
#include "imgui.h"
|
||||
@@ -6,15 +6,18 @@
|
||||
#include "imgui_impl_sdlrenderer3.h"
|
||||
|
||||
namespace SakuraVNE {
|
||||
ImGuiLayer::ImGuiLayer() : Layer("ImGuiLayer") {}
|
||||
ImGuiInit::ImGuiInit() { Init(); }
|
||||
ImGuiInit::~ImGuiInit() { Shutdown(); }
|
||||
|
||||
void ImGuiLayer::OnAttach() {
|
||||
void ImGuiInit::Init() {
|
||||
// Imgui init
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
@@ -24,23 +27,29 @@ void ImGuiLayer::OnAttach() {
|
||||
LOG_INFO("Imgui layer OnAttach ran");
|
||||
}
|
||||
|
||||
void ImGuiLayer::OnDetach() {
|
||||
void ImGuiInit::Shutdown() {
|
||||
ImGui_ImplSDLRenderer3_Shutdown();
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
LOG_WARN("Imgui on detach ran");
|
||||
}
|
||||
|
||||
void ImGuiLayer::Begin() {
|
||||
void ImGuiInit::Begin() {
|
||||
ImGui_ImplSDLRenderer3_NewFrame();
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
// for docking the imgui windows to the edge of the sdl window
|
||||
ImGui::DockSpaceOverViewport();
|
||||
}
|
||||
|
||||
void ImGuiLayer::End() {
|
||||
void ImGuiInit::End() {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
Application &app = Application::Get();
|
||||
io.DisplaySize = ImVec2((float)app.GetWindowData().width, (float)app.GetWindowData().height);
|
||||
io.DisplaySize = ImVec2((float)app.GetAppData().windowdata.width, (float)app.GetAppData().windowdata.height);
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), Application::Get().GetSDLRenderer());
|
||||
ImGui::EndFrame();
|
||||
}
|
||||
} // namespace SakuraVNE
|
||||
14
SakuraCore/src/imguiinit.h
Normal file
14
SakuraCore/src/imguiinit.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace SakuraVNE {
|
||||
class ImGuiInit {
|
||||
public:
|
||||
ImGuiInit();
|
||||
~ImGuiInit();
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Begin();
|
||||
void End();
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
namespace SakuraVNE {
|
||||
class ImGuiLayer : public Layer {
|
||||
public:
|
||||
ImGuiLayer();
|
||||
~ImGuiLayer() = default;
|
||||
|
||||
// virtual void OnStart() override;
|
||||
// virtual void OnFrame(float timestamp) override;
|
||||
// virtual void OnEnd() override;
|
||||
virtual void OnAttach() override;
|
||||
virtual void OnDetach() override;
|
||||
// virtual void OnEvent() override;
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
};
|
||||
} // namespace SakuraVNE
|
||||
@@ -3,19 +3,21 @@
|
||||
#include "Layer.h"
|
||||
#include "LayerStack.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
TEST_CASE("Layer operations", "[Layer]") {
|
||||
SakuraVNE::LayerStack lstack;
|
||||
const auto &layers = lstack.GetLayers();
|
||||
|
||||
SakuraVNE::Layer *layer1 = new SakuraVNE::Layer("layer1");
|
||||
lstack.PushLayer(layer1);
|
||||
// Create the unique_ptr, keep a raw pointer for testing Pop operations later, then move it.
|
||||
auto u_layer1 = std::make_unique<SakuraVNE::Layer>("layer1");
|
||||
SakuraVNE::Layer *layer1 = u_layer1.get();
|
||||
lstack.PushLayer(std::move(u_layer1));
|
||||
|
||||
SECTION("PushLayer should make the size 2") {
|
||||
SakuraVNE::Layer *layer2 = new SakuraVNE::Layer("layer2");
|
||||
lstack.PushLayer(layer2);
|
||||
auto u_layer2 = std::make_unique<SakuraVNE::Layer>("layer2");
|
||||
lstack.PushLayer(std::move(u_layer2));
|
||||
REQUIRE(layers.size() == 2);
|
||||
REQUIRE(layers[1]->GetName() == "layer2");
|
||||
}
|
||||
@@ -24,25 +26,26 @@ TEST_CASE("Layer operations", "[Layer]") {
|
||||
REQUIRE(layers.size() == 0);
|
||||
}
|
||||
SECTION("PushOverlay should always put at the end of the list and should always be after the last fence index") {
|
||||
SakuraVNE::Layer *layer2 = new SakuraVNE::Layer("layer2");
|
||||
lstack.PushOverLay(layer2);
|
||||
auto u_layer2 = std::make_unique<SakuraVNE::Layer>("layer2");
|
||||
lstack.PushOverLay(std::move(u_layer2));
|
||||
REQUIRE(layers[1]->GetName() == "layer2");
|
||||
|
||||
SakuraVNE::Layer *layer3 = new SakuraVNE::Layer("layer3");
|
||||
lstack.PushLayer(layer3);
|
||||
auto u_layer3 = std::make_unique<SakuraVNE::Layer>("layer3");
|
||||
lstack.PushLayer(std::move(u_layer3));
|
||||
|
||||
REQUIRE(layers[1]->GetName() == "layer3");
|
||||
REQUIRE(layers[2]->GetName() == "layer2");
|
||||
}
|
||||
SECTION("Pop overlay") {
|
||||
SakuraVNE::Layer *layer6 = new SakuraVNE::Layer("layer6");
|
||||
lstack.PushOverLay(layer6);
|
||||
auto u_layer6 = std::make_unique<SakuraVNE::Layer>("layer6");
|
||||
SakuraVNE::Layer *layer6 = u_layer6.get();
|
||||
lstack.PushOverLay(std::move(u_layer6));
|
||||
REQUIRE(layers[1]->GetName() == "layer6");
|
||||
|
||||
lstack.PopOverlay(layer6);
|
||||
|
||||
bool hasLayer2InVec = false;
|
||||
for (auto layer : layers) {
|
||||
for (auto &layer : layers) {
|
||||
if (layer->GetName() == "layer6") {
|
||||
hasLayer2InVec = true;
|
||||
}
|
||||
|
||||
Submodule libs/catch2 updated: ccc49ba664...be2dfb45cc
Submodule libs/imgui updated: 5ffba73d97...75929b5e8a
Submodule libs/sdl3 updated: 5f78ded319...c2d0b59f29
Submodule libs/spdlog updated: 45b67eee66...75e93f4bdd
Reference in New Issue
Block a user