diff --git a/build/scripts/tools/unittests_server.lua b/build/scripts/tools/unittests_server.lua index b3eab27c0..44efbff84 100644 --- a/build/scripts/tools/unittests_server.lua +++ b/build/scripts/tools/unittests_server.lua @@ -23,6 +23,7 @@ TOOL.Files = { TOOL.FilesExcluded = { "../tests/Engine/Audio/**", "../tests/Engine/Graphics/**", + "../tests/Engine/Utility/**", "../tests/SDK/NDK/Application.cpp", "../tests/SDK/NDK/Systems/ListenerSystem.cpp", "../tests/SDK/NDK/Systems/RenderSystem.cpp" diff --git a/tests/Engine/Utility/EventHandler.cpp b/tests/Engine/Utility/EventHandler.cpp new file mode 100644 index 000000000..dedf3fc31 --- /dev/null +++ b/tests/Engine/Utility/EventHandler.cpp @@ -0,0 +1,82 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "EventHandler/StateContext.hpp" +#include "EventHandler/StateFactory.hpp" + +#include + +Ndk::EntityHandle AddCamera(Ndk::World& world, Nz::RenderWindow& window); + +/*! + Known issues on Linux: + + - There is no real double click event in X11 + - Should always the key be repeated in key pressed mode ? + - No smooth wheel, only 1.f or -1.f + - Modify dimension of window updates position (which is not wrong) + - Text entered is never repeated +*/ + +SCENARIO("EventHandler", "[UTILITY][EVENTHANDLER][INTERACTIVE][.]") +{ + GIVEN("An application") + { + Ndk::Application& app = *Ndk::Application::Instance(); + auto& window = app.AddWindow(); + if (!window.Create(Nz::VideoMode(1024, 768, 32), "EventHandler")) + { + NazaraError("Failed to create window. See NazaraLog.log for further informations"); + REQUIRE(false); + } + window.EnableVerticalSync(true); + + auto& world = app.AddWorld(); + + auto camera = AddCamera(world, window); + + StateContext context(window, world); + + StateFactory::Initialize(context); + Ndk::StateMachine fsm(StateFactory::Get(EventStatus::Menu)); + + Nz::Clock elapsedTimeClock; + while (app.Run()) + { + window.Display(); + float elapsedTime = elapsedTimeClock.GetSeconds(); + elapsedTimeClock.Restart(); + + if (!fsm.Update(elapsedTime)) + { + NazaraError("Failed to update state machine."); + REQUIRE(false); + } + } + + StateFactory::Uninitialize(); + REQUIRE(true); + } +} + +Ndk::EntityHandle AddCamera(Ndk::World& world, Nz::RenderWindow& window) +{ + Ndk::EntityHandle view = world.CreateEntity(); + auto& node = view->AddComponent(); + node.SetPosition(Nz::Vector3f::Zero()); + auto& cam = view->AddComponent(); + cam.SetProjectionType(Nz::ProjectionType_Orthogonal); // 2D + cam.SetTarget(&window); + + world.GetSystem().SetGlobalUp(Nz::Vector3f::Down()); + world.GetSystem().SetDefaultBackground(Nz::ColorBackground::New(Nz::Color::Black)); + + return view; +} diff --git a/tests/Engine/Utility/EventHandler/EventState.cpp b/tests/Engine/Utility/EventHandler/EventState.cpp new file mode 100644 index 000000000..d9ba49906 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/EventState.cpp @@ -0,0 +1,106 @@ +#include "EventState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +EventState::EventState(StateContext& context) : +State(), +m_context(context), +m_text(context), +m_count(0) +{ +} + +void EventState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_eventSlot.Connect(eventHandler.OnEvent, [&] (const Nz::EventHandler*, const Nz::WindowEvent& event) + { + AddEvent(event); + ++m_count; + }); +} + +void EventState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool EventState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void EventState::AddEvent(const Nz::WindowEvent& event) +{ + if (m_events.size() > 9) + m_events.pop_front(); + + m_events.push_back(Nz::String::Number(m_count) + " - " + ToString(event)); + + Nz::String content; + for (auto&& event : m_events) + { + content += event + "\n"; + } + content += "\nM for Menu"; + m_text.SetContent(content, 36); +} + +void EventState::DrawMenu() +{ + m_text.SetContent("Do whathever you want, this text should change !\nM for Menu"); +} + +Nz::String EventState::ToString(const Nz::WindowEvent& event) const +{ + switch (event.type) + { + case Nz::WindowEventType_GainedFocus: + return "WindowEventType_GainedFocus"; + case Nz::WindowEventType_LostFocus: + return "WindowEventType_LostFocus"; + case Nz::WindowEventType_KeyPressed: + return "WindowEventType_KeyPressed"; + case Nz::WindowEventType_KeyReleased: + return "WindowEventType_KeyReleased"; + case Nz::WindowEventType_MouseButtonDoubleClicked: + return "WindowEventType_MouseButtonDoubleClicked"; + case Nz::WindowEventType_MouseButtonPressed: + return "WindowEventType_MouseButtonPressed"; + case Nz::WindowEventType_MouseButtonReleased: + return "WindowEventType_MouseButtonReleased"; + case Nz::WindowEventType_MouseEntered: + return "WindowEventType_MouseEntered"; + case Nz::WindowEventType_MouseLeft: + return "WindowEventType_MouseLeft"; + case Nz::WindowEventType_MouseMoved: + return "WindowEventType_MouseMoved"; + case Nz::WindowEventType_MouseWheelMoved: + return "WindowEventType_MouseWheelMoved"; + case Nz::WindowEventType_Moved: + return "WindowEventType_Moved"; + case Nz::WindowEventType_Quit: + return "WindowEventType_Quit"; + case Nz::WindowEventType_Resized: + return "WindowEventType_Resized"; + case Nz::WindowEventType_TextEntered: + return "WindowEventType_TextEntered"; + default: + return "Not handled"; + } +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/EventState.hpp b/tests/Engine/Utility/EventHandler/EventState.hpp new file mode 100644 index 000000000..7b1cc63d7 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/EventState.hpp @@ -0,0 +1,36 @@ +#ifndef __EVENTSTATE_HPP__ +#define __EVENTSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +#include + +class StateContext; + +class EventState : public Ndk::State +{ + public: + EventState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void AddEvent(const Nz::WindowEvent& event); + void DrawMenu(); + Nz::String ToString(const Nz::WindowEvent& event) const; + + StateContext& m_context; + Text m_text; + std::deque m_events; + int m_count; + NazaraSlot(Nz::EventHandler, OnEvent, m_eventSlot); + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); +}; + +#endif // __EVENTSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/FocusState.cpp b/tests/Engine/Utility/EventHandler/FocusState.cpp new file mode 100644 index 000000000..520bcbbef --- /dev/null +++ b/tests/Engine/Utility/EventHandler/FocusState.cpp @@ -0,0 +1,54 @@ +#include "FocusState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +FocusState::FocusState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void FocusState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_gainedFocusSlot.Connect(eventHandler.OnGainedFocus, [&] (const Nz::EventHandler*) + { + m_text.SetContent("GAINED\nM for Menu"); + }); + + m_lostFocusSlot.Connect(eventHandler.OnLostFocus, [&] (const Nz::EventHandler*) + { + m_text.SetContent("LOST\nM for Menu"); + }); +} + +void FocusState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool FocusState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void FocusState::DrawMenu() +{ + m_text.SetContent("Click outside the windows, this text should change !\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/FocusState.hpp b/tests/Engine/Utility/EventHandler/FocusState.hpp new file mode 100644 index 000000000..9287722ab --- /dev/null +++ b/tests/Engine/Utility/EventHandler/FocusState.hpp @@ -0,0 +1,31 @@ +#ifndef __FOCUSSTATE_HPP__ +#define __FOCUSSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class FocusState : public Ndk::State +{ + public: + FocusState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnGainedFocus, m_gainedFocusSlot); + NazaraSlot(Nz::EventHandler, OnLostFocus, m_lostFocusSlot); + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); +}; + +#endif // __FOCUSSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/KeyState.cpp b/tests/Engine/Utility/EventHandler/KeyState.cpp new file mode 100644 index 000000000..76f4e7657 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/KeyState.cpp @@ -0,0 +1,90 @@ +#include "KeyState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +KeyState::KeyState(StateContext& context) : +State(), +m_context(context), +m_text(context), +m_keyStatus(KeyStatus::Pressed) +{ +} + +void KeyState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + ManageInput(KeyStatus::Pressed, key, fsm); + }); + + m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + ManageInput(KeyStatus::Released, key, fsm); + }); +} + +void KeyState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool KeyState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void KeyState::DrawMenu() +{ + m_text.SetContent("Clic on a key, this text should change !\nN for alternating event\nM for Menu"); +} + +void KeyState::ManageInput(KeyStatus isKeyPressed, const Nz::WindowEvent::KeyEvent& key, Ndk::StateMachine& fsm) +{ + if (key.code == Nz::Keyboard::Key::M && key.shift) + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + else if (key.code == Nz::Keyboard::Key::N && key.shift) + { + if (m_keyStatus == KeyStatus::Pressed) + m_keyStatus = KeyStatus::Released; + else + m_keyStatus = KeyStatus::Pressed; + } + else + { + Nz::String content; + if (m_keyStatus == KeyStatus::Pressed) + content = "Pressed: "; + else + content = "Released: "; + + Nz::String keyName = Nz::Keyboard::GetKeyName(key.code); + if (keyName.IsEmpty()) + { + m_text.SetContent("Unknown\nM for Menu"); + } + else + { + content += keyName; + if (key.alt) + content += " alt"; + if (key.control) + content += " control"; + if (key.repeated) + content += " repeated"; + if (key.shift) + content += " shift"; + if (key.system) + content += " system"; + + m_text.SetContent(content + "\nM for Menu"); + } + } +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/KeyState.hpp b/tests/Engine/Utility/EventHandler/KeyState.hpp new file mode 100644 index 000000000..9b0fb1fcd --- /dev/null +++ b/tests/Engine/Utility/EventHandler/KeyState.hpp @@ -0,0 +1,38 @@ +#ifndef __KEYSTATE_HPP__ +#define __KEYSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +enum class KeyStatus +{ + Pressed, + Released +}; + +class KeyState : public Ndk::State +{ + public: + KeyState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + void ManageInput(KeyStatus isKeyPressed, const Nz::WindowEvent::KeyEvent& key, Ndk::StateMachine& fsm); + + StateContext& m_context; + Text m_text; + KeyStatus m_keyStatus; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnKeyReleased, m_keyReleasedSlot); +}; + +#endif // __KEYSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MenuState.cpp b/tests/Engine/Utility/EventHandler/MenuState.cpp new file mode 100644 index 000000000..7838275a9 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MenuState.cpp @@ -0,0 +1,50 @@ +#include "MenuState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +MenuState::MenuState(StateContext& context) : +State(), +m_context(context), +m_text(context), +m_selectedNextState(-1) +{ +} + +void MenuState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [this] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code >= Nz::Keyboard::Key::A && key.code < (Nz::Keyboard::Key::A + static_cast(EventStatus::Max) - 1)) + { + m_selectedNextState = key.code - static_cast(Nz::Keyboard::Key::A); + } + }); +} + +void MenuState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); + m_selectedNextState = -1; +} + +bool MenuState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + if (m_selectedNextState != -1) { + fsm.ChangeState(StateFactory::Get(m_selectedNextState + 1)); + } + + return true; +} + +void MenuState::DrawMenu() +{ + m_text.SetContent("a. Event\nb. Focus\nc. Key\nd. Mouse click\ne. Mouse enter\nf. Mouse move\ng. Text enter\nh. Window modification"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MenuState.hpp b/tests/Engine/Utility/EventHandler/MenuState.hpp new file mode 100644 index 000000000..356a12a72 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MenuState.hpp @@ -0,0 +1,30 @@ +#ifndef __MENUSTATE_HPP__ +#define __MENUSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class MenuState : public Ndk::State +{ + public: + MenuState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + int m_selectedNextState; +}; + +#endif // __MENUSTATE_HPP__ diff --git a/tests/Engine/Utility/EventHandler/MouseClickState.cpp b/tests/Engine/Utility/EventHandler/MouseClickState.cpp new file mode 100644 index 000000000..d373d68a2 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseClickState.cpp @@ -0,0 +1,94 @@ +#include "MouseClickState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +MouseClickState::MouseClickState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void MouseClickState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_mouseButtonDoubleClickedSlot.Connect(eventHandler.OnMouseButtonDoubleClicked, [&] (const Nz::EventHandler*, const Nz::WindowEvent::MouseButtonEvent& mouse) + { + ManageInput(MouseStatus::DoubleClick, mouse, fsm); + }); + + m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::MouseButtonEvent& mouse) + { + ManageInput(MouseStatus::Pressed, mouse, fsm); + }); + + m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, [&] (const Nz::EventHandler*, const Nz::WindowEvent::MouseButtonEvent& mouse) + { + ManageInput(MouseStatus::Released, mouse, fsm); + }); +} + +void MouseClickState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool MouseClickState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void MouseClickState::DrawMenu() +{ + m_text.SetContent("Click in the windows, this text should change !\nM for Menu"); +} + +void MouseClickState::ManageInput(MouseStatus mouseStatus, const Nz::WindowEvent::MouseButtonEvent& mouse, Ndk::StateMachine& fsm) +{ + Nz::String content; + if (mouseStatus == MouseStatus::Pressed) + content = "Pressed: "; + else if (mouseStatus == MouseStatus::Released) + content = "Released: "; + else + content = "Double clicked: "; + + switch (mouse.button) + { + case Nz::Mouse::Left: + content += "Left"; + break; + case Nz::Mouse::Middle: + content += "Middle"; + break; + case Nz::Mouse::Right: + content += "Right"; + break; + case Nz::Mouse::XButton1: + content += "XButton1"; + break; + case Nz::Mouse::XButton2: + content += "XButton2"; + break; + default: + content += "Unknown"; + break; + } + + m_text.SetContent(content + "\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MouseClickState.hpp b/tests/Engine/Utility/EventHandler/MouseClickState.hpp new file mode 100644 index 000000000..28c4203a9 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseClickState.hpp @@ -0,0 +1,40 @@ +#ifndef __MOUSECLICKSTATE_HPP__ +#define __MOUSECLICKSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +enum class MouseStatus +{ + DoubleClick, + Pressed, + Released +}; + +class MouseClickState : public Ndk::State +{ + public: + MouseClickState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + void ManageInput(MouseStatus mouseStatus, const Nz::WindowEvent::MouseButtonEvent& mouse, Ndk::StateMachine& fsm); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnMouseButtonDoubleClicked, m_mouseButtonDoubleClickedSlot); + NazaraSlot(Nz::EventHandler, OnMouseButtonPressed, m_mouseButtonPressedSlot); + NazaraSlot(Nz::EventHandler, OnMouseButtonReleased, m_mouseButtonReleasedSlot); +}; + +#endif // __MOUSECLICKSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MouseEnterState.cpp b/tests/Engine/Utility/EventHandler/MouseEnterState.cpp new file mode 100644 index 000000000..9e770806f --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseEnterState.cpp @@ -0,0 +1,54 @@ +#include "MouseEnterState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +MouseEnterState::MouseEnterState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void MouseEnterState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_mouseEnteredSlot.Connect(eventHandler.OnMouseEntered, [&] (const Nz::EventHandler*) + { + m_text.SetContent("Entered\nM for Menu"); + }); + + m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, [&] (const Nz::EventHandler*) + { + m_text.SetContent("Left\nM for Menu"); + }); +} + +void MouseEnterState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool MouseEnterState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void MouseEnterState::DrawMenu() +{ + m_text.SetContent("Move your mouse outside the windows, this text should change !\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MouseEnterState.hpp b/tests/Engine/Utility/EventHandler/MouseEnterState.hpp new file mode 100644 index 000000000..b5c7a72be --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseEnterState.hpp @@ -0,0 +1,31 @@ +#ifndef __MOUSEENTERSTATE_HPP__ +#define __MOUSEENTERSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class MouseEnterState : public Ndk::State +{ + public: + MouseEnterState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnMouseEntered, m_mouseEnteredSlot); + NazaraSlot(Nz::EventHandler, OnMouseLeft, m_mouseLeftSlot); +}; + +#endif // __MOUSEENTERSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MouseMoveState.cpp b/tests/Engine/Utility/EventHandler/MouseMoveState.cpp new file mode 100644 index 000000000..a01ab163e --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseMoveState.cpp @@ -0,0 +1,54 @@ +#include "MouseMoveState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +MouseMoveState::MouseMoveState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void MouseMoveState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, [&] (const Nz::EventHandler*, const Nz::WindowEvent::MouseMoveEvent& event) + { + m_text.SetContent("Position(" + Nz::String::Number(event.x) + ", " + Nz::String::Number(event.y) + ") delta: (" + Nz::String::Number(event.deltaX) + ", " + Nz::String::Number(event.deltaY) + ") \nM for Menu"); + }); + + m_mouseWheelMovedSlot.Connect(eventHandler.OnMouseWheelMoved, [&] (const Nz::EventHandler*, const Nz::WindowEvent::MouseWheelEvent& event) + { + m_text.SetContent("Wheel delta: " + Nz::String::Number(event.delta) + "\nM for Menu"); + }); +} + +void MouseMoveState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool MouseMoveState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void MouseMoveState::DrawMenu() +{ + m_text.SetContent("Move your mouse or your wheel, this text should change !\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/MouseMoveState.hpp b/tests/Engine/Utility/EventHandler/MouseMoveState.hpp new file mode 100644 index 000000000..f94dc0998 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/MouseMoveState.hpp @@ -0,0 +1,31 @@ +#ifndef __MOUSEMOVESTATE_HPP__ +#define __MOUSEMOVESTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class MouseMoveState : public Ndk::State +{ + public: + MouseMoveState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnMouseMoved, m_mouseMovedSlot); + NazaraSlot(Nz::EventHandler, OnMouseWheelMoved, m_mouseWheelMovedSlot); +}; + +#endif // __MOUSEMOVESTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/StateContext.cpp b/tests/Engine/Utility/EventHandler/StateContext.cpp new file mode 100644 index 000000000..69739a616 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/StateContext.cpp @@ -0,0 +1,7 @@ +#include "StateContext.hpp" + +StateContext::StateContext(Nz::RenderWindow& windowContext, Ndk::World& worldContext) : +window(windowContext), +world(worldContext) +{ +} diff --git a/tests/Engine/Utility/EventHandler/StateContext.hpp b/tests/Engine/Utility/EventHandler/StateContext.hpp new file mode 100644 index 000000000..62614e073 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/StateContext.hpp @@ -0,0 +1,23 @@ +#ifndef __STATECONTEXT_HPP__ +#define __STATECONTEXT_HPP__ + +namespace Ndk +{ + class World; +} + +namespace Nz +{ + class RenderWindow; +} + +class StateContext +{ + public: + StateContext(Nz::RenderWindow& window, Ndk::World& world); + + Nz::RenderWindow& window; + Ndk::World& world; +}; + +#endif // __STATECONTEXT_HPP__ diff --git a/tests/Engine/Utility/EventHandler/StateFactory.cpp b/tests/Engine/Utility/EventHandler/StateFactory.cpp new file mode 100644 index 000000000..8086dea6b --- /dev/null +++ b/tests/Engine/Utility/EventHandler/StateFactory.cpp @@ -0,0 +1,46 @@ +#include "StateFactory.hpp" + +#include "MenuState.hpp" +#include "EventState.hpp" +#include "FocusState.hpp" +#include "KeyState.hpp" +#include "MouseClickState.hpp" +#include "MouseEnterState.hpp" +#include "MouseMoveState.hpp" +#include "TextEnterState.hpp" +#include "WindowModificationState.hpp" + +std::shared_ptr StateFactory::Get(EventStatus state) +{ + return s_states[state]; +} + +std::shared_ptr StateFactory::Get(unsigned int state) +{ + NazaraAssert(state < s_states.size(), "State out of range"); + auto it = s_states.begin(); + std::advance(it, state); + return it->second; +} + +bool StateFactory::Initialize(StateContext& context) +{ + s_states.emplace(std::make_pair(EventStatus::Menu, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::Event, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::Focus, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::Key, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::MouseClick, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::MouseEnter, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::MouseMove, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::TextEnter, std::make_shared(context))); + s_states.emplace(std::make_pair(EventStatus::WindowModification, std::make_shared(context))); + + return true; +} + +void StateFactory::Uninitialize() +{ + s_states.clear(); +} + +std::map> StateFactory::s_states; \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/StateFactory.hpp b/tests/Engine/Utility/EventHandler/StateFactory.hpp new file mode 100644 index 000000000..a17965d9d --- /dev/null +++ b/tests/Engine/Utility/EventHandler/StateFactory.hpp @@ -0,0 +1,42 @@ +#ifndef __STATEFACTORY_HPP__ +#define __STATEFACTORY_HPP__ + +#include + +#include +#include + +class StateContext; + +enum class EventStatus +{ + Min = 0, + Menu, + Event, + Focus, + Key, + MouseClick, + MouseEnter, + MouseMove, + TextEnter, + WindowModification, + Max = WindowModification +}; + +class StateFactory +{ + public: + + static std::shared_ptr Get(EventStatus state); + static std::shared_ptr Get(unsigned int state); + + static bool Initialize(StateContext& stateContext); + + static void Uninitialize(); + + private: + + static std::map> s_states; +}; + +#endif // __STATEFACTORY_HPP__ diff --git a/tests/Engine/Utility/EventHandler/Text.cpp b/tests/Engine/Utility/EventHandler/Text.cpp new file mode 100644 index 000000000..75cece5b9 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/Text.cpp @@ -0,0 +1,35 @@ +#include "Text.hpp" + +#include +#include +#include +#include +#include +#include + +Text::Text(StateContext& stateContext) : +m_context(stateContext) +{ + m_text = m_context.world.CreateEntity(); + Ndk::NodeComponent& nodeComponent = m_text->AddComponent(); + Ndk::GraphicsComponent& graphicsComponent = m_text->AddComponent(); + + m_textSprite = Nz::TextSprite::New(); + graphicsComponent.Attach(m_textSprite); +} + +Text::~Text() +{ + m_textSprite->Clear(); + m_text->Kill(); +} + +void Text::SetContent(const Nz::String& string, unsigned int size) +{ + m_textSprite->Update(Nz::SimpleTextDrawer::Draw(string, size)); +} + +void Text::SetVisible(bool shouldBeVisible) +{ + m_text->Enable(shouldBeVisible); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/Text.hpp b/tests/Engine/Utility/EventHandler/Text.hpp new file mode 100644 index 000000000..9026c8c41 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/Text.hpp @@ -0,0 +1,23 @@ +#ifndef __TEXT_HPP__ +#define __TEXT_HPP__ + +#include +#include +#include "StateContext.hpp" + +class Text +{ + public: + Text(StateContext& context); + ~Text(); + + void SetContent(const Nz::String& string, unsigned int size = 72); + void SetVisible(bool shouldBeVisible = true); + + private: + StateContext& m_context; + Ndk::EntityHandle m_text; + Nz::TextSpriteRef m_textSprite; +}; + +#endif // __TEXT_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/TextEnterState.cpp b/tests/Engine/Utility/EventHandler/TextEnterState.cpp new file mode 100644 index 000000000..8f3ae154c --- /dev/null +++ b/tests/Engine/Utility/EventHandler/TextEnterState.cpp @@ -0,0 +1,52 @@ +#include "TextEnterState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +TextEnterState::TextEnterState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void TextEnterState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_textEnteredSlot.Connect(eventHandler.OnTextEntered, [&] (const Nz::EventHandler*, const Nz::WindowEvent::TextEvent& event) + { + Nz::String content = "Character: " + Nz::String::Unicode(event.character); + if (event.repeated) + content += " repeated"; + m_text.SetContent(content + "\nM for Menu"); + }); +} + +void TextEnterState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool TextEnterState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void TextEnterState::DrawMenu() +{ + m_text.SetContent("Enter some text, this text should change !\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/TextEnterState.hpp b/tests/Engine/Utility/EventHandler/TextEnterState.hpp new file mode 100644 index 000000000..c9137c51d --- /dev/null +++ b/tests/Engine/Utility/EventHandler/TextEnterState.hpp @@ -0,0 +1,30 @@ +#ifndef __TEXTENTERSTATE_HPP__ +#define __TEXTENTERSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class TextEnterState : public Ndk::State +{ + public: + TextEnterState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnTextEntered, m_textEnteredSlot); +}; + +#endif // __TEXTENTERSTATE_HPP__ \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/WindowModificationState.cpp b/tests/Engine/Utility/EventHandler/WindowModificationState.cpp new file mode 100644 index 000000000..3f0bf7fc1 --- /dev/null +++ b/tests/Engine/Utility/EventHandler/WindowModificationState.cpp @@ -0,0 +1,54 @@ +#include "WindowModificationState.hpp" + +#include "StateContext.hpp" +#include "StateFactory.hpp" + +#include +#include + +WindowModificationState::WindowModificationState(StateContext& context) : +State(), +m_context(context), +m_text(context) +{ +} + +void WindowModificationState::Enter(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(true); + DrawMenu(); + + Nz::EventHandler& eventHandler = m_context.window.GetEventHandler(); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& key) + { + if (key.code == Nz::Keyboard::Key::M && key.shift) + { + fsm.ChangeState(StateFactory::Get(EventStatus::Menu)); + } + }); + + m_movedSlot.Connect(eventHandler.OnMoved, [&] (const Nz::EventHandler*, const Nz::WindowEvent::PositionEvent& event) + { + m_text.SetContent("Position(" + Nz::String::Number(event.x) + ", " + Nz::String::Number(event.y) + ")\nM for Menu"); + }); + + m_resizedSlot.Connect(eventHandler.OnResized, [&] (const Nz::EventHandler*, const Nz::WindowEvent::SizeEvent& event) + { + m_text.SetContent("Size(" + Nz::String::Number(event.width) + ", " + Nz::String::Number(event.height) + ")\nM for Menu"); + }); +} + +void WindowModificationState::Leave(Ndk::StateMachine& fsm) +{ + m_text.SetVisible(false); +} + +bool WindowModificationState::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + return true; +} + +void WindowModificationState::DrawMenu() +{ + m_text.SetContent("Move the window or resize it, this text should change !\nM for Menu"); +} \ No newline at end of file diff --git a/tests/Engine/Utility/EventHandler/WindowModificationState.hpp b/tests/Engine/Utility/EventHandler/WindowModificationState.hpp new file mode 100644 index 000000000..4fb84188d --- /dev/null +++ b/tests/Engine/Utility/EventHandler/WindowModificationState.hpp @@ -0,0 +1,31 @@ +#ifndef __WINDOWMODIFICATIONSTATE_HPP__ +#define __WINDOWMODIFICATIONSTATE_HPP__ + +#include "Text.hpp" + +#include + +#include + +class StateContext; + +class WindowModificationState : public Ndk::State +{ + public: + WindowModificationState(StateContext& stateContext); + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void DrawMenu(); + + StateContext& m_context; + Text m_text; + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnMoved, m_movedSlot); + NazaraSlot(Nz::EventHandler, OnResized, m_resizedSlot); +}; + +#endif // __WINDOWMODIFICATIONSTATE_HPP__ \ No newline at end of file