Skip to content

Commit

Permalink
#5923: RenderableTargetLines are no longer updating all of their geom…
Browse files Browse the repository at this point in the history
…etry on every frame.
  • Loading branch information
codereader committed Mar 19, 2022
1 parent d92ccbd commit 3f42ccd
Show file tree
Hide file tree
Showing 14 changed files with 176 additions and 46 deletions.
5 changes: 4 additions & 1 deletion include/ientity.h
Expand Up @@ -425,14 +425,17 @@ class ITargetManager
* Returns the Target with the given name.
* This never returns NULL, an ITargetableObject is created if it doesn't exist yet.
*/
virtual ITargetableObjectPtr getTarget(const std::string name) = 0;
virtual ITargetableObjectPtr getTarget(const std::string& name) = 0;

/**
* greebo: Associates the named Target with the given scene::INode.
* The Target will be created if it doesn't exist yet.
*/
virtual void associateTarget(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;

/**
* greebo: Disassociates the Target from the given name. The node
* must also be passed to allow the manager to check the request.
Expand Down
1 change: 1 addition & 0 deletions radiantcore/entity/EntityNode.cpp
Expand Up @@ -159,6 +159,7 @@ void EntityNode::createAttachedEntities()
void EntityNode::transformChanged()
{
Node::transformChanged();
TargetableNode::onTransformationChanged();

// Broadcast transformChanged to all attached entities so they can update
// their position
Expand Down
17 changes: 16 additions & 1 deletion radiantcore/entity/target/RenderableTargetLines.h
Expand Up @@ -33,19 +33,34 @@ class RenderableTargetLines :

Vector3 _worldPosition;

bool _updateNeeded;

public:
RenderableTargetLines(const IEntityNode& entity, const TargetKeyCollection& targetKeys) :
_entity(entity),
_targetKeys(targetKeys)
_targetKeys(targetKeys),
_updateNeeded(true)
{}

void queueUpdate()
{
_updateNeeded = true;
}

bool hasTargets() const
{
return !_targetKeys.empty();
}

void update(const ShaderPtr& shader, const Vector3& worldPosition)
{
// Force an update on position change
_updateNeeded |= worldPosition != _worldPosition;

if (!_updateNeeded) return;

_updateNeeded = false;

// Store the new world position for use in updateGeometry()
_worldPosition = worldPosition;

Expand Down
32 changes: 26 additions & 6 deletions radiantcore/entity/target/Target.h
Expand Up @@ -5,6 +5,7 @@
#include "ilightnode.h"
#include "math/Vector3.h"
#include "math/AABB.h"
#include <sigc++/signal.h>

namespace entity {

Expand All @@ -28,31 +29,39 @@ class Target :
// The actual node this Target refers to (can be NULL)
const scene::INode* _node;

sigc::signal<void> _sigPositionChanged;

public:
Target()
Target() :
_node(nullptr)
{}

Target(const scene::INode& node) :
_node(&node)
{}

const scene::INode* getNode() const override {
const scene::INode* getNode() const override
{
return _node;
}

void setNode(const scene::INode& node) {
void setNode(const scene::INode& node)
{
_node = &node;
}

bool isEmpty() const override {
bool isEmpty() const override
{
return _node == nullptr;
}

bool isVisible() const {
bool isVisible() const
{
return _node != nullptr && _node->visible();
}

void clear() {
void clear()
{
_node = nullptr;
}

Expand All @@ -76,6 +85,17 @@ class Target :

return node->worldAABB().getOrigin();
}

// Invoked by the TargetManager when an entity's position changed
void onPositionChanged()
{
signal_PositionChanged().emit();
}

sigc::signal<void>& signal_PositionChanged()
{
return _sigPositionChanged;
}
};
typedef std::shared_ptr<Target> TargetPtr;

Expand Down
12 changes: 12 additions & 0 deletions radiantcore/entity/target/TargetKey.cpp
Expand Up @@ -15,12 +15,15 @@ void TargetKey::onTargetManagerChanged()

if (manager == nullptr)
{
_positionChangedSignal.disconnect();
_target.reset();
return;
}

_target = std::static_pointer_cast<Target>(manager->getTarget(_curValue));
assert(_target);

_target->signal_PositionChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged));
}

const TargetPtr& TargetKey::getTarget() const
Expand Down Expand Up @@ -50,9 +53,18 @@ void TargetKey::onKeyValueChanged(const std::string& newValue)
{
// If we have a target manager, acquire the Target right away
// Acquire the Target object (will be created if nonexistent)
_positionChangedSignal.disconnect();

_target = std::static_pointer_cast<Target>(targetManager->getTarget(_curValue));
assert(_target);

_target->signal_PositionChanged().connect(sigc::mem_fun(this, &TargetKey::onTargetPositionChanged));
}
}

void TargetKey::onTargetPositionChanged()
{
_owner.onTargetPositionChanged();
}

} // namespace entity
6 changes: 6 additions & 0 deletions radiantcore/entity/target/TargetKey.h
@@ -1,6 +1,7 @@
#pragma once

#include "ientity.h"
#include <sigc++/connection.h>

#include "Target.h"

Expand Down Expand Up @@ -30,6 +31,8 @@ class TargetKey :

// The target this key is pointing to (can be empty)
TargetPtr _target;

sigc::connection _positionChangedSignal;
public:
TargetKey(TargetKeyCollection& owner);

Expand All @@ -47,6 +50,9 @@ class TargetKey :

// This gets called as soon as the "target" key in the spawnargs changes
void onKeyValueChanged(const std::string& newValue) override;

private:
void onTargetPositionChanged();
};

} // namespace entity
12 changes: 11 additions & 1 deletion radiantcore/entity/target/TargetKeyCollection.cpp
Expand Up @@ -55,7 +55,7 @@ void TargetKeyCollection::onKeyInsert(const std::string& key, EntityKeyValue& va
return;
}

TargetKeyMap::iterator i = _targetKeys.insert(std::make_pair(key, TargetKey(*this))).first;
auto i = _targetKeys.emplace(key, TargetKey(*this)).first;

i->second.attachToKeyValue(value);

Expand Down Expand Up @@ -86,4 +86,14 @@ void TargetKeyCollection::onKeyErase(const std::string& key, EntityKeyValue& val
_owner.onTargetKeyCollectionChanged();
}

sigc::signal<void>& TargetKeyCollection::signal_TargetPositionChanged()
{
return _sigTargetPositionChanged;
}

void TargetKeyCollection::onTargetPositionChanged()
{
_sigTargetPositionChanged.emit();
}

} // namespace entity
9 changes: 9 additions & 0 deletions radiantcore/entity/target/TargetKeyCollection.h
@@ -1,6 +1,7 @@
#pragma once

#include <map>
#include <sigc++/signal.h>
#include "TargetKey.h"

namespace entity
Expand All @@ -18,6 +19,8 @@ class TargetKeyCollection :
typedef std::map<std::string, TargetKey> TargetKeyMap;
TargetKeyMap _targetKeys;

sigc::signal<void> _sigTargetPositionChanged;

public:
TargetKeyCollection(TargetableNode& owner);

Expand Down Expand Up @@ -45,6 +48,12 @@ class TargetKeyCollection :
// Returns TRUE if there are no "target" keys observed
bool empty() const;

// The TargetLineNode listens to this to reconstructs its renderables
sigc::signal<void>& signal_TargetPositionChanged();

// Invoked by the TargetKey instance if a single Target changes its position
void onTargetPositionChanged();

private:
// Returns TRUE if the given key matches the pattern for target keys
bool isTargetKey(const std::string& key);
Expand Down
18 changes: 16 additions & 2 deletions radiantcore/entity/target/TargetLineNode.cpp
Expand Up @@ -10,13 +10,21 @@ TargetLineNode::TargetLineNode(EntityNode& owner) :
scene::Node(),
_owner(owner),
_targetLines(_owner, _owner.getTargetKeys())
{}
{
_owner.getTargetKeys().signal_TargetPositionChanged().connect(
sigc::mem_fun(this, &TargetLineNode::queueRenderableUpdate)
);
}

TargetLineNode::TargetLineNode(TargetLineNode& other) :
scene::Node(other),
_owner(other._owner),
_targetLines(_owner, _owner.getTargetKeys())
{}
{
_owner.getTargetKeys().signal_TargetPositionChanged().connect(
sigc::mem_fun(this, &TargetLineNode::queueRenderableUpdate)
);
}

scene::INode::Type TargetLineNode::getNodeType() const
{
Expand Down Expand Up @@ -64,6 +72,7 @@ void TargetLineNode::renderHighlights(IRenderableCollector& collector, const Vol
void TargetLineNode::onRenderSystemChanged()
{
_targetLines.clear();
_targetLines.queueUpdate();
}

void TargetLineNode::onVisibilityChanged(bool visible)
Expand Down Expand Up @@ -106,4 +115,9 @@ Vector3 TargetLineNode::getOwnerPosition() const
return light->getSelectAABB().getOrigin();
}

void TargetLineNode::queueRenderableUpdate()
{
_targetLines.queueUpdate();
}

}
6 changes: 5 additions & 1 deletion radiantcore/entity/target/TargetLineNode.h
@@ -1,5 +1,6 @@
#pragma once

#include <sigc++/trackable.h>
#include "scene/Node.h"
#include "RenderableTargetLines.h"

Expand All @@ -17,7 +18,8 @@ class EntityNode;
* get culled by the space partitioning system during rendering.
*/
class TargetLineNode final :
public scene::Node
public scene::Node,
public sigc::trackable
{
private:
EntityNode& _owner;
Expand All @@ -43,6 +45,8 @@ class TargetLineNode final :
void onInsertIntoScene(scene::IMapRootNode& root) override;
void onRemoveFromScene(scene::IMapRootNode& root) override;

void queueRenderableUpdate();

protected:
void onVisibilityChanged(bool isVisibleNow) override;

Expand Down

0 comments on commit 3f42ccd

Please sign in to comment.