From fa2a269e5a1d3ece89a238a4d05d649a07944ccc Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 6 May 2015 13:48:42 +0200 Subject: [PATCH] Utility/Node: Added listeners Former-commit-id: aeddcbc5c61b7b51333ed704065fe6a18f17b2dc --- include/Nazara/Utility/Node.hpp | 26 +++++++++++ src/Nazara/Graphics/SceneNode.cpp | 2 + src/Nazara/Utility/Node.cpp | 77 ++++++++++++++++++++++++++++++- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index 7f9662d33..bc24f9d7e 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -12,15 +12,20 @@ #include #include #include +#include #include class NAZARA_API NzNode { public: + class Listener; + NzNode(); NzNode(const NzNode& node); virtual ~NzNode(); + void AddListener(Listener* listener, void* userdata = nullptr) const; + void EnsureDerivedUpdate() const; void EnsureTransformMatrixUpdate() const; @@ -51,6 +56,7 @@ class NAZARA_API NzNode NzNode& Move(const NzVector3f& movement, nzCoordSys coordSys = nzCoordSys_Local); NzNode& Move(float movementX, float movementY, float movementZ = 0.f, nzCoordSys coordSys = nzCoordSys_Local); + void RemoveListener(Listener* listener) const; NzNode& Rotate(const NzQuaternionf& rotation, nzCoordSys coordSys = nzCoordSys_Local); NzNode& Scale(const NzVector3f& scale); @@ -88,6 +94,17 @@ class NAZARA_API NzNode 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); + }; + protected: void AddChild(NzNode* node) const; virtual void InvalidateNode(); @@ -113,6 +130,15 @@ class NAZARA_API NzNode bool m_inheritRotation; bool m_inheritScale; mutable bool m_transformMatrixUpdated; + + private: + void NotifyInvalidation(); + void NotifyParented(const NzNode* parent); + + private: + mutable std::unordered_map m_listeners; + bool m_listenersLocked; + }; #endif // NAZARA_NODE_HPP diff --git a/src/Nazara/Graphics/SceneNode.cpp b/src/Nazara/Graphics/SceneNode.cpp index 09a4148f3..e0e97e206 100644 --- a/src/Nazara/Graphics/SceneNode.cpp +++ b/src/Nazara/Graphics/SceneNode.cpp @@ -190,6 +190,8 @@ void NzSceneNode::InvalidateNode() void NzSceneNode::OnParenting(const NzNode* parent) { + NzNode::OnParenting(parent); + if (parent) { ///FIXME: Remonter jusqu'au premier parent de type SceneNode plutôt que de s'arrêter au premier venu diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index aea97ce63..be5fe899a 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -49,6 +49,16 @@ NzNode::~NzNode() } SetParent(nullptr); + + m_listenersLocked = true; + for (auto& pair : m_listeners) + pair.first->OnNodeReleased(this, pair.second); +} + +void NzNode::AddListener(Listener* listener, void* userdata) const +{ + if (!m_listenersLocked) + m_listeners.insert(std::make_pair(listener, userdata)); } void NzNode::EnsureDerivedUpdate() const @@ -283,6 +293,12 @@ NzNode& NzNode::Move(float moveX, float moveY, float moveZ, nzCoordSys coordSys) return Move(NzVector3f(moveX, moveY, moveZ), coordSys); } +void NzNode::RemoveListener(Listener* listener) const +{ + if (!m_listenersLocked) + m_listeners.erase(listener); +} + NzNode& NzNode::Rotate(const NzQuaternionf& rotation, nzCoordSys coordSys) { // Évitons toute mauvaise surprise .. @@ -645,11 +661,13 @@ void NzNode::InvalidateNode() for (NzNode* node : m_childs) node->InvalidateNode(); + + NotifyInvalidation(); } void NzNode::OnParenting(const NzNode* parent) { - NazaraUnused(parent); + NotifyParented(parent); } void NzNode::RemoveChild(NzNode* node) const @@ -703,3 +721,60 @@ void NzNode::UpdateTransformMatrix() const m_transformMatrix.MakeTransform(m_derivedPosition, m_derivedRotation, m_derivedScale); m_transformMatrixUpdated = true; } + +void NzNode::NotifyInvalidation() +{ + m_listenersLocked = true; + + auto it = m_listeners.begin(); + while (it != m_listeners.end()) + { + if (!it->first->OnNodeInvalidated(this, it->second)) + m_listeners.erase(it++); + else + ++it; + } + + m_listenersLocked = false; +} + +void NzNode::NotifyParented(const NzNode* parent) +{ + m_listenersLocked = true; + + auto it = m_listeners.begin(); + while (it != m_listeners.end()) + { + if (!it->first->OnNodeParented(this, parent, it->second)) + m_listeners.erase(it++); + else + ++it; + } + + m_listenersLocked = false; +} + +NzNode::Listener::~Listener() = default; + +bool NzNode::Listener::OnNodeInvalidated(const NzNode* node, void* userdata) +{ + NazaraUnused(node); + NazaraUnused(userdata); + + return true; +} + +bool NzNode::Listener::OnNodeParented(const NzNode* node, const NzNode* parent, void* userdata) +{ + NazaraUnused(node); + NazaraUnused(parent); + NazaraUnused(userdata); + + return true; +} + +void NzNode::Listener::OnNodeReleased(const NzNode* node, void* userdata) +{ + NazaraUnused(node); + NazaraUnused(userdata); +}