From 416c1ff183b950b6d3b45d2e7220ba763de9cb86 Mon Sep 17 00:00:00 2001 From: codereader Date: Sat, 19 Mar 2022 05:44:53 +0100 Subject: [PATCH] #5923: Handle visibility changes of targetable nodes --- include/ientity.h | 3 +++ radiantcore/entity/EntityNode.cpp | 1 + radiantcore/entity/target/Target.h | 12 ++++++++++-- radiantcore/entity/target/TargetKey.cpp | 4 ++-- radiantcore/entity/target/TargetManager.cpp | 14 ++++++++++++++ radiantcore/entity/target/TargetManager.h | 3 +++ radiantcore/entity/target/TargetableNode.cpp | 8 ++++++++ radiantcore/entity/target/TargetableNode.h | 2 ++ 8 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/ientity.h b/include/ientity.h index fe6576eb40..3741e19fd9 100644 --- a/include/ientity.h +++ b/include/ientity.h @@ -433,6 +433,9 @@ class ITargetManager */ virtual void associateTarget(const std::string& name, const scene::INode& node) = 0; + // Will be called by a TargetableNode to notify about visibility changes + virtual void onTargetVisibilityChanged(const std::string& name, const scene::INode& node) = 0; + // Will be called by a TargetableNode to notify about a position change virtual void onTargetPositionChanged(const std::string& name, const scene::INode& node) = 0; diff --git a/radiantcore/entity/EntityNode.cpp b/radiantcore/entity/EntityNode.cpp index 8523279a35..7c8e2015d6 100644 --- a/radiantcore/entity/EntityNode.cpp +++ b/radiantcore/entity/EntityNode.cpp @@ -478,6 +478,7 @@ std::size_t EntityNode::getHighlightFlags() void EntityNode::onVisibilityChanged(bool isVisibleNow) { SelectableNode::onVisibilityChanged(isVisibleNow); + TargetableNode::onVisibilityChanged(isVisibleNow); for (const auto& [node, _] : _attachedEnts) { diff --git a/radiantcore/entity/target/Target.h b/radiantcore/entity/target/Target.h index e44217349c..4d093646ed 100644 --- a/radiantcore/entity/target/Target.h +++ b/radiantcore/entity/target/Target.h @@ -62,6 +62,8 @@ class Target : void clear() { + // Notify any watchers on scene removal + signal_TargetChanged().emit(); _node = nullptr; } @@ -89,10 +91,16 @@ class Target : // Invoked by the TargetManager when an entity's position changed void onPositionChanged() { - signal_PositionChanged().emit(); + signal_TargetChanged().emit(); } - sigc::signal& signal_PositionChanged() + // Invoked by the TargetManager when an entity's visibility has changed + void onVisibilityChanged() + { + signal_TargetChanged().emit(); + } + + sigc::signal& signal_TargetChanged() { return _sigPositionChanged; } diff --git a/radiantcore/entity/target/TargetKey.cpp b/radiantcore/entity/target/TargetKey.cpp index 9422f47b75..035669f1cb 100644 --- a/radiantcore/entity/target/TargetKey.cpp +++ b/radiantcore/entity/target/TargetKey.cpp @@ -23,7 +23,7 @@ void TargetKey::onTargetManagerChanged() _target = std::static_pointer_cast(manager->getTarget(_curValue)); assert(_target); - _target->signal_PositionChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged)); + _target->signal_TargetChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged)); } const TargetPtr& TargetKey::getTarget() const @@ -58,7 +58,7 @@ void TargetKey::onKeyValueChanged(const std::string& newValue) _target = std::static_pointer_cast(targetManager->getTarget(_curValue)); assert(_target); - _target->signal_PositionChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged)); + _target->signal_TargetChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged)); } } diff --git a/radiantcore/entity/target/TargetManager.cpp b/radiantcore/entity/target/TargetManager.cpp index 33dd688a65..6a5d52dd11 100644 --- a/radiantcore/entity/target/TargetManager.cpp +++ b/radiantcore/entity/target/TargetManager.cpp @@ -36,6 +36,18 @@ ITargetableObjectPtr TargetManager::getTarget(const std::string& name) return target; } +void TargetManager::onTargetVisibilityChanged(const std::string& name, const scene::INode& node) +{ + if (name.empty()) return; + + auto existing = _targets.find(name); + + if (existing != _targets.end()) + { + existing->second->onVisibilityChanged(); + } +} + void TargetManager::onTargetPositionChanged(const std::string& name, const scene::INode& node) { if (name.empty()) return; @@ -63,6 +75,8 @@ void TargetManager::associateTarget(const std::string& name, const scene::INode& { // Already registered, but empty => associate it found->second->setNode(node); + // Trigger a visibility changed signal + found->second->onVisibilityChanged(); } else { // Non-empty target! diff --git a/radiantcore/entity/target/TargetManager.h b/radiantcore/entity/target/TargetManager.h index ed12da111c..7470441946 100644 --- a/radiantcore/entity/target/TargetManager.h +++ b/radiantcore/entity/target/TargetManager.h @@ -40,6 +40,9 @@ class TargetManager : */ void associateTarget(const std::string& name, const scene::INode& node) override; + // Is called by the TargetableNode to notify about visibility changes + void onTargetVisibilityChanged(const std::string& name, const scene::INode& node) override; + // Is called by the TargetableNode to notify about a position change void onTargetPositionChanged(const std::string& name, const scene::INode& node) override; diff --git a/radiantcore/entity/target/TargetableNode.cpp b/radiantcore/entity/target/TargetableNode.cpp index e674b1b79f..5f83282cfe 100644 --- a/radiantcore/entity/target/TargetableNode.cpp +++ b/radiantcore/entity/target/TargetableNode.cpp @@ -133,6 +133,14 @@ void TargetableNode::onRemoveFromScene(scene::IMapRootNode& root) _targetKeys.onTargetManagerChanged(); } +void TargetableNode::onVisibilityChanged(bool isVisibleNow) +{ + if (!_targetManager) return; + + // Notify the target manager that our position has changed + _targetManager->onTargetVisibilityChanged(_targetName, _node); +} + void TargetableNode::onTargetKeyCollectionChanged() { if (!_targetKeys.empty()) diff --git a/radiantcore/entity/target/TargetableNode.h b/radiantcore/entity/target/TargetableNode.h index 16089eaa60..52c6044330 100644 --- a/radiantcore/entity/target/TargetableNode.h +++ b/radiantcore/entity/target/TargetableNode.h @@ -69,6 +69,8 @@ class TargetableNode : void onInsertIntoScene(scene::IMapRootNode& root); void onRemoveFromScene(scene::IMapRootNode& root); + void onVisibilityChanged(bool isVisibleNow); + // Invoked by the TargetKeyCollection when the number of observed has changed void onTargetKeyCollectionChanged();