diff --git a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp index f7de91d..2fbf967 100644 --- a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp +++ b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp @@ -140,4 +140,16 @@ std::optional BIMAttributeDatabase::getAPIData(const BIMLink& lin std::optional BIMAttributeDatabase::getAPIStorey(const BIMLink& link) const { return m_engine->getAPIStorey(link); } //BIMAttributeDatabase::getAPIData + + +/*-------------------------------------------------------------------- + Get the ID of a storey from a specified index + + index: The storey index + + return: The storey ID (nullopt on failure) + --------------------------------------------------------------------*/ +std::optional BIMAttributeDatabase::getStoreyID(short index) const { + return m_engine->getStoreyID(index); +} //BIMAttributeDatabase::getStoreyID #endif diff --git a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h index 4ff21c8..0a28b89 100644 --- a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h +++ b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h @@ -80,6 +80,12 @@ namespace speckle::database { @return The AC API storey data */ std::optional getAPIStorey(const BIMLink& link) const; + /*! + Get the ID of a storey from a specified index + @param index The storey index + @return The storey ID (nullopt on failure) + */ + std::optional getStoreyID(short index) const; #endif private: diff --git a/SpeckleLib/Speckle/Database/Content/BIMRecord.h b/SpeckleLib/Speckle/Database/Content/BIMRecord.h index 916cd1c..a9964f3 100644 --- a/SpeckleLib/Speckle/Database/Content/BIMRecord.h +++ b/SpeckleLib/Speckle/Database/Content/BIMRecord.h @@ -3,6 +3,7 @@ #include "Active/Setting/Values/Measurement/Units/LengthUnit.h" #include "Speckle/Database/Content/Record.h" +#include "Speckle/Database/Identity/BIMIndex.h" #include "Speckle/Database/Identity/BIMLink.h" #include "Speckle/Database/Identity/BIMRecordID.h" @@ -94,12 +95,22 @@ namespace speckle::database { Set to the default package content */ void setDefault() override; + + protected: + /*! + Reset the BIM index (used in lazy loading contexts where the index cannot otherwise be established) + @param index The BIM application index + */ + void resetIndex(const BIMIndex& index) const { + m_applicationID = index; + m_applicationTableID = index.tableID; + } private: ///The BIM application record ID - BIMRecordID m_applicationID; + mutable BIMRecordID m_applicationID; ///The BIM application parent table ID - BIMRecordID m_applicationTableID; + mutable BIMRecordID m_applicationTableID; ///The BIM record unit of length measurement std::optional m_unit = active::measure::LengthType::metre; }; diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp index 2da5214..f16d675 100644 --- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp +++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp @@ -279,4 +279,19 @@ std::optional ArchicadAttributeDBaseEngine::getAPIStorey(const BI return std::nullopt; } //ArchicadAttributeDBaseEngine::getAPIStorey + +/*-------------------------------------------------------------------- + Get the ID of a storey from a specified index + + index: The storey index + + return: The storey ID (nullopt on failure) + --------------------------------------------------------------------*/ +std::optional ArchicadAttributeDBaseEngine::getStoreyID(short index) const { + if (!m_storeyCache) + m_storeyCache = std::make_unique(); + if (auto iter = m_storeyCache->find(index); iter != m_storeyCache->end()) + return Guid::fromInt(iter->floorId); + return std::nullopt; +} //ArchicadAttributeDBaseEngine::getStoreyID #endif diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h index f8a5787..0da60db 100644 --- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h @@ -127,6 +127,12 @@ namespace speckle::database { @return The AC API storey data */ std::optional getAPIStorey(const BIMLink& link) const; + /*! + Get the ID of a storey from a specified index + @param index The storey index + @return The storey ID (nullopt on failure) + */ + std::optional getStoreyID(short index) const; #endif private: diff --git a/SpeckleLib/Speckle/Record/Attribute/Storey.cpp b/SpeckleLib/Speckle/Record/Attribute/Storey.cpp index 6bee954..eb44742 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Storey.cpp +++ b/SpeckleLib/Speckle/Record/Attribute/Storey.cpp @@ -69,6 +69,18 @@ Storey::Storey() { } //Storey::Storey +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Constructor + + index: An index into the Archicad storey array + --------------------------------------------------------------------*/ +Storey::Storey(short index) { + +} //Storey::Storey +#endif + + /*-------------------------------------------------------------------- Constructor @@ -172,21 +184,35 @@ void Storey::setDefault() { void Storey::confirmData() const { if (m_data) return; +#ifdef ARCHICAD m_data = std::make_unique(getStoreyData()); +#endif } //Storey::confirmData +#ifdef ARCHICAD /*-------------------------------------------------------------------- Get the storey data from the host BIM application return: The storey data (for internal use to populate derived classes) --------------------------------------------------------------------*/ API_StoryType Storey::getStoreyData() const { - if (auto project = addon()->getActiveProject().lock(); project) { - if (auto storey = project->getAttributeDatabase()->getAPIStorey(getBIMLink()); storey) - return *storey; - } + do { + if (auto project = addon()->getActiveProject().lock(); project) { + auto attributeDatabase = project->getAttributeDatabase(); + if (m_storeyIndex) { + auto storeyID = attributeDatabase->getStoreyID(*m_storeyIndex); + m_storeyIndex.reset(); + if (!storeyID) + break; + resetIndex({Attribute::storeyTableID, Attribute::storeyTableID}); + } + if (auto storey = attributeDatabase->getAPIStorey(getBIMLink()); storey) + return *storey; + } + } while (false); API_StoryType storey; active::utility::Memory::erase(storey); return storey; } //Storey::getStoreyData +#endif diff --git a/SpeckleLib/Speckle/Record/Attribute/Storey.h b/SpeckleLib/Speckle/Record/Attribute/Storey.h index 67aeb35..803a772 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Storey.h +++ b/SpeckleLib/Speckle/Record/Attribute/Storey.h @@ -37,6 +37,11 @@ namespace speckle::record::attribute { */ Storey(const database::BIMRecordID& ID); #ifdef ARCHICAD + /*! + Constructor + @param index An index into the Archicad storey array + */ + Storey(short index); /*! Constructor @param attrData Archicad attribute data @@ -117,6 +122,9 @@ namespace speckle::record::attribute { @return The storey data (for internal use to populate derived classes) */ API_StoryType getStoreyData() const; + + ///An index into the Archicad storey array - used temporarily for looking up the storey data on demand + mutable std::optional m_storeyIndex; #endif class Data;