add (very) basic main menu

This commit is contained in:
2025-08-11 19:47:55 +02:00
parent 24252896c7
commit b5ff44d793
14 changed files with 246 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <memory>
#include <cassert> #include <cassert>
#include <memory>
namespace td { namespace td {
@@ -15,6 +15,11 @@ class StateMachine {
virtual TReturn Update(TArgs... args) = 0; virtual TReturn Update(TArgs... args) = 0;
template <typename T, typename... Args>
T* ChangeState(Args&&... args) {
return m_StateMachine.template ChangeState<T>(std::forward<Args>(args)...);
}
protected: protected:
TDerived& m_StateMachine; TDerived& m_StateMachine;
}; };

View File

@@ -0,0 +1,69 @@
#pragma once
#include <cassert>
#include <vector>
#include <memory>
namespace td {
template <typename TDerived, typename TReturn, typename... TArgs>
class StateStack {
public:
class State {
public:
State(TDerived& a_StateStack) : m_StateStack(a_StateStack) {}
virtual ~State() {}
virtual TReturn Update(TArgs... args) = 0;
protected:
/**
* \brief Called when enabled (can be used to connect signals)
*/
virtual void OnEnable() {}
/**
* \brief Called when disabled (can be used to disconnect signals)
*/
virtual void OnDisable() {}
protected:
TDerived& m_StateStack;
friend class StateStack;
};
StateStack() {}
StateStack(StateStack&&) = default;
virtual ~StateStack() {}
virtual TReturn Update(TArgs... args) {
assert(!m_States.empty() && "You must push at least one state before updating !");
return m_States.back()->Update(args...);
}
void PopState() {
assert(!m_States.empty() && "You must push at least one state before poping !");
m_States.back()->OnDisable();
m_States.pop_back();
if (m_States.empty())
return;
m_States.back()->OnEnable();
}
template <typename T, typename... Args>
T* PushState(Args&&... args) {
if (!m_States.empty())
m_States.back()->OnDisable();
auto newState = std::make_unique<T>(static_cast<TDerived&>(*this), std::forward<Args>(args)...);
newState->OnEnable();
m_States.push_back(std::move(newState));
return static_cast<T*>(newState.get());
}
private:
std::vector<std::unique_ptr<State>> m_States;
};
} // namespace td

View File

@@ -0,0 +1,15 @@
#pragma once
#include <td/display/state/MainMenuState.h>
namespace td {
class CreatePartyMenu : public MainMenuState::Menu {
public:
CreatePartyMenu(MainMenuState& a_MainMenu);
~CreatePartyMenu();
virtual void Update() override;
};
} // namespace td

View File

@@ -0,0 +1,15 @@
#pragma once
#include <td/display/state/MainMenuState.h>
namespace td {
class JoinPartyMenu : public MainMenuState::Menu {
public:
JoinPartyMenu(MainMenuState& a_MainMenu);
~JoinPartyMenu();
virtual void Update() override;
};
} // namespace td

View File

@@ -0,0 +1,15 @@
#pragma once
#include <td/display/state/MainMenuState.h>
namespace td {
class MainMenu : public MainMenuState::Menu {
public:
MainMenu(MainMenuState& a_MainMenu);
~MainMenu();
virtual void Update() override;
};
} // namespace td

View File

@@ -0,0 +1,15 @@
#pragma once
#include <td/display/state/MainMenuState.h>
namespace td {
class SettingsMenu : public MainMenuState::Menu {
public:
SettingsMenu(MainMenuState& a_MainMenu);
~SettingsMenu();
virtual void Update() override;
};
} // namespace td

View File

@@ -1,15 +1,27 @@
#pragma once #pragma once
#include <td/common/StateStack.h>
#include <td/display/DisplayState.h> #include <td/display/DisplayState.h>
namespace td { namespace td {
class MainMenuState : public DisplayState { class MainMenuState;
using MainMenuStateStack = StateStack<MainMenuState, void>;
class MainMenuState : public DisplayState, public MainMenuStateStack {
public: public:
using Menu = MainMenuStateStack::State;
MainMenuState(Display& a_Display); MainMenuState(Display& a_Display);
~MainMenuState(); ~MainMenuState();
virtual void Update(float a_Delta) override; virtual void Update(float a_Delta) override;
void RenderBackButton();
protected:
virtual void OnKeyDown(SDL_Keycode a_Key) override;
}; };
} // namespace td } // namespace td

View File

@@ -80,8 +80,7 @@ Display::Display(int a_Width, int a_Height, const std::string& a_Title) :
utils::LOG(utils::Format( utils::LOG(utils::Format(
"GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth)); "GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
utils::LOG(utils::Format( utils::LOG(utils::Format("MultiSamples : Buffers : %i, Samples : %i", mBuffers, mSamples));
"MultiSamples : Buffers : %i, Samples : %i", mBuffers, mSamples));
SDL_GL_MakeCurrent(m_Window, m_GLContext); SDL_GL_MakeCurrent(m_Window, m_GLContext);
@@ -148,7 +147,7 @@ void Display::PollEvents() {
} }
case SDL_EVENT_KEY_DOWN: { case SDL_EVENT_KEY_DOWN: {
if(!event.key.repeat) if (!event.key.repeat)
OnKeyDown(event.key.key); OnKeyDown(event.key.key);
break; break;
} }
@@ -166,6 +165,9 @@ void Display::PollEvents() {
void Display::Update(float a_Delta) { void Display::Update(float a_Delta) {
StateMachine::Update(a_Delta); StateMachine::Update(a_Delta);
#ifndef NDEBUG
ImGui::ShowDemoWindow();
#endif
ImGui::Render(); ImGui::Render();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);

View File

@@ -0,0 +1,16 @@
#include <td/display/menu/CreatePartyMenu.h>
#include <imgui.h>
namespace td {
CreatePartyMenu::CreatePartyMenu(MainMenuState& a_MainMenu) : MainMenuState::Menu(a_MainMenu) {}
CreatePartyMenu::~CreatePartyMenu() {}
void CreatePartyMenu::Update() {
ImGui::Text("CreatePartyMenu");
m_StateStack.RenderBackButton();
}
} // namespace td

View File

@@ -0,0 +1,16 @@
#include <td/display/menu/JoinPartyMenu.h>
#include <imgui.h>
namespace td {
JoinPartyMenu::JoinPartyMenu(MainMenuState& a_MainMenu) : MainMenuState::Menu(a_MainMenu) {}
JoinPartyMenu::~JoinPartyMenu() {}
void JoinPartyMenu::Update() {
ImGui::Text("JoinPartyMenu");
m_StateStack.RenderBackButton();
}
} // namespace td

View File

@@ -0,0 +1,28 @@
#include <td/display/menu/MainMenu.h>
#include <imgui.h>
#include <td/display/menu/CreatePartyMenu.h>
#include <td/display/menu/JoinPartyMenu.h>
#include <td/display/menu/SettingsMenu.h>
#include <td/display/state/DebugWorldState.h>
namespace td {
MainMenu::MainMenu(MainMenuState& a_MainMenu) : MainMenuState::Menu(a_MainMenu) {}
MainMenu::~MainMenu() {}
void MainMenu::Update() {
if (ImGui::Button("Create Party"))
m_StateStack.PushState<CreatePartyMenu>();
if (ImGui::Button("Join Party"))
m_StateStack.PushState<JoinPartyMenu>();
if (ImGui::Button("Settings"))
m_StateStack.PushState<SettingsMenu>();
#ifndef NDEBUG
if (ImGui::Button("Debug world"))
m_StateStack.ChangeState<DebugWorldState>();
#endif
}
} // namespace td

View File

@@ -0,0 +1,16 @@
#include <td/display/menu/SettingsMenu.h>
#include <imgui.h>
namespace td {
SettingsMenu::SettingsMenu(MainMenuState& a_MainMenu) : MainMenuState::Menu(a_MainMenu) {}
SettingsMenu::~SettingsMenu() {}
void SettingsMenu::Update() {
ImGui::Text("SettingsMenu");
m_StateStack.RenderBackButton();
}
} // namespace td

View File

@@ -1,18 +1,31 @@
#include <td/display/state/MainMenuState.h> #include <td/display/state/MainMenuState.h>
#include <td/display/state/DebugWorldState.h>
#include <imgui.h> #include <imgui.h>
#include <td/display/menu/MainMenu.h>
#include <td/display/state/DebugWorldState.h>
namespace td { namespace td {
MainMenuState::MainMenuState(Display& a_Display) : DisplayState(a_Display) {} MainMenuState::MainMenuState(Display& a_Display) : DisplayState(a_Display) {
PushState<MainMenu>();
}
MainMenuState::~MainMenuState() {} MainMenuState::~MainMenuState() {}
void MainMenuState::Update(float a_Delta) { void MainMenuState::Update(float a_Delta) {
ImGui::Begin("MainWindow"); ImGui::Begin("MainWindow");
if(ImGui::Button("Start debug world")) MainMenuStateStack::Update();
m_StateMachine.ChangeState<DebugWorldState>();
ImGui::End(); ImGui::End();
} }
void MainMenuState::RenderBackButton() {
if (ImGui::Button("Back"))
PopState();
}
void MainMenuState::OnKeyDown(SDL_Keycode a_Key) {
if (a_Key == SDLK_ESCAPE)
PopState();
}
} // namespace td } // namespace td

View File

@@ -16,7 +16,6 @@ WorldRenderer::~WorldRenderer() {}
void WorldRenderer::Render(float a_Lerp) { void WorldRenderer::Render(float a_Lerp) {
m_Shader->Start(); m_Shader->Start();
Renderer::Render(*m_WorldVao); Renderer::Render(*m_WorldVao);
ImGui::ShowDemoWindow();
} }
} // namespace render } // namespace render