From 0722857ca47a3c76c2fed51a9a45b9901b0fff45 Mon Sep 17 00:00:00 2001 From: Matthew Mott Date: Wed, 30 Mar 2022 20:14:19 +0100 Subject: [PATCH] #5907: EntityClass::getVisibility() returns value from spawnargs Instead of a constant value, getVisibility() now returns the correct value based on the presence of an "editor_visibility" spawnarg. The value is initialised lazily by way of a new Lazy class template which provides a generic means of lazily initialising a value using a callback function. --- libs/generic/Lazy.h | 30 ++++++++++++++++++++++++++++ radiantcore/eclass/EClassManager.cpp | 15 ++++++-------- radiantcore/eclass/EntityClass.cpp | 6 +++++- radiantcore/eclass/EntityClass.h | 3 ++- test/Entity.cpp | 1 + 5 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 libs/generic/Lazy.h diff --git a/libs/generic/Lazy.h b/libs/generic/Lazy.h new file mode 100644 index 0000000000..b5fcbe654c --- /dev/null +++ b/libs/generic/Lazy.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +/// Wrapper for an arbitrary object which is initialised lazily via a functor +template class Lazy +{ + // Contained value (may or may not be initialised) + mutable std::optional _value; + + // Functor to initialise _value when required + using InitialiseFunc = std::function; + InitialiseFunc _initFunc; + +public: + + /// Construct the Lazy wrapper with a functor to be called when initialisation is required + Lazy(InitialiseFunc func): _initFunc(func) + {} + + /// Return the contained value, initialising via the functor if necessary + T get() const + { + if (!_value) + _value = _initFunc(); + + return *_value; + } +}; \ No newline at end of file diff --git a/radiantcore/eclass/EClassManager.cpp b/radiantcore/eclass/EClassManager.cpp index 624efcce58..7be65c7c4a 100644 --- a/radiantcore/eclass/EClassManager.cpp +++ b/radiantcore/eclass/EClassManager.cpp @@ -129,18 +129,15 @@ void EClassManager::resolveModelInheritance(const std::string& name, const Doom3 void EClassManager::parseDefFiles() { - rMessage() << "searching vfs directory 'def' for *.def\n"; + // Increase the parse stamp for this run + _curParseStamp++; - // Increase the parse stamp for this run - _curParseStamp++; - - { - ScopedDebugTimer timer("EntityDefs parsed: "); + { + ScopedDebugTimer timer("EntityDefs parsed: "); GlobalFileSystem().forEachFile( - "def/", "def", - [&](const vfs::FileInfo& fileInfo) { parseFile(fileInfo); } + "def/", "def", [&](const vfs::FileInfo& fileInfo) { parseFile(fileInfo); } ); - } + } } void EClassManager::resolveInheritance() diff --git a/radiantcore/eclass/EntityClass.cpp b/radiantcore/eclass/EntityClass.cpp index f7af91c75e..13b1564490 100644 --- a/radiantcore/eclass/EntityClass.cpp +++ b/radiantcore/eclass/EntityClass.cpp @@ -19,6 +19,10 @@ namespace EntityClass::EntityClass(const std::string& name, bool fixedSize) : _name(name), + _visibility([this]() { + return (getAttributeValue("editor_visibility") == "hidden" ? vfs::Visibility::HIDDEN + : vfs::Visibility::NORMAL); + }), _colour(UndefinedColour), _fixedSize(fixedSize) {} @@ -41,7 +45,7 @@ const IEntityClass* EntityClass::getParent() const vfs::Visibility EntityClass::getVisibility() const { - return _visibility; + return _visibility.get(); } sigc::signal& EntityClass::changedSignal() diff --git a/radiantcore/eclass/EntityClass.h b/radiantcore/eclass/EntityClass.h index b256e9c372..6bf7cc8804 100644 --- a/radiantcore/eclass/EntityClass.h +++ b/radiantcore/eclass/EntityClass.h @@ -7,6 +7,7 @@ #include "math/Vector3.h" #include "math/AABB.h" #include "string/string.h" +#include "generic/Lazy.h" #include "parser/DefTokeniser.h" @@ -43,7 +44,7 @@ class EntityClass EntityClass* _parent = nullptr; // UI visibility of this entity class - vfs::Visibility _visibility = vfs::Visibility::NORMAL; + Lazy _visibility; // Should this entity type be treated as a light? bool _isLight = false; diff --git a/test/Entity.cpp b/test/Entity.cpp index 652cd34728..3d112205be 100644 --- a/test/Entity.cpp +++ b/test/Entity.cpp @@ -1999,6 +1999,7 @@ TEST_F(EntityTest, GetEClassVisibility) // Hidden entity auto entityBase = GlobalEntityClassManager().findClass("atdm:entity_base"); ASSERT_TRUE(entityBase); + EXPECT_EQ(entityBase->getAttributeValue("editor_visibility"), "hidden"); EXPECT_EQ(entityBase->getVisibility(), vfs::Visibility::HIDDEN); }