diff --git a/examples/tutorials/nb_python/ECCV_2020_Advanced_Features.py b/examples/tutorials/nb_python/ECCV_2020_Advanced_Features.py index e2b04a58b8..cff7459bd1 100644 --- a/examples/tutorials/nb_python/ECCV_2020_Advanced_Features.py +++ b/examples/tutorials/nb_python/ECCV_2020_Advanced_Features.py @@ -171,7 +171,11 @@ def build_dict_of_PhyObj_attrs(phys_obj_template): False, "boolean", ) - res_dict["is_dirty"] = (phys_obj_template.is_dirty, False, "boolean") + res_dict["filenames_are_dirty"] = ( + phys_obj_template.filenames_are_dirty, + False, + "boolean", + ) return res_dict diff --git a/examples/tutorials/nb_python/asset_viewer.py b/examples/tutorials/nb_python/asset_viewer.py index 800996632a..fc7aacb6fa 100644 --- a/examples/tutorials/nb_python/asset_viewer.py +++ b/examples/tutorials/nb_python/asset_viewer.py @@ -331,7 +331,11 @@ def build_dict_of_PhyObj_attrs(phys_obj_template): "boolean", ) res_dict["is_collidable"] = (phys_obj_template.is_collidable, True, "boolean") - res_dict["is_dirty"] = (phys_obj_template.is_dirty, False, "boolean") + res_dict["filenames_are_dirty"] = ( + phys_obj_template.filenames_are_dirty, + False, + "boolean", + ) return res_dict diff --git a/examples/tutorials/notebooks/ECCV_2020_Advanced_Features.ipynb b/examples/tutorials/notebooks/ECCV_2020_Advanced_Features.ipynb index ba236a60b4..4c70621a03 100644 --- a/examples/tutorials/notebooks/ECCV_2020_Advanced_Features.ipynb +++ b/examples/tutorials/notebooks/ECCV_2020_Advanced_Features.ipynb @@ -163,7 +163,11 @@ " False,\n", " \"boolean\",\n", " )\n", - " res_dict[\"is_dirty\"] = (phys_obj_template.is_dirty, False, \"boolean\")\n", + " res_dict[\"filenames_are_dirty\"] = (\n", + " phys_obj_template.filenames_are_dirty,\n", + " False,\n", + " \"boolean\",\n", + " )\n", " return res_dict\n", "\n", "\n", diff --git a/examples/tutorials/notebooks/asset_viewer.ipynb b/examples/tutorials/notebooks/asset_viewer.ipynb index 1d7e244125..b482cf35f0 100644 --- a/examples/tutorials/notebooks/asset_viewer.ipynb +++ b/examples/tutorials/notebooks/asset_viewer.ipynb @@ -329,7 +329,11 @@ " \"boolean\",\n", " )\n", " res_dict[\"is_collidable\"] = (phys_obj_template.is_collidable, True, \"boolean\")\n", - " res_dict[\"is_dirty\"] = (phys_obj_template.is_dirty, False, \"boolean\")\n", + " res_dict[\"filenames_are_dirty\"] = (\n", + " phys_obj_template.filenames_are_dirty,\n", + " False,\n", + " \"boolean\",\n", + " )\n", " return res_dict\n", "\n", "\n", diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index 3227d510b6..f0ad6df3fd 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -2885,7 +2885,7 @@ bool ResourceManager::instantiateAssetsOnDemand( // object has acquired a copy of its parent attributes. No object should // ever have a copy of attributes with isDirty == true - any editing of // attributes for objects requires object rebuilding. - if (objectAttributes->getIsDirty()) { + if (objectAttributes->getFilePathsAreDirty()) { CORRADE_ASSERT( (getObjectAttributesManager()->registerObject( objectAttributes, objectTemplateHandle) != ID_UNDEFINED), diff --git a/src/esp/bindings/AttributesBindings.cpp b/src/esp/bindings/AttributesBindings.cpp index e086ea896c..47e9e876f6 100644 --- a/src/esp/bindings/AttributesBindings.cpp +++ b/src/esp/bindings/AttributesBindings.cpp @@ -453,7 +453,11 @@ void initAttributesBindings(py::module& m) { R"(Class name of Attributes template.)") .def_property_readonly( "csv_info", &AbstractAttributes::getObjectInfo, - R"(Comma-separated informational string describing this Attributes template)"); + R"(Comma-separated informational string describing this Attributes template)") + .def_property_readonly( + "filenames_are_dirty", &AbstractAttributes::getFilePathsAreDirty, + R"(Whether filenames or paths in this attributes have been changed requiring + re-registration before they can be used to create an object. )"); // Attributes should only use named properties or subconfigurations to set // specific values, to guarantee essential value type integrity. This will @@ -680,11 +684,7 @@ void initAttributesBindings(py::module& m) { .def_property( "is_collidable", &ObjectAttributes::getIsCollidable, &ObjectAttributes::setIsCollidable, - R"(Whether constructions built from this template are collidable upon initialization.)") - .def_property_readonly( - "is_dirty", &AbstractObjectAttributes::getIsDirty, - R"(Whether values in this attributes have been changed requiring - re-registration before they can be used to create an object. )"); + R"(Whether constructions built from this template are collidable upon initialization.)"); // ==== ObjectAttributes ==== py::class_( diff --git a/src/esp/core/managedContainers/AbstractFileBasedManagedObject.h b/src/esp/core/managedContainers/AbstractFileBasedManagedObject.h index 402d8ee8ac..49d23239c6 100644 --- a/src/esp/core/managedContainers/AbstractFileBasedManagedObject.h +++ b/src/esp/core/managedContainers/AbstractFileBasedManagedObject.h @@ -42,6 +42,26 @@ class AbstractFileBasedManagedObject : public AbstractManagedObject { */ virtual std::string getActualFilename() const = 0; + /** + * @brief Get whether this ManagedObject has been saved to disk in its current + * state. Only applicable to registered ManagedObjects + */ + virtual bool isAttrSaved() const = 0; + + /** + * @brief Set that this ManagedObject has values that are different than its + * most recently saved-to-disk version. This is called when the ManagedObject + * is registered. + */ + + void setAttrIsNotSaved() { setFileSaveStatus(false); } + + /** + * @brief Set that this ManagedObject is the same as its saved-to-disk + * version. This is called when the ManagedObject is saved to disk. + */ + void setAttrIsSaved() { setFileSaveStatus(true); } + /** * @brief This will return a simplified version of the * AbstractFileBasedManagedObject handle, removing extensions and any parent @@ -66,6 +86,13 @@ class AbstractFileBasedManagedObject : public AbstractManagedObject { virtual io::JsonGenericValue writeToJsonObject( io::JsonAllocator& allocator) const = 0; + protected: + /** + * @brief Set this ManagedObject's save status (i.e. whether it matches its + * version on disk or not) + */ + virtual void setFileSaveStatus(bool _isSaved) = 0; + public: ESP_SMART_POINTERS(AbstractFileBasedManagedObject) }; // class AbstractFileBasedManagedObject diff --git a/src/esp/core/managedContainers/ManagedContainer.h b/src/esp/core/managedContainers/ManagedContainer.h index dd4590c011..4654c7939e 100644 --- a/src/esp/core/managedContainers/ManagedContainer.h +++ b/src/esp/core/managedContainers/ManagedContainer.h @@ -163,11 +163,10 @@ class ManagedContainer : public ManagedContainerBase { "registration, so registration aborted."; return ID_UNDEFINED; } - if ("" != objectHandle) { - return this->registerObjectInternal(std::move(managedObject), - objectHandle, forceRegistration); - } - std::string handleToSet = managedObject->getHandle(); + // If no handle give, query object for handle + std::string handleToSet = + ("" == objectHandle) ? managedObject->getHandle() : objectHandle; + // if still no handle, fail registration if ("" == handleToSet) { ESP_ERROR(Magnum::Debug::Flag::NoSpace) << "<" << this->objectType_ @@ -175,6 +174,7 @@ class ManagedContainer : public ManagedContainerBase { "so registration aborted."; return ID_UNDEFINED; } + // Perform actual registration return this->registerObjectInternal(std::move(managedObject), handleToSet, forceRegistration); } // ManagedContainer::registerObject @@ -193,8 +193,7 @@ class ManagedContainer : public ManagedContainerBase { */ ManagedPtr getObjectByID(int managedObjectID) const { std::string objectHandle = getObjectHandleByID(managedObjectID); - if (!checkExistsWithMessage(objectHandle, - "<" + this->objectType_ + ">::getObjectByID")) { + if (!checkExistsWithMessage(objectHandle, "getObjectByID")) { return nullptr; } return getObjectInternal(objectHandle); @@ -212,8 +211,7 @@ class ManagedContainer : public ManagedContainerBase { * exist */ ManagedPtr getObjectByHandle(const std::string& objectHandle) const { - if (!checkExistsWithMessage( - objectHandle, "<" + this->objectType_ + ">::getObjectByHandle")) { + if (!checkExistsWithMessage(objectHandle, "getObjectByHandle")) { return nullptr; } return getObjectInternal(objectHandle); @@ -250,7 +248,7 @@ class ManagedContainer : public ManagedContainerBase { /** * @brief Retrieve a map of key= std::string handle; value = copy of * ManagedPtr object where the handles match the passed @p . See @ref - * ManagedContainerBase::getObjectHandlesBySubStringPerType. + * ManagedContainerBase::getAllObjectHandlesBySubStringPerType. * @param subStr substring key to search for within existing managed objects. * @param contains whether to search for keys containing, or excluding, * passed @p subStr @@ -260,8 +258,8 @@ class ManagedContainer : public ManagedContainerBase { std::unordered_map getObjectsByHandleSubstring( const std::string& subStr = "", bool contains = true) { - std::vector keys = this->getObjectHandlesBySubStringPerType( - objectLibKeyByID_, subStr, contains, false); + std::vector keys = + this->getAllObjectHandlesBySubStringPerType(subStr, contains, false); std::unordered_map res; res.reserve(keys.size()); @@ -280,7 +278,7 @@ class ManagedContainer : public ManagedContainerBase { /** * @brief Templated version. Retrieve a map of key= std::string handle; value * = copy of ManagedPtr object where the handles match the passed @p . See - * @ref ManagedContainerBase::getObjectHandlesBySubStringPerType. + * @ref ManagedContainerBase::getAllObjectHandlesBySubStringPerType. * * @tparam Desired downcast class that inerheits from this ManagedContainer's * ManagedObject type. @@ -294,8 +292,11 @@ class ManagedContainer : public ManagedContainerBase { std::unordered_map> getObjectsByHandleSubstring(const std::string& subStr = "", bool contains = true) { - std::vector keys = this->getObjectHandlesBySubStringPerType( - objectLibKeyByID_, subStr, contains, false); + static_assert(std::is_base_of::value, + "ManagedContainer :: Desired type must be derived from " + "Managed object type"); + std::vector keys = + this->getAllObjectHandlesBySubStringPerType(subStr, contains, false); std::unordered_map> res; res.reserve(keys.size()); @@ -321,13 +322,10 @@ class ManagedContainer : public ManagedContainerBase { */ ManagedPtr removeObjectByID(int objectID) { std::string objectHandle = getObjectHandleByID(objectID); - if (!checkExistsWithMessage( - objectHandle, "<" + this->objectType_ + ">::removeObjectByID")) { + if (!checkExistsWithMessage(objectHandle, "removeObjectByID")) { return nullptr; } - return removeObjectInternal( - objectID, objectHandle, - "<" + this->objectType_ + ">::removeObjectByID"); + return removeObjectInternal(objectID, objectHandle, "removeObjectByID"); } /** @@ -339,17 +337,14 @@ class ManagedContainer : public ManagedContainerBase { * exist */ ManagedPtr removeObjectByHandle(const std::string& objectHandle) { - if (!checkExistsWithMessage(objectHandle, "<" + this->objectType_ + - ">::removeObjectByHandle")) { + if (!checkExistsWithMessage(objectHandle, "removeObjectByHandle")) { return nullptr; } int objectID = this->getObjectIDByHandle(objectHandle); if (objectID == ID_UNDEFINED) { return nullptr; } - return removeObjectInternal( - objectID, objectHandle, - "<" + this->objectType_ + ">::removeObjectByHandle"); + return removeObjectInternal(objectID, objectHandle, "removeObjectByHandle"); } /** @@ -461,6 +456,9 @@ class ManagedContainer : public ManagedContainerBase { */ template std::shared_ptr getObjectOrCopyByHandle(const std::string& objectHandle) { + static_assert(std::is_base_of::value, + "ManagedContainer :: Desired type must be derived from " + "Managed object type"); // call non-template version auto res = getObjectOrCopyByHandle(objectHandle); if (nullptr == res) { @@ -480,8 +478,7 @@ class ManagedContainer : public ManagedContainerBase { */ ManagedPtr getObjectCopyByID(int managedObjectID) { std::string objectHandle = getObjectHandleByID(managedObjectID); - if (!checkExistsWithMessage( - objectHandle, "<" + this->objectType_ + ">::getObjectCopyByID")) { + if (!checkExistsWithMessage(objectHandle, "getObjectCopyByID")) { return nullptr; } auto orig = getObjectInternal(objectHandle); @@ -496,8 +493,7 @@ class ManagedContainer : public ManagedContainerBase { * does not exist */ ManagedPtr getObjectCopyByHandle(const std::string& objectHandle) { - if (!checkExistsWithMessage(objectHandle, "<" + this->objectType_ + - ">::getObjectCopyByHandle")) { + if (!checkExistsWithMessage(objectHandle, "getObjectCopyByHandle")) { return nullptr; } auto orig = getObjectInternal(objectHandle); @@ -544,6 +540,9 @@ class ManagedContainer : public ManagedContainerBase { */ template std::shared_ptr getObjectCopyByID(int managedObjectID) { + static_assert(std::is_base_of::value, + "ManagedContainer :: Desired type must be derived from " + "Managed object type"); // call non-template version auto res = getObjectCopyByID(managedObjectID); if (nullptr == res) { @@ -563,6 +562,9 @@ class ManagedContainer : public ManagedContainerBase { */ template std::shared_ptr getObjectCopyByHandle(const std::string& objectHandle) { + static_assert(std::is_base_of::value, + "ManagedContainer :: Desired type must be derived from " + "Managed object type"); // call non-template version auto res = getObjectCopyByHandle(objectHandle); if (nullptr == res) { @@ -635,18 +637,22 @@ class ManagedContainer : public ManagedContainerBase { const std::string& src); /** - * @brief Build a shared pointer to a copy of a the passed managed object, - * of appropriate managed object type for passed object type. This is the - * function called by the copy constructor map. + * @brief This is the function called by the copy constructor map. Build a + * shared pointer to a copy of a the passed managed object, of appropriate + * managed object type for passed object type. + * * @tparam U Type of managed object being created - must be a derived class * of ManagedPtr * @param orig original object of type ManagedPtr being copied */ - template - ManagedPtr createObjectCopy(ManagedPtr& orig) { + template + ManagedPtr createObjCopyCtorMapEntry(ManagedPtr& orig) { + static_assert(std::is_base_of::value, + "ManagedContainer :: Desired type must be derived from " + "Managed object type"); // don't call init on copy - assume copy is already properly initialized. return U::create(*(static_cast(orig.get()))); - } // ManagedContainer:: + } // ManagedContainer::createObjCopyCtorMapEntry /** * @brief Build an @ref esp::core::managedContainers::AbstractManagedObject @@ -770,8 +776,7 @@ class ManagedContainer : public ManagedContainerBase { // original ManagedPtr managedObjectCopy = copyObject(object); // add to libraries - setObjectInternal(managedObjectCopy, objectHandle); - objectLibKeyByID_.emplace(objectID, objectHandle); + setObjectInternal(managedObjectCopy, objectID, objectHandle); return objectID; } // ManagedContainer::addObjectToLibrary @@ -817,8 +822,8 @@ auto ManagedContainer::removeObjectsBySubstring( getObjectHandlesBySubstring(subStr, contains); for (const std::string& objectHandle : handles) { int objID = this->getObjectIDByHandle(objectHandle); - ManagedPtr ptr = removeObjectInternal(objID, objectHandle, - "<" + this->objectType_ + ">"); + ManagedPtr ptr = + removeObjectInternal(objID, objectHandle, "removeObjectsBySubstring"); if (nullptr != ptr) { res.push_back(ptr); } @@ -832,19 +837,23 @@ auto ManagedContainer::removeObjectInternal( const std::string& objectHandle, const std::string& sourceStr) -> ManagedPtr { if (!checkExistsWithMessage(objectHandle, sourceStr)) { - ESP_DEBUG() << sourceStr << ": Unable to remove" << objectType_ - << "managed object" << objectHandle << ": Does not exist."; + ESP_DEBUG(Magnum::Debug::Flag::NoSpace) + << "<" + this->objectType_ + ">::" << sourceStr + << " : Unable to remove requested managed object `" << objectHandle + << "` : Does not exist."; return nullptr; } std::string msg; if (this->getIsUndeletable(objectHandle)) { msg = "Required Undeletable Managed Object"; } else if (this->getIsUserLocked(objectHandle)) { - msg = "User-locked Object. To delete managed object, unlock it"; + msg = "User-locked Object. To delete managed object, unlock it"; } if (msg.length() != 0) { - ESP_DEBUG() << sourceStr << ": Unable to remove" << objectType_ - << "managed object" << objectHandle << ":" << msg << "."; + ESP_DEBUG(Magnum::Debug::Flag::NoSpace) + << "<" + this->objectType_ + ">::" << sourceStr + << " : Unable to remove requested managed object `" << objectHandle + << "` : Object is a " << msg << "."; return nullptr; } ManagedPtr managedObject = getObjectInternal(objectHandle); diff --git a/src/esp/core/managedContainers/ManagedContainerBase.cpp b/src/esp/core/managedContainers/ManagedContainerBase.cpp index 099f2fc0ea..b7b4f25baf 100644 --- a/src/esp/core/managedContainers/ManagedContainerBase.cpp +++ b/src/esp/core/managedContainers/ManagedContainerBase.cpp @@ -15,8 +15,7 @@ namespace managedContainers { bool ManagedContainerBase::setLock(const std::string& objectHandle, bool lock) { // if managed object does not currently exist then do not attempt to modify // its lock state - if (!checkExistsWithMessage(objectHandle, - "<" + this->objectType_ + ">::setLock")) { + if (!checkExistsWithMessage(objectHandle, "setLock")) { return false; } // if setting lock else clearing lock diff --git a/src/esp/core/managedContainers/ManagedContainerBase.h b/src/esp/core/managedContainers/ManagedContainerBase.h index 6030f6f28a..aba0eb44be 100644 --- a/src/esp/core/managedContainers/ManagedContainerBase.h +++ b/src/esp/core/managedContainers/ManagedContainerBase.h @@ -92,7 +92,7 @@ class ManagedContainerBase { bool contains = true) { std::vector handles = getObjectHandlesBySubstring(subStr, contains); - return this->setLockByHandles(handles, lock); + return setLockByHandles(handles, lock); } // ManagedContainerBase::setLockBySubstring /** @@ -143,8 +143,8 @@ class ManagedContainerBase { * managed objects cannot be deleted, although they can be edited. */ std::vector getUndeletableObjectHandles() const { - std::vector res(this->undeletableObjectNames_.begin(), - this->undeletableObjectNames_.end()); + std::vector res(undeletableObjectNames_.begin(), + undeletableObjectNames_.end()); return res; } // ManagedContainerBase::getUndeletableObjectHandles @@ -154,7 +154,7 @@ class ManagedContainerBase { * @return True if handle exists and is undeletable. */ bool getIsUndeletable(const std::string& key) const { - return (this->undeletableObjectNames_.count(key) > 0); + return (undeletableObjectNames_.count(key) > 0); } /** @@ -164,8 +164,8 @@ class ManagedContainerBase { * locked. */ std::vector getUserLockedObjectHandles() const { - std::vector res(this->userLockedObjectNames_.begin(), - this->userLockedObjectNames_.end()); + std::vector res(userLockedObjectNames_.begin(), + userLockedObjectNames_.end()); return res; } // ManagedContainerBase::getUserLockedObjectHandles @@ -175,7 +175,7 @@ class ManagedContainerBase { * @return True if handle exists and is user-locked. */ bool getIsUserLocked(const std::string& key) const { - return (this->userLockedObjectNames_.count(key) > 0); + return (userLockedObjectNames_.count(key) > 0); } /** @@ -296,14 +296,16 @@ class ManagedContainerBase { } /** - * @brief Only used from class template AddObject method. put the passed + * @brief Only used from class template AddObject method. put the passed * smart poitner in the library. * @param ptr the smart pointer to the object being managed * @param handle the name (key) to use for the object in the library */ void setObjectInternal(const std::shared_ptr& ptr, + int objId, const std::string& handle) { objectLibrary_[handle] = ptr; + objectLibKeyByID_.emplace(objId, handle); } /** @@ -328,8 +330,9 @@ class ManagedContainerBase { const std::string& src) const { if (!getObjectLibHasHandle(objectHandle)) { ESP_ERROR(Magnum::Debug::Flag::NoSpace) - << src << ":" << objectType_ << " managed object handle `" - << objectHandle << "` not found in ManagedContainer, so aborting."; + << "<" + this->objectType_ + ">::" << src + << " : Managed object handle `" << objectHandle + << "` not found in ManagedContainer, so aborting."; return false; } return true; @@ -399,6 +402,26 @@ class ManagedContainerBase { bool contains, bool sorted) const; + /** + * @brief Get a list of all managed objects' handles of passed type whose + * origin handles contain substr, ignoring subStr's case. + * + * This version works on the internal objectLibKeyByID_ map + * @param subStr substring to search for within existing managed objects + * @param contains Whether to search for handles containing, or not + * containing, substr + * @param sorted whether the return vector values are sorted + * @return vector of 0 or more managed object handles containing/not + * containing the passed substring + */ + std::vector getAllObjectHandlesBySubStringPerType( + const std::string& subStr, + bool contains, + bool sorted) const { + return getObjectHandlesBySubStringPerType(objectLibKeyByID_, subStr, + contains, sorted); + } + /** * @brief Get a list of all managed objects' handles of passed type whose * origin handles contain substr, ignoring subStr's case. @@ -441,16 +464,40 @@ class ManagedContainerBase { virtual void resetFinalize() = 0; // ======== Instance Variables ======== - /** - * @brief Maps string keys to managed object managed objects - */ - std::unordered_map> objectLibrary_; /** @brief A descriptive name of the managed object being managed by this * manager. */ const std::string objectType_; + /** + * @brief Provide a const iterator over the @p objectLibrary_ + */ + std::pair< + std::unordered_map>::const_iterator, + std::unordered_map>::const_iterator> + getObjectLibIterator() const { + return std::make_pair(objectLibrary_.cbegin(), objectLibrary_.cend()); + } + + /** + * @brief Clear the mapping of undeletable object handles + */ + void clearUndeletableObjectNames() { undeletableObjectNames_.clear(); } + + /** + * @brief Add an undeleteable object's name to the mapping + */ + void addUndeletableObjectName(std::string objName) { + undeletableObjectNames_.insert(std::move(objName)); + } + + private: + /** + * @brief Maps string keys to managed object managed objects + */ + std::unordered_map> objectLibrary_; + /** * @brief Maps all object attribute IDs to the appropriate handles used * by lib diff --git a/src/esp/core/managedContainers/ManagedFileBasedContainer.h b/src/esp/core/managedContainers/ManagedFileBasedContainer.h index f7f0308766..d1bb7e701b 100644 --- a/src/esp/core/managedContainers/ManagedFileBasedContainer.h +++ b/src/esp/core/managedContainers/ManagedFileBasedContainer.h @@ -81,6 +81,9 @@ class ManagedFileBasedContainer : public ManagedContainer { const io::JsonGenericValue config = docConfig->GetObject(); ManagedFileIOPtr attr = this->buildManagedObjectFromDoc(filename, config); attr->setActualFilename(filename); + // Set attributes' status to saved (i.e. it matches the version on disk) + // since it was just loaded. + attr->setAttrIsSaved(); return this->postCreateRegister(std::move(attr), registerObject); } // ManagedFileBasedContainer::createObjectFromJSONFile @@ -110,6 +113,9 @@ class ManagedFileBasedContainer : public ManagedContainer { // convert doc to const value const io::JsonGenericValue config = docConfig->GetObject(); ManagedFileIOPtr attr = this->buildManagedObjectFromDoc(docName, config); + // Set attributes' status to saved (i.e. it matches the version on disk) + // since it was just built from an existing JSON string. + attr->setAttrIsSaved(); return this->postCreateRegister(std::move(attr), registerObject); } // ManagedFileBasedContainer::createObjectFromJSONString @@ -377,6 +383,8 @@ class ManagedFileBasedContainer : public ManagedContainer { // attributes. Note : this will not be "permanent" for the object unless // it is registered after this save. managedObject->setActualFilename(fullFilename); + // Set attributes' status to saved (i.e. it matches the version on disk) + managedObject->setAttrIsSaved(); } else { ESP_ERROR(Mn::Debug::Flag::NoSpace) << "<" << this->objectType_ << "> : Attempt to save to Filename `" diff --git a/src/esp/metadata/attributes/AbstractAttributes.cpp b/src/esp/metadata/attributes/AbstractAttributes.cpp index a1c3823101..6de0868cdc 100644 --- a/src/esp/metadata/attributes/AbstractAttributes.cpp +++ b/src/esp/metadata/attributes/AbstractAttributes.cpp @@ -22,6 +22,9 @@ AbstractAttributes::AbstractAttributes(const std::string& attributesClassKey, setHidden("__ID", 0); setHidden("__fileDirectory", ""); setHidden("__actualFilename", ""); + // Initialize attributes to be different than on version on disk, if one + // exists. This should be set to true on file load and on file save. + setHidden("__isAttrSaved", false); } } // namespace attributes diff --git a/src/esp/metadata/attributes/AbstractAttributes.h b/src/esp/metadata/attributes/AbstractAttributes.h index 8acf6880be..ba414933d8 100644 --- a/src/esp/metadata/attributes/AbstractAttributes.h +++ b/src/esp/metadata/attributes/AbstractAttributes.h @@ -186,7 +186,42 @@ class AbstractAttributes getObjectInfoInternal()); } + /** + * @brief Check whether filepath-based fields have been set by user input + * but have not been verified to exist (such verification occurs when the + * attributes is registered.) + */ + bool getFilePathsAreDirty() const { return get("__fileNamesDirty"); } + + /** + * @brief Clear the flag that specifies that filepath-based fields have been + * set but not verfified to exist (such verification occurs when the + * attributes is registered.) + */ + void setFilePathsAreClean() { setHidden("__fileNamesDirty", false); } + + /** + * @brief Get whether this ManagedObject has been saved to disk in its current + * state. Only applicable to registered ManagedObjects + */ + bool isAttrSaved() const override { return get("__isAttrSaved"); } + protected: + /** + * @brief Set this ManagedObject's save status (i.e. whether it matches its + * version on disk or not) + */ + void setFileSaveStatus(bool _isSaved) override { + setHidden("__isAttrSaved", _isSaved); + } + + /** + * @brief Used internally only. Set the flag that specifies a filepath-based + * field has been set to some value but has not yet been verified to + * exist (such verification occurs when the attributes is registered.) + */ + void setFilePathsAreDirty() { setHidden("__fileNamesDirty", true); } + /** * @brief Changing access to setter so that Configuration bindings cannot be * used to set a reserved value to an incorrect type. The inheritors of this diff --git a/src/esp/metadata/attributes/AbstractObjectAttributes.cpp b/src/esp/metadata/attributes/AbstractObjectAttributes.cpp index 828ae95e3f..02debe8a6c 100644 --- a/src/esp/metadata/attributes/AbstractObjectAttributes.cpp +++ b/src/esp/metadata/attributes/AbstractObjectAttributes.cpp @@ -51,7 +51,7 @@ AbstractObjectAttributes::AbstractObjectAttributes( // This specifies that we want to investigate the state of the render and // collision handles before we allow this attributes to be registered. // Hidden field - setIsDirty(); + setFilePathsAreDirty(); // set up an existing subgroup for marker_sets attributes addOrEditSubgroup("marker_sets"); } // AbstractObjectAttributes ctor diff --git a/src/esp/metadata/attributes/AbstractObjectAttributes.h b/src/esp/metadata/attributes/AbstractObjectAttributes.h index ff0f2f581a..be9258bb38 100644 --- a/src/esp/metadata/attributes/AbstractObjectAttributes.h +++ b/src/esp/metadata/attributes/AbstractObjectAttributes.h @@ -121,7 +121,7 @@ class AbstractObjectAttributes : public AbstractAttributes { */ void setRenderAssetHandle(const std::string& renderAssetHandle) { set("render_asset", renderAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -140,7 +140,7 @@ class AbstractObjectAttributes : public AbstractAttributes { */ void setRenderAssetFullPath(const std::string& renderAssetHandle) { setHidden("__renderAssetFullPath", renderAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -279,7 +279,7 @@ class AbstractObjectAttributes : public AbstractAttributes { */ void setCollisionAssetHandle(const std::string& collisionAssetHandle) { set("collision_asset", collisionAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -298,7 +298,7 @@ class AbstractObjectAttributes : public AbstractAttributes { */ void setCollisionAssetFullPath(const std::string& collisionAssetHandle) { setHidden("__collisionAssetFullPath", collisionAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -508,9 +508,6 @@ class AbstractObjectAttributes : public AbstractAttributes { */ bool getForceFlatShading() const { return get("force_flat_shading"); } - bool getIsDirty() const { return get("__isDirty"); } - void setIsClean() { setHidden("__isDirty", false); } - /** * @brief Populate a json object with all the first-level values held in this * configuration. Default is overridden to handle special cases for @@ -594,7 +591,6 @@ class AbstractObjectAttributes : public AbstractAttributes { * @brief get AbstractObject specific info for csv string */ virtual std::string getAbstractObjectInfoInternal() const { return ""; }; - void setIsDirty() { setHidden("__isDirty", true); } public: ESP_SMART_POINTERS(AbstractObjectAttributes) diff --git a/src/esp/metadata/attributes/ArticulatedObjectAttributes.cpp b/src/esp/metadata/attributes/ArticulatedObjectAttributes.cpp index eac17b58e9..ba19c0b70c 100644 --- a/src/esp/metadata/attributes/ArticulatedObjectAttributes.cpp +++ b/src/esp/metadata/attributes/ArticulatedObjectAttributes.cpp @@ -42,7 +42,10 @@ ArticulatedObjectAttributes::ArticulatedObjectAttributes( // Initialize these so they exist in the configuration setHidden("__urdfFullPath", ""); setHidden("__renderAssetFullPath", ""); - + // This specifies that we want to investigate the state of the urdf and skin + // render asset handles before we allow this attributes to be registered. + // Hidden field + setFilePathsAreDirty(); // set up an existing subgroup for marker_sets attributes addOrEditSubgroup("marker_sets"); } // ArticulatedObjectAttributes ctor diff --git a/src/esp/metadata/attributes/ArticulatedObjectAttributes.h b/src/esp/metadata/attributes/ArticulatedObjectAttributes.h index 5a9d6aa147..87998b450d 100644 --- a/src/esp/metadata/attributes/ArticulatedObjectAttributes.h +++ b/src/esp/metadata/attributes/ArticulatedObjectAttributes.h @@ -53,6 +53,7 @@ class ArticulatedObjectAttributes : public AbstractAttributes { */ void setRenderAssetHandle(const std::string& renderAsset) { set("render_asset", renderAsset); + setFilePathsAreDirty(); } /** * @brief Gets the string name for the render asset relative path @@ -68,6 +69,7 @@ class ArticulatedObjectAttributes : public AbstractAttributes { */ void setRenderAssetFullPath(const std::string& renderAssetHandle) { setHidden("__renderAssetFullPath", renderAssetHandle); + setFilePathsAreDirty(); } /** diff --git a/src/esp/metadata/attributes/PbrShaderAttributes.cpp b/src/esp/metadata/attributes/PbrShaderAttributes.cpp index cc2f1e4c8c..c063f75c58 100644 --- a/src/esp/metadata/attributes/PbrShaderAttributes.cpp +++ b/src/esp/metadata/attributes/PbrShaderAttributes.cpp @@ -28,16 +28,12 @@ PbrShaderAttributes::PbrShaderAttributes(const std::string& handle) // Default brdf lookup table is the brdflut from here: // https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/screenshots/tex_brdflut.png - // Setting the value directly so that it won't trigger the PbrIBLHelper handle - // creation. init("ibl_blut_filename", "brdflut_ldr_512x512.png"); - // Default equirectangular environment cube map - init("ibl_envmap_filename", "lythwood_room_1k.hdr"); - init("pbr_ibl_helper_key", - Cr::Utility::formatString("{}_{}", "brdflut_ldr_512x512", - "lythwood_room_1k.hdr")); + // Build the PbrIBLHelper key to check/retrive helpers in map in + // ResourceManager. + buildPbrShaderHelperKey("brdflut_ldr_512x512.png", "lythwood_room_1k.hdr"); init("tonemap_exposure", 4.5f); init("use_ibl_tonemap", true); diff --git a/src/esp/metadata/attributes/PbrShaderAttributes.h b/src/esp/metadata/attributes/PbrShaderAttributes.h index 2332c61925..252d852841 100644 --- a/src/esp/metadata/attributes/PbrShaderAttributes.h +++ b/src/esp/metadata/attributes/PbrShaderAttributes.h @@ -280,9 +280,8 @@ class PbrShaderAttributes : public AbstractAttributes { */ void setIBLBrdfLUTAssetHandle(const std::string& brdfLUTAsset) { set("ibl_blut_filename", brdfLUTAsset); - set("pbr_ibl_helper_key", - Cr::Utility::formatString("{}_{}", brdfLUTAsset, - get("ibl_envmap_filename"))); + buildPbrShaderHelperKey(brdfLUTAsset, + get("ibl_envmap_filename")); } /** * @brief Get the filename for the brdf lookup table used by the IBL @@ -299,9 +298,7 @@ class PbrShaderAttributes : public AbstractAttributes { */ void setIBLEnvMapAssetHandle(const std::string& envMapAsset) { set("ibl_envmap_filename", envMapAsset); - set("pbr_ibl_helper_key", - Cr::Utility::formatString( - "{}_{}", get("ibl_blut_filename"), envMapAsset)); + buildPbrShaderHelperKey(get("ibl_blut_filename"), envMapAsset); } /** @@ -319,7 +316,7 @@ class PbrShaderAttributes : public AbstractAttributes { * handle>'. */ std::string getPbrShaderHelperKey() const { - return get("pbr_ibl_helper_key"); + return get("__pbrIBLHelperKey"); } /** @@ -508,6 +505,17 @@ class PbrShaderAttributes : public AbstractAttributes { io::JsonAllocator& allocator) const override; protected: + /** + * @brief Used internally. Build the PbrShaderHelper Key from the ibl blut + * filename and the ibl envmap filename used to check/retrive helpers in map + * in ResourceManager. + */ + void buildPbrShaderHelperKey(const std::string& brdfLUTAsset, + const std::string& envMapAsset) { + setHidden("__pbrIBLHelperKey", + Cr::Utility::formatString("{}_{}", brdfLUTAsset, envMapAsset)); + } + /** * @brief Retrieve a comma-separated string holding the header values for the * info returned for this managed object, type-specific. diff --git a/src/esp/metadata/attributes/StageAttributes.h b/src/esp/metadata/attributes/StageAttributes.h index 7c7fbe9a24..e800fa28a4 100644 --- a/src/esp/metadata/attributes/StageAttributes.h +++ b/src/esp/metadata/attributes/StageAttributes.h @@ -82,7 +82,7 @@ class StageAttributes : public AbstractObjectAttributes { void setSemanticDescriptorFilename( const std::string& semantic_descriptor_filename) { set("semantic_descriptor_filename", semantic_descriptor_filename); - setIsDirty(); + setFilePathsAreDirty(); } /** * @brief Text file that describes the hierharchy of semantic information @@ -101,7 +101,7 @@ class StageAttributes : public AbstractObjectAttributes { void setSemanticDescriptorFullPath( const std::string& semanticDescriptorHandle) { setHidden("__semanticDescriptorFullPath", semanticDescriptorHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -121,7 +121,7 @@ class StageAttributes : public AbstractObjectAttributes { */ void setSemanticAssetHandle(const std::string& semanticAssetHandle) { set("semantic_asset", semanticAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -141,7 +141,7 @@ class StageAttributes : public AbstractObjectAttributes { */ void setSemanticAssetFullPath(const std::string& semanticAssetHandle) { setHidden("__semanticAssetFullPath", semanticAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** @@ -298,7 +298,7 @@ class StageAttributes : public AbstractObjectAttributes { void setNavmeshAssetHandle(const std::string& nav_asset) { set("nav_asset", nav_asset); - setIsDirty(); + setFilePathsAreDirty(); } std::string getNavmeshAssetHandle() const { return get("nav_asset"); @@ -311,7 +311,7 @@ class StageAttributes : public AbstractObjectAttributes { */ void setNavmeshAssetFullPath(const std::string& navmeshAssetHandle) { setHidden("__navmeshAssetFullPath", navmeshAssetHandle); - setIsDirty(); + setFilePathsAreDirty(); } /** diff --git a/src/esp/metadata/managers/AOAttributesManager.cpp b/src/esp/metadata/managers/AOAttributesManager.cpp index 1b26db54ca..5b047ef636 100644 --- a/src/esp/metadata/managers/AOAttributesManager.cpp +++ b/src/esp/metadata/managers/AOAttributesManager.cpp @@ -254,6 +254,8 @@ AOAttributesManager::preRegisterObjectFinalize( // filter all paths properly so that the handles don't have filepaths and the // accessors are hidden fields this->finalizeAttrPathsBeforeRegister(AOAttributesTemplate); + // Clear dirty flag from when asset handles are changed + AOAttributesTemplate->setFilePathsAreClean(); return core::managedContainers::ManagedObjectPreregistration::Success; } // AOAttributesManager::preRegisterObjectFinalize @@ -289,8 +291,11 @@ void AOAttributesManager::finalizeAttrPathsBeforeRegister( std::map AOAttributesManager::getArticulatedObjectModelFilenames() const { std::map articulatedObjPaths; - for (const auto& val : this->objectLibrary_) { - auto attr = this->getObjectByHandle(val.first); + + auto objIterPair = this->getObjectLibIterator(); + for (auto& objIter = objIterPair.first; objIter != objIterPair.second; + ++objIter) { + auto attr = this->getObjectByHandle(objIter->first); auto key = attr->getSimplifiedHandle(); auto urdf = attr->getURDFFullPath(); articulatedObjPaths[key] = urdf; diff --git a/src/esp/metadata/managers/AOAttributesManager.h b/src/esp/metadata/managers/AOAttributesManager.h index c415e133d2..b545718d75 100644 --- a/src/esp/metadata/managers/AOAttributesManager.h +++ b/src/esp/metadata/managers/AOAttributesManager.h @@ -28,7 +28,7 @@ class AOAttributesManager ManagedObjectAccess::Copy>:: AbstractAttributesManager("Articulated Object", "ao_config.json") { this->copyConstructorMap_["ArticulatedObjectAttributes"] = - &AOAttributesManager::createObjectCopy< + &AOAttributesManager::createObjCopyCtorMapEntry< attributes::ArticulatedObjectAttributes>; } // ctor @@ -43,7 +43,7 @@ class AOAttributesManager * overwritten with the newly created one if registerTemplate is true. * * @param aoConfigFilename The configuration file to parse. - * @param registerTemplate whether to add this template to the library. + * @param registerTemplate Whether to add this template to the library. * If the user is going to edit this template, this should be false - any * subsequent editing will require re-registration. Defaults to true. If * specified as true, then this function returns a copy of the registered diff --git a/src/esp/metadata/managers/AbstractAttributesManager.h b/src/esp/metadata/managers/AbstractAttributesManager.h index 5274f0c0ea..2ecd33b76f 100644 --- a/src/esp/metadata/managers/AbstractAttributesManager.h +++ b/src/esp/metadata/managers/AbstractAttributesManager.h @@ -425,7 +425,7 @@ AbstractAttributesManager::loadAllFileBasedTemplates( // save handles in list of defaults, so they are not removed, if desired. if (saveAsDefaults) { std::string tmpltHandle = tmplt->getHandle(); - this->undeletableObjectNames_.insert(std::move(tmpltHandle)); + this->addUndeletableObjectName(std::move(tmpltHandle)); } templateIndices[i] = tmplt->getID(); } diff --git a/src/esp/metadata/managers/AssetAttributesManager.cpp b/src/esp/metadata/managers/AssetAttributesManager.cpp index a5f08b0b67..0302915ef4 100644 --- a/src/esp/metadata/managers/AssetAttributesManager.cpp +++ b/src/esp/metadata/managers/AssetAttributesManager.cpp @@ -83,19 +83,25 @@ AssetAttributesManager::AssetAttributesManager() // function pointers to asset attributes copy constructors this->copyConstructorMap_["CapsulePrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + CapsulePrimitiveAttributes>; this->copyConstructorMap_["ConePrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + ConePrimitiveAttributes>; this->copyConstructorMap_["CubePrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + CubePrimitiveAttributes>; this->copyConstructorMap_["CylinderPrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + CylinderPrimitiveAttributes>; this->copyConstructorMap_["IcospherePrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + IcospherePrimitiveAttributes>; this->copyConstructorMap_["UVSpherePrimitiveAttributes"] = - &AssetAttributesManager::createObjectCopy; + &AssetAttributesManager::createObjCopyCtorMapEntry< + UVSpherePrimitiveAttributes>; // no entry added for PrimObjTypes::END_PRIM_OBJ_TYPES - this->undeletableObjectNames_.clear(); + this->clearUndeletableObjectNames(); // build default AbstractPrimitiveAttributes objects for (const std::pair& elem : PrimitiveNames3DMap) { @@ -105,7 +111,7 @@ AssetAttributesManager::AssetAttributesManager() auto tmplt = AssetAttributesManager::createObject(elem.second, true); std::string tmpltHandle = tmplt->getHandle(); defaultPrimAttributeHandles_[elem.second] = tmpltHandle; - this->undeletableObjectNames_.insert(std::move(tmpltHandle)); + this->addUndeletableObjectName(std::move(tmpltHandle)); } ESP_DEBUG() << "Built default primitive asset templates :" diff --git a/src/esp/metadata/managers/AssetAttributesManager.h b/src/esp/metadata/managers/AssetAttributesManager.h index 3c084061e4..75bd106828 100644 --- a/src/esp/metadata/managers/AssetAttributesManager.h +++ b/src/esp/metadata/managers/AssetAttributesManager.h @@ -224,8 +224,7 @@ class AssetAttributesManager return {}; } std::string subStr = PrimitiveNames3DMap.at(primType); - return this->getObjectHandlesBySubStringPerType(this->objectLibKeyByID_, - subStr, contains, true); + return this->getAllObjectHandlesBySubStringPerType(subStr, contains, true); } // AssetAttributeManager::getTemplateHandlesByPrimType /** diff --git a/src/esp/metadata/managers/LightLayoutAttributesManager.h b/src/esp/metadata/managers/LightLayoutAttributesManager.h index 5a2fcc4b9b..ef3ca652ff 100644 --- a/src/esp/metadata/managers/LightLayoutAttributesManager.h +++ b/src/esp/metadata/managers/LightLayoutAttributesManager.h @@ -27,7 +27,7 @@ class LightLayoutAttributesManager "lighting_config.json") { // build this manager's copy constructor map this->copyConstructorMap_["LightLayoutAttributes"] = - &LightLayoutAttributesManager::createObjectCopy< + &LightLayoutAttributesManager::createObjCopyCtorMapEntry< attributes::LightLayoutAttributes>; } @@ -82,7 +82,9 @@ class LightLayoutAttributesManager const std::string& lightConfigName); /** - * @brief This function will be called to finalize attributes' paths before + * @brief Not required for this manager. + * + * This function will be called to finalize attributes' paths before * registration, moving fully qualified paths to the appropriate hidden * attribute fields. This can also be called without registration to make sure * the paths specified in an attributes are properly configured. diff --git a/src/esp/metadata/managers/ObjectAttributesManager.cpp b/src/esp/metadata/managers/ObjectAttributesManager.cpp index c193e64d65..fc374553bd 100644 --- a/src/esp/metadata/managers/ObjectAttributesManager.cpp +++ b/src/esp/metadata/managers/ObjectAttributesManager.cpp @@ -67,7 +67,7 @@ void ObjectAttributesManager::createDefaultPrimBasedAttributesTemplates() { auto tmplt = createPrimBasedAttributesTemplate(elem, true); // save handles in list of defaults, so they are not removed std::string tmpltHandle = tmplt->getHandle(); - this->undeletableObjectNames_.insert(std::move(tmpltHandle)); + this->addUndeletableObjectName(std::move(tmpltHandle)); } } // ObjectAttributesManager::createDefaultPrimBasedAttributesTemplates @@ -301,7 +301,7 @@ ObjectAttributesManager::preRegisterObjectFinalize( // accessors are hidden fields this->finalizeAttrPathsBeforeRegister(objectTemplate); // Clear dirty flag from when asset handles are changed - objectTemplate->setIsClean(); + objectTemplate->setFilePathsAreClean(); return core::managedContainers::ManagedObjectPreregistration::Success; } // ObjectAttributesManager::preRegisterObjectFinalize diff --git a/src/esp/metadata/managers/ObjectAttributesManager.h b/src/esp/metadata/managers/ObjectAttributesManager.h index d68d73ff98..de49f52ee7 100644 --- a/src/esp/metadata/managers/ObjectAttributesManager.h +++ b/src/esp/metadata/managers/ObjectAttributesManager.h @@ -29,7 +29,7 @@ class ObjectAttributesManager AbstractObjectAttributesManager("Object", "object_config.json") { // build this manager's copy constructor map this->copyConstructorMap_["ObjectAttributes"] = - &ObjectAttributesManager::createObjectCopy< + &ObjectAttributesManager::createObjCopyCtorMapEntry< attributes::ObjectAttributes>; } diff --git a/src/esp/metadata/managers/PbrShaderAttributesManager.cpp b/src/esp/metadata/managers/PbrShaderAttributesManager.cpp index 47e36f8edb..8bbcf939ec 100644 --- a/src/esp/metadata/managers/PbrShaderAttributesManager.cpp +++ b/src/esp/metadata/managers/PbrShaderAttributesManager.cpp @@ -23,7 +23,7 @@ PbrShaderAttributes::ptr PbrShaderAttributesManager::createObject( pbrConfigFilename, msg, registerTemplate); if (nullptr != attrs) { - ESP_DEBUG() << msg << "pbr shader configuration created" + ESP_DEBUG() << msg << "PBR Shader Attributes created" << (registerTemplate ? "and registered." : "."); } return attrs; @@ -218,7 +218,24 @@ void PbrShaderAttributesManager::setValsFromJSONDoc( // check for user defined attributes this->parseUserDefinedJsonVals(pbrShaderAttribs, jsonConfig); -} // PbrShaderAttributesManager::createFileBasedAttributesTemplate +} // PbrShaderAttributesManager::setValsFromJSONDoc + +core::managedContainers::ManagedObjectPreregistration +PbrShaderAttributesManager::preRegisterObjectFinalize( + attributes::PbrShaderAttributes::ptr pbrShaderAttribs, + const std::string& /*objectHandle*/, + bool /*forceRegistration*/) { + // TODO : Verify filenames exist as files or as resources + this->finalizeAttrPathsBeforeRegister(pbrShaderAttribs); + return core::managedContainers::ManagedObjectPreregistration::Success; +} // PbrShaderAttributesManager::preRegisterObjectFinalize + +void PbrShaderAttributesManager::finalizeAttrPathsBeforeRegister( + const attributes::PbrShaderAttributes::ptr& attributes) const { + // TODO Verify getIBLBrdfLUTAssetHandle and getIBLEnvMapAssetHandle exist as + // either file-based assets or resources and build paths to be relative if + // file-based +} // PbrShaderAttributesManager::finalizeAttrPathsBeforeRegister PbrShaderAttributes::ptr PbrShaderAttributesManager::initNewObjectInternal( const std::string& handleName, diff --git a/src/esp/metadata/managers/PbrShaderAttributesManager.h b/src/esp/metadata/managers/PbrShaderAttributesManager.h index ec075011dc..2512bc8e2b 100644 --- a/src/esp/metadata/managers/PbrShaderAttributesManager.h +++ b/src/esp/metadata/managers/PbrShaderAttributesManager.h @@ -27,7 +27,7 @@ class PbrShaderAttributesManager ManagedObjectAccess::Copy>:: AbstractAttributesManager("PBR Rendering", "pbr_config.json") { this->copyConstructorMap_["PbrShaderAttributes"] = - &PbrShaderAttributesManager::createObjectCopy< + &PbrShaderAttributesManager::createObjCopyCtorMapEntry< attributes::PbrShaderAttributes>; } // ctor @@ -70,11 +70,14 @@ class PbrShaderAttributesManager * to have IBL either on or off. */ void setAllIBLEnabled(bool isIblEnabled) { - for (const auto& val : this->objectLibrary_) { + auto objIterPair = this->getObjectLibIterator(); + for (auto& objIter = objIterPair.first; objIter != objIterPair.second; + ++objIter) { + const std::string objHandle = objIter->first; // Don't change system default - if (val.first.find(ESP_DEFAULT_PBRSHADER_CONFIG_REL_PATH) == + if (objHandle.find(ESP_DEFAULT_PBRSHADER_CONFIG_REL_PATH) == std::string::npos) { - this->getObjectByHandle(val.first)->setEnableIBL(isIblEnabled); + this->getObjectByHandle(objHandle)->setEnableIBL(isIblEnabled); } } } // PbrShaderAttributesManager::setAllIBLEnabled @@ -84,11 +87,14 @@ class PbrShaderAttributesManager * to have Direct Ligthing either on or off. */ void setAllDirectLightsEnabled(bool isDirLightEnabled) { - for (const auto& val : this->objectLibrary_) { + auto objIterPair = this->getObjectLibIterator(); + for (auto& objIter = objIterPair.first; objIter != objIterPair.second; + ++objIter) { + const std::string objHandle = objIter->first; // Don't change system default - if (val.first.find(ESP_DEFAULT_PBRSHADER_CONFIG_REL_PATH) == + if (objHandle.find(ESP_DEFAULT_PBRSHADER_CONFIG_REL_PATH) == std::string::npos) { - this->getObjectByHandle(val.first)->setEnableDirectLighting( + this->getObjectByHandle(objHandle)->setEnableDirectLighting( isDirLightEnabled); } } @@ -102,11 +108,11 @@ class PbrShaderAttributesManager * * TODO : If/When we begin treating IBL filepaths like we do other paths, this * will need to be implemented. - * @param attributes The attributes to be filtered. + * @param pbrShaderAttribs The attributes to be filtered. */ void finalizeAttrPathsBeforeRegister( - CORRADE_UNUSED const attributes::PbrShaderAttributes::ptr& attributes) - const override{}; + CORRADE_UNUSED const attributes::PbrShaderAttributes::ptr& + pbrShaderAttribs) const override; protected: /** @@ -139,12 +145,10 @@ class PbrShaderAttributesManager CORRADE_UNUSED const std::string& templateHandle) override {} /** - * @brief Not required for this manager. - * - * This method will perform any essential updating to the managed object - * before registration is performed. If this updating fails, registration will - * also fail. - * @param object the managed object to be registered + * @brief This method will perform any essential updating to the managed + * object before registration is performed. If this updating fails, + * registration will also fail. + * @param pbrShaderAttribs the managed object to be registered * @param objectHandle the name to register the managed object with. * Expected to be valid. * @param forceRegistration Should register object even if conditional @@ -154,12 +158,9 @@ class PbrShaderAttributesManager */ core::managedContainers::ManagedObjectPreregistration preRegisterObjectFinalize( - CORRADE_UNUSED attributes::PbrShaderAttributes::ptr object, + attributes::PbrShaderAttributes::ptr pbrShaderAttribs, CORRADE_UNUSED const std::string& objectHandle, - CORRADE_UNUSED bool forceRegistration) override { - // No pre-registration conditioning performed - return core::managedContainers::ManagedObjectPreregistration::Success; - } + CORRADE_UNUSED bool forceRegistration) override; /** * @brief Not required for this manager. diff --git a/src/esp/metadata/managers/PhysicsAttributesManager.h b/src/esp/metadata/managers/PhysicsAttributesManager.h index 524cc74049..e418fcee84 100644 --- a/src/esp/metadata/managers/PhysicsAttributesManager.h +++ b/src/esp/metadata/managers/PhysicsAttributesManager.h @@ -28,7 +28,7 @@ class PhysicsAttributesManager AbstractAttributesManager("Physics Manager", "physics_config.json") { this->copyConstructorMap_["PhysicsManagerAttributes"] = - &PhysicsAttributesManager::createObjectCopy< + &PhysicsAttributesManager::createObjCopyCtorMapEntry< attributes::PhysicsManagerAttributes>; } // ctor diff --git a/src/esp/metadata/managers/SceneDatasetAttributesManager.cpp b/src/esp/metadata/managers/SceneDatasetAttributesManager.cpp index ea800d7427..5d2932804c 100644 --- a/src/esp/metadata/managers/SceneDatasetAttributesManager.cpp +++ b/src/esp/metadata/managers/SceneDatasetAttributesManager.cpp @@ -25,7 +25,7 @@ SceneDatasetAttributesManager::SceneDatasetAttributesManager( pbrShaderAttributesManager_(std::move(pbrShaderAttributesMgr)) { // build this manager's copy ctor map this->copyConstructorMap_["SceneDatasetAttributes"] = - &SceneDatasetAttributesManager::createObjectCopy< + &SceneDatasetAttributesManager::createObjCopyCtorMapEntry< attributes::SceneDatasetAttributes>; } // SceneDatasetAttributesManager ctor diff --git a/src/esp/metadata/managers/SceneDatasetAttributesManager.h b/src/esp/metadata/managers/SceneDatasetAttributesManager.h index 59c1136b96..d95ca497de 100644 --- a/src/esp/metadata/managers/SceneDatasetAttributesManager.h +++ b/src/esp/metadata/managers/SceneDatasetAttributesManager.h @@ -67,8 +67,10 @@ class SceneDatasetAttributesManager */ void setCurrPhysicsManagerAttributesHandle(const std::string& handle) { physicsManagerAttributesHandle_ = handle; - for (const auto& val : this->objectLibrary_) { - this->getObjectByHandle(val.first)->setPhysicsManagerHandle(handle); + auto objIterPair = this->getObjectLibIterator(); + for (auto& objIter = objIterPair.first; objIter != objIterPair.second; + ++objIter) { + this->getObjectByHandle(objIter->first)->setPhysicsManagerHandle(handle); } } // SceneDatasetAttributesManager::setCurrPhysicsManagerAttributesHandle @@ -87,9 +89,11 @@ class SceneDatasetAttributesManager */ void setDefaultPbrShaderAttributesHandle(const std::string& pbrHandle) { defaultPbrShaderAttributesHandle_ = pbrHandle; - for (const auto& val : this->objectLibrary_) { - this->getObjectByHandle(val.first)->setDefaultPbrShaderAttrHandle( - pbrHandle); + auto objIterPair = this->getObjectLibIterator(); + for (auto& objIter = objIterPair.first; objIter != objIterPair.second; + ++objIter) { + this->getObjectByHandle(objIter->first) + ->setDefaultPbrShaderAttrHandle(pbrHandle); } } // SceneDatasetAttributesManager::setDefaultPbrShaderAttributesHandle diff --git a/src/esp/metadata/managers/SceneInstanceAttributesManager.h b/src/esp/metadata/managers/SceneInstanceAttributesManager.h index c7e4e2bc7a..1cf0776b1d 100644 --- a/src/esp/metadata/managers/SceneInstanceAttributesManager.h +++ b/src/esp/metadata/managers/SceneInstanceAttributesManager.h @@ -24,7 +24,7 @@ class SceneInstanceAttributesManager AbstractAttributesManager("Scene Instance", "scene_instance.json") { // build this manager's copy constructor map this->copyConstructorMap_["SceneInstanceAttributes"] = - &SceneInstanceAttributesManager::createObjectCopy< + &SceneInstanceAttributesManager::createObjCopyCtorMapEntry< attributes::SceneInstanceAttributes>; } diff --git a/src/esp/metadata/managers/SemanticAttributesManager.h b/src/esp/metadata/managers/SemanticAttributesManager.h index e6c10150fa..76d3e9adf1 100644 --- a/src/esp/metadata/managers/SemanticAttributesManager.h +++ b/src/esp/metadata/managers/SemanticAttributesManager.h @@ -27,7 +27,7 @@ class SemanticAttributesManager AbstractAttributesManager("Semantic Attributes", "semantic_config.json") { this->copyConstructorMap_["SemanticAttributes"] = - &SemanticAttributesManager::createObjectCopy< + &SemanticAttributesManager::createObjCopyCtorMapEntry< attributes::SemanticAttributes>; } // ctor diff --git a/src/esp/metadata/managers/StageAttributesManager.cpp b/src/esp/metadata/managers/StageAttributesManager.cpp index 9c786856a4..5b611ffa2a 100644 --- a/src/esp/metadata/managers/StageAttributesManager.cpp +++ b/src/esp/metadata/managers/StageAttributesManager.cpp @@ -32,7 +32,8 @@ StageAttributesManager::StageAttributesManager( cfgLightSetup_(NO_LIGHT_KEY) { // build this manager's copy constructor map this->copyConstructorMap_["StageAttributes"] = - &StageAttributesManager::createObjectCopy; + &StageAttributesManager::createObjCopyCtorMapEntry< + attributes::StageAttributes>; } // StageAttributesManager::ctor @@ -42,7 +43,7 @@ void StageAttributesManager::createDefaultPrimBasedAttributesTemplates() { auto tmplt = this->postCreateRegister( StageAttributesManager::initNewObjectInternal("NONE", false), true); std::string tmpltHandle = tmplt->getHandle(); - this->undeletableObjectNames_.insert(std::move(tmpltHandle)); + this->addUndeletableObjectName(std::move(tmpltHandle)); } // StageAttributesManager::createDefaultPrimBasedAttributesTemplates StageAttributes::ptr StageAttributesManager::createPrimBasedAttributesTemplate( @@ -460,8 +461,8 @@ StageAttributesManager::preRegisterObjectFinalize( // accessors are hidden fields this->finalizeAttrPathsBeforeRegister(stageAttributes); - - stageAttributes->setIsClean(); + // Clear dirty flag from when asset handles are changed + stageAttributes->setFilePathsAreClean(); return core::managedContainers::ManagedObjectPreregistration::Success; diff --git a/src/esp/physics/objectManagers/ArticulatedObjectManager.cpp b/src/esp/physics/objectManagers/ArticulatedObjectManager.cpp index 8a11e463b9..959d596eab 100644 --- a/src/esp/physics/objectManagers/ArticulatedObjectManager.cpp +++ b/src/esp/physics/objectManagers/ArticulatedObjectManager.cpp @@ -12,7 +12,8 @@ ArticulatedObjectManager::ArticulatedObjectManager() PhysicsObjectBaseManager("ArticulatedObject") { // build this manager's copy constructor map this->copyConstructorMap_["ManagedArticulatedObject"] = - &ArticulatedObjectManager::createObjectCopy; + &ArticulatedObjectManager::createObjCopyCtorMapEntry< + ManagedArticulatedObject>; // build the function pointers to proper wrapper construction methods, keyed // by the wrapper names @@ -21,7 +22,7 @@ ArticulatedObjectManager::ArticulatedObjectManager() ManagedArticulatedObject>; this->copyConstructorMap_["ManagedBulletArticulatedObject"] = - &ArticulatedObjectManager::createObjectCopy< + &ArticulatedObjectManager::createObjCopyCtorMapEntry< ManagedBulletArticulatedObject>; managedObjTypeConstructorMap_["ManagedBulletArticulatedObject"] = &ArticulatedObjectManager::createPhysicsObjectWrapper< diff --git a/src/esp/physics/objectManagers/RigidObjectManager.cpp b/src/esp/physics/objectManagers/RigidObjectManager.cpp index 27fdc0e00f..b106e4fd7e 100644 --- a/src/esp/physics/objectManagers/RigidObjectManager.cpp +++ b/src/esp/physics/objectManagers/RigidObjectManager.cpp @@ -12,7 +12,7 @@ RigidObjectManager::RigidObjectManager() // build this manager's copy constructor map, keyed by the type name of the // wrappers it will manage this->copyConstructorMap_["ManagedRigidObject"] = - &RigidObjectManager::createObjectCopy; + &RigidObjectManager::createObjCopyCtorMapEntry; // build the function pointers to proper wrapper construction methods, keyed // by the wrapper names @@ -20,7 +20,7 @@ RigidObjectManager::RigidObjectManager() &RigidObjectManager::createPhysicsObjectWrapper; this->copyConstructorMap_["ManagedBulletRigidObject"] = - &RigidObjectManager::createObjectCopy; + &RigidObjectManager::createObjCopyCtorMapEntry; managedObjTypeConstructorMap_["ManagedBulletRigidObject"] = &RigidObjectManager::createPhysicsObjectWrapper; }