diff --git a/radiantcore/entity/EntityNode.cpp b/radiantcore/entity/EntityNode.cpp index e1e844cd9e..76988cd266 100644 --- a/radiantcore/entity/EntityNode.cpp +++ b/radiantcore/entity/EntityNode.cpp @@ -5,6 +5,8 @@ #include "icounter.h" #include "imodel.h" #include "itransformable.h" +#include "math/Hash.h" +#include "string/case_conv.h" #include "EntitySettings.h" @@ -202,6 +204,20 @@ const Vector3& EntityNode::getDirection() const return _direction; } +std::size_t EntityNode::getFingerprint() +{ + std::size_t hash = 0; + + // Entities are just a collection of key/value pairs, use them lower case, ignore inherited keys + _spawnArgs.forEachKeyValue([&](const std::string& key, const std::string& value) + { + math::combineHash(hash, std::hash()(string::to_lower_copy(key))); + math::combineHash(hash, std::hash()(string::to_lower_copy(value))); + }, false); + + return hash; +} + void EntityNode::testSelect(Selector& selector, SelectionTest& test) { test.BeginMesh(localToWorld()); diff --git a/radiantcore/entity/EntityNode.h b/radiantcore/entity/EntityNode.h index 5ea3608bb2..b835982361 100644 --- a/radiantcore/entity/EntityNode.h +++ b/radiantcore/entity/EntityNode.h @@ -3,6 +3,7 @@ #include #include "ientity.h" #include "inamespace.h" +#include "icomparablenode.h" #include "Bounded.h" #include "scene/SelectableNode.h" @@ -32,7 +33,8 @@ class EntityNode : public SelectionTestable, public Namespaced, public TargetableNode, - public Transformable + public Transformable, + public scene::IComparableNode { protected: // The entity class @@ -113,6 +115,9 @@ class EntityNode : Matrix4 localToParent() const override { return _localToParent; } Matrix4& localToParent() override { return _localToParent; } + // IComparableNode implementation + std::size_t getFingerprint() override; + // SelectionTestable implementation virtual void testSelect(Selector& selector, SelectionTest& test) override;