diff --git a/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp b/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp index 5761233..d98a57f 100644 --- a/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp +++ b/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp @@ -5,6 +5,7 @@ #include "Speckle/Database/Identity/RecordID.h" #include "Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h" #include "Speckle/Record/Element/Element.h" +#include "Speckle/Record/Element/Memo.h" #include @@ -107,6 +108,25 @@ Vector BIMElementDatabase::getElements() const { } //BIMElementDatabase::getElements +/*-------------------------------------------------------------------- + Get memo memo (supplementary) data for a specified element + + elementID: The of the source element + filter: Filter for the required supplementary data + + return: The requested element memo data (nullptr on failure) + --------------------------------------------------------------------*/ +Memo::Unique BIMElementDatabase::getMemo(const BIMRecordID& elementID, Part::filter_bits filter) const { + //NB: The filter bits are passed as the source document ID + auto result = m_engine->getObject(elementID, ArchicadElementDBaseEngine::memoTable, Guid::fromInt(filter)); + if (auto memo = dynamic_cast(result.get()); memo != nullptr) { + result.release(); + return Memo::Unique{memo}; + } + return nullptr; +} //BIMElementDatabase::getMemo + + /*-------------------------------------------------------------------- Write an element to storage diff --git a/SpeckleLib/Speckle/Database/BIMElementDatabase.h b/SpeckleLib/Speckle/Database/BIMElementDatabase.h index 27aa3db..efd1d18 100644 --- a/SpeckleLib/Speckle/Database/BIMElementDatabase.h +++ b/SpeckleLib/Speckle/Database/BIMElementDatabase.h @@ -3,12 +3,17 @@ #include "Speckle/Database/Identity/BIMLink.h" #include "Speckle/Record/Element/Element.h" +#include "Speckle/Record/Element/Interface/Part.h" #include "Speckle/Utility/Guid.h" namespace active::event { class Subscriber; } +namespace speckle::record::element { + class Memo; +} + namespace speckle::database { /*! @@ -43,19 +48,26 @@ namespace speckle::database { @param documentID Optional document ID (when the object is bound to a specific document) @return The requested element (nullptr on failure) */ - record::element::Element::Unique getElement(const BIMRecordID& elementID, std::optional tableID = std::nullopt, + std::unique_ptr getElement(const BIMRecordID& elementID, std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const; /*! Get a specified element @param link A link to the target element @return The requested element (nullptr on failure) */ - record::element::Element::Unique getElement(const BIMLink& link) const { return getElement(link, link.tableID, link.docID); } + std::unique_ptr getElement(const BIMLink& link) const { return getElement(link, link.tableID, link.docID); } /*! Get all model elements @return All the elements */ active::container::Vector getElements() const; + /*! + Get memo memo (supplementary) data for a specified element + @param elementID The of the source element + @param filter Filter for the required supplementary data + @return The requested element memo data (nullptr on failure) + */ + std::unique_ptr getMemo(const BIMRecordID& elementID, record::element::Part::filter_bits filter) const; /*! Write an element to storage @param element The element to write diff --git a/SpeckleLib/Speckle/Database/Content/Record.cpp b/SpeckleLib/Speckle/Database/Content/Record.cpp index 3df4c86..3d75448 100644 --- a/SpeckleLib/Speckle/Database/Content/Record.cpp +++ b/SpeckleLib/Speckle/Database/Content/Record.cpp @@ -40,7 +40,7 @@ bool Record::fillInventory(active::serialise::Inventory& inventory) const { }.withType(&typeid(base))); inventory.merge(Inventory{ { - { Identity{fieldID[speckleTypeID]}, speckleTypeID, element }, + { Identity{fieldID[speckleTypeID]}, speckleTypeID, attribute }, }, }.withType(&typeid(Record))); return true; diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp index 7438e6d..a1d7fd5 100644 --- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp +++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp @@ -10,6 +10,10 @@ #include "Speckle/Environment/Project.h" #include "Speckle/Event/Type/DocStoreMergeEvent.h" #include "Speckle/Event/Type/ProjectEvent.h" +#include "Speckle/Record/Element/Column.h" +#include "Speckle/Record/Element/ColumnSegment.h" +#include "Speckle/Record/Element/GenericElement.h" +#include "Speckle/Record/Element/Memo.h" #include "Speckle/Utility/Guid.h" #include "Speckle/Utility/String.h" @@ -67,9 +71,14 @@ namespace { @return A new element object (nullptr on failure) */ Element::Unique makeElement(const API_Element& elementData, const BIMRecordID& tableID) { - //Implement an object factory in future as classes for specific element types are implemented, e.g. Wall, Roof etc. using hash map - //The fallback for undefined element types will always be the base Element class - return std::make_unique(elementData, tableID); + switch (elementData.header.type.typeID) { + case API_ColumnID: + return std::make_unique(elementData, tableID); + case API_ColumnSegmentID: + return std::make_unique(elementData, tableID); + default: + return std::make_unique(elementData, tableID); + } } } @@ -120,7 +129,22 @@ BIMLinkList ArchicadElementDBaseEngine::getSelection() const { --------------------------------------------------------------------*/ std::unique_ptr ArchicadElementDBaseEngine::getObject(const BIMRecordID& ID, std::optional tableID, std::optional documentID) const { + //Check for memo table requests + if (tableID == memoTable) { + auto memo = std::make_unique(); + active::utility::Memory::erase(*memo); + //Use memo filtering when requested + uint64_t filter = documentID ? Guid::toInt(*documentID) : APIMemoMask_All; + if (auto err = ACAPI_Element_GetMemo(ID, memo.get(), filter); err != NoError) + ACAPI_DisposeElemMemoHdls(memo.get()); + else { + auto result = std::make_unique(); + result->set(std::move(memo)); + return result; + } + } if (!tableID) { + //Use the active table if none is specified tableID = getActiveTable(); if (!tableID) return nullptr; diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h index 103a11a..864ba6b 100644 --- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h +++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h @@ -18,16 +18,21 @@ namespace speckle::database { A database engine to read/write elements in an Archicad project database (local file or cloud-based) */ class ArchicadElementDBaseEngine : public ArchicadDBaseCore, - public active::database::DBaseEngine { + public active::database::DBaseEngine { public: // MARK: - Types - using base = active::database::DBaseEngine; + using base = active::database::DBaseEngine; using Element = record::element::Element; using Filter = base::Filter; using Outline = base::Outline; + // MARK: - Constants + + ///The memo table ID (supplementary element data) + static const inline utility::Guid memoTable{utility::String{"fdff96d2-8c34-4f8b-8a76-a96a2b242758"}}; + // MARK: - Static functions /*! diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp index c6925b4..e6bdee0 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp +++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp @@ -35,9 +35,6 @@ namespace { } - //True if a selection change subscriber has already started (only one is required - there are no variants) -bool speckle::event::SelectionSubscriber::m_isStarted = false; - /*-------------------------------------------------------------------- Get the event subscription list @@ -76,6 +73,7 @@ bool SelectionSubscriber::start() { #endif } //SelectionSubscriber::start + /*-------------------------------------------------------------------- Stop participation (release resources etc) --------------------------------------------------------------------*/ diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h index b68f2ed..c9e1da3 100644 --- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h +++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h @@ -45,13 +45,11 @@ namespace speckle::event { @return True if the event should be closed */ bool receive(const active::event::Event& event) override; - /*! Start the participant operation @return True if the participant is able to continue */ virtual bool start() override; - /*! Stop participation (release resources etc) */ @@ -60,15 +58,11 @@ namespace speckle::event { protected: /*! - Handle the menu selection + Handle a selection change @param event The selection event @return True if the event should be closed */ virtual bool handle(const SelectionEvent& event) = 0; - - private: - ///True if a selection change subscriber has already started (only one is required - there are no variants) - static bool m_isStarted; }; } diff --git a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp index 86d45dd..1861b6a 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp +++ b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp @@ -128,7 +128,6 @@ Finish::Finish(const ModelerAPI::Material& material) : base{Guid{Guid::fromInt(m attr.material.diffusePc = static_cast(material.GetDiffuseReflection() * 100); attr.material.specularPc = static_cast(material.GetSpecularReflection() * 100); attr.material.transpPc = static_cast(material.GetTransparency() * 100); - auto temp = material.GetShining(); attr.material.shine = static_cast(material.GetShining() * 100); attr.material.transpAtt = static_cast(material.GetTransparencyAttenuation() * 400); attr.material.emissionAtt = static_cast(material.GetEmissionAttenuation() * 65535); diff --git a/SpeckleLib/Speckle/Record/Element/Column.cpp b/SpeckleLib/Speckle/Record/Element/Column.cpp new file mode 100644 index 0000000..36aada6 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Column.cpp @@ -0,0 +1,174 @@ +#include "Speckle/Record/Element/Column.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Speckle/Environment/Addon.h" +#include "Speckle/Primitive/Mesh/Mesh.h" +#include "Speckle/SpeckleResource.h" +#include "Speckle/Utility/Guid.h" + +using namespace active::serialise; +using namespace speckle::environment; +using namespace speckle::record::attribute; +using namespace speckle::record::element; +using namespace speckle::utility; + +#include +#include + +namespace speckle::record::element { + + class Column::Data { + public: + friend class Column; + +#ifdef ARCHICAD + Data(const API_Element& elem) : root{ std::make_unique(elem.column) } {} + Data(const Data& source) : root{ std::make_unique(*source.root) } {} +#endif + + private: + std::unique_ptr root; + }; + +} + +namespace { + + ///Serialisation fields + enum FieldIndex { + segmentID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"segments"}, + }; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +Column::Column() { +} //Column::Column + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Constructor + + elemData: Archicad element data + tableID: The element table ID (AC database, e.g. floor plan, 3D) + --------------------------------------------------------------------*/ +Column::Column(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } { + m_data = std::make_unique(elemData); +} //Column::Column +#endif + + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +Column::Column(const Column& source) : base{ source } { + m_data = source.m_data ? std::make_unique(*m_data) : nullptr; +} //Column::Column + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +Column::~Column() {} + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Get the (immutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +const API_Elem_Head& Column::getHead() const { + return m_data->root->head; +} //Column::getHead + +/*-------------------------------------------------------------------- + Get the (mutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +API_Elem_Head& Column::getHead() { + return m_data->root->head; +} //Column::getHead + + +/*-------------------------------------------------------------------- + Load the element memo structure (elements must override according to requirements) + + filter: Filter bits specifying memo requirements + --------------------------------------------------------------------*/ +void Column::loadMemo(filter_bits filter, std::unique_ptr& memo) const { + //Establish the memo filter for this element + if (!SegmentedColumn::isMemoLoaded()) + filter |= SegmentedColumn::getPartFilter(); + Element::loadMemo(filter, memo); + //Receive the memo data into the element (when available) + if (memo) { + if (filter & SegmentedColumn::getPartFilter()) + SegmentedColumn::receive(*memo); + } + SegmentedColumn::setMemoLoaded(true); //Always mark the data as loaded to prevent repeated attempts on error +} //Column::loadMemo +#endif + + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool Column::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[segmentID], segmentID, getSegmentCount(), std::nullopt }, //TODO: implement other fields + }, + }.withType(&typeid(Column))); + return base::fillInventory(inventory); +} //Column::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique Column::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(Column)) + return base::getCargo(item); + using namespace active::serialise; + switch (item.index) { + case segmentID: + if (auto segment = getSegment(item.available); segment != nullptr) { + return Cargo::Unique{new PackageWrap{*segment}}; + } else + return nullptr; + default: + return nullptr; //Requested an unknown index + } +} //Column::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void Column::setDefault() { + base::setDefault(); + m_data.reset(); +} //Column::setDefault diff --git a/SpeckleLib/Speckle/Record/Element/Column.h b/SpeckleLib/Speckle/Record/Element/Column.h new file mode 100644 index 0000000..a70185f --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Column.h @@ -0,0 +1,142 @@ +#ifndef SPECKLE_RECORD_ELEMENT_COLUMN +#define SPECKLE_RECORD_ELEMENT_COLUMN + +#include "Speckle/Record/Element/ColumnSegment.h" +#include "Speckle/Record/Element/Element.h" +#include "Speckle/Record/Element/Interface/Assembly/Path.h" +#include "Speckle/Record/Element/Interface/SegmentedColumn.h" + +namespace speckle::record::element { + + class ColumnSegment; + + /*! + BIM column class + */ + class Column : public Element, public SegmentedColumn, public assembly::Path { + public: + + // MARK: - Types + + using base = Element; + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + + using base::base; + + /*! + Default constructor + */ + Column(); +#ifdef ARCHICAD + /*! + Constructor + @param elemData Archicad element data + @param tableID The column element ID (AC database, e.g. floor plan, 3D) + */ + Column(const API_Element& elemData, const speckle::utility::Guid& tableID); +#endif + /*! + Copy constructor + @param source The object to copy + */ + Column(const Column& source); + /*! + Destructor + */ + ~Column(); + + /*! + Object cloning + @return A clone of this object + */ + Column* clonePtr() const override { return new Column{*this}; } + + + // MARK: - Functions (const) + + /*! + Get the speckle type identifier + @return The speckle type (relevant objects should override as required) + */ + speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.Column"; } + /*! + Get the BIM application parent table ID + @return The BIM table ID + */ + virtual database::BIMRecordID getTableID() const override { return Element::getTableID(); } + /*! + Get the element body + @return nullptr (Columns don't explicitly have a 3D body - this comes from its child segments) + */ + virtual Body* getBody() const override { return nullptr; } + /*! + Get the number of segments in the path (elements must override according to requirements) + @return The segment count + */ + virtual size_t getSegmentCount() const override { return SegmentedColumn::getSegmentCount(); } + /*! + Get a segment from the path (elements must override according to requirements) + @param index The index of the required segment + @return The requested segment (nullptr on failure) + */ + virtual ColumnSegment* getSegment(size_t index) const override { return SegmentedColumn::getSegment(index); } +#ifdef ARCHICAD + /*! + Get the (immutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + const API_Elem_Head& getHead() const override; +#endif + + // MARK: - Functions (mutating) + +#ifdef ARCHICAD + /*! + Get the (mutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + API_Elem_Head& getHead() override; +#endif + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + protected: + /*! + Load the element memo structure (elements must override according to requirements) + @param filter Filter bits specifying memo requirements + */ + virtual void loadMemo(filter_bits filter, std::unique_ptr& memo) const override; + + private: + class Data; + ///The column data + std::unique_ptr m_data; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_COLUMN diff --git a/SpeckleLib/Speckle/Record/Element/ColumnSegment.cpp b/SpeckleLib/Speckle/Record/Element/ColumnSegment.cpp new file mode 100644 index 0000000..34d4cb2 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/ColumnSegment.cpp @@ -0,0 +1,159 @@ +#include "Speckle/Record/Element/ColumnSegment.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Speckle/Environment/Addon.h" +#include "Speckle/Primitive/Mesh/Mesh.h" +#include "Speckle/SpeckleResource.h" +#include "Speckle/Utility/Guid.h" + +#ifdef ARCHICAD +#include +#endif + +using namespace active::serialise; +using namespace speckle::environment; +using namespace speckle::record::attribute; +using namespace speckle::record::element; +using namespace speckle::utility; + +#include +#include + +namespace speckle::record::element { + + class ColumnSegment::Data { + public: + friend class ColumnSegment; + +#ifdef ARCHICAD + Data(const API_ColumnSegmentType& seg) : root{ std::make_unique(seg) } {} + Data(const Data& source) : root{ std::make_unique(*source.root) } {} + + private: + std::unique_ptr root; +#endif + }; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +ColumnSegment::ColumnSegment() { +} //ColumnSegment::ColumnSegment + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Constructor + + elemData: Archicad element data + tableID: The element table ID (AC database, e.g. floor plan, 3D) + --------------------------------------------------------------------*/ +ColumnSegment::ColumnSegment(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } { + m_data = std::make_unique(elemData.columnSegment); +} //ColumnSegment::ColumnSegment + + +/*-------------------------------------------------------------------- + Constructor + + segment: The segment element data + tableID: The parent table ID + cutOrigin: Cut at the segment origin + cutEnd: Cut at the segment end + scheme: The segment scheme + profile: The segment profile (nullptr = none) + --------------------------------------------------------------------*/ +ColumnSegment::ColumnSegment(const API_ColumnSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin, + const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme, + const API_AssemblySegmentProfileData* profile) : + base{segment.head.guid, tableID}, assembly::Segment{cutOrigin, cutEnd, scheme, profile} { + m_data = std::make_unique(segment); +} //ColumnSegment::ColumnSegment +#endif + + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +ColumnSegment::ColumnSegment(const ColumnSegment& source) : base{ source } { + m_data = source.m_data ? std::make_unique(*m_data) : nullptr; +} //ColumnSegment::ColumnSegment + + +/*-------------------------------------------------------------------- + Move constructor + + source: The object to move + --------------------------------------------------------------------*/ +ColumnSegment::ColumnSegment(ColumnSegment&& source) : base{source} { + m_data = std::move(source.m_data); +} //ColumnSegment::ColumnSegment + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +ColumnSegment::~ColumnSegment() {} + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Get the (immutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +const API_Elem_Head& ColumnSegment::getHead() const { + return m_data->root->head; +} //ColumnSegment::getHead + + +/*-------------------------------------------------------------------- + Get the (mutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +API_Elem_Head& ColumnSegment::getHead() { + return m_data->root->head; +} //ColumnSegment::getHead +#endif + + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool ColumnSegment::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + //TODO: Implement other fields as required + return base::fillInventory(inventory); +} //ColumnSegment::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique ColumnSegment::getCargo(const Inventory::Item& item) const { + //TODO: Implement other fields as required + return base::getCargo(item); +} //ColumnSegment::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void ColumnSegment::setDefault() { + m_data.reset(); +} //ColumnSegment::setDefault diff --git a/SpeckleLib/Speckle/Record/Element/ColumnSegment.h b/SpeckleLib/Speckle/Record/Element/ColumnSegment.h new file mode 100644 index 0000000..85c731b --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/ColumnSegment.h @@ -0,0 +1,135 @@ +#ifndef SPECKLE_RECORD_ELEMENT_COLUMN_SEGMENT +#define SPECKLE_RECORD_ELEMENT_COLUMN_SEGMENT + +#include "Speckle/Record/Element/Element.h" +#include "Speckle/Record/Element/Interface/Assembly/Segment.h" + +namespace speckle::record::element { + + class SegmentedColumn; + + /*! + BIM column class + */ + class ColumnSegment : public Element, public assembly::Segment { + public: + + // MARK: - Types + + using base = Element; + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + + using base::base; + + /*! + Default constructor + */ + ColumnSegment(); +#ifdef ARCHICAD + /*! + Constructor + @param elemData Archicad element data + @param tableID The element table ID (AC database, e.g. floor plan, 3D) + */ + ColumnSegment(const API_Element& elemData, const speckle::utility::Guid& tableID); +#endif + /*! + Copy constructor + @param source The object to copy + */ + ColumnSegment(const ColumnSegment& source); + /*! + Move constructor + @param source The object to move + */ + ColumnSegment(ColumnSegment&& source); + /*! + Destructor + */ + ~ColumnSegment(); + + /*! + Object cloning + @return A clone of this object + */ + ColumnSegment* clonePtr() const override { return new ColumnSegment{*this}; } + + + // MARK: - Functions (const) + + /*! + Get the speckle type identifier + @return The speckle type (relevant objects should override as required) + */ + speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.ColumnSegment"; } +#ifdef ARCHICAD + /*! + Get the (immutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + const API_Elem_Head& getHead() const override; +#endif + + // MARK: - Functions (mutating) + +#ifdef ARCHICAD + /*! + Get the (mutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + API_Elem_Head& getHead() override; +#endif + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + protected: + friend class SegmentedColumn; + +#ifdef ARCHICAD + /*! + Constructor + @param segment The segment element data + @param tableID The parent table ID + @param cutOrigin Cut at the segment origin + @param cutEnd Cut at the segment end + @param scheme The segment scheme + @param profile The segment profile (nullptr = none) + */ + ColumnSegment(const API_ColumnSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin, + const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme, + const API_AssemblySegmentProfileData* profile = nullptr); +#endif + + private: + class Data; + ///The column data + std::unique_ptr m_data; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_COLUMN_SEGMENT diff --git a/SpeckleLib/Speckle/Record/Element/Element.cpp b/SpeckleLib/Speckle/Record/Element/Element.cpp index 02fda04..5aa28e4 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.cpp +++ b/SpeckleLib/Speckle/Record/Element/Element.cpp @@ -3,19 +3,22 @@ #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" #include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Speckle/Database/BIMElementDatabase.h" #include "Speckle/Environment/Addon.h" +#include "Speckle/Environment/Project.h" #include "Speckle/Primitive/Mesh/Mesh.h" +#include "Speckle/Record/Element/Memo.h" #include "Speckle/SpeckleResource.h" #include "Speckle/Utility/Guid.h" #ifdef ARCHICAD -#include "Sight.hpp" -#include "Model.hpp" -#include "ModelMaterial.hpp" -#include "ModelElement.hpp" -#include "exp.h" -#include "ModelMeshBody.hpp" -#include "ConvexPolygon.hpp" +#include +#include +#include +#include +#include +#include +#include #endif using namespace active::serialise; @@ -32,14 +35,10 @@ namespace speckle::record::element { class Element::Data { public: friend class Element; - -#ifdef ARCHICAD - Data(const API_Element& elem) : root{ std::make_unique(elem) } {} - Data(const Data& source) : root{ std::make_unique(*source.root) } {} -#endif + Data() {} + Data(const Data& source) {} private: - std::unique_ptr root; std::unique_ptr m_cache; }; @@ -68,12 +67,13 @@ Element::Element() { /*-------------------------------------------------------------------- Constructor - - elemData: Archicad element data - tableID: The attribute table ID (attribute type) + + ID: The record ID + tableID: The parent table ID + unit: The record unit type --------------------------------------------------------------------*/ -Element::Element(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } { - m_data = std::make_unique(elemData); +Element::Element(const Guid& ID, const Guid& tableID, std::optional unit) : base{ID, tableID, unit} { + m_data = std::make_unique(); } //Element::Element @@ -87,6 +87,16 @@ Element::Element(const Element& source) : base{ source } { } //Element::Element +/*-------------------------------------------------------------------- + Move constructor + + source: The object to move + --------------------------------------------------------------------*/ +Element::Element(Element&& source) : base{source} { + m_data = std::move(source.m_data); +} //Element::Element + + /*-------------------------------------------------------------------- Destructor --------------------------------------------------------------------*/ @@ -213,27 +223,6 @@ Element::Body* Element::getBody() const { } -#ifdef ARCHICAD -/*-------------------------------------------------------------------- - Get the (immutable) API element header data - - return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) - --------------------------------------------------------------------*/ -const API_Elem_Head& Element::getHead() const { - return m_data->root->header; -} //Element::getHead - -/*-------------------------------------------------------------------- - Get the (mutable) API element header data - - return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) - --------------------------------------------------------------------*/ -API_Elem_Head& Element::getHead() { - return m_data->root->header; -} //Element::getHead -#endif - - /*-------------------------------------------------------------------- Fill an inventory with the package items @@ -285,3 +274,20 @@ void Element::setDefault() { base::setDefault(); m_data.reset(); } //Element::setDefault + + +/*-------------------------------------------------------------------- + Load the element memo structure (elements must override according to requirements) + + filter: Filter bits specifying memo requirements + --------------------------------------------------------------------*/ +void Element::loadMemo(Part::filter_bits filter, std::unique_ptr& memo) const { + //If the memo data isn't loaded, fetch it now + if (!memo) { + auto project = addon()->getActiveProject().lock(); + if (!project) + return; + if (auto loaded = project->getElementDatabase()->getMemo(getBIMID(), filter); loaded) + memo.reset(loaded.release()); + } +} //Element::loadMemo diff --git a/SpeckleLib/Speckle/Record/Element/Element.h b/SpeckleLib/Speckle/Record/Element/Element.h index 081119a..8a2bef1 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.h +++ b/SpeckleLib/Speckle/Record/Element/Element.h @@ -2,6 +2,7 @@ #define SPECKLE_RECORD_ELEMENT #include "Speckle/Database/Content/BIMRecord.h" +#include "Speckle/Record/Element/Interface/Part.h" #include "Speckle/Record/Attribute/Storey.h" #include "Speckle/Utility/String.h" @@ -11,6 +12,8 @@ namespace speckle::primitive { namespace speckle::record::element { + class Memo; + /*! Base BIM element class */ @@ -32,37 +35,33 @@ namespace speckle::record::element { // MARK: - Constructors - using base::base; - /*! Default constructor */ Element(); -#ifdef ARCHICAD /*! Constructor - @param elemData Archicad element data - @param tableID The element table ID (AC database, e.g. floor plan, 3D) + @param ID The record ID + @param tableID The parent table ID + @param unit The record unit type */ - Element(const API_Element& elemData, const speckle::utility::Guid& tableID); -#endif + Element(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID, + std::optional unit = active::measure::LengthType::metre); /*! Copy constructor @param source The object to copy */ Element(const Element& source); + /*! + Move constructor + @param source The object to move + */ + Element(Element&& source); /*! Destructor */ ~Element(); - /*! - Object cloning - @return A clone of this object - */ - Element* clonePtr() const override { return new Element{*this}; } - - // MARK: - Functions (const) /*! @@ -90,7 +89,7 @@ namespace speckle::record::element { Get the (immutable) API element header data @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) */ - virtual const API_Elem_Head& getHead() const; + virtual const API_Elem_Head& getHead() const = 0; #endif // MARK: - Functions (mutating) @@ -100,7 +99,7 @@ namespace speckle::record::element { Get the (mutable) API element header data @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) */ - virtual API_Elem_Head& getHead(); + virtual API_Elem_Head& getHead() = 0; #endif // MARK: - Serialisation @@ -122,6 +121,13 @@ namespace speckle::record::element { */ void setDefault() override; + protected: + /*! + Load the element memo structure (elements must override according to requirements) + @param filter Filter bits specifying memo requirements + */ + virtual void loadMemo(Part::filter_bits filter, std::unique_ptr& memo) const; + private: class Data; ///The element data diff --git a/SpeckleLib/Speckle/Record/Element/GenericElement.cpp b/SpeckleLib/Speckle/Record/Element/GenericElement.cpp new file mode 100644 index 0000000..9267061 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/GenericElement.cpp @@ -0,0 +1,157 @@ +#include "Speckle/Record/Element/GenericElement.h" + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Speckle/Environment/Addon.h" +#include "Speckle/Primitive/Mesh/Mesh.h" +#include "Speckle/SpeckleResource.h" +#include "Speckle/Utility/Guid.h" + +using namespace active::serialise; +using namespace speckle::environment; +using namespace speckle::record::attribute; +using namespace speckle::record::element; +using namespace speckle::utility; + +#include +#include + +namespace speckle::record::element { + + class GenericElement::Data { + public: + friend class GenericElement; + +#ifdef ARCHICAD + Data(const API_Element& elem) : root{ std::make_unique(elem) } {} + Data(const Data& source) : root{ std::make_unique(*source.root) } {} +#endif + + private: + std::unique_ptr root; + std::unique_ptr m_cache; + }; + +} + +namespace { + + ///Serialisation fields + enum FieldIndex { + bodyID, + }; + + ///Serialisation field IDs + static std::array fieldID = { + Identity{"displayValue"}, + }; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +GenericElement::GenericElement() { +} //GenericElement::GenericElement + + +/*-------------------------------------------------------------------- + Constructor + + elemData: Archicad element data + tableID: The attribute table ID (attribute type) + --------------------------------------------------------------------*/ +GenericElement::GenericElement(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } { + m_data = std::make_unique(elemData); +} //GenericElement::GenericElement + + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +GenericElement::GenericElement(const GenericElement& source) : base{ source } { + m_data = source.m_data ? std::make_unique(*m_data) : nullptr; +} //GenericElement::GenericElement + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +GenericElement::~GenericElement() {} + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Get the (immutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +const API_Elem_Head& GenericElement::getHead() const { + return m_data->root->header; +} //GenericElement::getHead + +/*-------------------------------------------------------------------- + Get the (mutable) API element header data + + return: The element header data (only use this data for low-level operations - for normal code, call getters/setters) + --------------------------------------------------------------------*/ +API_Elem_Head& GenericElement::getHead() { + return m_data->root->header; +} //GenericElement::getHead +#endif + + +/*-------------------------------------------------------------------- + Fill an inventory with the package items + + inventory: The inventory to receive the package items + + return: True if the package has added items to the inventory + --------------------------------------------------------------------*/ +bool GenericElement::fillInventory(Inventory& inventory) const { + using enum Entry::Type; + inventory.merge(Inventory{ + { + { fieldID[bodyID], bodyID, element }, //TODO: implement other fields + }, + }.withType(&typeid(GenericElement))); + return base::fillInventory(inventory); +} //GenericElement::fillInventory + + +/*-------------------------------------------------------------------- + Get the specified cargo + + item: The inventory item to retrieve + + return: The requested cargo (nullptr on failure) + --------------------------------------------------------------------*/ +Cargo::Unique GenericElement::getCargo(const Inventory::Item& item) const { + if (item.ownerType != &typeid(GenericElement)) + return base::getCargo(item); + using namespace active::serialise; + switch (item.index) { + case bodyID: + if (auto body = getBody(); body != nullptr) + { + return Cargo::Unique{ new active::serialise::ContainerWrap{*body} }; + } + else + return nullptr; + + default: + return nullptr; //Requested an unknown index + } +} //GenericElement::getCargo + + +/*-------------------------------------------------------------------- + Set to the default package content + --------------------------------------------------------------------*/ +void GenericElement::setDefault() { + base::setDefault(); + m_data.reset(); +} //GenericElement::setDefault diff --git a/SpeckleLib/Speckle/Record/Element/GenericElement.h b/SpeckleLib/Speckle/Record/Element/GenericElement.h new file mode 100644 index 0000000..a1d052e --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/GenericElement.h @@ -0,0 +1,112 @@ +#ifndef SPECKLE_RECORD_GENERIC_ELEMENT +#define SPECKLE_RECORD_GENERIC_ELEMENT + +#include "Speckle/Record/Element/Element.h" + +namespace speckle::record::element { + + /*! + Catch-all class for elements that are not represented by a specific class + */ + class GenericElement : public Element { + public: + + ///An element 3D body primitive + using Body = std::vector; + + // MARK: - Types + + using base = Element; + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + + using base::base; + + /*! + Default constructor + */ + GenericElement(); +#ifdef ARCHICAD + /*! + Constructor + @param elemData Archicad element data + @param tableID The element table ID (AC database, e.g. floor plan, 3D) + */ + GenericElement(const API_Element& elemData, const speckle::utility::Guid& tableID); +#endif + /*! + Copy constructor + @param source The object to copy + */ + GenericElement(const GenericElement& source); + /*! + Destructor + */ + ~GenericElement(); + + /*! + Object cloning + @return A clone of this object + */ + GenericElement* clonePtr() const override { return new GenericElement{*this}; } + + + // MARK: - Functions (const) + + /*! + Get the speckle type identifier + @return The speckle type (relevant objects should override as required) + */ + virtual speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.GenericElement:Objects.BuiltElements.GenericElement"; } +#ifdef ARCHICAD + /*! + Get the (immutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + virtual const API_Elem_Head& getHead() const override; +#endif + + // MARK: - Functions (mutating) + +#ifdef ARCHICAD + /*! + Get the (mutable) API element header data + @return The element header data (only use this data for low-level operations - for normal code, call getters/setters) + */ + virtual API_Elem_Head& getHead() override; +#endif + + // MARK: - Serialisation + + /*! + Fill an inventory with the package items + @param inventory The inventory to receive the package items + @return True if the package has added items to the inventory + */ + bool fillInventory(active::serialise::Inventory& inventory) const override; + /*! + Get the specified cargo + @param item The inventory item to retrieve + @return The requested cargo (nullptr on failure) + */ + Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Set to the default package content + */ + void setDefault() override; + + private: + class Data; + ///The element data + std::unique_ptr m_data; + }; + +} + +#endif //SPECKLE_RECORD_GENERIC_ELEMENT diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.cpp b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.cpp new file mode 100644 index 0000000..37534b0 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.cpp @@ -0,0 +1,23 @@ +#include "Speckle/Record/Element/Interface/Assembly/Path.h" + +#include "Active/Geometry/PolyEdge.h" + +#ifdef ARCHICAD +#include +#endif + +using namespace active::geometry; +using namespace speckle::database; +using namespace speckle::record::element::assembly; + +/*-------------------------------------------------------------------- + Get a specified edge from the segmented path + + index: The index of the required edge + + return: The requested edge (nullptr on failure) + --------------------------------------------------------------------*/ +std::unique_ptr Path::getSegmentEdge(const database::BIMIndex& index) const { + //TODO: Complete when required + return nullptr; +} diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.h b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.h new file mode 100644 index 0000000..62a286e --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Path.h @@ -0,0 +1,48 @@ +#ifndef SPECKLE_RECORD_ELEMENT_ASSEMBLY_PATH +#define SPECKLE_RECORD_ELEMENT_ASSEMBLY_PATH + +#include "Speckle/Database/Identity/BIMIndex.h" + +#include +#include + +namespace active::geometry { + class PolyEdge; +} + +namespace speckle::record::element::assembly { + + class Segment; + + /*! + Interface for assemblies forming a path made up of a consecutive series of segments, e.g. a portal frame made from a series of beams + */ + class Path { + public: + + // MARK: - Functions (const) + + /*! + Get a specified edge from the segmented path + @param index The index of the required edge + @return The requested edge (nullptr on failure) + */ + std::unique_ptr getSegmentEdge(const database::BIMIndex& index) const; + + protected: + /*! + Get the number of segments in the path (elements must override according to requirements) + @return The segment count + */ + virtual size_t getSegmentCount() const = 0; + /*! + Get a segment from the path (elements must override according to requirements) + @param index The index of the required segment + @return The requested segment (nullptr on failure) + */ + virtual Segment* getSegment(size_t index) const = 0; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_ASSEMBLY_PATH diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.cpp b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.cpp new file mode 100644 index 0000000..72b6973 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.cpp @@ -0,0 +1,67 @@ +#include "Speckle/Record/Element/Interface/Assembly/Segment.h" + +#include "Active/Geometry/PolyEdge.h" +#include "Active/Utility/Memory.h" + +#ifdef ARCHICAD +#include +#include +#include +#endif + +using namespace active::geometry; +using namespace speckle::record::element::assembly; + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +Segment::Segment() : + m_cutOrigin{std::make_unique()}, + m_cutEnd{std::make_unique()}, + m_scheme{std::make_unique()} { + +} //Segment::Segment + +/*-------------------------------------------------------------------- + Constructor + + cutOrigin: Cut at the segment origin + cutEnd: Cut at the segment end + scheme: The segment scheme + profile: The segment profile (nullptr = none) + --------------------------------------------------------------------*/ +Segment::Segment(const API_AssemblySegmentCutData& cutOrigin, const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme, + const API_AssemblySegmentProfileData* profile) : + m_cutOrigin{std::make_unique(cutOrigin)}, + m_cutEnd{std::make_unique(cutEnd)}, + m_scheme{std::make_unique(scheme)} { + if (profile != nullptr) { + if (profile->customOrigProfile != nullptr) + m_customProfile = std::make_unique(*profile->customOrigProfile); + if (profile->stretchedProfile != nullptr) + m_stretchedProfile = std::make_unique(*profile->stretchedProfile); + } +} //Segment::Segment + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +Segment::Segment(const Segment& source) : + m_cutOrigin{std::make_unique(*source.m_cutOrigin)}, + m_cutEnd{std::make_unique(*source.m_cutEnd)}, + m_scheme{std::make_unique(*source.m_scheme)}, + m_edge{source.m_edge ? std::make_unique(*source.m_edge) : nullptr}, + m_customProfile{source.m_customProfile ? std::make_unique(*source.m_customProfile) : nullptr}, + m_stretchedProfile{source.m_stretchedProfile ? std::make_unique(*source.m_stretchedProfile) : nullptr} { + m_path = source.m_path; +} //Segment::Segment + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +Segment::~Segment() {} + + diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.h b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.h new file mode 100644 index 0000000..bc6d248 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Assembly/Segment.h @@ -0,0 +1,91 @@ +#ifndef SPECKLE_RECORD_ELEMENT_ASSEMBLY_SEGMENT +#define SPECKLE_RECORD_ELEMENT_ASSEMBLY_SEGMENT + +#include "Speckle/Database/Identity/BIMIndex.h" + +#include +#include + +#ifdef ARCHICAD +struct API_AssemblySegmentCutData; +struct API_AssemblySegmentSchemeData; +class ProfileVectorImage; +#endif + +namespace active::geometry { + class PolyEdge; +} + +namespace speckle::record::element::assembly { + + class Path; + + /*! + Interface for elements forming a path made up of a consecutive series of segments, e.g. a portal frame made from a series of beams + */ + class Segment { + public: + /*! + Default constructor + */ + Segment(); + /*! + Copy constructor + @param source The object to copy + */ + Segment(const Segment& source); + /*! + Destructor + */ + ~Segment(); + + // MARK: - Functions (const) + + /*! + Get the segment path + @return The segment path (nullptr = undefined) + */ + const assembly::Path* getPath() const { return m_path; } + + // MARK: - Functions (mutating) + + /*! + Set the segment path + @param path The segment path + */ + void setPath(const assembly::Path* path) { m_path = path; } + + protected: + /*! + Constructor + @param cutOrigin Cut at the segment origin + @param cutEnd Cut at the segment end + @param scheme The segment scheme + @param profile The segment profile (nullptr = none) + */ + Segment(const API_AssemblySegmentCutData& cutOrigin, const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme, + const API_AssemblySegmentProfileData* profile = nullptr); + + private: +#ifdef ARCHICAD + //NB: The following properties are mutable to support lazy loading + ///Cut at the segment origin + mutable std::unique_ptr m_cutOrigin; + ///Cut at the segment end + mutable std::unique_ptr m_cutEnd; + ///The segment scheme + mutable std::unique_ptr m_scheme; + ///An optional custom profile (nullptr = none) + mutable std::unique_ptr m_customProfile; + ///An optional stretched profile (nullptr = none) + mutable std::unique_ptr m_stretchedProfile; +#endif + //The segment edge + mutable std::unique_ptr m_edge; + //The segment path + mutable const assembly::Path* m_path = nullptr; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_ASSEMBLY_SEGMENT diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Part.cpp b/SpeckleLib/Speckle/Record/Element/Interface/Part.cpp new file mode 100644 index 0000000..8c1fe9e --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Part.cpp @@ -0,0 +1,23 @@ +#include "Speckle/Record/Element/Interface/Part.h" + +#include "Speckle/Record/Element/Memo.h" + +using namespace active::serialise; +using namespace speckle::record::attribute; +using namespace speckle::record::element; +using namespace speckle::utility; + +/*-------------------------------------------------------------------- + Confirm that the element part data is loaded and valid (elements must override according to requirements) + + filter: Filter bits specifying memo requirements + + return: True if the part data is ready to use + --------------------------------------------------------------------*/ +bool Part::confirmPart(filter_bits filter) const { + if (!isMemoLoaded()) { + std::unique_ptr memo; + loadMemo(filter, memo); + } + return isMemoLoaded(); +} //Part::confirmPart diff --git a/SpeckleLib/Speckle/Record/Element/Interface/Part.h b/SpeckleLib/Speckle/Record/Element/Interface/Part.h new file mode 100644 index 0000000..faa383e --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/Part.h @@ -0,0 +1,92 @@ +#ifndef SPECKLE_RECORD_ELEMENT_PART +#define SPECKLE_RECORD_ELEMENT_PART + +#include +#include + +namespace speckle::record::element { + + class Memo; + + /*! + Interface for an element part, i.e. some component in an assembly element + + Although this concept is slanted toward Archicad's memo structure, the fundamentals are applicable to any data structures that separate out + the constituent parts of an assembly to support lazy loading + Note that this class is intended to be an interface - management and/or storage of the data should be provided by subclassing + */ + class Part { + public: + ///Filter bits for memo loading + using filter_bits = uint64_t; + + // MARK: - Types + + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + + /*! + Destructor + */ + virtual ~Part() {} + + // MARK: - Functions (const) + + + // MARK: - Functions (mutating) + + protected: + /*! + Determine if the element memo data has been successfully loaded and validated + @return True if the element memo data is loaded + */ + bool isMemoLoaded() const { return m_isLoaded && isPartValid(); } + /*! + Determine if the element memo content has been validated (elements must override according to requirements) + @return True if the element memo content is valid + */ + virtual bool isPartValid() const = 0; + /*! + Confirm that the element part data is loaded and valid (elements must override according to requirements) + @param filter Filter bits specifying memo requirements + @return True if the part data is ready to use + */ + virtual bool confirmPart(filter_bits filter) const; + /*! + Load the element memo structure (elements must override according to requirements) + @param filter Filter bits specifying memo requirements + */ + virtual void loadMemo(filter_bits filter, std::unique_ptr& memo) const = 0; + /*! + Set whether the element memo data has been loaded (does not establish validity, but prevents multiple attempts to reload) + @param state True if the element memo data is loaded + */ + void setMemoLoaded(bool state) const { m_isLoaded = state; } + + /*! + Send the element part back to a memo structure for storage (elements must override according to requirements) + @param memo The memo to carry the data + @return True if the data was successfully sent + */ + virtual bool send(Memo* memo) const = 0; + /*! + Receive the element memo data from a memo structure (elements must override according to requirements) + @param memo The memo carrying the data + @return True if the data was successfully received + */ + virtual bool receive(const Memo& memo) const = 0; + + private: + ///True if the memo data has been loaded into the element (mutable to support lazy loading) + mutable bool m_isLoaded = false; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_PART diff --git a/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.cpp b/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.cpp new file mode 100644 index 0000000..92bab68 --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.cpp @@ -0,0 +1,158 @@ +#include "Speckle/Record/Element/Interface/SegmentedColumn.h" + +#include "Speckle/Record/Element/ColumnSegment.h" +#include "Speckle/Record/Element/Memo.h" +#include "Speckle/Record/Element/Interface/Assembly/Path.h" +#include "Speckle/Utility/BIMMemory.h" + +using namespace active::serialise; +using namespace speckle::record::attribute; +using namespace speckle::record::element; +using namespace speckle::utility; + +namespace speckle::record::element { + + class SegmentedColumn::Data { + public: + friend class SegmentedColumn; + + std::vector segments; + }; + +} + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +SegmentedColumn::SegmentedColumn() { +} //SegmentedColumn::SegmentedColumn + + +/*-------------------------------------------------------------------- + Copy constructor + + source: The object to copy + --------------------------------------------------------------------*/ +SegmentedColumn::SegmentedColumn(const SegmentedColumn& source) : base{ source } { + m_data = source.m_data ? std::make_unique(*m_data) : nullptr; +} //SegmentedColumn::SegmentedColumn + + +/*-------------------------------------------------------------------- + Destructor + --------------------------------------------------------------------*/ +SegmentedColumn::~SegmentedColumn() {} + + +/*-------------------------------------------------------------------- + Get the number of segments + + return. The number of segments (0 on error) + --------------------------------------------------------------------*/ +size_t SegmentedColumn::getSegmentCount() const { + confirmPart(getPartFilter()); + return m_data ? m_data->segments.size() : 0; +} //SegmentedColumn::getSegmentCount + + +/*-------------------------------------------------------------------- + Get a column segment + + index: The index of the required segment + + return: The requested segment, nullptr on error + --------------------------------------------------------------------*/ +ColumnSegment* SegmentedColumn::getSegment(size_t index) const { + confirmPart(getPartFilter()); + return (m_data && (index < m_data->segments.size())) ? &m_data->segments[index] : nullptr; +} //SegmentedColumn::getSegment + + +/*-------------------------------------------------------------------- + Return the bits for the part filter required to load the data necessary to build this object + + return: The required filter bits + --------------------------------------------------------------------*/ +Part::filter_bits SegmentedColumn::getPartFilter() const { + return APIMemoMask_ColumnSegment | APIMemoMask_AssemblySegmentCut | APIMemoMask_AssemblySegmentScheme | APIMemoMask_AssemblySegmentProfile; +} //SegmentedColumn::getPartFilter + + +/*-------------------------------------------------------------------- + Determine if the element memo content has been validated (elements must override according to requirements) + + return: True if the element memo content is valid + --------------------------------------------------------------------*/ +bool SegmentedColumn::isPartValid() const { + return m_data && !m_data->segments.empty(); +} //SegmentedColumn::isPartValid + + +/*-------------------------------------------------------------------- + Load the element memo structure (elements must override according to requirements) + + filter: Filter bits specifying memo requirements + --------------------------------------------------------------------*/ +void SegmentedColumn::loadMemo(filter_bits filter, std::unique_ptr& memo) const { + +} //SegmentedColumn::loadMemo + + +/*-------------------------------------------------------------------- + Send the element part back to a memo structure for storage (elements must override according to requirements) + + memo: The memo to carry the data + + return: True if the data was successfully sent + --------------------------------------------------------------------*/ +bool SegmentedColumn::send(Memo* memo) const { + //TODO: Complete when required + return false; +} //SegmentedColumn::send + + +/*-------------------------------------------------------------------- + Receive the element memo data from a memo structure (elements must override according to requirements) + + memo: The memo carrying the data + + return: True if the data was successfully received + --------------------------------------------------------------------*/ +bool SegmentedColumn::receive(const Memo& memo) const { +#ifdef ARCHICAD + if (!memo || (memo.root()->columnSegments == nullptr)) + return false; + if (m_data) + m_data->segments.clear(); + else + m_data = std::make_unique(); + //Confirm that required data is present in the memo + auto segmentPtr = memo.root()->columnSegments; + auto cutPtr = memo.root()->assemblySegmentCuts; + auto schemePtr = memo.root()->assemblySegmentSchemes; + auto profilePtr = memo.root()->assemblySegmentProfiles; + if ((segmentPtr == nullptr) || (cutPtr == nullptr) || (schemePtr == nullptr)) + return false; + //Determine available item count + auto segmentCount = BIMMemory::getPtrSize(segmentPtr) / sizeof(API_ColumnSegmentType); + auto cutCount = BIMMemory::getPtrSize(cutPtr) / sizeof(API_AssemblySegmentCutData); + auto schemeCount = BIMMemory::getPtrSize(schemePtr) / sizeof(API_AssemblySegmentSchemeData); + auto profileCount = BIMMemory::getPtrSize(profilePtr) / sizeof(API_AssemblySegmentProfileData); + if ((segmentCount == 0) || (cutCount != (segmentCount + 1)) || (schemeCount != segmentCount)) + return false; + auto path = dynamic_cast(this); + for (size_t n = 0 ; n < segmentCount; ++n) { + const API_AssemblySegmentProfileData* thisProfile = nullptr; + for (size_t i = 0; i < profileCount; ++i) { + if (profilePtr[i].segmentIndex == n) { + thisProfile = profilePtr + i; + break; + } + } + m_data->segments.emplace_back(ColumnSegment{segmentPtr[n], getTableID(), cutPtr[n], cutPtr[n + 1], schemePtr[n], thisProfile}); + m_data->segments.back().setPath(path); + } + setMemoLoaded(true); +#endif + return true; +} //SegmentedColumn::receive diff --git a/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.h b/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.h new file mode 100644 index 0000000..912cddb --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Interface/SegmentedColumn.h @@ -0,0 +1,103 @@ +#ifndef SPECKLE_RECORD_ELEMENT_SEGMENTED_COLUMN +#define SPECKLE_RECORD_ELEMENT_SEGMENTED_COLUMN + +#include "Speckle/Database/Identity/BIMRecordID.h" +#include "Speckle/Record/Element/Interface/Part.h" + +namespace speckle::record::element { + + class ColumnSegment; + + /*! + Interface for a column type that is made up of consecutive segments + + Note that the child segments use lazy loading to avoid high overheads when accessing data relevant to the parent column only + */ + class SegmentedColumn : public Part { + public: + + // MARK: - Types + + using base = Part; + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + + /*! + Default constructor + */ + SegmentedColumn(); + /*! + Copy constructor + @param source The object to copy + */ + SegmentedColumn(const SegmentedColumn& source); + /*! + Destructor + */ + ~SegmentedColumn(); + + // MARK: - Functions (const) + + /*! + Get the BIM application parent table ID + @return The BIM table ID + */ + virtual database::BIMRecordID getTableID() const = 0; + /*! + Get the number of segments + @return The number of segments (0 on error) + */ + size_t getSegmentCount() const; + /*! + Get a column segment + @param index The index of the required segment + @return The requested segment, nullptr on error + */ + ColumnSegment* getSegment(size_t index) const; + + // MARK: - Functions (mutating) + + protected: + /*! + Return the bits for the part filter required to load the data necessary to build this object + @return The required filter bits */ + filter_bits getPartFilter() const; + /*! + Determine if the element part content has been validated (elements must override according to requirements) + @return True if the element part content is valid + */ + bool isPartValid() const override; + /*! + Load the element memo structure (elements must override according to requirements) + @param filter Filter bits specifying memo requirements + */ + void loadMemo(filter_bits filter, std::unique_ptr& memo) const override; + + /*! + Send the element part back to a memo structure for storage (elements must override according to requirements) + @param memo The memo to carry the data + @return True if the data was successfully sent + */ + bool send(Memo* memo) const override; + /*! + Receive the element memo data from a memo structure (elements must override according to requirements) + @param memo The memo carrying the data + @return True if the data was successfully received + */ + bool receive(const Memo& memo) const override; + + private: + class Data; + ///The segment data - mutable to support lazy loading + mutable std::unique_ptr m_data; + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_SEGMENTED_COLUMN diff --git a/SpeckleLib/Speckle/Record/Element/Memo.cpp b/SpeckleLib/Speckle/Record/Element/Memo.cpp new file mode 100644 index 0000000..d5bc00a --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Memo.cpp @@ -0,0 +1,54 @@ +#include "Speckle/Record/Element/Memo.h" + +#include "Active/Utility/Memory.h" + +#ifdef ARCHICAD +#include +#endif + +using namespace speckle::record::element; + +namespace speckle::record::element { + API_Elem_Head Memo::m_dummy{}; +} + + +#ifdef ARCHICAD +/*-------------------------------------------------------------------- + Default constructor + + memo: A memo structure - this object will take ownership of anything passed to the constructor + --------------------------------------------------------------------*/ +Memo::Memo(std::unique_ptr memo) : m_data{std::move(memo)} { + if (!memo) { + //If no data was supplied, we still allocate an empty in the event that a new element is being constructed + m_data = std::make_unique(); + active::utility::Memory::erase(*m_data); + } +} //Memo::Memo +#endif + + +/*-------------------------------------------------------------------- + Default constructor + --------------------------------------------------------------------*/ +Memo::~Memo() { +#ifdef ARCHICAD + if (m_data) + ACAPI_DisposeElemMemoHdls(m_data.get()); +#endif +} //Memo::Memo + + +/*-------------------------------------------------------------------- + Conversion operator + + return: True if the memo contains data + --------------------------------------------------------------------*/ +Memo::operator bool() const { +#ifdef ARCHICAD + return m_data.operator bool(); +#else + return false; +#endif +} //Memo::operator bool diff --git a/SpeckleLib/Speckle/Record/Element/Memo.h b/SpeckleLib/Speckle/Record/Element/Memo.h new file mode 100644 index 0000000..b78e77b --- /dev/null +++ b/SpeckleLib/Speckle/Record/Element/Memo.h @@ -0,0 +1,92 @@ +#ifndef SPECKLE_RECORD_ELEMENT_MEMO +#define SPECKLE_RECORD_ELEMENT_MEMO + +#include "Speckle/Record/Element/Element.h" + +#include +#include + +#ifdef ARCHICAD +struct API_ElementMemo; +#endif + +namespace speckle::record::element { + + /*! + Wrapper for Archicad memo data structure + + The main purpose for this wrapper is memory safely. In addition to maneging ownership of the memo structure, each handle/pointer allocation + within the structure must be released to prevent leaks. This wrapper will ensure these calls are made + */ + class Memo : public Element { + public: + + // MARK: - Types + + ///Unique pointer + using Unique = std::unique_ptr; + ///Shared pointer + using Shared = std::shared_ptr; + ///Optional + using Option = std::optional; + + // MARK: - Constructors + +#ifdef ARCHICAD + /*! + Default constructor + @param memo A memo structure - this object will take ownership of anything passed to the constructor + */ + Memo(std::unique_ptr memo = nullptr); +#endif + /*! + Destructor + */ + virtual ~Memo(); + + // MARK: - Operators + + /*! + Conversion operator + @return True if the memo contains data + */ + operator bool() const; + + // MARK: - Functions (const) + +#ifdef ARCHICAD + /*! + Get the memo root data + @return The memo root data (nullptr on failure) + */ + API_ElementMemo* root() const { return m_data.get(); } +#endif + + // MARK: - Functions (mutating) + +#ifdef ARCHICAD + /*! + Get the memo root data + @return The memo root data (nullptr on failure) + */ + Memo& set(std::unique_ptr memo) { + m_data = std::move(memo); + return *this; + } +#endif + + private: +#ifdef ARCHICAD + //NB: The following is functionally redundant for memos - requirement of base class + static API_Elem_Head m_dummy; + virtual const API_Elem_Head& getHead() const { return m_dummy; } + virtual API_Elem_Head& getHead() { return m_dummy; } + + ///The memo data + std::unique_ptr m_data; +#endif + }; + +} + +#endif //SPECKLE_RECORD_ELEMENT_MEMO diff --git a/SpeckleLib/Speckle/Utility/BIMMemory.cpp b/SpeckleLib/Speckle/Utility/BIMMemory.cpp new file mode 100644 index 0000000..c25a7bf --- /dev/null +++ b/SpeckleLib/Speckle/Utility/BIMMemory.cpp @@ -0,0 +1,39 @@ +#include "Speckle/Utility/BIMMemory.h" + +#ifdef ARCHICAD +#include "BM.hpp" +#endif + +using namespace speckle::utility; + +namespace { + +#ifdef ARCHICAD + /*! + Get the error code from the last memory operation + @return The last error + */ + GSErr getLastError() { + return BMError(); + } +#endif + +} + +/*-------------------------------------------------------------------- + Get the size of an allocated pointer block + + pointer: The target pointer + + return: The allocated pointer size + --------------------------------------------------------------------*/ +size_t BIMMemory::getPtrSize(void* pointer) { +#ifdef ARCHICAD + if (pointer == nullptr) + return 0; + auto size = BMGetPtrSize(reinterpret_cast(pointer)); + if (getLastError() != NoError) + throw; //TODO: Throw a specific exception type + return size; +#endif +} //BIMMemory::getPtrSize diff --git a/SpeckleLib/Speckle/Utility/BIMMemory.h b/SpeckleLib/Speckle/Utility/BIMMemory.h new file mode 100644 index 0000000..0dc5fed --- /dev/null +++ b/SpeckleLib/Speckle/Utility/BIMMemory.h @@ -0,0 +1,23 @@ +#ifndef SPECKLE_UTILITY_BIM_MEMORY +#define SPECKLE_UTILITY_BIM_MEMORY + +#include + +namespace speckle::utility { + + /*! + BIM memory functions + */ + class BIMMemory { + public: + /*! + Get the size of an allocated pointer block + @param pointer The target pointer + @return The allocated pointer size + */ + static size_t getPtrSize(void* pointer); + }; + +} + +#endif //SPECKLE_UTILITY_BIM_MEMORY diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index 0781bc6..1d1ec4a 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -51,6 +51,24 @@ 21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FB9F2CB880690023F24E /* FinishCollector.h */; }; 21A0FBB52CBA5E380023F24E /* Str256.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBB42CBA5E380023F24E /* Str256.h */; }; 21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */; }; + 21A0FBEA2CBD6B1A0023F24E /* ColumnSegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FBDF2CBD6B1A0023F24E /* ColumnSegment.cpp */; }; + 21A0FBEB2CBD6B1A0023F24E /* ColumnSegment.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBE22CBD6B1A0023F24E /* ColumnSegment.h */; }; + 21A0FBED2CBD6B1A0023F24E /* Part.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBE42CBD6B1A0023F24E /* Part.h */; }; + 21A0FBF02CBD6B1A0023F24E /* Column.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FBE82CBD6B1A0023F24E /* Column.cpp */; }; + 21A0FBF12CBD6B1A0023F24E /* Column.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBE92CBD6B1A0023F24E /* Column.h */; }; + 21A0FBF42CBD6B700023F24E /* Memo.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBF22CBD6B700023F24E /* Memo.h */; }; + 21A0FBF52CBD6B700023F24E /* Memo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FBF32CBD6B700023F24E /* Memo.cpp */; }; + 21A0FBF82CBDB9A70023F24E /* BIMMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FBF62CBDB9A70023F24E /* BIMMemory.cpp */; }; + 21A0FBF92CBDB9A70023F24E /* BIMMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBF72CBDB9A70023F24E /* BIMMemory.h */; }; + 21A0FC042CBE59A80023F24E /* SegmentedColumn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FBFF2CBE59A80023F24E /* SegmentedColumn.cpp */; }; + 21A0FC052CBE59A80023F24E /* SegmentedColumn.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FC002CBE59A80023F24E /* SegmentedColumn.h */; }; + 21A0FC062CBE59A80023F24E /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC012CBE59A80023F24E /* Path.cpp */; }; + 21A0FC072CBE59A80023F24E /* Path.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FC022CBE59A80023F24E /* Path.h */; }; + 21A0FC0A2CBE5E220023F24E /* Segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC082CBE5E220023F24E /* Segment.cpp */; }; + 21A0FC0B2CBE5E220023F24E /* Segment.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FC092CBE5E220023F24E /* Segment.h */; }; + 21A0FC0E2CBE92F10023F24E /* GenericElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC0C2CBE92F10023F24E /* GenericElement.cpp */; }; + 21A0FC0F2CBE92F10023F24E /* GenericElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FC0D2CBE92F10023F24E /* GenericElement.h */; }; + 21A0FC112CBEE5C30023F24E /* Part.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC102CBEE5C30023F24E /* Part.cpp */; }; 21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */; }; 21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */; }; 21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */; }; @@ -193,6 +211,24 @@ 21A0FBA92CB9324A0023F24E /* FinishProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = ""; }; 21A0FBB42CBA5E380023F24E /* Str256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Str256.h; sourceTree = ""; }; 21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadRGB.h; sourceTree = ""; }; + 21A0FBDF2CBD6B1A0023F24E /* ColumnSegment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColumnSegment.cpp; sourceTree = ""; }; + 21A0FBE22CBD6B1A0023F24E /* ColumnSegment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColumnSegment.h; sourceTree = ""; }; + 21A0FBE42CBD6B1A0023F24E /* Part.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Part.h; sourceTree = ""; }; + 21A0FBE82CBD6B1A0023F24E /* Column.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Column.cpp; sourceTree = ""; }; + 21A0FBE92CBD6B1A0023F24E /* Column.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Column.h; sourceTree = ""; }; + 21A0FBF22CBD6B700023F24E /* Memo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Memo.h; sourceTree = ""; }; + 21A0FBF32CBD6B700023F24E /* Memo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Memo.cpp; sourceTree = ""; }; + 21A0FBF62CBDB9A70023F24E /* BIMMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMMemory.cpp; sourceTree = ""; }; + 21A0FBF72CBDB9A70023F24E /* BIMMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMMemory.h; sourceTree = ""; }; + 21A0FBFF2CBE59A80023F24E /* SegmentedColumn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentedColumn.cpp; sourceTree = ""; }; + 21A0FC002CBE59A80023F24E /* SegmentedColumn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SegmentedColumn.h; sourceTree = ""; }; + 21A0FC012CBE59A80023F24E /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Path.cpp; sourceTree = ""; }; + 21A0FC022CBE59A80023F24E /* Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Path.h; sourceTree = ""; }; + 21A0FC082CBE5E220023F24E /* Segment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Segment.cpp; sourceTree = ""; }; + 21A0FC092CBE5E220023F24E /* Segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Segment.h; sourceTree = ""; }; + 21A0FC0C2CBE92F10023F24E /* GenericElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericElement.cpp; sourceTree = ""; }; + 21A0FC0D2CBE92F10023F24E /* GenericElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericElement.h; sourceTree = ""; }; + 21A0FC102CBEE5C30023F24E /* Part.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Part.cpp; path = Speckle/Record/Element/Interface/Part.cpp; sourceTree = SOURCE_ROOT; }; 21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = ""; }; 21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = ""; }; 21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachmentManager.h; sourceTree = ""; }; @@ -340,8 +376,17 @@ 215F087A2CA18E1400CD343B /* Element */ = { isa = PBXGroup; children = ( + 21A0FBE82CBD6B1A0023F24E /* Column.cpp */, + 21A0FBE92CBD6B1A0023F24E /* Column.h */, + 21A0FBDF2CBD6B1A0023F24E /* ColumnSegment.cpp */, + 21A0FBE22CBD6B1A0023F24E /* ColumnSegment.h */, 215F08782CA18E1400CD343B /* Element.cpp */, 215F08792CA18E1400CD343B /* Element.h */, + 21A0FC0C2CBE92F10023F24E /* GenericElement.cpp */, + 21A0FC0D2CBE92F10023F24E /* GenericElement.h */, + 21A0FBE72CBD6B1A0023F24E /* Interface */, + 21A0FBF32CBD6B700023F24E /* Memo.cpp */, + 21A0FBF22CBD6B700023F24E /* Memo.h */, ); path = Element; sourceTree = ""; @@ -429,6 +474,8 @@ 219351B02C62CC1A00E5A69C /* Utility */ = { isa = PBXGroup; children = ( + 21A0FBF62CBDB9A70023F24E /* BIMMemory.cpp */, + 21A0FBF72CBDB9A70023F24E /* BIMMemory.h */, 21B67CFE2C7CE15100FD64FC /* Exception.h */, 219351AC2C62CC1A00E5A69C /* Guid.cpp */, 219351AD2C62CC1A00E5A69C /* Guid.h */, @@ -499,6 +546,29 @@ path = Types; sourceTree = ""; }; + 21A0FBE72CBD6B1A0023F24E /* Interface */ = { + isa = PBXGroup; + children = ( + 21A0FC032CBE59A80023F24E /* Assembly */, + 21A0FC102CBEE5C30023F24E /* Part.cpp */, + 21A0FBE42CBD6B1A0023F24E /* Part.h */, + 21A0FBFF2CBE59A80023F24E /* SegmentedColumn.cpp */, + 21A0FC002CBE59A80023F24E /* SegmentedColumn.h */, + ); + path = Interface; + sourceTree = ""; + }; + 21A0FC032CBE59A80023F24E /* Assembly */ = { + isa = PBXGroup; + children = ( + 21A0FC012CBE59A80023F24E /* Path.cpp */, + 21A0FC022CBE59A80023F24E /* Path.h */, + 21A0FC082CBE5E220023F24E /* Segment.cpp */, + 21A0FC092CBE5E220023F24E /* Segment.h */, + ); + path = Assembly; + sourceTree = ""; + }; 21AEF9C72CA818EA000B8681 /* Detached */ = { isa = PBXGroup; children = ( @@ -705,6 +775,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 21A0FBF42CBD6B700023F24E /* Memo.h in Headers */, 215F088C2CA195EC00CD343B /* ArchicadDBaseCore.h in Headers */, 21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */, 21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */, @@ -721,10 +792,15 @@ 21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */, 210CC88F2C81A98500610F58 /* Guid64.h in Headers */, 21AEF9DD2CAAA4EA000B8681 /* DetachedObjectStore.h in Headers */, + 21A0FBF12CBD6B1A0023F24E /* Column.h in Headers */, + 21A0FC072CBE59A80023F24E /* Path.h in Headers */, 21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */, + 21A0FC0B2CBE5E220023F24E /* Segment.h in Headers */, 215F088D2CA195EC00CD343B /* ArchicadElementDBaseEngine.h in Headers */, 2196F2F42CB483D600450DFC /* Finish.h in Headers */, + 21A0FBED2CBD6B1A0023F24E /* Part.h in Headers */, 21B67D002C7CE15100FD64FC /* Exception.h in Headers */, + 21A0FBEB2CBD6B1A0023F24E /* ColumnSegment.h in Headers */, 21D0BD2C2C86FC350077E104 /* Record.h in Headers */, 21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */, 215F087E2CA18E1400CD343B /* Element.h in Headers */, @@ -734,7 +810,10 @@ 210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */, 21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */, 2196F3042CB57E8000450DFC /* Storey.h in Headers */, + 21A0FBF92CBDB9A70023F24E /* BIMMemory.h in Headers */, 21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */, + 21A0FC052CBE59A80023F24E /* SegmentedColumn.h in Headers */, + 21A0FC0F2CBE92F10023F24E /* GenericElement.h in Headers */, 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */, 21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */, 2196F2EC2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h in Headers */, @@ -863,6 +942,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 21A0FC0A2CBE5E220023F24E /* Segment.cpp in Sources */, 21D0BD552C890B1C0077E104 /* ServerMigration.cpp in Sources */, 21F69FA62C733EDA008B6A06 /* BridgeArgument.cpp in Sources */, 21F69F682C6DFB01008B6A06 /* RunMethod.cpp in Sources */, @@ -885,25 +965,33 @@ 2196F3052CB57E8000450DFC /* Storey.cpp in Sources */, 219245FE2CA2CC4300CF5703 /* BIMRecord.cpp in Sources */, 21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */, + 21A0FC062CBE59A80023F24E /* Path.cpp in Sources */, 2196F2F52CB483D600450DFC /* Finish.cpp in Sources */, + 21A0FBEA2CBD6B1A0023F24E /* ColumnSegment.cpp in Sources */, 2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */, 21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */, 219246042CA2CE2700CF5703 /* BIMLink.cpp in Sources */, 215F08952CA19AF800CD343B /* BIMElementDatabase.cpp in Sources */, + 21A0FC0E2CBE92F10023F24E /* GenericElement.cpp in Sources */, 219246122CA34DCE00CF5703 /* Mesh.cpp in Sources */, + 21A0FBF02CBD6B1A0023F24E /* Column.cpp in Sources */, 21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */, 210CC8902C81A98500610F58 /* Guid64.cpp in Sources */, 21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */, 219351B32C62CC1A00E5A69C /* String.cpp in Sources */, 219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */, 21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */, + 21A0FC112CBEE5C30023F24E /* Part.cpp in Sources */, 21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */, 215F08552C99DA8D00CD343B /* Project.cpp in Sources */, 21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */, 2196F2EB2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp in Sources */, + 21A0FC042CBE59A80023F24E /* SegmentedColumn.cpp in Sources */, 210CC89F2C81E34400610F58 /* Platform.cpp in Sources */, 21D0BD202C86F0280077E104 /* AccountDatabase.cpp in Sources */, 21F69F962C71087A008B6A06 /* Account.cpp in Sources */, + 21A0FBF82CBDB9A70023F24E /* BIMMemory.cpp in Sources */, + 21A0FBF52CBD6B700023F24E /* Memo.cpp in Sources */, 21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/SpeckleLib/SpeckleLib17.vcxproj b/SpeckleLib/SpeckleLib17.vcxproj index 6dc6cba..22f73ca 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj +++ b/SpeckleLib/SpeckleLib17.vcxproj @@ -71,7 +71,15 @@ + + + + + + + + @@ -84,6 +92,7 @@ + @@ -124,12 +133,21 @@ + + + + + + + + + diff --git a/SpeckleLib/SpeckleLib17.vcxproj.filters b/SpeckleLib/SpeckleLib17.vcxproj.filters index 42974d7..6550add 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj.filters +++ b/SpeckleLib/SpeckleLib17.vcxproj.filters @@ -98,6 +98,12 @@ {7f43d4ea-b876-4587-a646-90eab81f7976} + + {b35abbfd-3c47-45dc-8dab-58911f233a87} + + + {8e7a76da-47ac-4105-9c09-7d7ed62d7136} + @@ -310,6 +316,33 @@ Speckle\Serialise\Types + + Speckle\Record\Element + + + Speckle\Record\Element + + + Speckle\Record\Element + + + Speckle\Record\Element\Interface + + + Speckle\Record\Element\Interface + + + Speckle\Record\Element\Interface\Assembly + + + Speckle\Record\Element\Interface\Assembly + + + Speckle\Utility + + + Speckle\Record\Element + @@ -438,6 +471,33 @@ Speckle\Serialise\Types\Units + + Speckle\Record\Element + + + Speckle\Record\Element + + + Speckle\Record\Element + + + Speckle\Record\Element\Interface + + + Speckle\Record\Element\Interface + + + Speckle\Record\Element\Interface\Assembly + + + Speckle\Record\Element\Interface\Assembly + + + Speckle\Utility + + + Speckle\Record\Element +