diff --git a/SDK/include/NDK/Application.hpp b/SDK/include/NDK/Application.hpp index 9b6eedae1..644dcc971 100644 --- a/SDK/include/NDK/Application.hpp +++ b/SDK/include/NDK/Application.hpp @@ -8,6 +8,10 @@ #define NDK_APPLICATION_HPP #include +#include +#include +#include +#include namespace Ndk { @@ -15,7 +19,35 @@ namespace Ndk { public: inline Application(); + Application(const Application&) = delete; inline ~Application(); + + #ifndef NDK_SERVER + template T& AddWindow(Args&&... args); + #endif + template World& AddWorld(Args&&... args); + + bool Run(); + + inline void Quit(); + + Application& operator=(const Application&) = delete; + + inline static Application* Instance(); + + private: + #ifndef NDK_SERVER + std::vector> m_windows; + #endif + std::vector m_worlds; + Nz::Clock m_updateClock; + #ifndef NDK_SERVER + bool m_exitOnClosedWindows; + #endif + bool m_shouldQuit; + float m_updateTime; + + static Application* s_application; }; } diff --git a/SDK/include/NDK/Application.inl b/SDK/include/NDK/Application.inl index dafbd54d8..ca1fa1ffb 100644 --- a/SDK/include/NDK/Application.inl +++ b/SDK/include/NDK/Application.inl @@ -3,12 +3,21 @@ // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include +#include #include namespace Ndk { - inline Application::Application() + inline Application::Application() : + #ifndef NDK_SERVER + m_exitOnClosedWindows(true), + #endif + m_shouldQuit(false), + m_updateTime(0.f) { + NazaraAssert(s_application == nullptr, "You can create only one application instance per program"); + s_application = this; + Nz::ErrorFlags errFlags(Nz::ErrorFlag_ThrowException, true); // Initialisation du SDK @@ -17,9 +26,41 @@ namespace Ndk inline Application::~Application() { + m_worlds.clear(); + #ifndef NDK_SERVER + m_windows.clear(); + #endif + // Libération du SDK Sdk::Uninitialize(); // Libération automatique des modules + s_application = nullptr; + } + + template + T& Application::AddWindow(Args&&... args) + { + static_assert(std::is_base_of::value, "Type must inherit Window"); + + m_windows.emplace_back(new T(std::forward(args)...)); + return static_cast(*m_windows.back().get()); + } + + template + World& Application::AddWorld(Args&&... args) + { + m_worlds.emplace_back(std::forward(args)...); + return m_worlds.back(); + } + + inline void Application::Quit() + { + m_shouldQuit = true; + } + + inline Application* Application::Instance() + { + return s_application; } } diff --git a/SDK/include/NDK/State.hpp b/SDK/include/NDK/State.hpp new file mode 100644 index 000000000..0a113def3 --- /dev/null +++ b/SDK/include/NDK/State.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_STATE_HPP +#define NDK_STATE_HPP + +#include + +namespace Ndk +{ + class StateMachine; + + class State + { + public: + State(); + ~State(); + + virtual void Enter(StateMachine& fsm) = 0; + virtual void Leave(StateMachine& fsm) = 0; + virtual bool Update(StateMachine& fsm, float elapsedTime) = 0; + }; +} + +#endif // NDK_STATE_HPP \ No newline at end of file diff --git a/SDK/include/NDK/StateMachine.hpp b/SDK/include/NDK/StateMachine.hpp new file mode 100644 index 000000000..8e7ad2f64 --- /dev/null +++ b/SDK/include/NDK/StateMachine.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_STATEMACHINE_HPP +#define NDK_STATEMACHINE_HPP + +#include +#include +#include + +namespace Ndk +{ + class StateMachine + { + public: + inline StateMachine(std::shared_ptr originalState); + StateMachine(const StateMachine&) = delete; + inline StateMachine(StateMachine&& fsm) = default; + inline ~StateMachine(); + + inline void ChangeState(std::shared_ptr state); + + inline bool Update(float elapsedTime); + + inline StateMachine& operator=(StateMachine&& fsm) = default; + StateMachine& operator=(const StateMachine&) = delete; + + private: + std::shared_ptr m_currentState; + std::shared_ptr m_nextState; + }; +} + +#include + +#endif // NDK_STATEMACHINE_HPP \ No newline at end of file diff --git a/SDK/include/NDK/StateMachine.inl b/SDK/include/NDK/StateMachine.inl new file mode 100644 index 000000000..fc4c7f787 --- /dev/null +++ b/SDK/include/NDK/StateMachine.inl @@ -0,0 +1,40 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include + +namespace Ndk +{ + inline StateMachine::StateMachine(std::shared_ptr originalState) : + m_currentState(std::move(originalState)) + { + NazaraAssert(m_currentState, "StateMachine must have a state to begin with"); + m_currentState->Enter(*this); + } + + inline StateMachine::~StateMachine() + { + m_currentState->Leave(*this); + } + + + inline void StateMachine::ChangeState(std::shared_ptr state) + { + m_nextState = std::move(state); + } + + inline bool StateMachine::Update(float elapsedTime) + { + if (m_nextState) + { + m_currentState->Leave(*this); + m_currentState = std::move(m_nextState); + m_currentState->Enter(*this); + } + + return m_currentState->Update(*this, elapsedTime); + } +} diff --git a/SDK/src/NDK/Application.cpp b/SDK/src/NDK/Application.cpp index a2141b0f8..e15ba2f92 100644 --- a/SDK/src/NDK/Application.cpp +++ b/SDK/src/NDK/Application.cpp @@ -3,3 +3,47 @@ // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include + +namespace Ndk +{ + bool Application::Run() + { + #ifndef NDK_SERVER + bool hasAtLeastOneActiveWindow = false; + + auto it = m_windows.begin(); + while (it != m_windows.end()) + { + Nz::Window& window = **it; + + if (!window.IsOpen(true)) + { + it = m_windows.erase(it); + continue; + } + + hasAtLeastOneActiveWindow = true; + + ++it; + } + #endif + + float elapsedTime = m_updateClock.GetSeconds(); + m_updateClock.Restart(); + + for (World& world : m_worlds) + world.Update(elapsedTime); + + if (m_shouldQuit) + return false; + + #ifndef NDK_SERVER + if (m_exitOnClosedWindows && !hasAtLeastOneActiveWindow) + return false; + #endif + + return true; + } + + Application* Application::s_application = nullptr; +} \ No newline at end of file