Sdk/Application: Add Console and FPSCounter overlays
This allows any Nazara-powered application to enable a ready-to-use console or a working FPS counter Former-commit-id: 274b276313b530ff8c99f3e0fb43c8b78689d787 [formerly 36e3a7e9d0d050af4b217311bde4496597e37c37] [formerly 69146c2fc6887f86b9c39d0265a95a4ba003f41e [formerly 72a66d7a31ceb87197b800813c90d43f73fc26b4]] Former-commit-id: 3fda987313648101b8a423e5e3aa8b0cd67a1c72 [formerly 5f9d42cdc5ed5443846531bad26059f66670df63] Former-commit-id: 2ef1496fb4a379e14f9c11c788da306eff465719
This commit is contained in:
parent
449bcfc462
commit
6872616ca4
|
|
@ -8,18 +8,34 @@
|
||||||
#define NDK_APPLICATION_HPP
|
#define NDK_APPLICATION_HPP
|
||||||
|
|
||||||
#include <NDK/Prerequesites.hpp>
|
#include <NDK/Prerequesites.hpp>
|
||||||
|
#include <NDK/EntityOwner.hpp>
|
||||||
#include <NDK/World.hpp>
|
#include <NDK/World.hpp>
|
||||||
#include <Nazara/Core/Clock.hpp>
|
#include <Nazara/Core/Clock.hpp>
|
||||||
#include <Nazara/Utility/Window.hpp>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
#include <NDK/Console.hpp>
|
||||||
|
#include <Nazara/Core/Log.hpp>
|
||||||
|
#include <Nazara/Lua/LuaInstance.hpp>
|
||||||
|
#include <Nazara/Graphics/TextSprite.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
|
#include <Nazara/Utility/Window.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
class NDK_API Application
|
class NDK_API Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
struct ConsoleOverlay;
|
||||||
|
struct FPSCounterOverlay;
|
||||||
|
#endif
|
||||||
|
|
||||||
inline Application();
|
inline Application();
|
||||||
|
inline Application(int argc, const char* argv[]);
|
||||||
Application(const Application&) = delete;
|
Application(const Application&) = delete;
|
||||||
Application(Application&&) = delete;
|
Application(Application&&) = delete;
|
||||||
inline ~Application();
|
inline ~Application();
|
||||||
|
|
@ -29,8 +45,21 @@ namespace Ndk
|
||||||
#endif
|
#endif
|
||||||
template<typename... Args> World& AddWorld(Args&&... args);
|
template<typename... Args> World& AddWorld(Args&&... args);
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
inline void EnableConsole(bool enable);
|
||||||
|
inline void EnableFPSCounter(bool enable);
|
||||||
|
|
||||||
|
inline ConsoleOverlay& GetConsoleOverlay(std::size_t windowIndex = 0U);
|
||||||
|
inline FPSCounterOverlay& GetFPSCounterOverlay(std::size_t windowIndex = 0U);
|
||||||
|
#endif
|
||||||
|
|
||||||
inline float GetUpdateTime() const;
|
inline float GetUpdateTime() const;
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
inline bool IsConsoleEnabled() const;
|
||||||
|
inline bool IsFPSCounterEnabled() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Run();
|
bool Run();
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
|
@ -44,13 +73,56 @@ namespace Ndk
|
||||||
|
|
||||||
inline static Application* Instance();
|
inline static Application* Instance();
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
struct ConsoleOverlay
|
||||||
|
{
|
||||||
|
std::unique_ptr<Console> console;
|
||||||
|
Nz::LuaInstance lua;
|
||||||
|
|
||||||
|
NazaraSlot(Nz::EventHandler, OnEvent, eventSlot);
|
||||||
|
NazaraSlot(Nz::EventHandler, OnKeyPressed, keyPressedSlot);
|
||||||
|
NazaraSlot(Nz::EventHandler, OnResized, resizedSlot);
|
||||||
|
NazaraSlot(Nz::Log, OnLogWrite, logSlot);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPSCounterOverlay
|
||||||
|
{
|
||||||
|
Nz::TextSpriteRef sprite;
|
||||||
|
EntityOwner entity;
|
||||||
|
float elapsedTime = 0.f;
|
||||||
|
unsigned int frameCount = 0;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
std::vector<std::unique_ptr<Nz::Window>> m_windows;
|
enum OverlayFlags
|
||||||
|
{
|
||||||
|
OverlayFlags_Console = 0x1,
|
||||||
|
OverlayFlags_FPSCounter = 0x2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WindowInfo
|
||||||
|
{
|
||||||
|
inline WindowInfo(std::unique_ptr<Nz::Window>&& window);
|
||||||
|
|
||||||
|
Nz::RenderTarget* renderTarget;
|
||||||
|
std::unique_ptr<Nz::Window> window;
|
||||||
|
std::unique_ptr<ConsoleOverlay> console;
|
||||||
|
std::unique_ptr<FPSCounterOverlay> fpsCounter;
|
||||||
|
std::unique_ptr<World> overlayWorld;
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetupConsole(WindowInfo& info);
|
||||||
|
void SetupFPSCounter(WindowInfo& info);
|
||||||
|
void SetupOverlay(WindowInfo& info);
|
||||||
|
|
||||||
|
std::vector<WindowInfo> m_windows;
|
||||||
#endif
|
#endif
|
||||||
std::list<World> m_worlds;
|
std::list<World> m_worlds;
|
||||||
Nz::Clock m_updateClock;
|
Nz::Clock m_updateClock;
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
Nz::UInt32 m_overlayFlags;
|
||||||
bool m_exitOnClosedWindows;
|
bool m_exitOnClosedWindows;
|
||||||
#endif
|
#endif
|
||||||
bool m_shouldQuit;
|
bool m_shouldQuit;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Application.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <NDK/Sdk.hpp>
|
#include <NDK/Sdk.hpp>
|
||||||
|
|
@ -9,13 +10,15 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs an Application object by default
|
* \brief Constructs an Application object without passing command-line arguments
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if there's more than one application instance currently running
|
* This calls Sdk::Initialize()
|
||||||
|
*
|
||||||
|
* \remark Only one Application instance can exist at a time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline Application::Application() :
|
inline Application::Application() :
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
m_overlayFlags(0U),
|
||||||
m_exitOnClosedWindows(true),
|
m_exitOnClosedWindows(true),
|
||||||
#endif
|
#endif
|
||||||
m_shouldQuit(false),
|
m_shouldQuit(false),
|
||||||
|
|
@ -31,9 +34,26 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Destructs the object
|
* \brief Constructs an Application object with command-line arguments
|
||||||
|
*
|
||||||
|
* Pass the argc and argv arguments from the main function.
|
||||||
|
*
|
||||||
|
* Command-line arguments can be retrieved by application methods
|
||||||
|
*
|
||||||
|
* This calls Sdk::Initialize()
|
||||||
|
*
|
||||||
|
* \remark Only one Application instance can exist at a time
|
||||||
*/
|
*/
|
||||||
|
inline Application::Application(int argc, const char* argv[]) :
|
||||||
|
Application()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Destructs the application object
|
||||||
|
*
|
||||||
|
* This destroy all worlds and windows and then calls Sdk::Uninitialize
|
||||||
|
*/
|
||||||
inline Application::~Application()
|
inline Application::~Application()
|
||||||
{
|
{
|
||||||
m_worlds.clear();
|
m_worlds.clear();
|
||||||
|
|
@ -61,8 +81,28 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
static_assert(std::is_base_of<Nz::Window, T>::value, "Type must inherit Window");
|
static_assert(std::is_base_of<Nz::Window, T>::value, "Type must inherit Window");
|
||||||
|
|
||||||
m_windows.emplace_back(new T(std::forward<Args>(args)...));
|
m_windows.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
|
||||||
return static_cast<T&>(*m_windows.back().get());
|
WindowInfo& info = m_windows.back();
|
||||||
|
|
||||||
|
T& window = static_cast<T&>(*info.window.get()); //< Warning: ugly
|
||||||
|
|
||||||
|
if (std::is_base_of<Nz::RenderTarget, T>())
|
||||||
|
{
|
||||||
|
info.renderTarget = &window;
|
||||||
|
|
||||||
|
if (m_overlayFlags)
|
||||||
|
{
|
||||||
|
SetupOverlay(info);
|
||||||
|
|
||||||
|
if (m_overlayFlags & OverlayFlags_Console)
|
||||||
|
SetupConsole(info);
|
||||||
|
|
||||||
|
if (m_overlayFlags & OverlayFlags_FPSCounter)
|
||||||
|
SetupFPSCounter(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -80,22 +120,159 @@ namespace Ndk
|
||||||
return m_worlds.back();
|
return m_worlds.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Enable/disable debug console
|
||||||
|
*
|
||||||
|
* \param enable Should the console overlay be enabled
|
||||||
|
*/
|
||||||
|
inline void Application::EnableConsole(bool enable)
|
||||||
|
{
|
||||||
|
if (enable != ((m_overlayFlags & OverlayFlags_Console) != 0))
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (m_overlayFlags == 0)
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
SetupOverlay(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
SetupConsole(info);
|
||||||
|
|
||||||
|
m_overlayFlags |= OverlayFlags_Console;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
info.console.reset();
|
||||||
|
|
||||||
|
m_overlayFlags &= ~OverlayFlags_Console;
|
||||||
|
if (m_overlayFlags == 0)
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
info.overlayWorld.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Enable/disable debug FPS counter
|
||||||
|
*
|
||||||
|
* \param enable Should the FPS counter be displayed
|
||||||
|
*/
|
||||||
|
inline void Application::EnableFPSCounter(bool enable)
|
||||||
|
{
|
||||||
|
if (enable != ((m_overlayFlags & OverlayFlags_FPSCounter) != 0))
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (m_overlayFlags == 0)
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
SetupOverlay(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
SetupFPSCounter(info);
|
||||||
|
|
||||||
|
m_overlayFlags |= OverlayFlags_FPSCounter;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
info.fpsCounter.reset();
|
||||||
|
|
||||||
|
m_overlayFlags &= ~OverlayFlags_FPSCounter;
|
||||||
|
if (m_overlayFlags == 0)
|
||||||
|
{
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
info.overlayWorld.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the console overlay for a specific window
|
||||||
|
*
|
||||||
|
* \param windowIndex Index of the window to get
|
||||||
|
*
|
||||||
|
* \remark The console overlay must be enabled
|
||||||
|
*
|
||||||
|
* \return A reference to the console overlay of the window
|
||||||
|
*
|
||||||
|
* \see IsConsoleOverlayEnabled
|
||||||
|
*/
|
||||||
|
inline Application::ConsoleOverlay& Application::GetConsoleOverlay(std::size_t windowIndex)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_overlayFlags & OverlayFlags_Console, "Console overlay is not enabled");
|
||||||
|
NazaraAssert(windowIndex <= m_windows.size(), "Window index is out of range");
|
||||||
|
|
||||||
|
return *m_windows[windowIndex].console;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the console overlay for a specific window
|
||||||
|
*
|
||||||
|
* \param windowIndex Index of the window to get
|
||||||
|
*
|
||||||
|
* \remark The console overlay must be enabled
|
||||||
|
*
|
||||||
|
* \return A reference to the console overlay of the window
|
||||||
|
*
|
||||||
|
* \see IsFPSCounterEnabled
|
||||||
|
*/
|
||||||
|
inline Application::FPSCounterOverlay& Application::GetFPSCounterOverlay(std::size_t windowIndex)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_overlayFlags & OverlayFlags_FPSCounter, "FPS counter overlay is not enabled");
|
||||||
|
NazaraAssert(windowIndex <= m_windows.size(), "Window index is out of range");
|
||||||
|
|
||||||
|
return *m_windows[windowIndex].fpsCounter;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the update time of the application
|
* \brief Gets the update time of the application
|
||||||
* \return Update rate
|
* \return Update rate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline float Application::GetUpdateTime() const
|
inline float Application::GetUpdateTime() const
|
||||||
{
|
{
|
||||||
return m_updateTime;
|
return m_updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if the console overlay is enabled
|
||||||
|
*
|
||||||
|
* \remark This has nothing to do with the visibility state of the console
|
||||||
|
*
|
||||||
|
* \return True if the console overlay is enabled
|
||||||
|
*
|
||||||
|
* \see GetConsoleOverlay
|
||||||
|
*/
|
||||||
|
inline bool Application::IsConsoleEnabled() const
|
||||||
|
{
|
||||||
|
return (m_overlayFlags & OverlayFlags_Console) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if the FPS counter overlay is enabled
|
||||||
|
* \return True if the FPS counter overlay is enabled
|
||||||
|
*
|
||||||
|
* \see GetFPSCounterOverlay
|
||||||
|
*/
|
||||||
|
inline bool Application::IsFPSCounterEnabled() const
|
||||||
|
{
|
||||||
|
return (m_overlayFlags & OverlayFlags_FPSCounter) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Makes the application exit when there's no more open window
|
* \brief Makes the application exit when there's no more open window
|
||||||
*
|
*
|
||||||
* \param exitOnClosedWindows Should exit be called when no more window is open
|
* \param exitOnClosedWindows Should exit be called when no more window is open
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
inline void Application::MakeExitOnLastWindowClosed(bool exitOnClosedWindows)
|
inline void Application::MakeExitOnLastWindowClosed(bool exitOnClosedWindows)
|
||||||
{
|
{
|
||||||
|
|
@ -121,4 +298,10 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
return s_application;
|
return s_application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Application::WindowInfo::WindowInfo(std::unique_ptr<Nz::Window>&& window) :
|
||||||
|
window(std::move(window)),
|
||||||
|
renderTarget(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,15 @@
|
||||||
|
|
||||||
#include <NDK/Application.hpp>
|
#include <NDK/Application.hpp>
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
#include <NDK/Components/CameraComponent.hpp>
|
||||||
|
#include <NDK/Components/GraphicsComponent.hpp>
|
||||||
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Systems/RenderSystem.hpp>
|
||||||
|
#include <NDK/LuaAPI.hpp>
|
||||||
|
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -15,7 +24,6 @@ namespace Ndk
|
||||||
/*!
|
/*!
|
||||||
* \brief Runs the application by updating worlds, taking care about windows, ...
|
* \brief Runs the application by updating worlds, taking care about windows, ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Application::Run()
|
bool Application::Run()
|
||||||
{
|
{
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
|
@ -24,7 +32,7 @@ namespace Ndk
|
||||||
auto it = m_windows.begin();
|
auto it = m_windows.begin();
|
||||||
while (it != m_windows.end())
|
while (it != m_windows.end())
|
||||||
{
|
{
|
||||||
Nz::Window& window = **it;
|
Nz::Window& window = *it->window;
|
||||||
|
|
||||||
window.ProcessEvents();
|
window.ProcessEvents();
|
||||||
|
|
||||||
|
|
@ -54,8 +62,128 @@ namespace Ndk
|
||||||
for (World& world : m_worlds)
|
for (World& world : m_worlds)
|
||||||
world.Update(m_updateTime);
|
world.Update(m_updateTime);
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
for (WindowInfo& info : m_windows)
|
||||||
|
{
|
||||||
|
if (info.fpsCounter)
|
||||||
|
{
|
||||||
|
FPSCounterOverlay& fpsCounter = *info.fpsCounter;
|
||||||
|
|
||||||
|
fpsCounter.frameCount++;
|
||||||
|
|
||||||
|
fpsCounter.elapsedTime += m_updateTime;
|
||||||
|
if (fpsCounter.elapsedTime >= 1.f)
|
||||||
|
{
|
||||||
|
fpsCounter.sprite->Update(Nz::SimpleTextDrawer::Draw("FPS: " + Nz::String::Number(fpsCounter.frameCount), 36));
|
||||||
|
fpsCounter.frameCount = 0;
|
||||||
|
fpsCounter.elapsedTime = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info.overlayWorld->Update(m_updateTime);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::SetupConsole(WindowInfo& info)
|
||||||
|
{
|
||||||
|
std::unique_ptr<ConsoleOverlay> overlay = std::make_unique<ConsoleOverlay>();
|
||||||
|
|
||||||
|
overlay->console = std::make_unique<Console>(*info.overlayWorld, Nz::Vector2f(Nz::Vector2ui(info.window->GetWidth(), info.window->GetHeight() / 4)), overlay->lua);
|
||||||
|
|
||||||
|
Console& consoleRef = *overlay->console;
|
||||||
|
// Redirect logs toward the console
|
||||||
|
overlay->logSlot.Connect(Nz::Log::OnLogWrite, [&consoleRef] (const Nz::String& str)
|
||||||
|
{
|
||||||
|
consoleRef.AddLine(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
LuaAPI::RegisterClasses(overlay->lua);
|
||||||
|
|
||||||
|
// Override "print" function to add a line in the console
|
||||||
|
overlay->lua.PushFunction([&consoleRef] (Nz::LuaInstance& instance)
|
||||||
|
{
|
||||||
|
Nz::StringStream stream;
|
||||||
|
|
||||||
|
unsigned int argCount = instance.GetStackTop();
|
||||||
|
instance.GetGlobal("tostring");
|
||||||
|
for (unsigned int i = 1; i <= argCount; ++i)
|
||||||
|
{
|
||||||
|
instance.PushValue(-1); // tostring function
|
||||||
|
instance.PushValue(i); // argument
|
||||||
|
instance.Call(1, 1);
|
||||||
|
|
||||||
|
std::size_t length;
|
||||||
|
const char* str = instance.CheckString(-1, &length);
|
||||||
|
if (i > 1)
|
||||||
|
stream << '\t';
|
||||||
|
|
||||||
|
stream << Nz::String(str, length);
|
||||||
|
instance.Pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleRef.AddLine(stream);
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
overlay->lua.SetGlobal("print");
|
||||||
|
|
||||||
|
// Define a few base variables to allow our interface to interact with the application
|
||||||
|
overlay->lua.PushGlobal("Application", Ndk::Application::Instance());
|
||||||
|
overlay->lua.PushGlobal("Console", consoleRef.CreateHandle());
|
||||||
|
|
||||||
|
// Setup a few event callback to handle the console
|
||||||
|
Nz::EventHandler& eventHandler = info.window->GetEventHandler();
|
||||||
|
|
||||||
|
overlay->eventSlot.Connect(eventHandler.OnEvent, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent& event)
|
||||||
|
{
|
||||||
|
if (consoleRef.IsVisible())
|
||||||
|
consoleRef.SendEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
overlay->keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& event)
|
||||||
|
{
|
||||||
|
if (event.code == Nz::Keyboard::F9)
|
||||||
|
consoleRef.Show(!consoleRef.IsVisible());
|
||||||
|
});
|
||||||
|
|
||||||
|
overlay->resizedSlot.Connect(eventHandler.OnResized, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::SizeEvent& event)
|
||||||
|
{
|
||||||
|
consoleRef.SetSize({float(event.width), event.height / 4.f});
|
||||||
|
});
|
||||||
|
|
||||||
|
info.console = std::move(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::SetupFPSCounter(WindowInfo& info)
|
||||||
|
{
|
||||||
|
std::unique_ptr<FPSCounterOverlay> fpsCounter = std::make_unique<FPSCounterOverlay>();
|
||||||
|
fpsCounter->sprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
|
fpsCounter->entity = info.overlayWorld->CreateEntity();
|
||||||
|
fpsCounter->entity->AddComponent<NodeComponent>();
|
||||||
|
fpsCounter->entity->AddComponent<GraphicsComponent>().Attach(fpsCounter->sprite);
|
||||||
|
|
||||||
|
info.fpsCounter = std::move(fpsCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::SetupOverlay(WindowInfo& info)
|
||||||
|
{
|
||||||
|
info.overlayWorld = std::make_unique<World>(false); //< No default system
|
||||||
|
|
||||||
|
RenderSystem& renderSystem = info.overlayWorld->AddSystem<RenderSystem>();
|
||||||
|
renderSystem.ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
|
||||||
|
renderSystem.SetDefaultBackground(nullptr);
|
||||||
|
renderSystem.SetGlobalUp(Nz::Vector3f::Down());
|
||||||
|
|
||||||
|
EntityHandle viewer = info.overlayWorld->CreateEntity();
|
||||||
|
CameraComponent& camComponent = viewer->AddComponent<CameraComponent>();
|
||||||
|
viewer->AddComponent<NodeComponent>();
|
||||||
|
|
||||||
|
camComponent.SetProjectionType(Nz::ProjectionType_Orthogonal);
|
||||||
|
camComponent.SetTarget(info.renderTarget);
|
||||||
|
}
|
||||||
|
|
||||||
Application* Application::s_application = nullptr;
|
Application* Application::s_application = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,14 @@ namespace Ndk
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
//application.SetMethod("AddWindow", &Application::AddWindow);
|
//application.SetMethod("AddWindow", &Application::AddWindow);
|
||||||
|
|
||||||
|
application.BindMethod("EnableConsole", &Application::EnableConsole);
|
||||||
|
application.BindMethod("EnableFPSCounter", &Application::EnableFPSCounter);
|
||||||
|
|
||||||
|
application.BindMethod("IsConsoleEnabled", &Application::IsConsoleEnabled);
|
||||||
|
application.BindMethod("IsFPSCounterEnabled", &Application::IsFPSCounterEnabled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
application.BindMethod("AddWorld", [] (Nz::LuaInstance& instance, Application* application) -> int
|
application.BindMethod("AddWorld", [] (Nz::LuaInstance& instance, Application* application) -> int
|
||||||
{
|
{
|
||||||
instance.Push(application->AddWorld().CreateHandle());
|
instance.Push(application->AddWorld().CreateHandle());
|
||||||
|
|
|
||||||
|
|
@ -256,81 +256,19 @@ int main()
|
||||||
// On lie la caméra à la fenêtre
|
// On lie la caméra à la fenêtre
|
||||||
cameraComp.SetTarget(&window);
|
cameraComp.SetTarget(&window);
|
||||||
|
|
||||||
// Et on créé deux horloges pour gérer le temps
|
// Et on créé une horloge pour gérer le temps
|
||||||
Nz::Clock secondClock, updateClock;
|
Nz::Clock updateClock;
|
||||||
Nz::UInt64 updateAccumulator = 0;
|
Nz::UInt64 updateAccumulator = 0;
|
||||||
|
|
||||||
// Ainsi qu'un compteur de FPS improvisé
|
|
||||||
unsigned int fps = 0;
|
|
||||||
|
|
||||||
// Quelques variables de plus pour notre caméra
|
// Quelques variables de plus pour notre caméra
|
||||||
bool smoothMovement = true;
|
bool smoothMovement = true;
|
||||||
Nz::Vector3f targetPos = cameraNode.GetPosition();
|
Nz::Vector3f targetPos = cameraNode.GetPosition();
|
||||||
|
|
||||||
// Pour ajouter une console à notre application, nous avons besoin d'un monde 2D pour gérer ces rendus
|
|
||||||
Ndk::WorldHandle world2D = application.AddWorld().CreateHandle();
|
|
||||||
world2D->GetSystem<Ndk::RenderSystem>().SetDefaultBackground(nullptr);
|
|
||||||
world2D->GetSystem<Ndk::RenderSystem>().SetGlobalUp(Nz::Vector3f::Down());
|
|
||||||
|
|
||||||
// Nous ajoutons une caméra comme précédement
|
|
||||||
Ndk::EntityHandle viewEntity = world2D->CreateEntity();
|
|
||||||
viewEntity->AddComponent<Ndk::NodeComponent>();
|
|
||||||
|
|
||||||
// À la différence que celui-ci effectuera une projection orthogonale
|
|
||||||
Ndk::CameraComponent& viewer = viewEntity->AddComponent<Ndk::CameraComponent>();
|
|
||||||
viewer.SetTarget(&window);
|
|
||||||
viewer.SetProjectionType(Nz::ProjectionType_Orthogonal);
|
|
||||||
|
|
||||||
// Nous créons un environnement Lua pour gérer nos scripts
|
|
||||||
Nz::LuaInstance lua;
|
|
||||||
|
|
||||||
// Faisons en sorte d'enregistrer les classes du moteur dans cet environnement
|
|
||||||
Ndk::LuaAPI::RegisterClasses(lua);
|
|
||||||
|
|
||||||
// Ensuite nous créons la console en elle-même
|
|
||||||
Ndk::Console console(*world2D, Nz::Vector2f(window.GetWidth(), window.GetHeight() / 4), lua);
|
|
||||||
|
|
||||||
// Nous redirigeons les logs vers cette console
|
|
||||||
Nz::Log::OnLogWriteType::ConnectionGuard logGuard = Nz::Log::OnLogWrite.Connect([&console] (const Nz::String& str)
|
|
||||||
{
|
|
||||||
console.AddLine(str);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Nous réécrivons la fonction "print" du Lua pour la rediriger vers la console
|
|
||||||
lua.PushFunction([&console] (Nz::LuaInstance& instance)
|
|
||||||
{
|
|
||||||
Nz::StringStream stream;
|
|
||||||
|
|
||||||
unsigned int argCount = instance.GetStackTop();
|
|
||||||
instance.GetGlobal("tostring");
|
|
||||||
for (unsigned int i = 1; i <= argCount; ++i)
|
|
||||||
{
|
|
||||||
instance.PushValue(-1); // ToString
|
|
||||||
instance.PushValue(i); // Arg
|
|
||||||
instance.Call(1, 1);
|
|
||||||
|
|
||||||
std::size_t length;
|
|
||||||
const char* str = instance.CheckString(-1, &length);
|
|
||||||
if (i > 1)
|
|
||||||
stream << '\t';
|
|
||||||
|
|
||||||
stream << Nz::String(str, length);
|
|
||||||
instance.Pop(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.AddLine(stream);
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
lua.SetGlobal("print");
|
|
||||||
|
|
||||||
// Définissons quelques variables de base
|
|
||||||
lua.PushGlobal("Application", Ndk::Application::Instance());
|
|
||||||
lua.PushGlobal("Console", console.CreateHandle());
|
|
||||||
lua.PushGlobal("Spaceship", spaceship->CreateHandle());
|
|
||||||
lua.PushGlobal("World", world->CreateHandle());
|
|
||||||
|
|
||||||
window.EnableEventPolling(true); // Déprécié
|
window.EnableEventPolling(true); // Déprécié
|
||||||
|
|
||||||
|
application.EnableConsole(true);
|
||||||
|
application.EnableFPSCounter(true);
|
||||||
|
|
||||||
// Début de la boucle de rendu du programme (s'occupant par exemple de mettre à jour le monde)
|
// Début de la boucle de rendu du programme (s'occupant par exemple de mettre à jour le monde)
|
||||||
while (application.Run())
|
while (application.Run())
|
||||||
{
|
{
|
||||||
|
|
@ -342,8 +280,12 @@ int main()
|
||||||
{
|
{
|
||||||
case Nz::WindowEventType_MouseMoved: // La souris a bougé
|
case Nz::WindowEventType_MouseMoved: // La souris a bougé
|
||||||
{
|
{
|
||||||
if (console.IsVisible())
|
if (application.IsConsoleEnabled())
|
||||||
|
{
|
||||||
|
Ndk::Application::ConsoleOverlay& consoleOverlay = application.GetConsoleOverlay();
|
||||||
|
if (consoleOverlay.console->IsVisible())
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Gestion de la caméra free-fly (Rotation)
|
// Gestion de la caméra free-fly (Rotation)
|
||||||
float sensitivity = 0.3f; // Sensibilité de la souris
|
float sensitivity = 0.3f; // Sensibilité de la souris
|
||||||
|
|
@ -368,9 +310,6 @@ int main()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Nz::WindowEventType_KeyPressed: // Une touche a été pressée !
|
case Nz::WindowEventType_KeyPressed: // Une touche a été pressée !
|
||||||
if (console.IsVisible())
|
|
||||||
console.SendEvent(event);
|
|
||||||
|
|
||||||
if (event.key.code == Nz::Keyboard::Key::Escape)
|
if (event.key.code == Nz::Keyboard::Key::Escape)
|
||||||
window.Close();
|
window.Close();
|
||||||
else if (event.key.code == Nz::Keyboard::F1)
|
else if (event.key.code == Nz::Keyboard::F1)
|
||||||
|
|
@ -383,19 +322,6 @@ int main()
|
||||||
else
|
else
|
||||||
smoothMovement = true;
|
smoothMovement = true;
|
||||||
}
|
}
|
||||||
else if (event.key.code == Nz::Keyboard::F9)
|
|
||||||
console.Show(!console.IsVisible());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Nz::WindowEventType_TextEntered:
|
|
||||||
{
|
|
||||||
if (console.IsVisible())
|
|
||||||
console.SendCharacter(event.text.character);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Nz::WindowEventType_Resized:
|
|
||||||
console.SetSize({float(event.size.width), event.size.height / 4.f});
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -419,7 +345,16 @@ int main()
|
||||||
// Vitesse de déplacement de la caméra
|
// Vitesse de déplacement de la caméra
|
||||||
float cameraSpeed = 3.f * elapsedTime; // Trois mètres par seconde
|
float cameraSpeed = 3.f * elapsedTime; // Trois mètres par seconde
|
||||||
|
|
||||||
if (!console.IsVisible())
|
bool move = true;
|
||||||
|
|
||||||
|
if (application.IsConsoleEnabled())
|
||||||
|
{
|
||||||
|
Ndk::Application::ConsoleOverlay& consoleOverlay = application.GetConsoleOverlay();
|
||||||
|
if (consoleOverlay.console->IsVisible())
|
||||||
|
move = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move)
|
||||||
{
|
{
|
||||||
// Si la touche espace est enfoncée, notre vitesse de déplacement est multipliée par deux
|
// Si la touche espace est enfoncée, notre vitesse de déplacement est multipliée par deux
|
||||||
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::Space))
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::Space))
|
||||||
|
|
@ -460,28 +395,6 @@ int main()
|
||||||
// Après avoir dessiné sur la fenêtre, il faut s'assurer qu'elle affiche cela
|
// Après avoir dessiné sur la fenêtre, il faut s'assurer qu'elle affiche cela
|
||||||
// Cet appel ne fait rien d'autre qu'échanger les buffers de rendu (Double Buffering)
|
// Cet appel ne fait rien d'autre qu'échanger les buffers de rendu (Double Buffering)
|
||||||
window.Display();
|
window.Display();
|
||||||
|
|
||||||
// On incrémente le compteur de FPS improvisé
|
|
||||||
fps++;
|
|
||||||
|
|
||||||
if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes
|
|
||||||
{
|
|
||||||
// Et on insère ces données dans le titre de la fenêtre
|
|
||||||
window.SetTitle(windowTitle + " - " + Nz::String::Number(fps) + " FPS");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier,
|
|
||||||
via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res".
|
|
||||||
Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier),
|
|
||||||
cela fonctionnera aussi comme ceci : "Chaîne de caractères".
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Et on réinitialise le compteur de FPS
|
|
||||||
fps = 0;
|
|
||||||
|
|
||||||
// Et on relance l'horloge pour refaire ça dans une seconde
|
|
||||||
secondClock.Restart();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue