Utility/Cursor: Rework Cursor as a handled object
This commit is contained in:
parent
c4574ed7ec
commit
670199b557
|
|
@ -8,28 +8,34 @@
|
||||||
#define NAZARA_CURSOR_HPP
|
#define NAZARA_CURSOR_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/ObjectRef.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Utility/Config.hpp>
|
#include <Nazara/Utility/Config.hpp>
|
||||||
#include <Nazara/Utility/Image.hpp>
|
#include <Nazara/Utility/Image.hpp>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class CursorImpl;
|
class CursorImpl;
|
||||||
|
|
||||||
class NAZARA_UTILITY_API Cursor
|
class Cursor;
|
||||||
|
|
||||||
|
using CursorConstRef = ObjectRef<const Cursor>;
|
||||||
|
using CursorRef = ObjectRef<Cursor>;
|
||||||
|
|
||||||
|
class NAZARA_UTILITY_API Cursor : public RefCounted
|
||||||
{
|
{
|
||||||
friend class Utility;
|
friend class Utility;
|
||||||
friend class WindowImpl;
|
friend class WindowImpl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline Cursor();
|
inline Cursor();
|
||||||
inline Cursor(SystemCursor systemCursor); //< implicit conversion intended
|
inline Cursor(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder);
|
||||||
Cursor(const Cursor&) = delete;
|
Cursor(const Cursor&) = delete;
|
||||||
inline Cursor(Cursor&& cursor) noexcept;
|
Cursor(Cursor&&) = delete;
|
||||||
inline ~Cursor();
|
inline ~Cursor();
|
||||||
|
|
||||||
bool Create(const Image& cursor, const Vector2i& hotSpot);
|
bool Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder);
|
||||||
bool Create(SystemCursor cursor);
|
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
|
@ -39,16 +45,24 @@ namespace Nz
|
||||||
inline bool IsValid() const;
|
inline bool IsValid() const;
|
||||||
|
|
||||||
Cursor& operator=(const Cursor&) = delete;
|
Cursor& operator=(const Cursor&) = delete;
|
||||||
inline Cursor& operator=(Cursor&& cursor);
|
Cursor& operator=(Cursor&&) = delete;
|
||||||
|
|
||||||
|
static inline Cursor* Get(SystemCursor cursor);
|
||||||
|
template<typename... Args> static CursorRef New(Args&&... args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline explicit Cursor(SystemCursor systemCursor);
|
||||||
|
|
||||||
|
bool Create(SystemCursor cursor);
|
||||||
|
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
Image m_cursorImage;
|
Image m_cursorImage;
|
||||||
SystemCursor m_systemCursor;
|
SystemCursor m_systemCursor;
|
||||||
CursorImpl* m_impl;
|
CursorImpl* m_impl;
|
||||||
bool m_usesSystemCursor;
|
|
||||||
|
static std::array<Cursor, SystemCursor_Max + 1> s_systemCursors;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,21 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline Cursor::Cursor() :
|
inline Cursor::Cursor() :
|
||||||
m_impl(nullptr),
|
m_impl(nullptr)
|
||||||
m_usesSystemCursor(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) :
|
inline Cursor::Cursor(SystemCursor systemCursor) :
|
||||||
Cursor()
|
Cursor()
|
||||||
{
|
{
|
||||||
|
|
@ -21,12 +31,6 @@ namespace Nz
|
||||||
Create(systemCursor);
|
Create(systemCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Cursor::Cursor(Cursor&& cursor) noexcept :
|
|
||||||
Cursor()
|
|
||||||
{
|
|
||||||
operator=(std::move(cursor));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Cursor::~Cursor()
|
inline Cursor::~Cursor()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
@ -35,7 +39,7 @@ namespace Nz
|
||||||
inline const Image& Cursor::GetImage() const
|
inline const Image& Cursor::GetImage() const
|
||||||
{
|
{
|
||||||
NazaraAssert(IsValid(), "Invalid cursor");
|
NazaraAssert(IsValid(), "Invalid cursor");
|
||||||
NazaraAssert(!m_usesSystemCursor, "System cursors have no image");
|
NazaraAssert(m_cursorImage.IsValid(), "System cursors have no image");
|
||||||
|
|
||||||
return m_cursorImage;
|
return m_cursorImage;
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +47,6 @@ namespace Nz
|
||||||
inline SystemCursor Cursor::GetSystemCursor() const
|
inline SystemCursor Cursor::GetSystemCursor() const
|
||||||
{
|
{
|
||||||
NazaraAssert(IsValid(), "Invalid cursor");
|
NazaraAssert(IsValid(), "Invalid cursor");
|
||||||
NazaraAssert(m_usesSystemCursor, "Custom cursor uses an image");
|
|
||||||
|
|
||||||
return m_systemCursor;
|
return m_systemCursor;
|
||||||
}
|
}
|
||||||
|
|
@ -53,16 +56,13 @@ namespace Nz
|
||||||
return m_impl != nullptr;
|
return m_impl != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Cursor& Cursor::operator=(Cursor&& cursor)
|
template<typename... Args>
|
||||||
|
CursorRef Cursor::New(Args&&... args)
|
||||||
{
|
{
|
||||||
m_cursorImage = std::move(cursor.m_cursorImage);
|
std::unique_ptr<Cursor> object(new Cursor(std::forward<Args>(args)...));
|
||||||
m_systemCursor = cursor.m_systemCursor;
|
object->SetPersistent(false);
|
||||||
m_impl = cursor.m_impl;
|
|
||||||
m_usesSystemCursor = cursor.m_usesSystemCursor;
|
|
||||||
|
|
||||||
cursor.m_impl = nullptr;
|
return object.release();
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ namespace Nz
|
||||||
CursorController(CursorController&&) = default;
|
CursorController(CursorController&&) = default;
|
||||||
~CursorController() = default;
|
~CursorController() = default;
|
||||||
|
|
||||||
inline void UpdateCursor(const Cursor& cursor);
|
inline void UpdateCursor(const CursorRef& cursor);
|
||||||
|
|
||||||
CursorController& operator=(const CursorController&) = delete;
|
CursorController& operator=(const CursorController&) = delete;
|
||||||
CursorController& operator=(CursorController&&) = default;
|
CursorController& operator=(CursorController&&) = default;
|
||||||
|
|
||||||
NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const Cursor& /*cursor*/);
|
NazaraSignal(OnCursorUpdated, const CursorController* /*cursorController*/, const CursorRef& /*cursor*/);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline void CursorController::UpdateCursor(const Cursor& cursor)
|
inline void CursorController::UpdateCursor(const CursorRef& cursor)
|
||||||
{
|
{
|
||||||
OnCursorUpdated(this, cursor);
|
OnCursorUpdated(this, cursor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ namespace Nz
|
||||||
void EnableKeyRepeat(bool enable);
|
void EnableKeyRepeat(bool enable);
|
||||||
void EnableSmoothScrolling(bool enable);
|
void EnableSmoothScrolling(bool enable);
|
||||||
|
|
||||||
|
inline const CursorRef& GetCursor() const;
|
||||||
inline CursorController& GetCursorController();
|
inline CursorController& GetCursorController();
|
||||||
inline EventHandler& GetEventHandler();
|
inline EventHandler& GetEventHandler();
|
||||||
WindowHandle GetHandle() const;
|
WindowHandle GetHandle() const;
|
||||||
|
|
@ -81,7 +82,8 @@ namespace Nz
|
||||||
|
|
||||||
void ProcessEvents(bool block = false);
|
void ProcessEvents(bool block = false);
|
||||||
|
|
||||||
void SetCursor(const Cursor& cursor);
|
void SetCursor(CursorRef cursor);
|
||||||
|
inline void SetCursor(SystemCursor systemCursor);
|
||||||
void SetEventListener(bool listener);
|
void SetEventListener(bool listener);
|
||||||
void SetFocus();
|
void SetFocus();
|
||||||
void SetIcon(const Icon& icon);
|
void SetIcon(const Icon& icon);
|
||||||
|
|
@ -122,6 +124,7 @@ namespace Nz
|
||||||
std::vector<WindowEvent> m_pendingEvents;
|
std::vector<WindowEvent> m_pendingEvents;
|
||||||
ConditionVariable m_eventCondition;
|
ConditionVariable m_eventCondition;
|
||||||
CursorController m_cursorController;
|
CursorController m_cursorController;
|
||||||
|
CursorRef m_cursor;
|
||||||
EventHandler m_eventHandler;
|
EventHandler m_eventHandler;
|
||||||
Mutex m_eventMutex;
|
Mutex m_eventMutex;
|
||||||
Mutex m_eventConditionMutex;
|
Mutex m_eventConditionMutex;
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,11 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const CursorRef& Window::GetCursor() const
|
||||||
|
{
|
||||||
|
return m_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
inline CursorController& Nz::Window::GetCursorController()
|
inline CursorController& Nz::Window::GetCursorController()
|
||||||
{
|
{
|
||||||
return m_cursorController;
|
return m_cursorController;
|
||||||
|
|
@ -101,6 +106,11 @@ namespace Nz
|
||||||
return m_impl != nullptr;
|
return m_impl != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Window::SetCursor(SystemCursor systemCursor)
|
||||||
|
{
|
||||||
|
SetCursor(Cursor::Get(systemCursor));
|
||||||
|
}
|
||||||
|
|
||||||
inline void Window::HandleEvent(const WindowEvent& event)
|
inline void Window::HandleEvent(const WindowEvent& event)
|
||||||
{
|
{
|
||||||
if (m_eventPolling)
|
if (m_eventPolling)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot)
|
bool Cursor::Create(const Image& cursor, const Vector2i& hotSpot, SystemCursor placeholder)
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
|
|
@ -29,10 +29,24 @@ namespace Nz
|
||||||
|
|
||||||
m_cursorImage = cursor;
|
m_cursorImage = cursor;
|
||||||
m_impl = impl.release();
|
m_impl = impl.release();
|
||||||
|
m_systemCursor = placeholder;
|
||||||
|
|
||||||
return true;
|
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)
|
bool Cursor::Create(SystemCursor cursor)
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
@ -46,31 +60,28 @@ namespace Nz
|
||||||
|
|
||||||
m_impl = impl.release();
|
m_impl = impl.release();
|
||||||
m_systemCursor = cursor;
|
m_systemCursor = cursor;
|
||||||
m_usesSystemCursor = true;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cursor::Destroy()
|
|
||||||
{
|
|
||||||
if (m_impl)
|
|
||||||
{
|
|
||||||
m_impl->Destroy();
|
|
||||||
|
|
||||||
delete m_impl;
|
|
||||||
m_impl = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_usesSystemCursor = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Cursor::Initialize()
|
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<SystemCursor>(i));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cursor::Uninitialize()
|
void Cursor::Uninitialize()
|
||||||
{
|
{
|
||||||
|
for (Cursor& cursor : s_systemCursors)
|
||||||
|
cursor.Destroy();
|
||||||
|
|
||||||
CursorImpl::Uninitialize();
|
CursorImpl::Uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<Cursor, SystemCursor_Max + 1> Cursor::s_systemCursors;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Nz
|
||||||
m_eventPolling(false),
|
m_eventPolling(false),
|
||||||
m_waitForEvent(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())
|
if (IsValid())
|
||||||
SetCursor(cursor);
|
SetCursor(cursor);
|
||||||
|
|
@ -104,11 +104,12 @@ namespace Nz
|
||||||
// Paramètres par défaut
|
// Paramètres par défaut
|
||||||
m_impl->EnableKeyRepeat(true);
|
m_impl->EnableKeyRepeat(true);
|
||||||
m_impl->EnableSmoothScrolling(false);
|
m_impl->EnableSmoothScrolling(false);
|
||||||
m_impl->SetCursor(SystemCursor_Default);
|
|
||||||
m_impl->SetMaximumSize(-1, -1);
|
m_impl->SetMaximumSize(-1, -1);
|
||||||
m_impl->SetMinimumSize(-1, -1);
|
m_impl->SetMinimumSize(-1, -1);
|
||||||
m_impl->SetVisible(true);
|
m_impl->SetVisible(true);
|
||||||
|
|
||||||
|
SetCursor(Cursor::Get(SystemCursor_Default));
|
||||||
|
|
||||||
if (opened)
|
if (opened)
|
||||||
m_impl->SetPosition(position.x, position.y);
|
m_impl->SetPosition(position.x, position.y);
|
||||||
|
|
||||||
|
|
@ -151,6 +152,8 @@ namespace Nz
|
||||||
|
|
||||||
void Window::Destroy()
|
void Window::Destroy()
|
||||||
{
|
{
|
||||||
|
m_cursor.Reset();
|
||||||
|
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
OnWindowDestroy();
|
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(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)
|
void Window::SetEventListener(bool listener)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue