diff --git a/include/Nazara/Utility/Cursor.hpp b/include/Nazara/Utility/Cursor.hpp index 7fe0b2831..77684cfc5 100644 --- a/include/Nazara/Utility/Cursor.hpp +++ b/include/Nazara/Utility/Cursor.hpp @@ -8,28 +8,34 @@ #define NAZARA_CURSOR_HPP #include +#include #include #include #include +#include namespace Nz { class CursorImpl; - class NAZARA_UTILITY_API Cursor + class Cursor; + + using CursorConstRef = ObjectRef; + using CursorRef = ObjectRef; + + class NAZARA_UTILITY_API Cursor : public RefCounted { friend class Utility; friend class WindowImpl; public: inline Cursor(); - inline Cursor(SystemCursor systemCursor); //< implicit conversion intended + inline Cursor(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder); Cursor(const Cursor&) = delete; - inline Cursor(Cursor&& cursor) noexcept; + Cursor(Cursor&&) = delete; inline ~Cursor(); - bool Create(const Image& cursor, const Vector2i& hotSpot); - bool Create(SystemCursor cursor); + bool Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder); void Destroy(); @@ -39,16 +45,24 @@ namespace Nz inline bool IsValid() const; Cursor& operator=(const Cursor&) = delete; - inline Cursor& operator=(Cursor&& cursor); + Cursor& operator=(Cursor&&) = delete; + + static inline Cursor* Get(SystemCursor cursor); + template static CursorRef New(Args&&... args); private: + inline explicit Cursor(SystemCursor systemCursor); + + bool Create(SystemCursor cursor); + static bool Initialize(); static void Uninitialize(); Image m_cursorImage; SystemCursor m_systemCursor; CursorImpl* m_impl; - bool m_usesSystemCursor; + + static std::array s_systemCursors; }; } diff --git a/include/Nazara/Utility/Cursor.inl b/include/Nazara/Utility/Cursor.inl index dc0ce68db..ba817eb9b 100644 --- a/include/Nazara/Utility/Cursor.inl +++ b/include/Nazara/Utility/Cursor.inl @@ -9,11 +9,21 @@ namespace Nz { inline Cursor::Cursor() : - m_impl(nullptr), - m_usesSystemCursor(false) + m_impl(nullptr) { } + inline Cursor::Cursor(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder) + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + Create(cursor, hotSpot, placeholder); + } + + inline Cursor* Cursor::Get(SystemCursor cursor) + { + return &s_systemCursors[cursor]; + } + inline Cursor::Cursor(SystemCursor systemCursor) : Cursor() { @@ -21,12 +31,6 @@ namespace Nz Create(systemCursor); } - inline Cursor::Cursor(Cursor&& cursor) noexcept : - Cursor() - { - operator=(std::move(cursor)); - } - inline Cursor::~Cursor() { Destroy(); @@ -35,7 +39,7 @@ namespace Nz inline const Image& Cursor::GetImage() const { NazaraAssert(IsValid(), "Invalid cursor"); - NazaraAssert(!m_usesSystemCursor, "System cursors have no image"); + NazaraAssert(m_cursorImage.IsValid(), "System cursors have no image"); return m_cursorImage; } @@ -43,7 +47,6 @@ namespace Nz inline SystemCursor Cursor::GetSystemCursor() const { NazaraAssert(IsValid(), "Invalid cursor"); - NazaraAssert(m_usesSystemCursor, "Custom cursor uses an image"); return m_systemCursor; } @@ -53,16 +56,13 @@ namespace Nz return m_impl != nullptr; } - inline Cursor& Cursor::operator=(Cursor&& cursor) + template + CursorRef Cursor::New(Args&&... args) { - m_cursorImage = std::move(cursor.m_cursorImage); - m_systemCursor = cursor.m_systemCursor; - m_impl = cursor.m_impl; - m_usesSystemCursor = cursor.m_usesSystemCursor; + std::unique_ptr object(new Cursor(std::forward(args)...)); + object->SetPersistent(false); - cursor.m_impl = nullptr; - - return *this; + return object.release(); } } diff --git a/include/Nazara/Utility/CursorController.hpp b/include/Nazara/Utility/CursorController.hpp index f91f3d9ff..5b994e11e 100644 --- a/include/Nazara/Utility/CursorController.hpp +++ b/include/Nazara/Utility/CursorController.hpp @@ -28,12 +28,12 @@ namespace Nz CursorController(CursorController&&) = default; ~CursorController() = default; - inline void UpdateCursor(const Cursor& cursor); + inline void UpdateCursor(const CursorRef& cursor); CursorController& operator=(const CursorController&) = delete; CursorController& operator=(CursorController&&) = default; - NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const Cursor& /*cursor*/); + NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const CursorRef& /*cursor*/); }; } diff --git a/include/Nazara/Utility/CursorController.inl b/include/Nazara/Utility/CursorController.inl index 0d6f2402d..1de20a17a 100644 --- a/include/Nazara/Utility/CursorController.inl +++ b/include/Nazara/Utility/CursorController.inl @@ -7,7 +7,7 @@ namespace Nz { - inline void CursorController::UpdateCursor(const Cursor& cursor) + inline void CursorController::UpdateCursor(const CursorRef& cursor) { OnCursorUpdated(this, cursor); } diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index ae7b876f9..7360dd13e 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -58,6 +58,7 @@ namespace Nz void EnableKeyRepeat(bool enable); void EnableSmoothScrolling(bool enable); + inline const CursorRef& GetCursor() const; inline CursorController& GetCursorController(); inline EventHandler& GetEventHandler(); WindowHandle GetHandle() const; @@ -81,7 +82,8 @@ namespace Nz void ProcessEvents(bool block = false); - void SetCursor(const Cursor& cursor); + void SetCursor(CursorRef cursor); + inline void SetCursor(SystemCursor systemCursor); void SetEventListener(bool listener); void SetFocus(); void SetIcon(const Icon& icon); @@ -122,6 +124,7 @@ namespace Nz std::vector m_pendingEvents; ConditionVariable m_eventCondition; CursorController m_cursorController; + CursorRef m_cursor; EventHandler m_eventHandler; Mutex m_eventMutex; Mutex m_eventConditionMutex; diff --git a/include/Nazara/Utility/Window.inl b/include/Nazara/Utility/Window.inl index cf820b8fb..0fca50c4d 100644 --- a/include/Nazara/Utility/Window.inl +++ b/include/Nazara/Utility/Window.inl @@ -67,6 +67,11 @@ namespace Nz } } + inline const CursorRef& Window::GetCursor() const + { + return m_cursor; + } + inline CursorController& Nz::Window::GetCursorController() { return m_cursorController; @@ -101,6 +106,11 @@ namespace Nz return m_impl != nullptr; } + inline void Window::SetCursor(SystemCursor systemCursor) + { + SetCursor(Cursor::Get(systemCursor)); + } + inline void Window::HandleEvent(const WindowEvent& event) { if (m_eventPolling) diff --git a/src/Nazara/Utility/Cursor.cpp b/src/Nazara/Utility/Cursor.cpp index f03a42052..115eefe0e 100644 --- a/src/Nazara/Utility/Cursor.cpp +++ b/src/Nazara/Utility/Cursor.cpp @@ -16,7 +16,7 @@ namespace Nz { - bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot) + bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder) { Destroy(); @@ -29,10 +29,24 @@ namespace Nz m_cursorImage = cursor; m_impl = impl.release(); + m_systemCursor = placeholder; return true; } + void Cursor::Destroy() + { + m_cursorImage.Destroy(); + + if (m_impl) + { + m_impl->Destroy(); + + delete m_impl; + m_impl = nullptr; + } + } + bool Cursor::Create(SystemCursor cursor) { Destroy(); @@ -46,31 +60,28 @@ namespace Nz m_impl = impl.release(); m_systemCursor = cursor; - m_usesSystemCursor = true; return true; } - void Cursor::Destroy() - { - if (m_impl) - { - m_impl->Destroy(); - - delete m_impl; - m_impl = nullptr; - } - - m_usesSystemCursor = false; - } - bool Cursor::Initialize() { - return CursorImpl::Initialize(); + if (!CursorImpl::Initialize()) + return false; + + for (std::size_t i = 0; i <= SystemCursor_Max; ++i) + s_systemCursors[i].Create(static_cast(i)); + + return true; } void Cursor::Uninitialize() { + for (Cursor& cursor : s_systemCursors) + cursor.Destroy(); + CursorImpl::Uninitialize(); } + + std::array Cursor::s_systemCursors; } diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 043258e26..7746a4236 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -36,7 +36,7 @@ namespace Nz m_eventPolling(false), m_waitForEvent(false) { - m_cursorController.OnCursorUpdated.Connect([this](const CursorController*, const Cursor& cursor) + m_cursorController.OnCursorUpdated.Connect([this](const CursorController*, const CursorRef& cursor) { if (IsValid()) SetCursor(cursor); @@ -104,11 +104,12 @@ namespace Nz // Paramètres par défaut m_impl->EnableKeyRepeat(true); m_impl->EnableSmoothScrolling(false); - m_impl->SetCursor(SystemCursor_Default); m_impl->SetMaximumSize(-1, -1); m_impl->SetMinimumSize(-1, -1); m_impl->SetVisible(true); + SetCursor(Cursor::Get(SystemCursor_Default)); + if (opened) m_impl->SetPosition(position.x, position.y); @@ -151,6 +152,8 @@ namespace Nz void Window::Destroy() { + m_cursor.Reset(); + if (m_impl) { OnWindowDestroy(); @@ -364,12 +367,13 @@ namespace Nz } } - void Window::SetCursor(const Cursor& cursor) + void Window::SetCursor(CursorRef cursor) { NazaraAssert(m_impl, "Window not created"); - NazaraAssert(cursor.IsValid(), "Invalid cursor"); + NazaraAssert(cursor && cursor->IsValid(), "Invalid cursor"); - m_impl->SetCursor(cursor); + m_cursor = std::move(cursor); + m_impl->SetCursor(*m_cursor); } void Window::SetEventListener(bool listener)