From fe252491360f2434d49eb595a923c3524672039a Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 7 Jun 2015 15:16:11 +0200 Subject: [PATCH] Replace Listenable system by signals Former-commit-id: 16fb0b3e703ca4b41ceb97fab938cebb05f677d4 --- SDK/include/NDK/BaseComponent.hpp | 1 + .../NDK/Components/CameraComponent.hpp | 17 ++-- .../NDK/Components/CameraComponent.inl | 25 ++++-- SDK/src/NDK/Components/CameraComponent.cpp | 28 +++---- include/Nazara/Core/Listenable.hpp | 33 -------- include/Nazara/Core/Listenable.inl | 68 ---------------- include/Nazara/Core/Signal.hpp | 10 +++ include/Nazara/Graphics/Camera.hpp | 11 ++- .../Graphics/DeferredRenderTechnique.hpp | 2 +- include/Nazara/Graphics/TextSprite.hpp | 19 +++-- include/Nazara/Graphics/View.hpp | 11 ++- include/Nazara/Renderer/RenderTarget.hpp | 18 ++--- include/Nazara/Utility/AbstractAtlas.hpp | 17 ++-- include/Nazara/Utility/Font.hpp | 12 ++- include/Nazara/Utility/Node.hpp | 19 ++--- src/Nazara/Graphics/Camera.cpp | 33 +++----- src/Nazara/Graphics/TextSprite.cpp | 81 ++++++++----------- src/Nazara/Graphics/View.cpp | 29 +++---- src/Nazara/Renderer/RenderTarget.cpp | 26 +----- src/Nazara/Renderer/RenderTexture.cpp | 4 +- src/Nazara/Renderer/RenderWindow.cpp | 6 +- src/Nazara/Utility/AbstractAtlas.cpp | 28 +------ src/Nazara/Utility/Font.cpp | 28 +++---- src/Nazara/Utility/GuillotineImageAtlas.cpp | 4 +- 24 files changed, 182 insertions(+), 348 deletions(-) delete mode 100644 include/Nazara/Core/Listenable.hpp delete mode 100644 include/Nazara/Core/Listenable.inl diff --git a/SDK/include/NDK/BaseComponent.hpp b/SDK/include/NDK/BaseComponent.hpp index 317261ea7..e8fc59c14 100644 --- a/SDK/include/NDK/BaseComponent.hpp +++ b/SDK/include/NDK/BaseComponent.hpp @@ -45,6 +45,7 @@ namespace Ndk virtual void OnComponentAttached(BaseComponent& component); virtual void OnComponentDetached(BaseComponent& component); virtual void OnDetached(); + void SetEntity(Entity* entity); static bool Initialize(); diff --git a/SDK/include/NDK/Components/CameraComponent.hpp b/SDK/include/NDK/Components/CameraComponent.hpp index d0e1e91a6..1e72aac74 100644 --- a/SDK/include/NDK/Components/CameraComponent.hpp +++ b/SDK/include/NDK/Components/CameraComponent.hpp @@ -19,11 +19,12 @@ namespace Ndk { class Entity; - class NDK_API CameraComponent : public Component, public NzAbstractViewer, NzNode::Listener, NzRenderTarget::Listener + class NDK_API CameraComponent : public Component, public NzAbstractViewer { public: - CameraComponent(); - ~CameraComponent(); + inline CameraComponent(); + inline CameraComponent(const CameraComponent& camera); + ~CameraComponent() = default; void ApplyView() const override; @@ -66,15 +67,19 @@ namespace Ndk void OnComponentAttached(BaseComponent& component) override; void OnComponentDetached(BaseComponent& component) override; void OnDetached() override; - bool OnNodeInvalidated(const NzNode* node, void* userdata) override; - void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) override; - bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override; + void OnNodeInvalidated(const NzNode* node); + void OnRenderTargetRelease(const NzRenderTarget* renderTarget); + void OnRenderTargetSizeChange(const NzRenderTarget* renderTarget); void UpdateFrustum() const; void UpdateProjectionMatrix() const; void UpdateViewMatrix() const; void UpdateViewport() const; + NazaraSlot(NzNode, OnNodeInvalidation, m_nodeInvalidationSlot); + NazaraSlot(NzRenderTarget, OnRenderTargetRelease, m_targetReleaseSlot); + NazaraSlot(NzRenderTarget, OnRenderTargetSizeChange, m_targetResizeSlot); + mutable NzFrustumf m_frustum; mutable NzMatrix4f m_projectionMatrix; mutable NzMatrix4f m_viewMatrix; diff --git a/SDK/include/NDK/Components/CameraComponent.inl b/SDK/include/NDK/Components/CameraComponent.inl index fbaa7a1bd..f66e08a15 100644 --- a/SDK/include/NDK/Components/CameraComponent.inl +++ b/SDK/include/NDK/Components/CameraComponent.inl @@ -21,10 +21,22 @@ namespace Ndk { } - inline CameraComponent::~CameraComponent() + inline CameraComponent::CameraComponent(const CameraComponent& camera) : + Component(camera), + NzAbstractViewer(camera), + m_targetRegion(camera.m_targetRegion), + m_target(camera.m_target), + m_frustumUpdated(false), + m_projectionMatrixUpdated(false), + m_viewMatrixUpdated(false), + m_viewportUpdated(false), + m_aspectRatio(camera.m_aspectRatio), + m_fov(camera.m_fov), + m_zFar(camera.m_zFar), + m_zNear(camera.m_zNear), + m_layer(camera.m_layer) { - if (m_target) - m_target->RemoveListener(this); + } inline void CameraComponent::EnsureFrustumUpdate() const @@ -126,12 +138,11 @@ namespace Ndk inline void CameraComponent::SetTarget(const NzRenderTarget* renderTarget) { - if (m_target) - m_target->RemoveListener(this); - m_target = renderTarget; if (m_target) - m_target->AddListener(this); + m_targetReleaseSlot = NazaraConnect(*m_target, OnRenderTargetRelease, OnRenderTargetRelease); + else + NazaraDisconnect(m_targetReleaseSlot); } inline void CameraComponent::SetTargetRegion(const NzRectf& region) diff --git a/SDK/src/NDK/Components/CameraComponent.cpp b/SDK/src/NDK/Components/CameraComponent.cpp index fe0cf28e2..d4d57a0f0 100644 --- a/SDK/src/NDK/Components/CameraComponent.cpp +++ b/SDK/src/NDK/Components/CameraComponent.cpp @@ -46,6 +46,9 @@ namespace Ndk void CameraComponent::OnAttached() { + if (m_entity->HasComponent()) + m_nodeInvalidationSlot = NazaraConnect(m_entity->GetComponent(), OnNodeInvalidation, OnNodeInvalidated); + InvalidateViewMatrix(); } @@ -54,7 +57,7 @@ namespace Ndk if (IsComponent(component)) { NodeComponent& nodeComponent = static_cast(component); - nodeComponent.AddListener(this); + m_nodeInvalidationSlot = NazaraConnect(nodeComponent, OnNodeInvalidation, OnNodeInvalidated); InvalidateViewMatrix(); } @@ -65,7 +68,7 @@ namespace Ndk if (IsComponent(component)) { NodeComponent& nodeComponent = static_cast(component); - nodeComponent.RemoveListener(this); + NazaraDisconnect(m_nodeInvalidationSlot); InvalidateViewMatrix(); } @@ -73,44 +76,33 @@ namespace Ndk void CameraComponent::OnDetached() { + NazaraDisconnect(m_nodeInvalidationSlot); + InvalidateViewMatrix(); } - bool CameraComponent::OnNodeInvalidated(const NzNode* node, void* userdata) + void CameraComponent::OnNodeInvalidated(const NzNode* node) { NazaraUnused(node); - NazaraUnused(userdata); // Our view matrix depends on NodeComponent position/rotation InvalidateViewMatrix(); - return true; } - void CameraComponent::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) + void CameraComponent::OnRenderTargetRelease(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) m_target = nullptr; else NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); } - bool CameraComponent::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) + void CameraComponent::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) - { InvalidateViewport(); - - return true; - } else - { NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); - return false; - } } void CameraComponent::UpdateFrustum() const diff --git a/include/Nazara/Core/Listenable.hpp b/include/Nazara/Core/Listenable.hpp deleted file mode 100644 index 66c6edcd3..000000000 --- a/include/Nazara/Core/Listenable.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Core module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_LISTENABLE_HPP -#define NAZARA_LISTENABLE_HPP - -#include -#include - -template -class NzListenable -{ - public: - NzListenable(); - ~NzListenable() = default; - - template void AddListener(L* listener, void* userdata = nullptr) const; - template void RemoveListener(L* listener) const; - - template void Notify(F callback, Args&&... args); - template void NotifyRelease(F callback); - - private: - mutable std::unordered_map m_listeners; - bool m_listenersLocked; -}; - -#include - -#endif // NAZARA_LISTENABLE_HPP diff --git a/include/Nazara/Core/Listenable.inl b/include/Nazara/Core/Listenable.inl deleted file mode 100644 index c69dc6260..000000000 --- a/include/Nazara/Core/Listenable.inl +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Core module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include - -template -NzListenable::NzListenable() : -m_listenersLocked(false) -{ -} - -template -template -void NzListenable::AddListener(L* listener, void* userdata) const -{ - static_assert(std::is_base_of::value, "`listener` does not derive from a Listener"); - - if (!m_listenersLocked) - m_listeners.insert(std::make_pair(listener, userdata)); -} - -template -template -void NzListenable::RemoveListener(L* listener) const -{ - static_assert(std::is_base_of::value, "`listener` does not derive from a Listener"); - - if (!m_listenersLocked) - m_listeners.erase(listener); -} - -template -template -void NzListenable::Notify(F callback, Args&&... args) -{ - using Listener = typename Base::Listener; - - m_listenersLocked = true; - - auto it = m_listeners.begin(); - while (it != m_listeners.end()) - { - Listener* listener = static_cast(it->first); - if (!(listener->*callback)(static_cast(this), std::forward(args)..., it->second)) - m_listeners.erase(it++); - else - ++it; - } - - m_listenersLocked = false; -} - -template -template -void NzListenable::NotifyRelease(F callback) -{ - using Listener = typename Base::Listener; - - m_listenersLocked = true; - for (auto& pair : m_listeners) - { - Listener* listener = static_cast(pair.first); - (listener->*callback)(static_cast(this), pair.second); - } -} - -#include diff --git a/include/Nazara/Core/Signal.hpp b/include/Nazara/Core/Signal.hpp index 2ff03b229..d06ddd0c5 100644 --- a/include/Nazara/Core/Signal.hpp +++ b/include/Nazara/Core/Signal.hpp @@ -11,6 +11,16 @@ #include #include +#define NazaraSignal(SignalName, ...) using SignalName ## Type = NzSignal<__VA_ARGS__>; \ + mutable SignalName ## Type SignalName + +#define NazaraSlotType(Class, SignalName) Class::SignalName ## Type::ConnectionGuard +#define NazaraSlot(Class, SignalName, SlotName) NazaraSlotType(Class, SignalName) SlotName + +#define NazaraConnect(Instance, SignalName, Callback) (Instance).SignalName.Connect(this, Callback) +#define NazaraDisconnect(SlotName) SlotName.GetConnection().Disconnect() + + template class NzSignal { diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 8e3622484..7343e2391 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -16,11 +16,11 @@ #include #include -class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener +class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode { public: NzCamera(); - ~NzCamera(); + ~NzCamera() = default; void EnsureFrustumUpdate() const; void EnsureProjectionMatrixUpdate() const; @@ -55,14 +55,17 @@ class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarg void ApplyView() const override; void InvalidateNode() override; - void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) override; - bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override; + void OnRenderTargetRelease(const NzRenderTarget* renderTarget); + void OnRenderTargetSizeChange(const NzRenderTarget* renderTarget); void UpdateFrustum() const; void UpdateProjectionMatrix() const; void UpdateViewMatrix() const; void UpdateViewport() const; + NazaraSlot(NzRenderTarget, OnRenderTargetRelease, m_targetReleaseSlot); + NazaraSlot(NzRenderTarget, OnRenderTargetSizeChange, m_targetResizeSlot); + mutable NzFrustumf m_frustum; mutable NzMatrix4f m_projectionMatrix; mutable NzMatrix4f m_viewMatrix; diff --git a/include/Nazara/Graphics/DeferredRenderTechnique.hpp b/include/Nazara/Graphics/DeferredRenderTechnique.hpp index a49475315..303486603 100644 --- a/include/Nazara/Graphics/DeferredRenderTechnique.hpp +++ b/include/Nazara/Graphics/DeferredRenderTechnique.hpp @@ -22,7 +22,7 @@ #include #include -class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, public NzRenderTarget::Listener +class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique { friend class NzGraphics; diff --git a/include/Nazara/Graphics/TextSprite.hpp b/include/Nazara/Graphics/TextSprite.hpp index a0730d669..ae0bd11f7 100644 --- a/include/Nazara/Graphics/TextSprite.hpp +++ b/include/Nazara/Graphics/TextSprite.hpp @@ -16,12 +16,12 @@ #include #include -class NAZARA_API NzTextSprite : public NzSceneNode, NzAbstractAtlas::Listener +class NAZARA_API NzTextSprite : public NzSceneNode { public: NzTextSprite(); NzTextSprite(const NzTextSprite& sprite); - ~NzTextSprite(); + ~NzTextSprite() = default; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; @@ -46,12 +46,10 @@ class NAZARA_API NzTextSprite : public NzSceneNode, NzAbstractAtlas::Listener NzTextSprite& operator=(const NzTextSprite& text); private: - void ClearAtlases(); void InvalidateNode() override; void MakeBoundingVolume() const override; - bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override; - bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override; - void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override; + void OnAtlasInvalidated(const NzAbstractAtlas* atlas); + void OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer); void Register() override; void Unregister() override; void UpdateVertices() const; @@ -62,7 +60,14 @@ class NAZARA_API NzTextSprite : public NzSceneNode, NzAbstractAtlas::Listener unsigned int count; }; - std::set m_atlases; + struct AtlasSlots + { + NazaraSlot(NzAbstractAtlas, OnAtlasCleared, clearSlot); + NazaraSlot(NzAbstractAtlas, OnAtlasLayerChange, layerChangeSlot); + NazaraSlot(NzAbstractAtlas, OnAtlasRelease, releaseSlot); + }; + + std::unordered_map m_atlases; mutable std::unordered_map m_renderInfos; mutable std::vector m_localVertices; mutable std::vector m_vertices; diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index 30f8ba73c..0e4f89a90 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -16,12 +16,12 @@ #include #include -class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget::Listener +class NAZARA_API NzView : public NzAbstractViewer, public NzNode { public: NzView(); NzView(const NzVector2f& size); - ~NzView(); + ~NzView() = default; void EnsureFrustumUpdate() const; void EnsureProjectionMatrixUpdate() const; @@ -62,8 +62,8 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget void ApplyView() const override; void InvalidateNode() override; - void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) override; - bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override; + void OnRenderTargetRelease(const NzRenderTarget* renderTarget); + void OnRenderTargetSizeChange(const NzRenderTarget* renderTarget); void UpdateFrustum() const; void UpdateInvViewProjMatrix() const; @@ -72,6 +72,9 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget void UpdateViewProjMatrix() const; void UpdateViewport() const; + NazaraSlot(NzRenderTarget, OnRenderTargetRelease, m_targetReleaseSlot); + NazaraSlot(NzRenderTarget, OnRenderTargetSizeChange, m_targetResizeSlot); + mutable NzFrustumf m_frustum; mutable NzMatrix4f m_invViewProjMatrix; mutable NzMatrix4f m_projectionMatrix; diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp index d6affd968..cbce568d9 100644 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ b/include/Nazara/Renderer/RenderTarget.hpp @@ -8,14 +8,14 @@ #define NAZARA_RENDERTARGET_HPP #include -#include +#include #include #include #include class NzRenderer; -class NAZARA_API NzRenderTarget : public NzListenable +class NAZARA_API NzRenderTarget { friend class NzRenderer; @@ -35,16 +35,10 @@ class NAZARA_API NzRenderTarget : public NzListenable // Fonctions OpenGL virtual bool HasContext() const = 0; - class NAZARA_API Listener - { - public: - Listener() = default; - virtual ~Listener(); - - virtual bool OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata); - virtual void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata); - virtual bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata); - }; + // Signals + NazaraSignal(OnRenderTargetParametersChange, const NzRenderTarget*); //< Args: me + NazaraSignal(OnRenderTargetRelease, const NzRenderTarget*); //< Args: me + NazaraSignal(OnRenderTargetSizeChange, const NzRenderTarget*); //< Args: me protected: virtual bool Activate() const = 0; diff --git a/include/Nazara/Utility/AbstractAtlas.hpp b/include/Nazara/Utility/AbstractAtlas.hpp index b9f49181a..31f316b03 100644 --- a/include/Nazara/Utility/AbstractAtlas.hpp +++ b/include/Nazara/Utility/AbstractAtlas.hpp @@ -8,7 +8,7 @@ #define NAZARA_ABSTRACTATLAS_HPP #include -#include +#include #include #include #include @@ -17,7 +17,7 @@ class NzAbstractImage; class NzImage; -class NAZARA_API NzAbstractAtlas : public NzListenable +class NAZARA_API NzAbstractAtlas { public: NzAbstractAtlas() = default; @@ -30,16 +30,9 @@ class NAZARA_API NzAbstractAtlas : public NzListenable virtual nzUInt32 GetStorage() const = 0; virtual bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0; - class NAZARA_API Listener - { - public: - Listener() = default; - virtual ~Listener(); - - virtual bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata); - virtual bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata); - virtual void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata); - }; + NazaraSignal(OnAtlasCleared, const NzAbstractAtlas*); //< Args: me + NazaraSignal(OnAtlasLayerChange, const NzAbstractAtlas*, NzAbstractImage*, NzAbstractImage*); //< Args: me, oldLayer, newLayer + NazaraSignal(OnAtlasRelease, const NzAbstractAtlas*); //< Args: me }; #endif // NAZARA_ABSTRACTATLAS_HPP diff --git a/include/Nazara/Utility/Font.hpp b/include/Nazara/Utility/Font.hpp index 1c99ba4be..fa03eef48 100644 --- a/include/Nazara/Utility/Font.hpp +++ b/include/Nazara/Utility/Font.hpp @@ -37,7 +37,7 @@ using NzFontListener = NzObjectListenerWrapper; using NzFontLoader = NzResourceLoader; using NzFontRef = NzObjectRef; -class NAZARA_API NzFont : public NzRefCounted, public NzResource, NzAbstractAtlas::Listener, NzNonCopyable +class NAZARA_API NzFont : public NzRefCounted, public NzResource, NzNonCopyable { friend NzFontLibrary; friend NzFontLoader; @@ -128,14 +128,18 @@ class NAZARA_API NzFont : public NzRefCounted, public NzResource, NzAbstractAtla using GlyphMap = std::unordered_map; nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const; - bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override; - bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override; - void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override; + void OnAtlasCleared(const NzAbstractAtlas* atlas); + void OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer); + void OnAtlasRelease(const NzAbstractAtlas* atlas); const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const; static bool Initialize(); static void Uninitialize(); + NazaraSlot(NzAbstractAtlas, OnAtlasCleared, m_atlasClearedSlot); + NazaraSlot(NzAbstractAtlas, OnAtlasLayerChange, m_atlasLayerChangeSlot); + NazaraSlot(NzAbstractAtlas, OnAtlasRelease, m_atlasReleaseSlot); + std::shared_ptr m_atlas; std::unique_ptr m_data; mutable std::unordered_map> m_kerningCache; diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index 116dd1045..52a811e99 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -8,7 +8,7 @@ #define NAZARA_NODE_HPP #include -#include +#include #include #include #include @@ -16,7 +16,7 @@ #include #include -class NAZARA_API NzNode : public NzListenable +class NAZARA_API NzNode { public: NzNode(); @@ -90,16 +90,10 @@ class NAZARA_API NzNode : public NzListenable NzNode& operator=(const NzNode& node); - class NAZARA_API Listener - { - public: - Listener() = default; - virtual ~Listener(); - - virtual bool OnNodeInvalidated(const NzNode* node, void* userdata); - virtual bool OnNodeParented(const NzNode* node, const NzNode* parent, void* userdata); - virtual void OnNodeReleased(const NzNode* node, void* userdata); - }; + // Signals + NazaraSignal(OnNodeInvalidation, const NzNode*); //< Args: me + NazaraSignal(OnNodeNewParent, const NzNode*, const NzNode*); //< Args: me + NazaraSignal(OnNodeRelease, const NzNode*); //< Args: me protected: void AddChild(NzNode* node) const; @@ -126,7 +120,6 @@ class NAZARA_API NzNode : public NzListenable bool m_inheritRotation; bool m_inheritScale; mutable bool m_transformMatrixUpdated; - }; #endif // NAZARA_NODE_HPP diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index 6b51c0fb5..c738cfe64 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -22,12 +22,6 @@ m_zNear(1.f) { } -NzCamera::~NzCamera() -{ - if (m_target) - m_target->RemoveListener(this); -} - void NzCamera::EnsureFrustumUpdate() const { if (!m_frustumUpdated) @@ -165,12 +159,18 @@ void NzCamera::SetFOV(float fov) void NzCamera::SetTarget(const NzRenderTarget* renderTarget) { - if (m_target) - m_target->RemoveListener(this); - m_target = renderTarget; + if (m_target) - m_target->AddListener(this); + { + m_targetReleaseSlot = NazaraConnect(*m_target, OnRenderTargetRelease, OnRenderTargetRelease); + m_targetResizeSlot = NazaraConnect(*m_target, OnRenderTargetSizeChange, OnRenderTargetSizeChange); + } + else + { + NazaraDisconnect(m_targetReleaseSlot); + NazaraDisconnect(m_targetResizeSlot); + } m_frustumUpdated = false; m_projectionMatrixUpdated = false; @@ -266,33 +266,24 @@ void NzCamera::InvalidateNode() m_viewMatrixUpdated = false; } -void NzCamera::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) +void NzCamera::OnRenderTargetRelease(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) m_target = nullptr; else NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); } -bool NzCamera::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) +void NzCamera::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) { m_frustumUpdated = false; m_projectionMatrixUpdated = false; m_viewportUpdated = false; - - return true; } else - { NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); - return false; - } } void NzCamera::UpdateFrustum() const diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 4259035a6..8419b0408 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -21,7 +21,6 @@ m_verticesUpdated(false) NzTextSprite::NzTextSprite(const NzTextSprite& sprite) : NzSceneNode(sprite), -m_atlases(sprite.m_atlases), m_renderInfos(sprite.m_renderInfos), m_localVertices(sprite.m_localVertices), m_vertices(sprite.m_vertices), @@ -32,13 +31,15 @@ m_verticesUpdated(sprite.m_verticesUpdated) { SetParent(sprite.GetParent()); - for (const NzAbstractAtlas* atlas : m_atlases) - atlas->AddListener(this); -} + for (auto it = sprite.m_atlases.begin(); it != sprite.m_atlases.end(); ++it) + { + const NzAbstractAtlas* atlas = it->first; + AtlasSlots& slots = m_atlases[atlas]; -NzTextSprite::~NzTextSprite() -{ - ClearAtlases(); + slots.clearSlot = NazaraConnect(*atlas, OnAtlasCleared, OnAtlasInvalidated); + slots.layerChangeSlot = NazaraConnect(*atlas, OnAtlasLayerChange, OnAtlasLayerChange); + slots.releaseSlot = NazaraConnect(*atlas, OnAtlasRelease, OnAtlasInvalidated); + } } void NzTextSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const @@ -58,7 +59,7 @@ void NzTextSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const void NzTextSprite::Clear() { - ClearAtlases(); + m_atlases.clear(); m_boundingVolume.MakeNull(); m_localVertices.clear(); m_renderInfos.clear(); @@ -126,7 +127,7 @@ void NzTextSprite::SetMaterial(NzMaterial* material) void NzTextSprite::Update(const NzAbstractTextDrawer& drawer) { - ClearAtlases(); + m_atlases.clear(); NzCallOnExit clearOnFail([this]() { @@ -148,8 +149,14 @@ void NzTextSprite::Update(const NzAbstractTextDrawer& drawer) } #endif - if (m_atlases.insert(atlas).second) - atlas->AddListener(this); + if (m_atlases.find(atlas) == m_atlases.end()) + { + AtlasSlots& slots = m_atlases[atlas]; + + slots.clearSlot = NazaraConnect(*atlas, OnAtlasCleared, OnAtlasInvalidated); + slots.layerChangeSlot = NazaraConnect(*atlas, OnAtlasLayerChange, OnAtlasLayerChange); + slots.releaseSlot = NazaraConnect(*atlas, OnAtlasRelease, OnAtlasInvalidated); + } } unsigned int glyphCount = drawer.GetGlyphCount(); @@ -256,27 +263,31 @@ NzTextSprite& NzTextSprite::operator=(const NzTextSprite& text) { NzSceneNode::operator=(text); - m_atlases = text.m_atlases; + m_atlases.clear(); + m_color = text.m_color; m_material = text.m_material; m_renderInfos = text.m_renderInfos; m_localBounds = text.m_localBounds; m_localVertices = text.m_localVertices; + // Connect to the slots of the new atlases + for (auto it = text.m_atlases.begin(); it != text.m_atlases.end(); ++it) + { + const NzAbstractAtlas* atlas = it->first; + AtlasSlots& slots = m_atlases[atlas]; + + slots.clearSlot = NazaraConnect(*atlas, OnAtlasCleared, OnAtlasInvalidated); + slots.layerChangeSlot = NazaraConnect(*atlas, OnAtlasLayerChange, OnAtlasLayerChange); + slots.releaseSlot = NazaraConnect(*atlas, OnAtlasRelease, OnAtlasInvalidated); + } + // On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon m_verticesUpdated = false; return *this; } -void NzTextSprite::ClearAtlases() -{ - for (const NzAbstractAtlas* atlas : m_atlases) - atlas->RemoveListener(this); - - m_atlases.clear(); -} - void NzTextSprite::InvalidateNode() { NzSceneNode::InvalidateNode(); @@ -296,10 +307,8 @@ void NzTextSprite::MakeBoundingVolume() const m_boundingVolume.Set(min.x*right + min.y*down, max.x*right + max.y*down); } -bool NzTextSprite::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) +void NzTextSprite::OnAtlasInvalidated(const NzAbstractAtlas* atlas) { - NazaraUnused(userdata); - #ifdef NAZARA_DEBUG if (m_atlases.find(atlas) == m_atlases.end()) { @@ -308,16 +317,13 @@ bool NzTextSprite::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) } #endif - NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been cleared"); + NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " has been invalidated (cleared or released)"); Clear(); - - return false; } -bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) +void NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer) { NazaraUnused(atlas); - NazaraUnused(userdata); #ifdef NAZARA_DEBUG if (m_atlases.find(atlas) == m_atlases.end()) @@ -356,25 +362,6 @@ bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractIm m_renderInfos.erase(it); m_renderInfos.insert(std::make_pair(newTexture, std::move(indices))); } - - return true; -} - -void NzTextSprite::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) -{ - NazaraUnused(userdata); - - #ifdef NAZARA_DEBUG - if (m_atlases.find(atlas) == m_atlases.end()) - { - NazaraInternalError("Not listening to " + NzString::Pointer(atlas)); - return; - } - #endif - - // L'atlas a été libéré alors que le TextSprite l'utilisait encore, notre seule option (pour éviter un crash) est de nous réinitialiser - NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " has been released"); - Clear(); } void NzTextSprite::Register() diff --git a/src/Nazara/Graphics/View.cpp b/src/Nazara/Graphics/View.cpp index b58e10ead..eb3e9e871 100644 --- a/src/Nazara/Graphics/View.cpp +++ b/src/Nazara/Graphics/View.cpp @@ -29,12 +29,6 @@ NzView() // On délègue SetSize(size); } -NzView::~NzView() -{ - if (m_target) - m_target->RemoveListener(this); -} - void NzView::EnsureFrustumUpdate() const { if (!m_frustumUpdated) @@ -221,12 +215,17 @@ void NzView::SetSize(float width, float height) void NzView::SetTarget(const NzRenderTarget* renderTarget) { - if (m_target) - m_target->RemoveListener(this); - m_target = renderTarget; if (m_target) - m_target->AddListener(this); + { + m_targetReleaseSlot = NazaraConnect(*m_target, OnRenderTargetRelease, OnRenderTargetRelease); + m_targetResizeSlot = NazaraConnect(*m_target, OnRenderTargetSizeChange, OnRenderTargetSizeChange); + } + else + { + NazaraDisconnect(m_targetReleaseSlot); + NazaraDisconnect(m_targetResizeSlot); + } } void NzView::SetTarget(const NzRenderTarget& renderTarget) @@ -318,20 +317,16 @@ void NzView::InvalidateNode() m_viewProjMatrixUpdated = false; } -void NzView::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) +void NzView::OnRenderTargetRelease(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) m_target = nullptr; else NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); } -bool NzView::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) +void NzView::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget) { - NazaraUnused(userdata); - if (renderTarget == m_target) { m_frustumUpdated = false; @@ -340,8 +335,6 @@ bool NzView::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* } else NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget)); - - return true; } void NzView::UpdateFrustum() const diff --git a/src/Nazara/Renderer/RenderTarget.cpp b/src/Nazara/Renderer/RenderTarget.cpp index 86625ff2d..8276aeb3f 100644 --- a/src/Nazara/Renderer/RenderTarget.cpp +++ b/src/Nazara/Renderer/RenderTarget.cpp @@ -8,7 +8,7 @@ NzRenderTarget::~NzRenderTarget() { - NotifyRelease(Listener::OnRenderTargetReleased); + OnRenderTargetRelease(this); } bool NzRenderTarget::IsActive() const @@ -30,27 +30,3 @@ void NzRenderTarget::Desactivate() const { // Seuls les target sans contextes (ex: NzRenderTexture) nécessitent une désactivation } - -NzRenderTarget::Listener::~Listener() = default; - -bool NzRenderTarget::Listener::OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata) -{ - NazaraUnused(renderTarget); - NazaraUnused(userdata); - - return true; -} - -void NzRenderTarget::Listener::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) -{ - NazaraUnused(renderTarget); - NazaraUnused(userdata); -} - -bool NzRenderTarget::Listener::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) -{ - NazaraUnused(renderTarget); - NazaraUnused(userdata); - - return true; -} diff --git a/src/Nazara/Renderer/RenderTexture.cpp b/src/Nazara/Renderer/RenderTexture.cpp index 6ecf0d628..af1b136cc 100644 --- a/src/Nazara/Renderer/RenderTexture.cpp +++ b/src/Nazara/Renderer/RenderTexture.cpp @@ -379,8 +379,8 @@ bool NzRenderTexture::Create(bool lock) onExit.Reset(); } - Notify(Listener::OnRenderTargetParametersChange); - Notify(Listener::OnRenderTargetSizeChange); + OnRenderTargetParametersChange(this); + OnRenderTargetSizeChange(this); return true; } diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index c7ac5ca49..97eb793d4 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -278,8 +278,8 @@ bool NzRenderWindow::OnWindowCreated() NzOpenGL::SetScissorBox(NzRecti(0, 0, size.x, size.y)); NzOpenGL::SetViewport(NzRecti(0, 0, size.x, size.y)); - Notify(Listener::OnRenderTargetParametersChange); - Notify(Listener::OnRenderTargetSizeChange); + OnRenderTargetParametersChange(this); + OnRenderTargetSizeChange(this); m_clock.Restart(); @@ -300,5 +300,5 @@ void NzRenderWindow::OnWindowDestroy() void NzRenderWindow::OnWindowResized() { - Notify(Listener::OnRenderTargetSizeChange); + OnRenderTargetSizeChange(this); } diff --git a/src/Nazara/Utility/AbstractAtlas.cpp b/src/Nazara/Utility/AbstractAtlas.cpp index 14283bb88..59b04762e 100644 --- a/src/Nazara/Utility/AbstractAtlas.cpp +++ b/src/Nazara/Utility/AbstractAtlas.cpp @@ -7,31 +7,5 @@ NzAbstractAtlas::~NzAbstractAtlas() { - NotifyRelease(Listener::OnAtlasReleased); -} - -NzAbstractAtlas::Listener::~Listener() = default; - -bool NzAbstractAtlas::Listener::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) -{ - NazaraUnused(atlas); - NazaraUnused(userdata); - - return true; -} - -bool NzAbstractAtlas::Listener::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) -{ - NazaraUnused(atlas); - NazaraUnused(oldLayer); - NazaraUnused(newLayer); - NazaraUnused(userdata); - - return true; -} - -void NzAbstractAtlas::Listener::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) -{ - NazaraUnused(atlas); - NazaraUnused(userdata); + OnAtlasRelease(this); } diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 754e9c455..17561decc 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -290,12 +290,19 @@ void NzFont::SetAtlas(const std::shared_ptr& atlas) { ClearGlyphCache(); - if (m_atlas) - m_atlas->RemoveListener(this); - m_atlas = atlas; if (m_atlas) - m_atlas->AddListener(this); + { + m_atlasClearedSlot = NazaraConnect(*m_atlas, OnAtlasCleared, OnAtlasCleared); + m_atlasLayerChangeSlot = NazaraConnect(*m_atlas, OnAtlasLayerChange, OnAtlasLayerChange); + m_atlasReleaseSlot = NazaraConnect(*m_atlas, OnAtlasRelease, OnAtlasRelease); + } + else + { + NazaraDisconnect(m_atlasClearedSlot); + NazaraDisconnect(m_atlasLayerChangeSlot); + NazaraDisconnect(m_atlasReleaseSlot); + } NotifyModified(ModificationCode_AtlasChanged); } @@ -403,10 +410,9 @@ nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const return (stylePart << 32) | sizePart; } -bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) +void NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas) { NazaraUnused(atlas); - NazaraUnused(userdata); #ifdef NAZARA_DEBUG // Est-ce qu'il s'agit bien de notre atlas ? @@ -420,16 +426,13 @@ bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) // Notre atlas vient d'être vidé, détruisons le cache de glyphe m_glyphes.clear(); NotifyModified(ModificationCode_GlyphCacheCleared); - - return true; } -bool NzFont::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) +void NzFont::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer) { NazaraUnused(atlas); NazaraUnused(oldLayer); NazaraUnused(newLayer); - NazaraUnused(userdata); #ifdef NAZARA_DEBUG // Est-ce qu'il s'agit bien de notre atlas ? @@ -442,14 +445,11 @@ bool NzFont::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* o // Pour faciliter le travail des ressources qui nous écoutent NotifyModified(ModificationCode_AtlasLayerChanged); - - return true; } -void NzFont::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) +void NzFont::OnAtlasRelease(const NzAbstractAtlas* atlas) { NazaraUnused(atlas); - NazaraUnused(userdata); #ifdef NAZARA_DEBUG // Est-ce qu'il s'agit bien de notre atlas ? diff --git a/src/Nazara/Utility/GuillotineImageAtlas.cpp b/src/Nazara/Utility/GuillotineImageAtlas.cpp index 94aafd47d..b80e739c6 100644 --- a/src/Nazara/Utility/GuillotineImageAtlas.cpp +++ b/src/Nazara/Utility/GuillotineImageAtlas.cpp @@ -22,7 +22,7 @@ NzGuillotineImageAtlas::~NzGuillotineImageAtlas() = default; void NzGuillotineImageAtlas::Clear() { m_layers.clear(); - Notify(Listener::OnAtlasCleared); + OnAtlasCleared(this); } void NzGuillotineImageAtlas::Free(NzSparsePtr rects, NzSparsePtr layers, unsigned int count) @@ -187,7 +187,7 @@ bool NzGuillotineImageAtlas::ResizeLayer(Layer& layer, const NzVector2ui& size) // On indique à ceux que ça intéresse qu'on a changé de pointeur // (chose très importante pour ceux qui le stockent) - Notify(Listener::OnAtlasLayerChange, layer.image.get(), newImage.get()); + OnAtlasLayerChange(this, layer.image.get(), newImage.get()); // Et on ne met à jour le pointeur qu'après (car cette ligne libère également l'ancienne image) layer.image = std::move(newImage);