Added BIM property database + engine

Added property classes including:
- templates
- settings
- values
Added Classified interface for records supporting classification
Added Propertied interface for records supporting attached properties
Distinguished model elements from drawing elements (only model elements support classification/properties) with:
- DrawingElement (2D only)
- ModelElement (having a 3D/model presence)
This commit is contained in:
Ralph Wessel
2024-10-21 16:25:23 +01:00
parent 878988df95
commit 35f4e58a58
39 changed files with 3070 additions and 271 deletions
@@ -31,11 +31,6 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Get the current user attribute selection
@return A list of selected attribute IDs
*/
BIMLinkList getSelection() const;
/*!
Get a specified attribute
@param attributeID The ID of the target attribute
@@ -0,0 +1,141 @@
#include "Speckle/Database/BIMPropertyDatabase.h"
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h"
#include "Speckle/Record/Property/Setting.h"
#include <array>
using namespace active::container;
using namespace active::database;
using namespace active::event;
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::record;
using namespace speckle::record::property;
using namespace speckle::database;
using namespace speckle::utility;
namespace speckle::database {
///Define other platform engines here as required
#ifdef ARCHICAD
using PropertyDatabaseEngine = ArchicadPropertyDBaseEngine;
#endif
///Property database engine declaration
class BIMPropertyDatabase::Engine : public PropertyDatabaseEngine {
using base = ArchicadPropertyDBaseEngine;
using base::base;
};
///Property database storage declaration
class BIMPropertyDatabase::Store : public Storage<Template, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID> {
using base = Storage<Template, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID>;
using base::base;
};
}
namespace {
///The database storage identifier for properties
const char* propertyDBaseName = "speckle::database::BIMPropertyDatabase";
///The primary model table, e.g. floor plan in Archicad
const char* modelTableName = "Model";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
BIMPropertyDatabase::BIMPropertyDatabase() {
m_engine = std::make_shared<Engine>(propertyDBaseName,
//Schema
DBaseSchema{active::utility::String{propertyDBaseName},
//Tables
{
//Model property table
{
modelTableName, 0, 0, {} //The primary model. Additonal tables could be linked to other drawings/layouts in future
}
}
}
);
m_store = std::make_shared<Store>(m_engine);
} //BIMPropertyDatabase::BIMPropertyDatabase
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
BIMPropertyDatabase::~BIMPropertyDatabase() {}
/*--------------------------------------------------------------------
Get a specified property
propertyID: The ID of the target property
return: The requested property (nullptr on failure)
--------------------------------------------------------------------*/
Template::Unique BIMPropertyDatabase::getProperty(const BIMRecordID& propertyID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_engine->getObject(propertyID, tableID, documentID);
} //BIMPropertyDatabase::getProperty
/*--------------------------------------------------------------------
Get a specified property
link: A link to the target property
return: The requested property (nullptr on failure)
--------------------------------------------------------------------*/
Template::Unique BIMPropertyDatabase::getProperty(const BIMLink& link) const {
return getProperty(link, link.tableID, link.docID);
} //BIMPropertyDatabase::getProperty
/*--------------------------------------------------------------------
Get all properties
return: All the properties
--------------------------------------------------------------------*/
Vector<Template> BIMPropertyDatabase::getProperties() const {
return m_store->getObjects();
} //BIMPropertyDatabase::getPropertys
/*--------------------------------------------------------------------
Find all property templates linked to specified classifications
classifications: The classifications
return: A list of shared pointers to linked property templates
--------------------------------------------------------------------*/
std::vector<std::shared_ptr<Template>> BIMPropertyDatabase::findTemplatesByClassification(const BIMRecordIDList& classifications) const {
return m_engine->findTemplatesByClassification(classifications);
} //BIMPropertyDatabase::findTemplatesByClassification
/*--------------------------------------------------------------------
Write an property to storage
property: The property to write
--------------------------------------------------------------------*/
void BIMPropertyDatabase::write(const Template& property) const {
m_store->write(property);
} //BIMPropertyDatabase::write
/*--------------------------------------------------------------------
Erase an property
propertyID: The ID of the property to erase
--------------------------------------------------------------------*/
void BIMPropertyDatabase::erase(const Guid& propertyID) const {
m_store->erase(propertyID);
} //BIMPropertyDatabase::erase
@@ -0,0 +1,83 @@
#ifndef CONNECTOR_DATABASE_BIM_PROPERTY_DATABASE
#define CONNECTOR_DATABASE_BIM_PROPERTY_DATABASE
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Property/Template.h"
#include "Speckle/Utility/Guid.h"
namespace active::event {
class Subscriber;
}
namespace speckle::database {
/*!
Database of property templates relating to a specific project
Note that this database manages just the property templates, not the values. Property values are attached to elements
*/
class BIMPropertyDatabase {
public:
// MARK: - Constructors
/*!
Constructor
*/
BIMPropertyDatabase();
BIMPropertyDatabase(const BIMPropertyDatabase&) = delete;
/*!
Destructor
*/
~BIMPropertyDatabase();
// MARK: - Functions (const)
/*!
Get a specified property
@param propertyID The ID of the target property
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested property (nullptr on failure)
*/
record::property::Template::Unique getProperty(const BIMRecordID& propertyID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get a specified property
@param link A link to the target property
@return The requested property (nullptr on failure)
*/
record::property::Template::Unique getProperty(const BIMLink& link) const;
/*!
Get all model properties
@return All the properties
*/
active::container::Vector<record::property::Template> getProperties() const;
/*!
Find all property templates linked to specified classifications
@param classifications The classifications
@return A list of shared pointers to linked property templates
*/
std::vector<std::shared_ptr<record::property::Template>> findTemplatesByClassification(const BIMRecordIDList& classifications) const;
/*!
Write an property to storage
@param property The property to write
*/
void write(const record::property::Template& property) const;
/*!
Erase an property
@param propertyID The ID of the property to erase
*/
void erase(const speckle::utility::Guid& propertyID) const;
private:
class Engine;
class Store;
///Model property database storage
std::shared_ptr<Engine> m_engine;
std::shared_ptr<Store> m_store;
};
}
#endif //CONNECTOR_DATABASE_BIM_PROPERTY_DATABASE
@@ -3,6 +3,8 @@
#include "Speckle/Utility/Guid.h"
#include <unordered_set>
namespace speckle::database {
#ifdef ARCHICAD
@@ -14,10 +16,14 @@ namespace speckle::database {
using BIMDocID = speckle::utility::Guid;
//Common BIM database identifier type (e.g. model database, library database, attribute database)
using BIMDBaseID = speckle::utility::Guid;
//Common BIM record identifier pair type (e.g. pairing a record with a parent)
using BIMRecordIDPair = std::pair<speckle::utility::Guid, speckle::utility::Guid>;
#endif
//A list of BIM record IDs
using BIMRecordIDList = std::vector<BIMRecordID>;
using BIMRecordIDList = std::unordered_set<BIMRecordID>;
//A list of BIM record ID pairs
using BIMRecordIDPairList = std::unordered_set<BIMRecordIDPair>;
}
@@ -125,6 +125,7 @@ namespace {
Constructor
id: The document storage identifier
schema: The document storage schema
--------------------------------------------------------------------*/
ArchicadAttributeDBaseEngine::ArchicadAttributeDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) :
ArchicadDBaseCore{id, std::move(schema)} {
@@ -40,6 +40,7 @@ namespace speckle::database {
/*!
Constructor
@param id The document storage identifier
@param schema The document storage schema
*/
ArchicadAttributeDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema);
ArchicadAttributeDBaseEngine(const ArchicadAttributeDBaseEngine&) = delete;
@@ -12,7 +12,7 @@
#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/ModelElement.h"
#include "Speckle/Record/Element/Memo.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
@@ -77,7 +77,7 @@ namespace {
case API_ColumnSegmentID:
return std::make_unique<ColumnSegment>(elementData, tableID);
default:
return std::make_unique<GenericElement>(elementData, tableID);
return std::make_unique<ModelElement>(elementData, tableID);
}
}
@@ -46,6 +46,7 @@ namespace speckle::database {
/*!
Constructor
@param id The document storage identifier
@param schema The document storage schema
*/
ArchicadElementDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) : ArchicadDBaseCore{id, std::move(schema)} {}
ArchicadElementDBaseEngine(const ArchicadElementDBaseEngine&) = delete;
@@ -0,0 +1,256 @@
#include "Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h"
#ifdef ARCHICAD
#include "Active/Utility/Memory.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Record/Property/Setting.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <ACAPinc.h>
#include <ACAPI_Database.h>
#include <BM.hpp>
using namespace active::event;
using namespace active::setting;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::record::property;
using namespace speckle::utility;
using enum ArchicadDBaseCore::Status;
namespace {
/*!
Make a new template object
@param templateData The API template representation
@return A new template object (nullptr on failure)
*/
Template::Shared makeTemplate(const API_PropertyDefinition& templateData) {
//NB: This function has been written to allow for the future possibility of different methods for constructing a template and/or
//failure to make one
return std::make_shared<Template>(templateData);
}
}
namespace speckle::database {
class ArchicadPropertyDBaseEngine::Cache : public std::unordered_map<Guid, std::shared_ptr<Template>> {
public:
/*!
Default constructor
*/
Cache() { rebuild(); }
/*!
Rebuild the property template cache
*/
void rebuild() {
//Request all Archicad template definitions
GS::Array<API_PropertyDefinition> definitions;
if (auto err = ACAPI_Property_GetPropertyDefinitions(APINULLGuid, definitions); err != NoError)
return;
//Populate the template cache from the collected definitions
for (auto iter = definitions.Begin(); iter != definitions.End(); ++iter)
if (auto propTemplate = makeTemplate(*iter); propTemplate)
insert({propTemplate->getBIMID(), propTemplate});
}
};
}
/*--------------------------------------------------------------------
Constructor
id: The document storage identifier
schema: The document storage schema
--------------------------------------------------------------------*/
ArchicadPropertyDBaseEngine::ArchicadPropertyDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) :
ArchicadDBaseCore{id, std::move(schema)} {
} //ArchicadPropertyDBaseEngine::ArchicadPropertyDBaseEngine
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ArchicadPropertyDBaseEngine::~ArchicadPropertyDBaseEngine() {
} //ArchicadPropertyDBaseEngine::~ArchicadPropertyDBaseEngine
/*--------------------------------------------------------------------
Find all property templates linked to specified classifications
classifications: The classifications
return: A list of shared pointers to linked property templates
--------------------------------------------------------------------*/
std::vector<std::shared_ptr<Template>> ArchicadPropertyDBaseEngine::findTemplatesByClassification(const BIMRecordIDList& classifications) const {
std::vector<std::shared_ptr<Template>> result;
if (validateCache()) {
for (const auto& templ : *m_cache) {
for (const auto& classID : classifications) {
if (templ.second->linksToClassification(classID)) {
result.push_back(templ.second);
break;
}
}
}
}
return result;
} //ArchicadPropertyDBaseEngine::findTemplatesByClassification
/*--------------------------------------------------------------------
Get an object by ID
objID: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested object (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Template> ArchicadPropertyDBaseEngine::getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
if (!validateCache() || (tableID != Template::propertyTableID))
return nullptr;
if (auto found = m_cache->find(objID); found != m_cache->end())
return std::make_unique<Template>(*found->second);
return nullptr;
} //ArchicadPropertyDBaseEngine::getObject
/*--------------------------------------------------------------------
Get an object in a transportable form, e.g. packaged for serialisation
index: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested wrapped cargo (nullptr on failure)
--------------------------------------------------------------------*/
active::serialise::Cargo::Unique ArchicadPropertyDBaseEngine::getObjectCargo(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return nullptr; //TODO: Implement
} //ArchicadPropertyDBaseEngine::getObject
/*--------------------------------------------------------------------
Get all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Template> ArchicadPropertyDBaseEngine::getObjects(std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadPropertyDBaseEngine::getObjects
/*--------------------------------------------------------------------
Get all objects
filter: The object filter
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Template> ArchicadPropertyDBaseEngine::getObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadPropertyDBaseEngine::getObjects
/*--------------------------------------------------------------------
Write an object to the database
object: The object to write
objID: The object ID
objDocID: The object document-specific ID (unique within a specific document - nullopt if not document-bound)
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
void ArchicadPropertyDBaseEngine::write(const Template& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID,
std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadPropertyDBaseEngine::write
/*--------------------------------------------------------------------
Erase an object by index
objID: The object ID
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: True if the object was successfully erased
--------------------------------------------------------------------*/
void ArchicadPropertyDBaseEngine::erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadPropertyDBaseEngine::erase
/*--------------------------------------------------------------------
Erase all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
--------------------------------------------------------------------*/
void ArchicadPropertyDBaseEngine::erase(std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadPropertyDBaseEngine::erase
/*--------------------------------------------------------------------
Get the database outline
return: The database outline
--------------------------------------------------------------------*/
ArchicadPropertyDBaseEngine::Outline ArchicadPropertyDBaseEngine::getOutline() const {
return {}; //TODO: Implement
} //ArchicadPropertyDBaseEngine::getOutline
/*--------------------------------------------------------------------
Handle a project event
event: The project event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool ArchicadPropertyDBaseEngine::handle(const event::ProjectEvent& event) {
using enum ProjectEvent::Type;
switch (event.getType()) {
case newDocument: case newAndReset: case open: case close: case quit:
//Reset the template template cache on any event that changes the active project
m_cache.reset();
break;
default:
break;
}
return false;
} //ArchicadPropertyDBaseEngine::handle
/*--------------------------------------------------------------------
Ensure the cache is current
return: True if the cache contains valid te templates
--------------------------------------------------------------------*/
bool ArchicadPropertyDBaseEngine::validateCache() const {
if (!m_cache)
m_cache = std::make_unique<Cache>();
return !m_cache->empty();
} //ArchicadPropertyDBaseEngine::validateCache
#endif //ARCHICAD
@@ -0,0 +1,143 @@
#ifndef SPECKLE_DATABASE_ARCHICAD_PROPERTY_DBASE_ENGINE
#define SPECKLE_DATABASE_ARCHICAD_PROPERTY_DBASE_ENGINE
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Property/Template.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <algorithm>
#include <ranges>
namespace speckle::database {
/*!
A database engine to read/write property templates in an Archicad project database (local file or cloud-based)
Property templates describe the characteristics and metadate attached to element property values. As such the templates may be shared
amongst any number of Property objects
*/
class ArchicadPropertyDBaseEngine : public ArchicadDBaseCore,
public active::database::DBaseEngine<record::property::Template, BIMRecordID, BIMRecordID, BIMRecordID> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<record::property::Template, BIMRecordID, BIMRecordID, BIMRecordID>;
using Template = record::property::Template;
using Filter = base::Filter;
using Outline = base::Outline;
// MARK: - Constructors
/*!
Constructor
@param id The document storage identifier
@param schema The document storage schema
*/
ArchicadPropertyDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema);
ArchicadPropertyDBaseEngine(const ArchicadPropertyDBaseEngine&) = delete;
/*!
Destructor
*/
~ArchicadPropertyDBaseEngine();
// MARK: - Functions (const)
/*!
Find all property templates linked to specified classifications
@param classifications The classifications
@return A list of shared pointers to linked property templates
*/
std::vector<std::shared_ptr<Template>> findTemplatesByClassification(const BIMRecordIDList& classifications) const;
/*!
Get an object by ID
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested object (nullptr on failure)
*/
std::unique_ptr<Template> getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get an object in a transportable form, e.g. packaged for serialisation
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return: The requested wrapped cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getObjectCargo(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The requested objects (nullptr on failure)
*/
active::container::Vector<Template> getObjects(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get a filtered list of objects
@param filter The object filter
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The filtered objects (nullptr on failure)
*/
active::container::Vector<Template> getObjects(const Filter& filter, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Write an object to the database
@param object The object to write
@param objID The object ID
@param objDocID The object document-specific ID (unique within a specific document - nullopt if not document-bound)
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
void write(const Template& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID = std::nullopt,
std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase an object by index
@param ID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get the database outline
@return The database outline
*/
Outline getOutline() const override;
// MARK: - Functions (mutating)
/*!
Handle a project event
@param event The project event
@return True if the event should be closed
*/
bool handle(const event::ProjectEvent& event) override;
private:
/*!
Ensure the cache is current
@return True if the cache contains valid te templates
*/
bool validateCache() const;
//Cached templates
class Cache;
mutable std::unique_ptr<Cache> m_cache;
};
}
#endif //SPECKLE_DATABASE_ARCHICAD_PROPERTY_DBASE_ENGINE
+3 -1
View File
@@ -2,6 +2,7 @@
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Database/BIMPropertyDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/SpeckleResource.h"
@@ -23,8 +24,9 @@ namespace {
identity: Optional name/ID for the subscriber
--------------------------------------------------------------------*/
Project::Project() {
m_element = std::make_unique<BIMElementDatabase>();
m_attribute = std::make_unique<BIMAttributeDatabase>();
m_element = std::make_unique<BIMElementDatabase>();
m_property = std::make_unique<BIMPropertyDatabase>();
} //Project::Project
+11 -3
View File
@@ -7,6 +7,7 @@
namespace speckle::database {
class BIMAttributeDatabase;
class BIMElementDatabase;
class BIMPropertyDatabase;
}
namespace speckle::environment {
@@ -55,6 +56,11 @@ namespace speckle::environment {
@return Project information
*/
Info getInfo() const;
/*!
Get the account database
@return The account database
*/
const database::BIMAttributeDatabase* getAttributeDatabase() const { return m_attribute.get(); }
/*!
Get the account database
@return The account database
@@ -64,7 +70,7 @@ namespace speckle::environment {
Get the account database
@return The account database
*/
const database::BIMAttributeDatabase* getAttributeDatabase() const { return m_attribute.get(); }
const database::BIMPropertyDatabase* getPropertyDatabase() const { return m_property.get(); }
// MARK: - Functions (mutating)
@@ -79,10 +85,12 @@ namespace speckle::environment {
Project();
private:
///The BIM element database
std::unique_ptr<database::BIMElementDatabase> m_element;
///The BIM attribute database
std::unique_ptr<database::BIMAttributeDatabase> m_attribute;
///The BIM element database
std::unique_ptr<database::BIMElementDatabase> m_element;
///The BIM property database
std::unique_ptr<database::BIMPropertyDatabase> m_property;
};
}
@@ -0,0 +1,30 @@
#include "Speckle/Record/Classification/Classified.h"
#include "Speckle/Database/Content/BIMRecord.h"
using namespace speckle::database;
using namespace speckle::record::classify;
using namespace speckle::utility;
/*--------------------------------------------------------------------
Get the IDs of all classifications attached to the record
return: The list of classification IDs (classification system ID paired with the leaf ID)
--------------------------------------------------------------------*/
BIMRecordIDList Classified::getClassificationIDs() const {
//TODO: Retrieve other classification data in future rather than just a list of IDs - this is a placeholder to support properties
BIMRecordIDList result;
//Establish that this is a BIM record (an can potentially have attached classifications)
auto record = dynamic_cast<const BIMRecord*>(this);
if (record != nullptr) {
#if ARCHICAD
GS::Array<GS::Pair<API_Guid, API_Guid>> items;
//Collect any classifications attached to the record
if (ACAPI_Element_GetClassificationItems(record->getBIMID(), items) == NoError) {
for (const auto& item : items)
result.insert(item.second);
}
#endif
}
return result;
} //Classified::getClassificationIDs
@@ -0,0 +1,48 @@
#ifndef SPECKLE_RECORD_ELEMENT_CLASSIFIED
#define SPECKLE_RECORD_ELEMENT_CLASSIFIED
#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::record::classify {
/*!
Interface for records with attached classifications
*/
class Classified {
public:
// MARK: - Types
///Unique pointer
using Unique = std::unique_ptr<Classified>;
///Shared pointer
using Shared = std::shared_ptr<Classified>;
///Optional
using Option = std::optional<Classified>;
// MARK: - Constructors
/*!
Default constructor
*/
Classified() {}
/*!
Destructor
*/
virtual ~Classified() {}
// MARK: - Functions (const)
/*!
Get the IDs of all classifications attached to the record
@return The list of classification IDs
*/
database::BIMRecordIDList getClassificationIDs() const;
// MARK: - Functions (mutating)
};
}
#endif //SPECKLE_RECORD_ELEMENT_CLASSIFIED
+1 -1
View File
@@ -113,7 +113,7 @@ void Column::loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const {
//Establish the memo filter for this element
if (!SegmentedColumn::isMemoLoaded())
filter |= SegmentedColumn::getPartFilter();
Element::loadMemo(filter, memo);
ModelElement::loadMemo(filter, memo);
//Receive the memo data into the element (when available)
if (memo) {
if (filter & SegmentedColumn::getPartFilter())
+4 -4
View File
@@ -2,7 +2,7 @@
#define SPECKLE_RECORD_ELEMENT_COLUMN
#include "Speckle/Record/Element/ColumnSegment.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Record/Element/ModelElement.h"
#include "Speckle/Record/Element/Interface/Assembly/Path.h"
#include "Speckle/Record/Element/Interface/SegmentedColumn.h"
@@ -13,12 +13,12 @@ namespace speckle::record::element {
/*!
BIM column class
*/
class Column : public Element, public SegmentedColumn, public assembly::Path {
class Column : public ModelElement, public SegmentedColumn, public assembly::Path {
public:
// MARK: - Types
using base = Element;
using base = ModelElement;
///Unique pointer
using Unique = std::unique_ptr<Column>;
///Shared pointer
@@ -65,7 +65,7 @@ namespace speckle::record::element {
Get the BIM application parent table ID
@return The BIM table ID
*/
virtual database::BIMRecordID getTableID() const override { return Element::getTableID(); }
virtual database::BIMRecordID getTableID() const override { return ModelElement::getTableID(); }
/*!
Get the element body
@return nullptr (Columns don't explicitly have a 3D body - this comes from its child segments)
@@ -1,7 +1,7 @@
#ifndef SPECKLE_RECORD_ELEMENT_COLUMN_SEGMENT
#define SPECKLE_RECORD_ELEMENT_COLUMN_SEGMENT
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Record/Element/ModelElement.h"
#include "Speckle/Record/Element/Interface/Assembly/Segment.h"
namespace speckle::record::element {
@@ -11,12 +11,12 @@ namespace speckle::record::element {
/*!
BIM column class
*/
class ColumnSegment : public Element, public assembly::Segment {
class ColumnSegment : public ModelElement, public assembly::Segment {
public:
// MARK: - Types
using base = Element;
using base = ModelElement;
///Unique pointer
using Unique = std::unique_ptr<ColumnSegment>;
///Shared pointer
@@ -1,4 +1,4 @@
#include "Speckle/Record/Element/GenericElement.h"
#include "Speckle/Record/Element/DrawingElement.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
@@ -19,9 +19,9 @@ using namespace speckle::utility;
namespace speckle::record::element {
class GenericElement::Data {
class DrawingElement::Data {
public:
friend class GenericElement;
friend class DrawingElement;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_Element>(elem) } {}
@@ -30,21 +30,6 @@ namespace speckle::record::element {
private:
std::unique_ptr<API_Element> root;
std::unique_ptr<GenericElement::Body> m_cache;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
bodyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"displayValue"},
};
}
@@ -52,8 +37,8 @@ namespace {
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
GenericElement::GenericElement() {
} //GenericElement::GenericElement
DrawingElement::DrawingElement() {
} //DrawingElement::DrawingElement
/*--------------------------------------------------------------------
@@ -62,9 +47,9 @@ GenericElement::GenericElement() {
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 } {
DrawingElement::DrawingElement(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //GenericElement::GenericElement
} //DrawingElement::DrawingElement
/*--------------------------------------------------------------------
@@ -72,15 +57,15 @@ GenericElement::GenericElement(const API_Element& elemData, const speckle::utili
source: The object to copy
--------------------------------------------------------------------*/
GenericElement::GenericElement(const GenericElement& source) : base{ source } {
DrawingElement::DrawingElement(const DrawingElement& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //GenericElement::GenericElement
} //DrawingElement::DrawingElement
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
GenericElement::~GenericElement() {}
DrawingElement::~DrawingElement() {}
#ifdef ARCHICAD
@@ -89,18 +74,18 @@ GenericElement::~GenericElement() {}
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 {
const API_Elem_Head& DrawingElement::getHead() const {
return m_data->root->header;
} //GenericElement::getHead
} //DrawingElement::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() {
API_Elem_Head& DrawingElement::getHead() {
return m_data->root->header;
} //GenericElement::getHead
} //DrawingElement::getHead
#endif
@@ -111,15 +96,9 @@ API_Elem_Head& GenericElement::getHead() {
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
bool DrawingElement::fillInventory(Inventory& inventory) const {
return base::fillInventory(inventory); //Not implemented yet
} //DrawingElement::fillInventory
/*--------------------------------------------------------------------
@@ -129,29 +108,15 @@ bool GenericElement::fillInventory(Inventory& inventory) const {
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
Cargo::Unique DrawingElement::getCargo(const Inventory::Item& item) const {
return base::getCargo(item); //Not implemented yet
} //DrawingElement::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void GenericElement::setDefault() {
void DrawingElement::setDefault() {
base::setDefault();
m_data.reset();
} //GenericElement::setDefault
} //DrawingElement::setDefault
@@ -1,28 +1,25 @@
#ifndef SPECKLE_RECORD_GENERIC_ELEMENT
#define SPECKLE_RECORD_GENERIC_ELEMENT
#ifndef SPECKLE_RECORD_DISPLAY_ELEMENT
#define SPECKLE_RECORD_DISPLAY_ELEMENT
#include "Speckle/Record/Element/Element.h"
namespace speckle::record::element {
/*!
Catch-all class for elements that are not represented by a specific class
Base class for drawing (illustrative) elements, i.e. appearing in 2D only and typically used in 2D drawings
*/
class GenericElement : public Element {
class DrawingElement : public Element {
public:
///An element 3D body primitive
using Body = std::vector<primitive::Mesh>;
// MARK: - Types
using base = Element;
///Unique pointer
using Unique = std::unique_ptr<GenericElement>;
using Unique = std::unique_ptr<DrawingElement>;
///Shared pointer
using Shared = std::shared_ptr<GenericElement>;
using Shared = std::shared_ptr<DrawingElement>;
///Optional
using Option = std::optional<GenericElement>;
using Option = std::optional<DrawingElement>;
// MARK: - Constructors
@@ -31,30 +28,30 @@ namespace speckle::record::element {
/*!
Default constructor
*/
GenericElement();
DrawingElement();
#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);
DrawingElement(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
GenericElement(const GenericElement& source);
DrawingElement(const DrawingElement& source);
/*!
Destructor
*/
~GenericElement();
~DrawingElement();
/*!
Object cloning
@return A clone of this object
*/
GenericElement* clonePtr() const override { return new GenericElement{*this}; }
DrawingElement* clonePtr() const override { return new DrawingElement{*this}; }
// MARK: - Functions (const)
@@ -104,4 +101,4 @@ namespace speckle::record::element {
}
#endif //SPECKLE_RECORD_GENERIC_ELEMENT
#endif //SPECKLE_RECORD_DISPLAY_ELEMENT
+1 -156
View File
@@ -11,16 +11,6 @@
#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>
#endif
using namespace active::serialise;
using namespace speckle::environment;
using namespace speckle::record::attribute;
@@ -30,34 +20,6 @@ using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::element {
class Element::Data {
public:
friend class Element;
Data() {}
Data(const Data& source) {}
private:
std::unique_ptr<Element::Body> m_cache;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
bodyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"displayValue"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
@@ -73,7 +35,6 @@ Element::Element() {
unit: The record unit type
--------------------------------------------------------------------*/
Element::Element(const Guid& ID, const Guid& tableID, std::optional<active::measure::LengthType> unit) : base{ID, tableID, unit} {
m_data = std::make_unique<Data>();
} //Element::Element
@@ -83,7 +44,6 @@ Element::Element(const Guid& ID, const Guid& tableID, std::optional<active::meas
source: The object to copy
--------------------------------------------------------------------*/
Element::Element(const Element& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //Element::Element
@@ -93,7 +53,6 @@ Element::Element(const Element& source) : base{ source } {
source: The object to move
--------------------------------------------------------------------*/
Element::Element(Element&& source) : base{source} {
m_data = std::move(source.m_data);
} //Element::Element
@@ -130,99 +89,6 @@ String Element::getTypeName() const {
} //Element::getTypeName
/*--------------------------------------------------------------------
Get the element body as a list of faces or Meshes
return: A pointer to the element body
--------------------------------------------------------------------*/
Element::Body* Element::getBody() const {
#ifdef ARCHICAD
if (m_data->m_cache) {
return m_data->m_cache.get();
}
void* dummy = nullptr;
GSErrCode err = ACAPI_Sight_GetCurrentWindowSight(&dummy);
if (err != NoError)
{
// TODO: should this throw?
}
Modeler::SightPtr currentSightPtr((Modeler::Sight*)dummy); // init the shared ptr with the raw pointer
ModelerAPI::Model acModel;
Modeler::IAttributeReader* attrReader = ACAPI_Attribute_GetCurrentAttributeSetReader();
err = EXPGetModel(currentSightPtr, &acModel, attrReader);
if (err != NoError)
{
// TODO: should this throw?
}
auto elementBody = new Element::Body();
Int32 nElements = acModel.GetElementCount();
for (Int32 iElement = 1; iElement <= nElements; iElement++)
{
ModelerAPI::Element elem{};
acModel.GetElement(iElement, &elem);
if (elem.GetElemGuid() != getHead().guid)
continue;
Int32 nBodies = elem.GetTessellatedBodyCount();
for (Int32 bodyIndex = 1; bodyIndex <= nBodies; ++bodyIndex)
{
ModelerAPI::MeshBody body{};
elem.GetTessellatedBody(bodyIndex, &body);
Int32 polyCount = body.GetPolygonCount();
for (Int32 polyIndex = 1; polyIndex <= polyCount; ++polyIndex)
{
ModelerAPI::Polygon polygon{};
body.GetPolygon(polyIndex, &polygon);
ModelerAPI::Material material{};
polygon.GetMaterial(&material);
Int32 convexPolyCount = polygon.GetConvexPolygonCount();
for (Int32 convPolyIndex = 1; convPolyIndex <= convexPolyCount; ++convPolyIndex)
{
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
ModelerAPI::ConvexPolygon convexPolygon{};
polygon.GetConvexPolygon(convPolyIndex, &convexPolygon);
Int32 vertexCount = convexPolygon.GetVertexCount();
faces.push_back(vertexCount);
for (Int32 vertexIndex = 1; vertexIndex <= vertexCount; ++vertexIndex)
{
ModelerAPI::Vertex vertex{};
body.GetVertex(convexPolygon.GetVertexIndex(vertexIndex), &vertex);
// TODO: change vertices array to hold Vertex instead of double values
vertices.push_back(vertex.x);
vertices.push_back(vertex.y);
vertices.push_back(vertex.z);
//double alpha = material.GetTransparency();
//ModelerAPI::Color color = material.GetSurfaceColor();
//colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue));
faces.push_back(vertexIndex - 1);
}
elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors), material));
}
}
}
}
m_data->m_cache.reset(elementBody);
return m_data->m_cache.get();
#endif
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -231,12 +97,6 @@ Element::Body* Element::getBody() const {
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Element::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[bodyID], bodyID, element }, //TODO: implement other fields
},
}.withType(&typeid(Element)));
return base::fillInventory(inventory);
} //Element::fillInventory
@@ -249,21 +109,7 @@ bool Element::fillInventory(Inventory& inventory) const {
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Element::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Element))
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
}
return base::getCargo(item);
} //Element::getCargo
@@ -272,7 +118,6 @@ Cargo::Unique Element::getCargo(const Inventory::Item& item) const {
--------------------------------------------------------------------*/
void Element::setDefault() {
base::setDefault();
m_data.reset();
} //Element::setDefault
@@ -19,9 +19,6 @@ namespace speckle::record::element {
*/
class Element : public speckle::database::BIMRecord {
public:
///An element 3D body primitive
using Body = std::vector<primitive::Mesh>;
// MARK: - Types
@@ -74,11 +71,6 @@ namespace speckle::record::element {
@return The element storey (nullopt if the element isn't linked to a storey)
*/
virtual attribute::Storey::Option getStorey() const;
/*!
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
virtual Body* getBody() const;
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@@ -122,11 +114,6 @@ namespace speckle::record::element {
@param filter Filter bits specifying memo requirements
*/
virtual void loadMemo(Part::filter_bits filter, std::unique_ptr<Memo>& memo) const;
private:
class Data;
///The element data
std::unique_ptr<Data> m_data;
};
}
@@ -0,0 +1,122 @@
#include "Speckle/Record/Element/GenericDrawingElement.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 <array>
#include <memory>
namespace speckle::record::element {
class GenericDrawingElement::Data {
public:
friend class GenericDrawingElement;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_Element>(elem) } {}
Data(const Data& source) : root{ std::make_unique<API_Element>(*source.root) } {}
#endif
private:
std::unique_ptr<API_Element> root;
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
GenericDrawingElement::GenericDrawingElement() {
} //GenericDrawingElement::GenericDrawingElement
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The attribute table ID (attribute type)
--------------------------------------------------------------------*/
GenericDrawingElement::GenericDrawingElement(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //GenericDrawingElement::GenericDrawingElement
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
GenericDrawingElement::GenericDrawingElement(const GenericDrawingElement& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //GenericDrawingElement::GenericDrawingElement
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
GenericDrawingElement::~GenericDrawingElement() {}
#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& GenericDrawingElement::getHead() const {
return m_data->root->header;
} //GenericDrawingElement::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& GenericDrawingElement::getHead() {
return m_data->root->header;
} //GenericDrawingElement::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 GenericDrawingElement::fillInventory(Inventory& inventory) const {
return base::fillInventory(inventory); //Not implemented yet
} //GenericDrawingElement::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique GenericDrawingElement::getCargo(const Inventory::Item& item) const {
return base::getCargo(item); //Not implemented yet
} //GenericDrawingElement::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void GenericDrawingElement::setDefault() {
base::setDefault();
m_data.reset();
} //GenericDrawingElement::setDefault
@@ -0,0 +1,104 @@
#ifndef SPECKLE_RECORD_MODEL_ELEMENT
#define SPECKLE_RECORD_MODEL_ELEMENT
#include "Speckle/Record/Element/Element.h"
namespace speckle::record::element {
/*!
Base class for generic drawing (2D) elements, i.e. not defined by a specific element type
*/
class GenericDrawingElement : public Element {
public:
// MARK: - Types
using base = Element;
///Unique pointer
using Unique = std::unique_ptr<GenericDrawingElement>;
///Shared pointer
using Shared = std::shared_ptr<GenericDrawingElement>;
///Optional
using Option = std::optional<GenericDrawingElement>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
GenericDrawingElement();
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
*/
GenericDrawingElement(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
GenericDrawingElement(const GenericDrawingElement& source);
/*!
Destructor
*/
~GenericDrawingElement();
/*!
Object cloning
@return A clone of this object
*/
GenericDrawingElement* clonePtr() const override { return new GenericDrawingElement{*this}; }
// MARK: - Functions (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)
*/
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<Data> m_data;
};
}
#endif //SPECKLE_RECORD_MODEL_ELEMENT
@@ -0,0 +1,122 @@
#include "Speckle/Record/Element/GenericModelElement.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 <array>
#include <memory>
namespace speckle::record::element {
class GenericModelElement::Data {
public:
friend class GenericModelElement;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_Element>(elem) } {}
Data(const Data& source) : root{ std::make_unique<API_Element>(*source.root) } {}
#endif
private:
std::unique_ptr<API_Element> root;
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
GenericModelElement::GenericModelElement() {
} //GenericModelElement::GenericModelElement
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The attribute table ID (attribute type)
--------------------------------------------------------------------*/
GenericModelElement::GenericModelElement(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //GenericModelElement::GenericModelElement
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
GenericModelElement::GenericModelElement(const GenericModelElement& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //GenericModelElement::GenericModelElement
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
GenericModelElement::~GenericModelElement() {}
#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& GenericModelElement::getHead() const {
return m_data->root->header;
} //GenericModelElement::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& GenericModelElement::getHead() {
return m_data->root->header;
} //GenericModelElement::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 GenericModelElement::fillInventory(Inventory& inventory) const {
return base::fillInventory(inventory);
} //GenericModelElement::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique GenericModelElement::getCargo(const Inventory::Item& item) const {
return base::getCargo(item);
} //GenericModelElement::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void GenericModelElement::setDefault() {
base::setDefault();
m_data.reset();
} //GenericModelElement::setDefault
@@ -0,0 +1,103 @@
#ifndef SPECKLE_RECORD_GENERIC_MODEL_ELEMENT
#define SPECKLE_RECORD_GENERIC_MODEL_ELEMENT
#include "Speckle/Record/Element/ModelElement.h"
namespace speckle::record::element {
/*!
Base class for generic model elements, i.e. not defined by a specific element type
*/
class GenericModelElement : public ModelElement {
public:
// MARK: - Types
using base = ModelElement;
///Unique pointer
using Unique = std::unique_ptr<GenericModelElement>;
///Shared pointer
using Shared = std::shared_ptr<GenericModelElement>;
///Optional
using Option = std::optional<GenericModelElement>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
GenericModelElement();
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
*/
GenericModelElement(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
GenericModelElement(const GenericModelElement& source);
/*!
Destructor
*/
~GenericModelElement();
/*!
Object cloning
@return A clone of this object
*/
GenericModelElement* clonePtr() const override { return new GenericModelElement{*this}; }
// MARK: - Functions (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)
*/
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<Data> m_data;
};
}
#endif //SPECKLE_RECORD_GENERIC_MODEL_ELEMENT
@@ -0,0 +1,272 @@
#include "Speckle/Record/Element/ModelElement.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 <Sight.hpp>
#include <Model.hpp>
#include <ModelMaterial.hpp>
#include <ModelElement.hpp>
#include <exp.h>
#include <ModelMeshBody.hpp>
#include <ConvexPolygon.hpp>
#endif
using namespace active::measure;
using namespace active::serialise;
using namespace speckle::environment;
using namespace speckle::record::attribute;
using namespace speckle::record::element;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::element {
class ModelElement::Data {
public:
friend class ModelElement;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_Element>(elem) } {}
Data(const Data& source) : root{ std::make_unique<API_Element>(*source.root) } {}
#endif
private:
std::unique_ptr<API_Element> root;
std::unique_ptr<ModelElement::Body> m_cache;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
bodyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"displayValue"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
ModelElement::ModelElement() {
} //ModelElement::ModelElement
/*--------------------------------------------------------------------
Constructor
ID: The record ID
tableID: The parent table ID
unit: The record unit type
--------------------------------------------------------------------*/
ModelElement::ModelElement(const Guid& ID, const Guid& tableID, std::optional<LengthType> unit) : Element{ID, tableID, unit} {
} //ModelElement::ModelElement
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The attribute table ID (attribute type)
--------------------------------------------------------------------*/
ModelElement::ModelElement(const API_Element& elemData, const Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //ModelElement::ModelElement
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
ModelElement::ModelElement(const ModelElement& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //ModelElement::ModelElement
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ModelElement::~ModelElement() {}
/*--------------------------------------------------------------------
Get the element body as a list of faces or Meshes
return: A pointer to the element body
--------------------------------------------------------------------*/
ModelElement::Body* ModelElement::getBody() const {
#ifdef ARCHICAD
if (m_data->m_cache) {
return m_data->m_cache.get();
}
void* dummy = nullptr;
GSErrCode err = ACAPI_Sight_GetCurrentWindowSight(&dummy);
if (err != NoError)
{
// TODO: should this throw?
}
Modeler::SightPtr currentSightPtr((Modeler::Sight*)dummy); // init the shared ptr with the raw pointer
ModelerAPI::Model acModel;
Modeler::IAttributeReader* attrReader = ACAPI_Attribute_GetCurrentAttributeSetReader();
err = EXPGetModel(currentSightPtr, &acModel, attrReader);
if (err != NoError)
{
// TODO: should this throw?
}
auto elementBody = new ModelElement::Body();
Int32 nElements = acModel.GetElementCount();
for (Int32 iElement = 1; iElement <= nElements; iElement++)
{
ModelerAPI::Element elem{};
acModel.GetElement(iElement, &elem);
if (elem.GetElemGuid() != getHead().guid)
continue;
Int32 nBodies = elem.GetTessellatedBodyCount();
for (Int32 bodyIndex = 1; bodyIndex <= nBodies; ++bodyIndex)
{
ModelerAPI::MeshBody body{};
elem.GetTessellatedBody(bodyIndex, &body);
Int32 polyCount = body.GetPolygonCount();
for (Int32 polyIndex = 1; polyIndex <= polyCount; ++polyIndex)
{
ModelerAPI::Polygon polygon{};
body.GetPolygon(polyIndex, &polygon);
ModelerAPI::Material material{};
polygon.GetMaterial(&material);
Int32 convexPolyCount = polygon.GetConvexPolygonCount();
for (Int32 convPolyIndex = 1; convPolyIndex <= convexPolyCount; ++convPolyIndex)
{
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
ModelerAPI::ConvexPolygon convexPolygon{};
polygon.GetConvexPolygon(convPolyIndex, &convexPolygon);
Int32 vertexCount = convexPolygon.GetVertexCount();
faces.push_back(vertexCount);
for (Int32 vertexIndex = 1; vertexIndex <= vertexCount; ++vertexIndex)
{
ModelerAPI::Vertex vertex{};
body.GetVertex(convexPolygon.GetVertexIndex(vertexIndex), &vertex);
// TODO: change vertices array to hold Vertex instead of double values
vertices.push_back(vertex.x);
vertices.push_back(vertex.y);
vertices.push_back(vertex.z);
//double alpha = material.GetTransparency();
//ModelerAPI::Color color = material.GetSurfaceColor();
//colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue));
faces.push_back(vertexIndex - 1);
}
elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors), material));
}
}
}
}
m_data->m_cache.reset(elementBody);
return m_data->m_cache.get();
#endif
}
#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& ModelElement::getHead() const {
return m_data->root->header;
} //ModelElement::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& ModelElement::getHead() {
return m_data->root->header;
} //ModelElement::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 ModelElement::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[bodyID], bodyID, element }, //TODO: implement other fields
},
}.withType(&typeid(ModelElement)));
return base::fillInventory(inventory);
} //ModelElement::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ModelElement::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(ModelElement))
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
}
} //ModelElement::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void ModelElement::setDefault() {
base::setDefault();
m_data.reset();
} //ModelElement::setDefault
@@ -0,0 +1,119 @@
#ifndef SPECKLE_RECORD_MODEL_ELEMENT
#define SPECKLE_RECORD_MODEL_ELEMENT
#include "Speckle/Record/Element/Element.h"
namespace speckle::record::element {
/*!
Base class for model elements, i.e. with 3D bodies and typically representing the project model
*/
class ModelElement : public Element {
public:
// MARK: - Types
using base = Element;
///Unique pointer
using Unique = std::unique_ptr<ModelElement>;
///Shared pointer
using Shared = std::shared_ptr<ModelElement>;
///Optional
using Option = std::optional<ModelElement>;
///A model element 3D body primitive
using Body = std::vector<primitive::Mesh>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
ModelElement();
/*!
Constructor
@param ID The record ID
@param tableID The parent table ID
@param unit The record unit type
*/
ModelElement(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID,
std::optional<active::measure::LengthType> unit = active::measure::LengthType::metre);
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
*/
ModelElement(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
ModelElement(const ModelElement& source);
/*!
Destructor
*/
~ModelElement();
/*!
Object cloning
@return A clone of this object
*/
ModelElement* clonePtr() const override { return new ModelElement{*this}; }
// MARK: - Functions (const)
/*!
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
virtual Body* 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)
*/
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<Data> m_data;
};
}
#endif //SPECKLE_RECORD_MODEL_ELEMENT
@@ -0,0 +1,83 @@
#include "Speckle/Record/Property/Propertied.h"
#include "Speckle/Database/BIMPropertyDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Record/Classification/Classified.h"
#include "Speckle/Record/Property/Setting.h"
#include "Speckle/Utility/BIMMemory.h"
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::classify;
using namespace speckle::record::property;
using namespace speckle::utility;
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Propertied::Propertied() {
} //Propertied::Propertied
/*--------------------------------------------------------------------
Get the attached properties
return: The attached properties
--------------------------------------------------------------------*/
const std::vector<Property>& Propertied::getProperties() const {
rebuild();
return *m_properties;
} //Propertied
/*--------------------------------------------------------------------
Rebuild the list of properties
return: True if any properties were found
--------------------------------------------------------------------*/
bool Propertied::rebuild() const {
if (m_properties)
return !m_properties->empty();
m_properties = std::make_unique<std::vector<Property>>();
//Ensure this is a BIM record (only BIM records can potentially have attached properties)
auto record = dynamic_cast<const BIMRecord*>(this);
if (record == nullptr)
return false;
auto project = addon()->getActiveProject().lock();
if (!project)
return false;
//Establish that this record can be classified (and therefore bind to properties - NB: this logic may vary for other BIM platforms)
auto classified = dynamic_cast<const Classified*>(this);
if (classified == nullptr)
return false;
//Get the record classifications - an empty set means no properties are attached
auto classificationIDs{classified->getClassificationIDs()};
if (classificationIDs.empty())
return false;
//Get properties linked to the record classifications
auto propertyDbase = project->getPropertyDatabase();
auto templates = propertyDbase->findTemplatesByClassification(classificationIDs);
if (templates.empty())
return false;
GS::Array<API_Guid> propertyIDs;
for (const auto& propTemplate : templates)
propertyIDs.Push(propTemplate->getBIMID());
//Get property values for this record based on the linked properties
GS::Array<API_Property> properties;
if (ACAPI_Element_GetPropertyValuesByGuid(record->getBIMID(), propertyIDs, properties) != NoError)
return false;
for (const auto& property : properties) {
if (property.status != API_Property_HasValue)
continue;
if (auto iter = std::find_if(templates.begin(), templates.end(),
[&property](const auto& propTemplate){
return propTemplate->getBIMID() == Guid{property.definition.guid};
}); iter != templates.end()) {
Setting setting;
if ((**iter).convert(property.value, setting))
m_properties->emplace_back(Property{setting, *iter});
}
}
return true;
} //Propertied::rebuild
@@ -0,0 +1,57 @@
#ifndef SPECKLE_RECORD_ELEMENT_PROPERTIED
#define SPECKLE_RECORD_ELEMENT_PROPERTIED
#include "Speckle/Record/Property/Property.h"
namespace speckle::record::property {
/*!
Interface for records with attached properties
*/
class Propertied {
public:
// MARK: - Types
///Unique pointer
using Unique = std::unique_ptr<Propertied>;
///Shared pointer
using Shared = std::shared_ptr<Propertied>;
///Optional
using Option = std::optional<Propertied>;
// MARK: - Constructors
/*!
Default constructor
*/
Propertied();
/*!
Destructor
*/
virtual ~Propertied() {}
// MARK: - Functions (const)
/*!
Get the attached properties
@return The attached properties
*/
const std::vector<Property>& getProperties() const;
// MARK: - Functions (mutating)
private:
/*!
Rebuild the list of properties
@return True if any properties were found
*/
bool rebuild() const;
///The attached properties - mutable to support lazy loading
mutable std::unique_ptr<std::vector<Property>> m_properties;
};
}
#endif //SPECKLE_RECORD_ELEMENT_PROPERTIED
@@ -0,0 +1,132 @@
#include "Speckle/Record/Property/Property.h"
#include "Speckle/Database/BIMPropertyDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Record/Property/Setting.h"
#include "Speckle/Record/Property/Template.h"
#include "Speckle/Record/Property/Value.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::property;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace {
///Serialisation fields
enum FieldIndex {
nameID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"name"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Property::Property() {
} //Property::Property
/*--------------------------------------------------------------------
Constructor
propTemplate: The property template
--------------------------------------------------------------------*/
Property::Property(std::shared_ptr<Template> propTemplate) : m_template(propTemplate) {
} //Property::Property
/*--------------------------------------------------------------------
Constructor
value: A property value
propTemplate: The property template (NB: may override the specified value if it does not meet the template criteria)
--------------------------------------------------------------------*/
Property::Property(const Value& value, std::shared_ptr<Template> propTemplate) :
m_setting{std::make_unique<Setting>(value)}, m_template{propTemplate} {
} //Property::Property
/*--------------------------------------------------------------------
Constructor
setting: A property setting
propTemplate: The property template (NB: may override the specified value if it does not meet the template criteria)
--------------------------------------------------------------------*/
Property::Property(const Setting& setting, std::shared_ptr<Template> propTemplate) :
m_setting{std::make_unique<Setting>(setting)}, m_template{propTemplate} {
} //Property::Property
/*--------------------------------------------------------------------
Move constructor
source: the property to move
--------------------------------------------------------------------*/
Property::Property(Property&& source) noexcept : m_setting{std::move(source.m_setting)}, m_template{source.m_template} {
} //Property::Property
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
Property::~Property() {}
/*--------------------------------------------------------------------
Get the property name
return: The property name
--------------------------------------------------------------------*/
String Property::getName() const {
return m_template ? m_template->getName() : String{};
} //Property::getName
/*--------------------------------------------------------------------
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 Property::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[nameID], nameID, element },
},
}.withType(&typeid(Property)));
return true;
} //Property::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Property::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Property))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case nameID:
default:
return nullptr; //Requested an unknown index
}
} //Property::getCargo
@@ -0,0 +1,103 @@
#ifndef SPECKLE_RECORD_PROPERTY
#define SPECKLE_RECORD_PROPERTY
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Utility/String.h"
namespace speckle::record::property {
class Setting;
class Template;
class Value;
/*!
Class holding a property value attached to a BIM model element
Properties are always coupled with a template that defines its characteristics (type, name, units etc). This object primarily holds the
property value, coupled with a reference to the template
Values are always stored with an optional key value (for enumerated types). For other values, the key will be undefined
Note that some properties support multiple values - the property holds all these values individually, but always exports a single as a single
value by concatonating values usng the Archicad convention of a separating semi-colon, e.g. "Value1; Value 2". This can be revisited in
future if alernative export/display methods should be supported
*/
class Property : public active::serialise::Package {
public:
// MARK: - Types
///Unique pointer
using Unique = std::unique_ptr<Property>;
///Shared pointer
using Shared = std::shared_ptr<Property>;
///Optional
using Option = std::optional<Property>;
// MARK: - Constructors
/*!
Default constructor
*/
Property();
/*!
Constructor
@param propTemplate The property template
*/
Property(std::shared_ptr<Template> propTemplate);
/*!
Constructor
@param value A property value
@param propTemplate The property template (NB: may override the specified value if it does not meet the template criteria)
*/
Property(const Value& value, std::shared_ptr<Template> propTemplate);
/*!
Constructor
@param setting A property setting
@param propTemplate The property template (NB: may override the specified value if it does not meet the template criteria)
*/
Property(const Setting& setting, std::shared_ptr<Template> propTemplate);
/*!
Move constructor
@param source the property to move
*/
Property(Property&& source) noexcept;
/*!
Destructor
*/
~Property();
// MARK: - Functions (const)
/*!
Get the property name
@return The property name
*/
speckle::utility::String getName() const;
// MARK: - Functions (mutating)
// 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;
private:
///The property setting
std::unique_ptr<Setting> m_setting;
///The property template
std::shared_ptr<Template> m_template;
};
}
#endif //SPECKLE_RECORD_PROPERTY
@@ -0,0 +1,87 @@
#include "Speckle/Record/Property/Setting.h"
#include "Speckle/Utility/String.h"
using namespace speckle::record::property;
using namespace speckle::utility;
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
source: An Archicad property array value
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
--------------------------------------------------------------------*/
Setting::Setting(const API_ListVariant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
for (const auto& val : source.variants)
m_values.emplace_back(Value{val, status, measure});
} //Setting::Setting
#endif
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Receive a value from an Archicad property
source: An Archicad property
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the property data was successfully received
--------------------------------------------------------------------*/
bool Setting::receive(const API_Variant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
m_values.clear();
m_values.emplace_back(Value{source, status, measure});
return true;
} //Setting::receive
/*--------------------------------------------------------------------
Receive a value from an Archicad property
source: An Archicad property single value
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the property data was successfully received
--------------------------------------------------------------------*/
bool Setting::receive(const API_SingleVariant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
m_values.clear();
m_values.emplace_back(Value{source.variant, status, measure});
return true;
} //Setting::receive
/*--------------------------------------------------------------------
Receive a list of values from an Archicad property
source: An Archicad property array value
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the property data was successfully received
--------------------------------------------------------------------*/
bool Setting::receive(const API_ListVariant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
m_values.clear();
for (const auto& val : source.variants)
m_values.emplace_back(Value{val, status, measure});
return true;
} //Setting::receive
/*--------------------------------------------------------------------
Receive an enumnerated value from an Archicad property
source: An Archicad property
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the value was successfully received
--------------------------------------------------------------------*/
bool Setting::receive(const API_SingleEnumerationVariant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
m_values.clear();
m_values.emplace_back(Value{source, status, measure});
return true;
} //Setting::receive
#endif
@@ -0,0 +1,127 @@
#ifndef SPECKLE_RECORD_PROPERTY_SETTING
#define SPECKLE_RECORD_PROPERTY_SETTING
#include "Speckle/Record/Property/Value.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
namespace speckle::record::property {
/*!
Class holding a property setting (as attached to an element)
A property setting may have multiple values, distinguishing the Value from the Setting class (which may hold multiple Values)
*/
class Setting final {
public:
// MARK: - Types
///Unique pointer
using Unique = std::unique_ptr<Setting>;
///Shared pointer
using Shared = std::shared_ptr<Setting>;
///Optional
using Option = std::optional<Setting>;
// MARK: - Constructors
/*!
Default constructor
*/
Setting() {}
/*!
Constructor
@param value The property value
*/
Setting(const Value& value) : m_values{value} {}
#ifdef ARCHICAD
/*!
Constructor
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Setting(const API_Variant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType) : m_values{Value{source, status, measure}} {}
/*!
Constructor
@param source An Archicad property single value
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Setting(const API_SingleVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType) : m_values{Value{source.variant, status, measure}} {}
/*!
Constructor
@param source An Archicad property array value
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Setting(const API_ListVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
/*!
Constructor
@param source An Archicad property enumerated single value
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Setting(const API_SingleEnumerationVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType) : m_values{Value{source, status, measure}} {}
#endif
// MARK: - Functions (const)
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Receive a value from an Archicad property
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the property data was successfully received
*/
bool receive(const API_Variant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
/*!
Receive a value from an Archicad property
@param source An Archicad property single value
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the property data was successfully received
*/
bool receive(const API_SingleVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
/*!
Receive a list of values from an Archicad property
@param source An Archicad property array value
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the property data was successfully received
*/
bool receive(const API_ListVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
/*!
Receive an enumnerated value from an Archicad property
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the value was successfully received
*/
bool receive(const API_SingleEnumerationVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
#endif
private:
///The property values
std::vector<Value> m_values;
};
}
#endif //SPECKLE_RECORD_PROPERTY_SETTING
@@ -0,0 +1,210 @@
#include "Speckle/Record/Property/Template.h"
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Record/Property/Setting.h"
#include "Speckle/Serialise/Types/Str256.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::property;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace {
///Serialisation fields
enum FieldIndex {
nameID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"name"},
};
}
/*--------------------------------------------------------------------
Constructor
ID: The template ID
--------------------------------------------------------------------*/
Template::Template(const database::BIMRecordID& ID) : base{ID, propertyTableID} {
} //Template::Template
/*--------------------------------------------------------------------
Constructor
ID: The record ID
tableID: The parent table ID
unit: The record unit type
--------------------------------------------------------------------*/
Template::Template(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID, std::optional<active::measure::LengthType> unit) :
base{ID, tableID, unit} {
} //Template::Template
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Template::Template(const Template& source) : m_origin{source.m_origin}, m_type{source.m_type}, m_valueType{source.m_valueType},
m_measure{source.m_measure}, m_group{source.m_group}, m_name{source.m_name}, m_description{source.m_description},
m_defaultValue{source.m_defaultValue ? std::make_unique<Setting>(*source.m_defaultValue) : nullptr}, m_expressions{source.m_expressions},
m_classifications{source.m_classifications}, m_enumValues{source.m_enumValues}, m_isValueEditable{source.m_isValueEditable} {
} //Template::Template
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Convert an Archicad API measure type to a Measure
type: The API measure type
return: An equivalent Measure
--------------------------------------------------------------------*/
Template::Measure Template::convert(API_PropertyMeasureType type) {
switch (type) {
case API_PropertyLengthMeasureType:
return Measure::length;
case API_PropertyAreaMeasureType:
return Measure::area;
case API_PropertyVolumeMeasureType:
return Measure::volume;
case API_PropertyAngleMeasureType:
return Measure::angle;
default:
break;
}
return Measure::none;
} //Template::convert
/*--------------------------------------------------------------------
Convert Measure to an Archicad API property value type
type: The Measure
return: An equivalent API measure type
--------------------------------------------------------------------*/
API_PropertyMeasureType Template::convert(Template::Measure type) {
switch (type) {
case Measure::length:
return API_PropertyLengthMeasureType;
case Measure::area:
return API_PropertyAreaMeasureType;
case Measure::volume:
return API_PropertyVolumeMeasureType;
case Measure::angle:
return API_PropertyAngleMeasureType;
default:
break;
}
return API_PropertyDefaultMeasureType;
} //Template::convert
#endif
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Template::Template() {
} //Template::Template
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
source: An Archicad property definition to copy
--------------------------------------------------------------------*/
Template::Template(const API_PropertyDefinition& source) : base{source.guid, propertyTableID},
m_group{source.groupGuid}, m_name(source.name), m_description(source.description) {
m_origin = static_cast<Origin>(source.definitionType);
m_type = static_cast<Type>(source.collectionType);
m_valueType = Value::convert(source.valueType);
m_measure = Template::convert(source.measureType);
//Either collect expressions driving the property setting or a default setting
if (source.defaultValue.hasExpression) {
for (auto iter = source.defaultValue.propertyExpressions.Begin(); iter != source.defaultValue.propertyExpressions.End(); ++iter)
m_expressions.push_back(*iter);
} else {
m_defaultValue = std::make_unique<Setting>();
convert(source.defaultValue.basicValue, *m_defaultValue);
}
for (const auto& guid : source.availability)
m_classifications.insert(guid);
for (const auto& enumVal : source.possibleEnumValues)
m_enumValues.emplace_back(enumVal);
m_isValueEditable = source.canValueBeEditable;
} //Template::Template
#endif
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Convert an API_PropertyValue to a Setting. NB: This cannot be done independent of a template (which contains the value characteristics)
value: An Archicad property value
setting: A property setting to receive the property value
return: True if the conversion was successful
--------------------------------------------------------------------*/
bool Template::convert(const API_PropertyValue& value, Setting& setting) const {
auto measure = Template::convert(m_measure);
switch (m_type) {
case Type::single: case Type::singleEnum:
return setting.receive(value.singleVariant, API_VariantStatusNormal, measure);
case Type::array: case Type::arrayEnum:
return setting.receive(value.listVariant, API_VariantStatusNormal, measure);
default:
break;
}
return false;
} //Template::convert
/*--------------------------------------------------------------------
Convert a setting to an API_PropertyValue. NB: This cannot be done independent of a template (which contains the value characteristics)
setting: A property setting
value: An Archicad property value to receive the setting
return: True if the conversion was successful
--------------------------------------------------------------------*/
bool Template::convert(const Setting& setting, API_PropertyValue& value) const {
return false; //TODO: Implement when required
} //Template::convert
#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 Template::fillInventory(Inventory& inventory) const {
//Implement when required
return base::fillInventory(inventory);
} //Template::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Template::getCargo(const Inventory::Item& item) const {
//Implement when required
return base::getCargo(item);
} //Template::getCargo
@@ -0,0 +1,192 @@
#ifndef SPECKLE_RECORD_PROPERTY_TEMPLATE
#define SPECKLE_RECORD_PROPERTY_TEMPLATE
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Record/Property/Value.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
namespace speckle::record::property {
class Setting;
/*!
Class defining the characteristics of a property value
Properties carry both a template (the property metadata) and a value. The template defines the value characteristics, e.g. name, type etc
and can be shared amongst any number of properties
Property templates are persisted in the BIM property database
*/
class Template : public speckle::database::BIMRecord {
public:
// MARK: - Types
using base = speckle::database::BIMRecord;
///Unique pointer
using Unique = std::unique_ptr<Template>;
///Shared pointer
using Shared = std::shared_ptr<Template>;
///Optional
using Option = std::optional<Template>;
///Template origin, e.g. built-in or custom
enum class Origin {
builtInStatic, ///<A built-in static property template
builtInDynamic, ///<A built-in dynamic property template
custom, ///<A custom (user-defined) template
};
///Template data type
enum class Type {
undefined, ///<No data
single, ///<The property contains a single value
array, ///<The property contains an array of values
singleEnum, ///<The property contains a single value from an enumeration og permitted values
arrayEnum, ///<The property contains an array of values from an enumeration of permitted values
};
///Template value measurement type
enum class Measure {
none, ///<No measurement type
length, ///<Length measure
area, ///<Area measure
volume, ///<Volumne measure
angle, ///<Angle measure
};
// MARK: - Static functions
#ifdef ARCHICAD
/*!
Convert an Archicad API measure type to a Measure
@param type The API measure type
@return An equivalent Measure
*/
static Measure convert(API_PropertyMeasureType type);
/*!
Convert Measure to an Archicad API property value type
@param type The Measure
@return An equivalent API measure type
*/
static API_PropertyMeasureType convert(Measure type);
#endif
// MARK: - Constants
///Identifier for a property table
inline static utility::Guid propertyTableID{utility::String{"ae66bc4a-9530-45c9-af57-628562a0d783"}};
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Template();
#ifdef ARCHICAD
/*!
Constructor
@param source An Archicad property definition to copy
*/
Template(const API_PropertyDefinition& source);
#endif
/*!
Constructor
@param ID The template ID
*/
Template(const database::BIMRecordID& ID);
/*!
Constructor
@param ID The record ID
@param tableID The parent table ID
@param unit The record unit type
*/
Template(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID,
std::optional<active::measure::LengthType> unit = active::measure::LengthType::metre);
/*!
Copy constructor
@param source The object to copy
*/
Template(const Template& source);
// MARK: - Functions (const)
/*!
Get the template name
@return The template name
*/
speckle::utility::String getName() const { return m_name; }
/*!
Get the classifications linked to the template
@return A set containing the IDs of classifications linked to the template
*/
const speckle::database::BIMRecordIDList& getClassifications() const { return m_classifications; }
/*!
Determine if the template is linked to a specified classification
@param classificationID The ID of the target classification
@return True if the template is linked to a specified classification
*/
bool linksToClassification(const database::BIMRecordID& classificationID) const { return m_classifications.contains(classificationID); }
/*!
Convert an API_PropertyValue to a Setting. NB: This cannot be done independent of a template (which contains the value characteristics)
@param value An Archicad property value
@param setting A property setting to receive the property value
@return True if the conversion was successful
*/
bool convert(const API_PropertyValue& value, Setting& setting) const;
/*!
Convert a setting to an API_PropertyValue. NB: This cannot be done independent of a template (which contains the value characteristics)
@param setting A property setting
@param value An Archicad property value to receive the setting
@return True if the conversion was successful
*/
bool convert(const Setting& setting, API_PropertyValue& value) const;
// MARK: - Functions (mutating)
// 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;
private:
///The template origin (built-in or custom)
Origin m_origin;
///The template data type
Type m_type;
///The template value type
active::setting::Value::Type m_valueType;
///The template data messurement type
Measure m_measure;
///Group ID
speckle::database::BIMRecordID m_group;
///Name
speckle::utility::String m_name;
///Description
speckle::utility::String m_description;
///The default value for new property instances
std::unique_ptr<Setting> m_defaultValue;
///Expression(s) generating the property value
std::vector<utility::String> m_expressions;
///The classifications linked to this template (i.e. elements with any one or these classifications is linked to this template)
speckle::database::BIMRecordIDList m_classifications;
///Possible values for enumerated types
std::vector<Value> m_enumValues;
///True if the property value is editable
bool m_isValueEditable;
};
}
#endif //SPECKLE_RECORD_PROPERTY_TEMPLATE
@@ -0,0 +1,189 @@
#include "Speckle/Record/Property/Value.h"
#include "Active/Setting/Values/BoolValue.h"
#include "Active/Setting/Values/GuidValue.h"
#include "Active/Setting/Values/Int64Value.h"
#include "Active/Setting/Values/Measurement/AngleValue.h"
#include "Active/Setting/Values/Measurement/AreaValue.h"
#include "Active/Setting/Values/Measurement/LengthValue.h"
#include "Active/Setting/Values/Measurement/VolumeValue.h"
#include "Active/Setting/Values/NullValue.h"
#include "Active/Setting/Values/StringValue.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
using namespace speckle::record::property;
using namespace speckle::utility;
namespace {
//Factory for values from BIM API properties
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Make a value from an Archicad property value
source: An Archicad property
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: A new value copied from the property value
--------------------------------------------------------------------*/
active::setting::Value::Unique makeValue(const API_Variant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyUndefinedMeasureType) {
active::setting::Value::Unique result;
//Create a value according to the source type
switch (source.type) {
case API_PropertyIntegerValueType:
result = std::make_unique<active::setting::Int64Value>(source.intValue);
case API_PropertyRealValueType: {
//Ensure measured values are an appropriate type
switch (measure) {
case API_PropertyLengthMeasureType:
result = std::make_unique<active::setting::LengthValue>(source.doubleValue);
case API_PropertyAreaMeasureType:
result = std::make_unique<active::setting::AreaValue>(source.doubleValue);
case API_PropertyVolumeMeasureType:
result = std::make_unique<active::setting::VolumeValue>(source.doubleValue);
case API_PropertyAngleMeasureType:
result = std::make_unique<active::setting::AngleValue>(source.doubleValue);
default:
result = std::make_unique<active::setting::DoubleValue>(source.doubleValue);
}
}
case API_PropertyStringValueType:
result = std::make_unique<active::setting::StringValue>(String{source.uniStringValue});
case API_PropertyBooleanValueType:
result = std::make_unique<active::setting::BoolValue>(source.boolValue);
case API_PropertyGuidValueType:
result = std::make_unique<active::setting::GuidValue>(Guid{source.guidValue});
default:
result = std::make_unique<active::setting::NullValue>(); //TODO: Is this a possible/valid outcome?
}
//If the value hasn't already been established as bad, apply the source status
if (result->status != active::setting::Value::bad) {
switch (status) {
case API_VariantStatusNull:
result->status = active::setting::Value::bad; //NB: In this context we treat a null value as 'bad'
break;
case API_VariantStatusUserUndefined:
result->status = active::setting::Value::undefined;
break;
case API_VariantStatusNormal:
result->status = active::setting::Value::good;
break;
}
}
return result;
} //makeValue
#endif
}
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Convert an Archicad API property value type to a Value::Type
type: The API property value type
return: An equivalent Value::Type
--------------------------------------------------------------------*/
active::setting::Value::Type Value::convert(API_VariantType type) {
switch (type) {
case API_PropertyIntegerValueType:
return active::setting::Value::intType;
case API_PropertyRealValueType:
return active::setting::Value::floatType;
case API_PropertyStringValueType:
return active::setting::Value::stringType;
case API_PropertyBooleanValueType:
return active::setting::Value::boolType;
case API_PropertyGuidValueType:
return active::setting::Value::idType;
default:
break;
}
return active::setting::Value::null;
} //Value::convert
/*--------------------------------------------------------------------
Convert Value::Type to an Archicad API property value type
type: The Value::Type
return: An equivalent API property value type
--------------------------------------------------------------------*/
API_VariantType Value::convert(active::setting::Value::Type type) {
switch (type) {
case active::setting::Value::intType:
return API_PropertyIntegerValueType;
case active::setting::Value::floatType:
return API_PropertyRealValueType;
case active::setting::Value::stringType:
return API_PropertyStringValueType;
case active::setting::Value::boolType:
return API_PropertyBooleanValueType;
case active::setting::Value::idType:
return API_PropertyGuidValueType;
default:
break;
}
return API_PropertyUndefinedValueType;
} //Value::convert
#endif
/*--------------------------------------------------------------------
Assignment operator
source: The object to copy
return: A reference to this
--------------------------------------------------------------------*/
Value& Value::operator=(const Value& source) {
if (this != &source) {
m_value = source.m_value ? clone(*source.m_value) : nullptr;
m_key = source.m_key ? clone(*source.m_key) : nullptr;
}
return *this;
} //Value::operator=
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Receive a value from an Archicad property
source: An Archicad property
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the value was successfully received
--------------------------------------------------------------------*/
bool Value::receive(const API_SingleEnumerationVariant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
//Get the value key (if defined)
if (source.keyVariant.type != API_PropertyUndefinedValueType) {
m_key = makeValue(source.keyVariant);
if (m_key->status != active::setting::Value::good)
m_key.reset();
}
//Get the property value
m_value = makeValue(source.displayVariant, status, measure);
return true;
} //Value::receive
/*--------------------------------------------------------------------
Receive a value from an Archicad property
source: An Archicad property
status: The property status
measure: An optional measurement type, e.g. length, angle (where applicable)
return: True if the value was successfully received
--------------------------------------------------------------------*/
bool Value::receive(const API_Variant& source, API_VariantStatus status, API_PropertyMeasureType measure) {
m_key.reset();
m_value = makeValue(source, status, measure);
return true;
} //Value::receive
#endif
+140
View File
@@ -0,0 +1,140 @@
#ifndef SPECKLE_RECORD_PROPERTY_VALUE
#define SPECKLE_RECORD_PROPERTY_VALUE
#include "Active/Setting/Values/Value.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
namespace speckle::record::property {
/*!
Class holding a property value
Note that this object holds a bare, single value only, e.g. no metadata. Properties will allow for multiple values and couple them with a
property template (defining name etc)
Some properties support a key/value pairing, so this object can hold an optional key (undefined when no key is required)
NB: This class is not currently intended to be subclassed, but can be revisited in future
*/
class Value final {
public:
// MARK: - Types
///Unique pointer
using Unique = std::unique_ptr<Value>;
///Shared pointer
using Shared = std::shared_ptr<Value>;
///Optional
using Option = std::optional<Value>;
#ifdef ARCHICAD
/*!
Convert an Archicad API property value type to a Value::Type
@param type The API property value type
@return An equivalent Value::Type
*/
static active::setting::Value::Type convert(API_VariantType type);
/*!
Convert Value::Type to an Archicad API property value type
@param type The Value::Type
@return An equivalent API property value type
*/
static API_VariantType convert(active::setting::Value::Type type);
#endif
// MARK: - Constructors
/*!
Default constructor
*/
Value() {}
/*!
Constructor
@param value The property value
*/
Value(const active::setting::Value& value) : m_value{clone(value)} {}
/*!
Constructor
@param value The property value
*/
Value(const active::setting::Value& key, const active::setting::Value& value) : m_key{clone(key)}, m_value{clone(value)} {}
#ifdef ARCHICAD
/*!
Constructor
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Value(const API_SingleEnumerationVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType) { receive(source, status, measure); }
/*!
Constructor
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
*/
Value(const API_Variant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType) { receive(source, status, measure); }
#endif
/*!
Copy constructor
@param source The object to copy
*/
Value(const Value& source) : m_value{source.m_value ? clone(*source.m_value) : nullptr}, m_key{source.m_key ? clone(*source.m_key) : nullptr} {}
// MARK: - Operators
/*!
Assignment operator
@param source The object to copy
@return A reference to this
*/
Value& operator=(const Value& source);
// MARK: - Functions (const)
/*!
Get the property value key
@return The property value key (nullptr if undefined)
*/
active::setting::Value* getKey() const { return m_key.get(); }
/*!
Get the property value
@return The property value (nullptr if undefined)
*/
active::setting::Value* getValue() const { return m_value.get(); }
// MARK: - Functions (mutating)
/*!
Receive a value from an Archicad property
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the value was successfully received
*/
bool receive(const API_SingleEnumerationVariant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
/*!
Receive a value from an Archicad property
@param source An Archicad property
@param status The property status
@param measure An optional measurement type, e.g. length, angle (where applicable)
@return True if the value was successfully received
*/
bool receive(const API_Variant& source, API_VariantStatus status = API_VariantStatusNormal,
API_PropertyMeasureType measure = API_PropertyDefaultMeasureType);
private:
///The value key
active::setting::Value::Unique m_key;
///The property value
active::setting::Value::Unique m_value;
};
}
#endif //SPECKLE_RECORD_PROPERTY_VALUE
+16
View File
@@ -73,4 +73,20 @@ namespace speckle::utility {
}
///Hashing for Guid class, e.g. to use as a key in unordered_map
template<>
struct std::hash<speckle::utility::Guid> {
std::size_t operator() (const active::utility::Guid& guid) const {
return static_cast<std::size_t>(guid.raw().first | std::rotr(guid.raw().second, 8 * sizeof(uint64_t)));
}
};
///Hashing for a Guid pair, e.g. to use as a key in unordered_map
template<>
struct std::hash<std::pair<speckle::utility::Guid, speckle::utility::Guid>> {
std::size_t operator() (const std::pair<speckle::utility::Guid, speckle::utility::Guid>& pair) const {
return std::hash<speckle::utility::Guid>()(pair.first) | std::rotr(std::hash<speckle::utility::Guid>()(pair.second), 8 * sizeof(std::size_t));
}
};
#endif //SPECKLE_UTILITY_GUID
+121 -9
View File
@@ -66,9 +66,31 @@
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 */; };
21A0FC0E2CBE92F10023F24E /* ModelElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC0C2CBE92F10023F24E /* ModelElement.cpp */; };
21A0FC0F2CBE92F10023F24E /* ModelElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FC0D2CBE92F10023F24E /* ModelElement.h */; };
21A0FC112CBEE5C30023F24E /* Part.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FC102CBEE5C30023F24E /* Part.cpp */; };
21A890C42CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890BF2CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp */; };
21A890C52CC171D80087E732 /* ArchicadPropertyDBaseEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A890C02CC171D80087E732 /* ArchicadPropertyDBaseEngine.h */; };
21A890C82CC1B5FF0087E732 /* DrawingElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890C62CC1B5FF0087E732 /* DrawingElement.cpp */; };
21A890C92CC1B5FF0087E732 /* DrawingElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A890C72CC1B5FF0087E732 /* DrawingElement.h */; };
21A890CE2CC1B87C0087E732 /* GenericDrawingElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890CA2CC1B87B0087E732 /* GenericDrawingElement.cpp */; };
21A890CF2CC1B87C0087E732 /* GenericDrawingElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A890CB2CC1B87B0087E732 /* GenericDrawingElement.h */; };
21A890D02CC1B87C0087E732 /* GenericModelElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A890CC2CC1B87B0087E732 /* GenericModelElement.h */; };
21A890D12CC1B87C0087E732 /* GenericModelElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890CD2CC1B87C0087E732 /* GenericModelElement.cpp */; };
21AE19512CC273F1004DBCFC /* Property.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE194A2CC273F1004DBCFC /* Property.cpp */; };
21AE19522CC273F1004DBCFC /* Property.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE194B2CC273F1004DBCFC /* Property.h */; };
21AE19532CC273F1004DBCFC /* Template.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE194C2CC273F1004DBCFC /* Template.cpp */; };
21AE19542CC273F1004DBCFC /* Template.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE194D2CC273F1004DBCFC /* Template.h */; };
21AE19572CC27DB3004DBCFC /* Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19552CC27DB3004DBCFC /* Value.cpp */; };
21AE19582CC27DB3004DBCFC /* Value.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19562CC27DB3004DBCFC /* Value.h */; };
21AE19612CC2D358004DBCFC /* Setting.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE195F2CC2D358004DBCFC /* Setting.h */; };
21AE19622CC2D358004DBCFC /* Setting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19602CC2D358004DBCFC /* Setting.cpp */; };
21AE19652CC2F702004DBCFC /* BIMPropertyDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19632CC2F702004DBCFC /* BIMPropertyDatabase.cpp */; };
21AE19662CC2F702004DBCFC /* BIMPropertyDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19642CC2F702004DBCFC /* BIMPropertyDatabase.h */; };
21AE19692CC57832004DBCFC /* Propertied.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19672CC57832004DBCFC /* Propertied.cpp */; };
21AE196A2CC57832004DBCFC /* Propertied.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19682CC57832004DBCFC /* Propertied.h */; };
21AE196E2CC64D37004DBCFC /* Classified.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE196B2CC64D37004DBCFC /* Classified.cpp */; };
21AE196F2CC64D37004DBCFC /* Classified.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE196C2CC64D37004DBCFC /* Classified.h */; };
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 */; };
@@ -226,9 +248,31 @@
21A0FC022CBE59A80023F24E /* Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Path.h; sourceTree = "<group>"; };
21A0FC082CBE5E220023F24E /* Segment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Segment.cpp; sourceTree = "<group>"; };
21A0FC092CBE5E220023F24E /* Segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Segment.h; sourceTree = "<group>"; };
21A0FC0C2CBE92F10023F24E /* GenericElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericElement.cpp; sourceTree = "<group>"; };
21A0FC0D2CBE92F10023F24E /* GenericElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericElement.h; sourceTree = "<group>"; };
21A0FC0C2CBE92F10023F24E /* ModelElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModelElement.cpp; sourceTree = "<group>"; };
21A0FC0D2CBE92F10023F24E /* ModelElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelElement.h; sourceTree = "<group>"; };
21A0FC102CBEE5C30023F24E /* Part.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Part.cpp; path = Speckle/Record/Element/Interface/Part.cpp; sourceTree = SOURCE_ROOT; };
21A890BF2CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchicadPropertyDBaseEngine.cpp; sourceTree = "<group>"; };
21A890C02CC171D80087E732 /* ArchicadPropertyDBaseEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadPropertyDBaseEngine.h; sourceTree = "<group>"; };
21A890C62CC1B5FF0087E732 /* DrawingElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawingElement.cpp; sourceTree = "<group>"; };
21A890C72CC1B5FF0087E732 /* DrawingElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawingElement.h; sourceTree = "<group>"; };
21A890CA2CC1B87B0087E732 /* GenericDrawingElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericDrawingElement.cpp; sourceTree = "<group>"; };
21A890CB2CC1B87B0087E732 /* GenericDrawingElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericDrawingElement.h; sourceTree = "<group>"; };
21A890CC2CC1B87B0087E732 /* GenericModelElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericModelElement.h; sourceTree = "<group>"; };
21A890CD2CC1B87C0087E732 /* GenericModelElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenericModelElement.cpp; sourceTree = "<group>"; };
21AE194A2CC273F1004DBCFC /* Property.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Property.cpp; sourceTree = "<group>"; };
21AE194B2CC273F1004DBCFC /* Property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Property.h; sourceTree = "<group>"; };
21AE194C2CC273F1004DBCFC /* Template.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Template.cpp; sourceTree = "<group>"; };
21AE194D2CC273F1004DBCFC /* Template.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Template.h; sourceTree = "<group>"; };
21AE19552CC27DB3004DBCFC /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Value.cpp; sourceTree = "<group>"; };
21AE19562CC27DB3004DBCFC /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Value.h; sourceTree = "<group>"; };
21AE195F2CC2D358004DBCFC /* Setting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Setting.h; sourceTree = "<group>"; };
21AE19602CC2D358004DBCFC /* Setting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Setting.cpp; sourceTree = "<group>"; };
21AE19632CC2F702004DBCFC /* BIMPropertyDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMPropertyDatabase.cpp; sourceTree = "<group>"; };
21AE19642CC2F702004DBCFC /* BIMPropertyDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMPropertyDatabase.h; sourceTree = "<group>"; };
21AE19672CC57832004DBCFC /* Propertied.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Propertied.cpp; sourceTree = "<group>"; };
21AE19682CC57832004DBCFC /* Propertied.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Propertied.h; sourceTree = "<group>"; };
21AE196B2CC64D37004DBCFC /* Classified.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Classified.cpp; sourceTree = "<group>"; };
21AE196C2CC64D37004DBCFC /* Classified.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Classified.h; sourceTree = "<group>"; };
21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = "<group>"; };
21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = "<group>"; };
21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachmentManager.h; sourceTree = "<group>"; };
@@ -380,10 +424,16 @@
21A0FBE92CBD6B1A0023F24E /* Column.h */,
21A0FBDF2CBD6B1A0023F24E /* ColumnSegment.cpp */,
21A0FBE22CBD6B1A0023F24E /* ColumnSegment.h */,
21A890C62CC1B5FF0087E732 /* DrawingElement.cpp */,
21A890C72CC1B5FF0087E732 /* DrawingElement.h */,
215F08782CA18E1400CD343B /* Element.cpp */,
215F08792CA18E1400CD343B /* Element.h */,
21A0FC0C2CBE92F10023F24E /* GenericElement.cpp */,
21A0FC0D2CBE92F10023F24E /* GenericElement.h */,
21A890CA2CC1B87B0087E732 /* GenericDrawingElement.cpp */,
21A890CB2CC1B87B0087E732 /* GenericDrawingElement.h */,
21A890CD2CC1B87C0087E732 /* GenericModelElement.cpp */,
21A890CC2CC1B87B0087E732 /* GenericModelElement.h */,
21A0FC0C2CBE92F10023F24E /* ModelElement.cpp */,
21A0FC0D2CBE92F10023F24E /* ModelElement.h */,
21A0FBE72CBD6B1A0023F24E /* Interface */,
21A0FBF32CBD6B700023F24E /* Memo.cpp */,
21A0FBF22CBD6B700023F24E /* Memo.h */,
@@ -398,6 +448,7 @@
215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */,
2196F2EA2CB4816B00450DFC /* Attribute */,
219246062CA2D22D00CF5703 /* Element */,
21A890C12CC171D80087E732 /* Property */,
);
path = ArchicadDBase;
sourceTree = "<group>";
@@ -569,6 +620,41 @@
path = Assembly;
sourceTree = "<group>";
};
21A890C12CC171D80087E732 /* Property */ = {
isa = PBXGroup;
children = (
21A890BF2CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp */,
21A890C02CC171D80087E732 /* ArchicadPropertyDBaseEngine.h */,
);
path = Property;
sourceTree = "<group>";
};
21AE194E2CC273F1004DBCFC /* Property */ = {
isa = PBXGroup;
children = (
21AE19672CC57832004DBCFC /* Propertied.cpp */,
21AE19682CC57832004DBCFC /* Propertied.h */,
21AE194A2CC273F1004DBCFC /* Property.cpp */,
21AE194B2CC273F1004DBCFC /* Property.h */,
21AE19602CC2D358004DBCFC /* Setting.cpp */,
21AE195F2CC2D358004DBCFC /* Setting.h */,
21AE194C2CC273F1004DBCFC /* Template.cpp */,
21AE194D2CC273F1004DBCFC /* Template.h */,
21AE19552CC27DB3004DBCFC /* Value.cpp */,
21AE19562CC27DB3004DBCFC /* Value.h */,
);
path = Property;
sourceTree = "<group>";
};
21AE196D2CC64D37004DBCFC /* Classification */ = {
isa = PBXGroup;
children = (
21AE196B2CC64D37004DBCFC /* Classified.cpp */,
21AE196C2CC64D37004DBCFC /* Classified.h */,
);
path = Classification;
sourceTree = "<group>";
};
21AEF9C72CA818EA000B8681 /* Detached */ = {
isa = PBXGroup;
children = (
@@ -601,6 +687,8 @@
2196F2F72CB51ED400450DFC /* BIMAttributeDatabase.h */,
215F08932CA19AF800CD343B /* BIMElementDatabase.cpp */,
215F08942CA19AF800CD343B /* BIMElementDatabase.h */,
21AE19632CC2F702004DBCFC /* BIMPropertyDatabase.cpp */,
21AE19642CC2F702004DBCFC /* BIMPropertyDatabase.h */,
21D0BD272C86FC350077E104 /* Content */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BDB02C8F8AB60077E104 /* Storage */,
@@ -736,8 +824,10 @@
isa = PBXGroup;
children = (
2196F2EF2CB4823C00450DFC /* Attribute */,
215F087A2CA18E1400CD343B /* Element */,
21AE196D2CC64D37004DBCFC /* Classification */,
21F69F942C71087A008B6A06 /* Credentials */,
215F087A2CA18E1400CD343B /* Element */,
21AE194E2CC273F1004DBCFC /* Property */,
);
path = Record;
sourceTree = "<group>";
@@ -783,16 +873,20 @@
210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */,
210CC8A02C81E34400610F58 /* Platform.h in Headers */,
219246132CA34DCE00CF5703 /* Mesh.h in Headers */,
21A890CF2CC1B87C0087E732 /* GenericDrawingElement.h in Headers */,
219246032CA2CE2700CF5703 /* BIMLink.h in Headers */,
21B67D0D2C7E0E8D00FD64FC /* ErrorReport.h in Headers */,
215F08962CA19AF800CD343B /* BIMElementDatabase.h in Headers */,
2196F2F12CB4823C00450DFC /* Attribute.h in Headers */,
21D0BD332C86FE090077E104 /* Link.h in Headers */,
21AE19612CC2D358004DBCFC /* Setting.h in Headers */,
21D0BD5A2C8910400077E104 /* UserInfo.h in Headers */,
21A890C92CC1B5FF0087E732 /* DrawingElement.h in Headers */,
21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */,
210CC88F2C81A98500610F58 /* Guid64.h in Headers */,
21AEF9DD2CAAA4EA000B8681 /* DetachedObjectStore.h in Headers */,
21A0FBF12CBD6B1A0023F24E /* Column.h in Headers */,
21AE19662CC2F702004DBCFC /* BIMPropertyDatabase.h in Headers */,
21A0FC072CBE59A80023F24E /* Path.h in Headers */,
21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */,
21A0FC0B2CBE5E220023F24E /* Segment.h in Headers */,
@@ -810,13 +904,20 @@
210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */,
21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */,
2196F3042CB57E8000450DFC /* Storey.h in Headers */,
21AE196F2CC64D37004DBCFC /* Classified.h in Headers */,
21AE19522CC273F1004DBCFC /* Property.h in Headers */,
21A0FBF92CBDB9A70023F24E /* BIMMemory.h in Headers */,
21AE19542CC273F1004DBCFC /* Template.h in Headers */,
21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */,
21A0FC052CBE59A80023F24E /* SegmentedColumn.h in Headers */,
21A0FC0F2CBE92F10023F24E /* GenericElement.h in Headers */,
21A0FC0F2CBE92F10023F24E /* ModelElement.h in Headers */,
21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */,
21A890D02CC1B87C0087E732 /* GenericModelElement.h in Headers */,
21A890C52CC171D80087E732 /* ArchicadPropertyDBaseEngine.h in Headers */,
21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */,
21AE196A2CC57832004DBCFC /* Propertied.h in Headers */,
2196F2EC2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h in Headers */,
21AE19582CC27DB3004DBCFC /* Value.h in Headers */,
21D0BD312C86FE090077E104 /* Index.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -960,10 +1061,13 @@
215F087D2CA18E1400CD343B /* Element.cpp in Sources */,
2196F2F82CB51ED400450DFC /* BIMAttributeDatabase.cpp in Sources */,
21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */,
21AE19512CC273F1004DBCFC /* Property.cpp in Sources */,
21B67D0E2C7E0E8D00FD64FC /* ErrorReport.cpp in Sources */,
21AE19692CC57832004DBCFC /* Propertied.cpp in Sources */,
21F69F7E2C6FD9FC008B6A06 /* GetCallResult.cpp in Sources */,
2196F3052CB57E8000450DFC /* Storey.cpp in Sources */,
219245FE2CA2CC4300CF5703 /* BIMRecord.cpp in Sources */,
21AE19572CC27DB3004DBCFC /* Value.cpp in Sources */,
21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */,
21A0FC062CBE59A80023F24E /* Path.cpp in Sources */,
2196F2F52CB483D600450DFC /* Finish.cpp in Sources */,
@@ -971,21 +1075,29 @@
2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */,
21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */,
219246042CA2CE2700CF5703 /* BIMLink.cpp in Sources */,
21A890CE2CC1B87C0087E732 /* GenericDrawingElement.cpp in Sources */,
215F08952CA19AF800CD343B /* BIMElementDatabase.cpp in Sources */,
21A0FC0E2CBE92F10023F24E /* GenericElement.cpp in Sources */,
21A0FC0E2CBE92F10023F24E /* ModelElement.cpp in Sources */,
219246122CA34DCE00CF5703 /* Mesh.cpp in Sources */,
21A0FBF02CBD6B1A0023F24E /* Column.cpp in Sources */,
21A890C42CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp in Sources */,
21AE196E2CC64D37004DBCFC /* Classified.cpp in Sources */,
21A890C82CC1B5FF0087E732 /* DrawingElement.cpp in Sources */,
21AE19652CC2F702004DBCFC /* BIMPropertyDatabase.cpp in Sources */,
21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */,
210CC8902C81A98500610F58 /* Guid64.cpp in Sources */,
21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */,
21AE19622CC2D358004DBCFC /* Setting.cpp in Sources */,
219351B32C62CC1A00E5A69C /* String.cpp in Sources */,
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */,
21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */,
21A0FC112CBEE5C30023F24E /* Part.cpp in Sources */,
21A890D12CC1B87C0087E732 /* GenericModelElement.cpp in Sources */,
21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */,
215F08552C99DA8D00CD343B /* Project.cpp in Sources */,
21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */,
2196F2EB2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp in Sources */,
21AE19532CC273F1004DBCFC /* Template.cpp in Sources */,
21A0FC042CBE59A80023F24E /* SegmentedColumn.cpp in Sources */,
210CC89F2C81E34400610F58 /* Platform.cpp in Sources */,
21D0BD202C86F0280077E104 /* AccountDatabase.cpp in Sources */,