Compare commits

..

40 Commits

Author SHA1 Message Date
David Kekesi 3f772150ff no need to start project subscriber after installation 2024-10-24 16:28:57 +02:00
David Kekesi e00fd99d3c modelcards are loaded on document switch 2024-10-24 16:25:27 +02:00
David Kekesi 72e8ea78d9 Merge branch 'develop' into david/cnx-660-document-switch-and-model-cards 2024-10-24 15:50:42 +02:00
Ralph Wessel ede131ca0b Merge pull request #10 from specklesystems/david/cnx-667-model-card-highlighting
cnx 667 model card highlighting
2024-10-24 13:03:32 +01:00
David Kekesi c4fcce4df8 BimElementDatabase setSelection, clearSelection implemented 2024-10-24 13:59:17 +02:00
David Kekesi dcbd795b1f ElementIDList moved to SpeckleLib, added setSelection method to BIMElementDatabase 2024-10-24 12:28:04 +02:00
David Kekesi 8a37d3fbd6 Beam regression fixed 2024-10-24 11:28:32 +02:00
David Kekesi 7256e11c3a Merge branch 'develop' into david/cnx-667-model-card-highlighting 2024-10-24 10:32:06 +02:00
David Kekesi 9b8ab47eab code cleanup 2024-10-24 10:31:25 +02:00
Ralph Wessel f72d5202f9 ModelElement should be an abstract base rather than holding an element
ModelElement::getBody didn't check for null m_data
ArchicadElementDBaseEngine should default to returning GenericModelElement is type is unknown
2024-10-24 09:24:01 +01:00
David Kekesi dcac8390cf Merge branch 'develop' into david/cnx-667-model-card-highlighting 2024-10-24 09:21:40 +02:00
Ralph Wessel 8893653583 ContainerWrap should specify item tag where it differs from the default 2024-10-23 22:53:26 +01:00
David Kekesi 0d5dd7156e Merge branch 'develop' into david/cnx-667-model-card-highlighting 2024-10-23 15:20:35 +02:00
David Kekesi a5b681a6ed added HighlightModel method 2024-10-23 15:19:52 +02:00
Ralph Wessel 0c09205935 JSArgs for incoming commands need to allow the wrapped argument object to reset to its default values 2024-10-23 13:47:28 +01:00
Ralph Wessel 405d183124 Updated Xcode projects 2024-10-23 09:59:55 +01:00
Ralph Wessel 7a1335681a Merge branch 'feature/CNX-651_Add_Properties_from_Properties_and_Classification_tab_to_send' into develop 2024-10-23 09:54:55 +01:00
Ralph Wessel 889019a3e8 Merge branch 'develop' into feature/CNX-651_Add_Properties_from_Properties_and_Classification_tab_to_send
# Conflicts:
#	SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp
#	SpeckleLib/Speckle/Record/Element/Element.cpp
#	SpeckleLib/SpeckleLib17.vcxproj.filters
2024-10-23 09:54:11 +01:00
Ralph Wessel 0dee313366 Fixed conversion of enum property values 2024-10-23 09:32:05 +01:00
Ralph Wessel a169d8b1d2 Improved detection of null property settings/values to avoid serialising null values in PropertiedWrap 2024-10-22 21:49:37 +01:00
Ralph Wessel 6d51b2d868 Updated VS projects
Added missing break statements in Value.cpp
2024-10-22 21:24:19 +01:00
Ralph Wessel 2c6909e98e Added property::Group
Added property Group database
Property template group & group name access added
2024-10-22 20:09:01 +01:00
Ralph Wessel eeb4dab690 Property dbase should not check tableID if none is specified 2024-10-22 16:31:30 +01:00
Ralph Wessel e27808b73d Updated VS projects 2024-10-22 16:09:33 +01:00
Ralph Wessel 5f1c942584 Added serialisation for Propertied objects and Properties
Added serialisation hierarchy for properties within ModelElements
Additional data access to Setting, Template, Value and Property
2024-10-22 15:49:16 +01:00
kekesidavid 7dfe8fb964 Merge pull request #9 from specklesystems/david/cnx-664-create-one-mesh-per-material
cnx 664 create one mesh per material
2024-10-22 13:39:04 +02:00
David Kekesi 73b04a7588 code cleanup 2024-10-22 12:38:22 +02:00
Ralph Wessel 63bb28db0f Adding properties to element serialisation 2024-10-22 10:24:46 +01:00
David Kekesi 3368e7a6dc one mesh per material, Mesh::appendFace 2024-10-22 10:34:04 +02:00
Ralph Wessel 01bb88b4a1 ModelElement subclassed from Classified and Propertied 2024-10-21 21:45:07 +01:00
Ralph Wessel 35f4e58a58 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)
2024-10-21 16:25:23 +01:00
David Kekesi 6d14607634 bridge listens to open event instead of close 2024-10-21 16:36:39 +02:00
David Kekesi 5363819e8d BaseBridge listens to project events 2024-10-21 16:35:30 +02:00
kekesidavid 3be1676b1a Merge pull request #8 from specklesystems/david/cnx-650-create-beam-and-supporting-classes
Create beam and supporting classes
2024-10-21 10:04:41 +02:00
David Kekesi f5b5ff6487 create Beam and supporting classes 2024-10-21 09:41:55 +02:00
Ralph Wessel 878988df95 Update Xcode project
BIM core dbase engines should be able to react to project events
Attribute dbase resets storey cache on project changes
2024-10-17 17:22:51 +01:00
Ralph Wessel f44f0413d0 ColumnSegment move constructor should be noexcept 2024-10-16 17:00:03 +01:00
Ralph Wessel b80b5aef94 Fixed ColumnSegment copy constructor 2024-10-16 16:44:38 +01:00
Ralph Wessel 702f99eced Reduced the number of objects that define a name for 'speckle_type' (default to 'Base' instead) 2024-10-16 15:06:06 +01:00
Ralph Wessel 42cf641a01 Merge pull request #7 from specklesystems/david/cnx-150-implement-selectionbinding
David/cnx 150 implement selectionbinding
2024-10-16 15:04:58 +01:00
101 changed files with 6038 additions and 387 deletions
+2
View File
@@ -104,6 +104,7 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetDocumentState.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationName.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationVersion.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\HighlightModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.cpp" />
@@ -159,6 +160,7 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetDocumentState.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationName.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationVersion.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\HighlightModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.h" />
@@ -243,6 +243,9 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.cpp">
<Filter>Connector\Interface\Browser\Bridge\Selection\Arg</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\HighlightModel.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Connector\ConnectorResource.h">
@@ -411,5 +414,8 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.h">
<Filter>Connector\Interface\Browser\Bridge\Selection\Arg</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\HighlightModel.h">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -32,6 +32,9 @@
2192460D2CA3469D00CF5703 /* ProjectCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2192460B2CA3469D00CF5703 /* ProjectCollection.cpp */; };
219F30422C769283009834E9 /* ConfigTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219F30402C769282009834E9 /* ConfigTests.cpp */; };
21A0FB982CB723240023F24E /* FinishProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FB942CB723240023F24E /* FinishProxy.cpp */; };
21A890BC2CC15C540087E732 /* SelectionInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890B22CC15C540087E732 /* SelectionInfo.cpp */; };
21A890BD2CC15C540087E732 /* GetSelection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890B52CC15C540087E732 /* GetSelection.cpp */; };
21A890BE2CC15C540087E732 /* SelectionBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A890B72CC15C540087E732 /* SelectionBridge.cpp */; };
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E32CAB56E5000B8681 /* SendError.cpp */; };
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */; };
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9EE2CAB5720000B8681 /* SendObject.cpp */; };
@@ -314,6 +317,12 @@
219F30432C7693B6009834E9 /* Connector-AC27-Debug.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Connector-AC27-Debug.xctestplan"; sourceTree = SOURCE_ROOT; };
21A0FB942CB723240023F24E /* FinishProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FinishProxy.cpp; sourceTree = "<group>"; };
21A0FB972CB723240023F24E /* FinishProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = "<group>"; };
21A890B22CC15C540087E732 /* SelectionInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionInfo.cpp; sourceTree = "<group>"; };
21A890B32CC15C540087E732 /* SelectionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionInfo.h; sourceTree = "<group>"; };
21A890B52CC15C540087E732 /* GetSelection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSelection.cpp; sourceTree = "<group>"; };
21A890B62CC15C540087E732 /* GetSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetSelection.h; sourceTree = "<group>"; };
21A890B72CC15C540087E732 /* SelectionBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionBridge.cpp; sourceTree = "<group>"; };
21A890B82CC15C540087E732 /* SelectionBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionBridge.h; sourceTree = "<group>"; };
21AEF9E32CAB56E5000B8681 /* SendError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendError.cpp; sourceTree = "<group>"; };
21AEF9E42CAB56E5000B8681 /* SendError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendError.h; sourceTree = "<group>"; };
21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendViaBrowserArgs.cpp; sourceTree = "<group>"; };
@@ -963,6 +972,27 @@
path = ConnectorTests;
sourceTree = "<group>";
};
21A890B42CC15C540087E732 /* Arg */ = {
isa = PBXGroup;
children = (
21A890B22CC15C540087E732 /* SelectionInfo.cpp */,
21A890B32CC15C540087E732 /* SelectionInfo.h */,
);
path = Arg;
sourceTree = "<group>";
};
21A890B92CC15C540087E732 /* Selection */ = {
isa = PBXGroup;
children = (
21A890B42CC15C540087E732 /* Arg */,
21A890B52CC15C540087E732 /* GetSelection.cpp */,
21A890B62CC15C540087E732 /* GetSelection.h */,
21A890B72CC15C540087E732 /* SelectionBridge.cpp */,
21A890B82CC15C540087E732 /* SelectionBridge.h */,
);
path = Selection;
sourceTree = "<group>";
};
21AEF9E72CAB56E5000B8681 /* Arg */ = {
isa = PBXGroup;
children = (
@@ -1202,6 +1232,7 @@
21B67CAB2C77329800FD64FC /* Base */,
21F69FB82C762EF0008B6A06 /* Config */,
21D0BD5D2C89BFEA0077E104 /* Send */,
21A890B92CC15C540087E732 /* Selection */,
21B67CD82C78C83800FD64FC /* Test */,
);
path = Bridge;
@@ -1456,6 +1487,7 @@
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */,
21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */,
21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */,
21A890BE2CC15C540087E732 /* SelectionBridge.cpp in Sources */,
21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */,
21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */,
21B67CF72C78D4DE00FD64FC /* GetComplexType.cpp in Sources */,
@@ -1478,6 +1510,7 @@
21FF70492CA1A7F400AAD99A /* RecordCollection.cpp in Sources */,
21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */,
21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */,
21A890BD2CC15C540087E732 /* GetSelection.cpp in Sources */,
21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */,
21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */,
21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */,
@@ -1485,6 +1518,7 @@
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */,
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */,
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */,
21A890BC2CC15C540087E732 /* SelectionInfo.cpp in Sources */,
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
@@ -1,16 +1,8 @@
#ifndef CONNECTOR_DATABASE_ID
#define CONNECTOR_DATABASE_ID
#include "Speckle/Utility/Guid.h"
namespace connector::database {
//BIM element record identifier
using ElementID = speckle::utility::Guid;
//A list of element IDs
using ElementIDList = std::vector<ElementID>;
}
#endif //CONNECTOR_DATABASE_ID
@@ -10,12 +10,6 @@ using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<PackageWrap, DocumentInfo>;
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
@@ -1,5 +1,4 @@
#include "Connector/Interface/Browser/Bridge/Base/BaseBridge.h"
#include "Connector/Interface/Browser/Bridge/Base/AddModel.h"
#include "Connector/Interface/Browser/Bridge/Base/GetConnectorVersion.h"
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentInfo.h"
@@ -8,6 +7,7 @@
#include "Connector/Interface/Browser/Bridge/Base/GetSourceApplicationVersion.h"
#include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h"
#include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h"
#include "Connector/Interface/Browser/Bridge/Base/HighlightModel.h"
using namespace connector::interfac::browser::bridge;
@@ -24,4 +24,24 @@ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} {
addMethod<GetSourceApplicationVersion>();
addMethod<RemoveModel>();
addMethod<UpdateModel>();
addMethod<HighlightModel>();
} //BaseBridge::BaseBridge
/*--------------------------------------------------------------------
Handle a project event
event: The project event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool BaseBridge::handle(const speckle::event::ProjectEvent& event) {
using enum speckle::event::ProjectEvent::Type;
switch (event.getType()) {
case open:
sendEvent("documentChanged");
break;
default:
break;
}
return false;
} //BaseBridge::handle
@@ -2,13 +2,15 @@
#define CONNECTOR_INTERFACE_BRIDGE_BASE_BRIDGE
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
#include "Speckle/Event/Type/ProjectEvent.h"
namespace connector::interfac::browser::bridge {
/*!
A browser bridge to provide configuration settings
*/
class BaseBridge : public speckle::interfac::browser::bridge::BrowserBridge {
class BaseBridge : public speckle::interfac::browser::bridge::BrowserBridge, public speckle::event::ProjectSubscriber {
public:
// MARK: - Types
@@ -22,6 +24,14 @@ namespace connector::interfac::browser::bridge {
Default constructor
*/
BaseBridge();
protected:
/*!
Handle the project events
@param event The project event
@return True if the event should be closed
*/
bool handle(const speckle::event::ProjectEvent& event) override;
};
}
@@ -0,0 +1,61 @@
#include "Connector/Interface/Browser/Bridge/Base/HighlightModel.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Connector/Record/Model/SenderModelCard.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Environment/Project.h"
#include <array>
using namespace speckle::record::element;
using namespace connector::interfac::browser::bridge;
using namespace connector::record;
using namespace speckle::utility;
namespace {
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
HighlightModel::HighlightModel() : BridgeMethod{"HighlightModel", [&](const SendArgs& args) {
run(args);
}} {}
/*--------------------------------------------------------------------
Higlight the model card selection
modelCardID: The ID of the model to send
--------------------------------------------------------------------*/
void HighlightModel::run(const String& modelCardID) const {
// Find the specified model card
auto modelCardDatabase = connector()->getModelCardDatabase();
auto modelCard = modelCardDatabase->getCard(modelCardID);
if (!modelCard) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, modelCardNotFoundID), modelCardID));
return;
}
if (auto senderCard = dynamic_cast<SenderModelCard*>(modelCard.get())) {
auto modelCardSelection = senderCard->getFilter().getElementIDs();
auto project = connector()->getActiveProject().lock();
if (!project) {
// TODO: is this OK? should this throw?
return;
}
auto elementDatabase = project->getElementDatabase();
elementDatabase->clearSelection();
elementDatabase->setSelection(modelCardSelection);
}
} //HighlightModel::run
@@ -0,0 +1,42 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_HIGHLIGHT_MODEL
#define CONNECTOR_INTERFACE_BRIDGE_HIGHLIGHT_MODEL
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
class ConnectorConfig;
///Argument parameter for a string
using StringHold = active::serialise::CargoHold<active::serialise::ValueWrap<speckle::utility::String>, speckle::utility::String>;
///Argument type for this method
using SendArgs = speckle::interfac::browser::bridge::JSArgType<StringHold>;
/*!
JS Function class to send a specified model
*/
class HighlightModel : public speckle::interfac::browser::bridge::BridgeMethod<SendArgs, void> {
public:
// MARK: - Constructors
/*!
Constructor
*/
HighlightModel();
// MARK: - Functions (const)
/*!
Higlight the model card selection
@param modelCardID The ID of the model to send
*/
void run(const speckle::utility::String& modelCardID) const;
};
}
#endif //CONNECTOR_INTERFACE_HIGHLIGHT_MODEL
@@ -29,13 +29,9 @@ namespace {
}
SelectionInfo::SelectionInfo() {
initialize();
}
void SelectionInfo::initialize() {
auto project = connector()->getActiveProject().lock();
if (!project) {
// TODO: is thi OK?
// TODO: is this OK?
return;
}
@@ -51,6 +47,7 @@ void SelectionInfo::initialize() {
}
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -83,7 +80,7 @@ Cargo::Unique SelectionInfo::getCargo(const Inventory::Item& item) const {
using namespace active::serialise;
switch (item.index) {
case selectedObjectIdsID:
return std::make_unique<ContainerWrap<std::vector<active::utility::Guid>>>(m_selectedElementIds);
return std::make_unique<ContainerWrap<std::vector<active::utility::Guid>>>(m_selectedElementIds, false, fieldID[selectedObjectIdsID].name);
case summaryID:
return std::make_unique<ValueWrap<active::utility::String>>(m_summary);
default:
@@ -39,10 +39,6 @@ namespace connector::interfac::browser::bridge {
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
void initialize();
};
}
@@ -14,11 +14,14 @@ SelectionBridge::SelectionBridge() : BrowserBridge{"selectionBinding"} {
addMethod<GetSelection>();
} //SelectionBridge::SelectionBridge
/*!
Handle the menu selection
@param event The selection event
@return True if the event should be closed
*/
/*--------------------------------------------------------------------
Handle a selection change
event: The selection event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool SelectionBridge::handle(const speckle::event::SelectionEvent& event) {
auto selectionInfo = std::make_unique<SelectionInfo>();
auto wrapped = std::make_unique<CargoHold<PackageWrap, SelectionInfo>>(std::move(selectionInfo));
@@ -8,7 +8,7 @@
namespace connector::interfac::browser::bridge {
/*!
A browser bridge to support sending model data to a Speckle server
A browser bridge to manage element selection information passed between the JS UI and the BIM application
*/
class SelectionBridge : public speckle::interfac::browser::bridge::BrowserBridge, public speckle::event::SelectionSubscriber {
public:
@@ -27,7 +27,7 @@ namespace connector::interfac::browser::bridge {
protected:
/*!
Handle the menu selection
Handle a selection change
@param event The selection event
@return True if the event should be closed
*/
@@ -166,15 +166,23 @@ BrowserPalette::BrowserPalette() :
BeginEventProcessing();
//Install required connector bridges
install<AccountBridge>();
install<BaseBridge>();
if (auto ref = install<BaseBridge>(); ref) {
if (auto baseBridgeRef = std::dynamic_pointer_cast<BaseBridge>(ref); baseBridgeRef) {
connector::connector()->addWeak(baseBridgeRef);
}
}
install<ConfigBridge>();
install<SendBridge>();
if (auto ref = install<SelectionBridge>(); ref) {
if (auto selectionBridgeRef = std::dynamic_pointer_cast<SelectionBridge>(ref); selectionBridgeRef) {
connector::connector()->addWeak(selectionBridgeRef);
selectionBridgeRef->start();
}
}
install<TestBridge>();
InitBrowserControl();
}
@@ -1,8 +1,3 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/CardMover.h"
#include "Connector/Record/Model/ReceiverModelCard.h"
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER
#define CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/EverythingSendFilter.h"
namespace connector::record {
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER
#define CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h"
namespace connector::record {
@@ -7,7 +7,7 @@
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace speckle::database;
using namespace connector::record;
using namespace speckle::utility;
@@ -56,7 +56,7 @@ Cargo::Unique DirectSelectionSendFilter::getCargo(const Inventory::Item& item) c
using namespace active::serialise;
switch (item.index) {
case selectedElemID:
return std::make_unique<ContainerWrap<ElementIDList>>(m_selectedElements);
return std::make_unique<ContainerWrap<ElementIDList>>(m_selectedElements, false, fieldID[selectedElemID].name);
default:
return nullptr; //Requested an unknown index
}
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER
#define CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
namespace connector::record {
@@ -36,7 +36,7 @@ namespace connector::record {
Get the filtered element IDs
@return The filter elements
*/
const database::ElementIDList& getElementIDs() const override { return m_selectedElements; }
const speckle::database::ElementIDList& getElementIDs() const override { return m_selectedElements; }
// MARK: - Serialisation
@@ -59,7 +59,7 @@ namespace connector::record {
private:
///A list of selected element IDs
database::ElementIDList m_selectedElements;
speckle::database::ElementIDList m_selectedElements;
};
}
@@ -9,7 +9,7 @@
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace speckle::database;
using namespace connector::record;
using namespace speckle::utility;
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_EVERYTHING_SEND_FILTER
#define CONNECTOR_RECORD_EVERYTHING_SEND_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
namespace connector::record {
@@ -36,13 +36,13 @@ namespace connector::record {
Get the filtered element IDs
@return The filter elements
*/
const database::ElementIDList& getElementIDs() const override { return m_emptyList; }
const speckle::database::ElementIDList& getElementIDs() const override { return m_emptyList; }
/*!
Determine if the filter has expired because an element in the selection has changed
@param changed The list of changed element IDs
@return True if the one of the changed elements is in the selection
*/
virtual bool checkExpiry(const database::ElementIDList& changed) const override { return true; }
virtual bool checkExpiry(const speckle::database::ElementIDList& changed) const override { return true; }
// MARK: - Serialisation
@@ -65,7 +65,7 @@ namespace connector::record {
private:
///Enables a const empty list to be returned
database::ElementIDList m_emptyList;
speckle::database::ElementIDList m_emptyList;
};
}
@@ -1,8 +1,3 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/Filter/FilterMover.h"
#include "Connector/Record/Model/Filter/ArchicadEverythingFilter.h"
@@ -5,7 +5,7 @@
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace speckle::database;
using namespace connector::record;
using namespace speckle::utility;
@@ -3,7 +3,7 @@
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/Cloner.h"
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Utility/String.h"
namespace connector::record {
@@ -59,13 +59,13 @@ namespace connector::record {
Get the filtered element IDs
@return The filter elements
*/
virtual const database::ElementIDList& getElementIDs() const = 0;
virtual const speckle::database::ElementIDList& getElementIDs() const = 0;
/*!
Determine if the filter has expired because an element in the selection has changed
@param changed The list of changed element IDs
@return True if the one of the changed elements is in the selection
*/
virtual bool checkExpiry(const database::ElementIDList& changed) const;
virtual bool checkExpiry(const speckle::database::ElementIDList& changed) const;
// MARK: - Serialisation
@@ -6,7 +6,7 @@
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace speckle::database;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::utility;
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_RECEIVER_MODEL_CARD
#define CONNECTOR_RECORD_RECEIVER_MODEL_CARD
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Connector/Record/Model/ModelCard.h"
namespace connector::record {
@@ -37,7 +37,7 @@ namespace connector::record {
const speckle::database::RecordID& modelID, const speckle::utility::String& modelName,
const speckle::database::RecordID& selectedVersion, const speckle::database::RecordID& latestVersion,
const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL,
bool hasDimissedWarning, database::ElementIDList&& bakedObjects, const SettingList& settings) :
bool hasDimissedWarning, speckle::database::ElementIDList&& bakedObjects, const SettingList& settings) :
ModelCard{modelID, projectID, accountID, serverURL, settings},
m_projectName{projectName}, m_modelName{modelName}, m_selectedVersionID{selectedVersion}, m_latestVersionID{latestVersion},
m_hasDismissedUpdateWarning{hasDimissedWarning}, m_bakedObjectIDs{bakedObjects} {}
@@ -78,7 +78,7 @@ namespace connector::record {
Get the IDs of objects accepted in the receive
@return The accepted object IDs
*/
const database::ElementIDList& getBakedObjectIDs() const { return m_bakedObjectIDs; }
const speckle::database::ElementIDList& getBakedObjectIDs() const { return m_bakedObjectIDs; }
// MARK: - Serialisation
@@ -111,7 +111,7 @@ namespace connector::record {
///True if the user has already dismissed an alert to update
bool m_hasDismissedUpdateWarning = false;
///IDs of objects accepted in the receive
database::ElementIDList m_bakedObjectIDs;
speckle::database::ElementIDList m_bakedObjectIDs;
};
}
@@ -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
@@ -85,6 +85,22 @@ BIMLinkList BIMElementDatabase::getSelection() const {
} //BIMElementDatabase::getSelection
/*--------------------------------------------------------------------
Set the element selection
--------------------------------------------------------------------*/
void BIMElementDatabase::setSelection(const BIMLinkList& elementIDs) const {
m_engine->setSelection(elementIDs);
} //BIMElementDatabase::setSelection
/*--------------------------------------------------------------------
Clear the element selection
--------------------------------------------------------------------*/
void BIMElementDatabase::clearSelection() const {
m_engine->clearSelection();
} //BIMElementDatabase::clearSelection
/*--------------------------------------------------------------------
Get a specified element
@@ -41,6 +41,14 @@ namespace speckle::database {
@return A list of selected element IDs
*/
BIMLinkList getSelection() const;
/*!
Set the element selection
*/
void setSelection(const BIMLinkList& elementIDs) const;
/*!
Clear the element selection
*/
void clearSelection() const;
/*!
Get a specified element
@param elementID The ID of the target element
@@ -0,0 +1,129 @@
#include "Speckle/Database/BIMGroupDatabase.h"
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.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 GroupDatabaseEngine = ArchicadGroupDBaseEngine;
#endif
///Group database engine declaration
class BIMGroupDatabase::Engine : public GroupDatabaseEngine {
using base = ArchicadGroupDBaseEngine;
using base::base;
};
///Group database storage declaration
class BIMGroupDatabase::Store : public Storage<Group, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID> {
using base = Storage<Group, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID>;
using base::base;
};
}
namespace {
///The database storage identifier for groups
const char* groupDBaseName = "speckle::database::BIMGroupDatabase";
///The primary groups table
const char* groupTableName = "Groups";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
BIMGroupDatabase::BIMGroupDatabase() {
m_engine = std::make_shared<Engine>(groupDBaseName,
//Schema
DBaseSchema{active::utility::String{groupDBaseName},
//Tables
{
//Model group table
{
groupTableName, 0, 0, {}
}
}
}
);
m_store = std::make_shared<Store>(m_engine);
} //BIMGroupDatabase::BIMGroupDatabase
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
BIMGroupDatabase::~BIMGroupDatabase() {}
/*--------------------------------------------------------------------
Get a specified group
groupID: The ID of the target group
return: The requested group (nullptr on failure)
--------------------------------------------------------------------*/
Group::Unique BIMGroupDatabase::getGroup(const BIMRecordID& groupID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_engine->getObject(groupID, tableID, documentID);
} //BIMGroupDatabase::getGroup
/*--------------------------------------------------------------------
Get a specified group
link: A link to the target group
return: The requested group (nullptr on failure)
--------------------------------------------------------------------*/
Group::Unique BIMGroupDatabase::getGroup(const BIMLink& link) const {
return getGroup(link, link.tableID, link.docID);
} //BIMGroupDatabase::getGroup
/*--------------------------------------------------------------------
Get all groups
return: All the groups
--------------------------------------------------------------------*/
Vector<Group> BIMGroupDatabase::getGroups() const {
return m_store->getObjects();
} //BIMGroupDatabase::getGroups
/*--------------------------------------------------------------------
Write an group to storage
group: The group to write
--------------------------------------------------------------------*/
void BIMGroupDatabase::write(const Group& group) const {
m_store->write(group);
} //BIMGroupDatabase::write
/*--------------------------------------------------------------------
Erase an group
groupID: The ID of the group to erase
--------------------------------------------------------------------*/
void BIMGroupDatabase::erase(const Guid& groupID) const {
m_store->erase(groupID);
} //BIMGroupDatabase::erase
@@ -0,0 +1,77 @@
#ifndef CONNECTOR_DATABASE_BIM_GROUP_DATABASE
#define CONNECTOR_DATABASE_BIM_GROUP_DATABASE
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Property/Group.h"
#include "Speckle/Utility/Guid.h"
namespace active::event {
class Subscriber;
}
namespace speckle::database {
/*!
Database of group templates relating to a specific project
Note that this database manages just the group templates, not the values. Group values are attached to elements
*/
class BIMGroupDatabase {
public:
// MARK: - Constructors
/*!
Constructor
*/
BIMGroupDatabase();
BIMGroupDatabase(const BIMGroupDatabase&) = delete;
/*!
Destructor
*/
~BIMGroupDatabase();
// MARK: - Functions (const)
/*!
Get a specified group
@param groupID The ID of the target group
@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 group (nullptr on failure)
*/
record::property::Group::Unique getGroup(const BIMRecordID& groupID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get a specified group
@param link A link to the target group
@return The requested group (nullptr on failure)
*/
record::property::Group::Unique getGroup(const BIMLink& link) const;
/*!
Get all model groups
@return All the groups
*/
active::container::Vector<record::property::Group> getGroups() const;
/*!
Write an group to storage
@param group The group to write
*/
void write(const record::property::Group& group) const;
/*!
Erase an group
@param groupID The ID of the group to erase
*/
void erase(const speckle::utility::Guid& groupID) const;
private:
class Engine;
class Store;
///Model group database storage
std::shared_ptr<Engine> m_engine;
std::shared_ptr<Store> m_store;
};
}
#endif //CONNECTOR_DATABASE_BIM_GROUP_DATABASE
@@ -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 properties table
const char* propertyTableName = "Properties";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
BIMPropertyDatabase::BIMPropertyDatabase() {
m_engine = std::make_shared<Engine>(propertyDBaseName,
//Schema
DBaseSchema{active::utility::String{propertyDBaseName},
//Tables
{
//Model property table
{
propertyTableName, 0, 0, {}
}
}
}
);
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
@@ -62,7 +62,7 @@ namespace speckle::database {
Get a link to the BIM record
@return The BIM record link
*/
BIMLink getBIMLink() const { return BIMLink{ BIMLink::base{m_applicationID, m_applicationTableID} }; }
BIMLink getBIMLink() const { return BIMLink{ BIMLink::base {m_applicationID, m_applicationTableID} }; }
/*!
Get the record unit type
@return The record unit type (nullopt if the record has no applicable unit type)
+2 -2
View File
@@ -37,13 +37,13 @@ namespace speckle::database {
*/
virtual ~Record() {}
// MARK: - Functions (const)
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required, but "Base" is still considered a type on its own)
*/
virtual speckle::utility::String getSpeckleType() const { return "speckle::database::Record"; }
virtual speckle::utility::String getSpeckleType() const { return "Base"; }
// MARK: - Functions (mutating)
@@ -13,6 +13,12 @@ using namespace speckle::utility;
BIMLink::BIMLink(const API_Neig& selected, const BIMRecordID& tableID) : base{Guid{selected.guid}, tableID} {
//More info should be extracted from API_Neig in future (as required) - extract into link settings, e.g. selection target etc
} //Link::Link
BIMLinkList::BIMLinkList(const ElementIDList& elementIDList) {
for (const auto& id : elementIDList)
push_back(id);
}
#endif
+13 -1
View File
@@ -4,6 +4,7 @@
#include "Active/Setting/SettingList.h"
#include "Active/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace speckle::database {
@@ -41,7 +42,18 @@ namespace speckle::database {
};
//A list of links to BIM records
using BIMLinkList = std::vector<BIMLink>;
//using BIMLinkList = std::vector<BIMLink>;
class BIMLinkList : public std::vector<BIMLink> {
public:
using base = std::vector<BIMLink>;
using base::base;
BIMLinkList() = default;
BIMLinkList(const ElementIDList& elementIDList);
};
}
@@ -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>;
}
@@ -2,6 +2,7 @@
#define SPECKLE_DATABASE_ID
#include "Speckle/Utility/String.h"
#include "Speckle/Utility/Guid.h"
namespace speckle::database {
@@ -14,6 +15,12 @@ namespace speckle::database {
//A list of record IDs
using RecordIDList = std::vector<RecordID>;
//BIM element record identifier
using ElementID = speckle::utility::Guid;
//A list of element IDs
using ElementIDList = std::vector<ElementID>;
}
@@ -7,7 +7,6 @@
#include "Active/Setting/SettingList.h"
#include "Active/Database/Storage/DBaseSchema.h"
#include "Active/Utility/NameID.h"
#include "Speckle/Event/Subscriber/DocStoreSubscriber.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
namespace speckle::database {
@@ -19,7 +18,7 @@ namespace speckle::database {
Currently implement for Archicad Add-On Objects
*/
class ArchicadDBaseCore {
class ArchicadDBaseCore : public event::ProjectSubscriber {
public:
// MARK: - Types
@@ -69,8 +68,12 @@ namespace speckle::database {
// MARK: - Functions (mutating)
protected:
/*!
Handle a project event
@param event The project event
@return True if the event should be closed
*/
bool handle(const event::ProjectEvent& event) override { return false; }
private:
///The database schema
@@ -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)} {
@@ -295,3 +296,24 @@ std::optional<BIMRecordID> ArchicadAttributeDBaseEngine::getStoreyID(short index
return std::nullopt;
} //ArchicadAttributeDBaseEngine::getStoreyID
#endif
/*--------------------------------------------------------------------
Handle a project event
event: The project event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool ArchicadAttributeDBaseEngine::handle(const event::ProjectEvent& event) {
using enum ProjectEvent::Type;
switch (event.getType()) {
case newDocument: case newAndReset: case open: case close: case quit:
//Reset the storey cache on any event that changes the active project
m_storeyCache.reset();
break;
default:
break;
}
return false;
} //ArchicadAttributeDBaseEngine::handle
@@ -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;
@@ -134,6 +135,15 @@ namespace speckle::database {
*/
std::optional<BIMRecordID> getStoreyID(short index) const;
#endif
// 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:
void setTable(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt);
@@ -12,7 +12,9 @@
#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/GenericModelElement.h"
#include "Speckle/Record/Element/Beam.h"
#include "Speckle/Record/Element/BeamSegment.h"
#include "Speckle/Record/Element/Memo.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
@@ -76,11 +78,14 @@ namespace {
return std::make_unique<Column>(elementData, tableID);
case API_ColumnSegmentID:
return std::make_unique<ColumnSegment>(elementData, tableID);
case API_BeamID:
return std::make_unique<Beam>(elementData, tableID);
case API_BeamSegmentID:
return std::make_unique<BeamSegment>(elementData, tableID);
default:
return std::make_unique<GenericElement>(elementData, tableID);
return std::make_unique<GenericModelElement>(elementData, tableID);
}
}
}
/*--------------------------------------------------------------------
@@ -118,6 +123,27 @@ BIMLinkList ArchicadElementDBaseEngine::getSelection() const {
} //ArchicadElementDBaseEngine::getSelection
/*--------------------------------------------------------------------
Set the element selection
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::setSelection(const BIMLinkList& elementIDs) const {
GS::Array<API_Neig> selNeigs;
for (const auto elemID : elementIDs) {
API_Neig neig(elemID);
selNeigs.Push(neig);
}
ACAPI_Selection_Select(selNeigs, true);
} //ArchicadElementDBaseEngine::setSelection
/*--------------------------------------------------------------------
Clear the element selection
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::clearSelection() const {
ACAPI_Selection_DeselectAll();
} //ArchicadElementDBaseEngine::clearSelection
/*--------------------------------------------------------------------
Get an object by index
@@ -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;
@@ -57,6 +58,14 @@ namespace speckle::database {
@return A list of selected element IDs
*/
BIMLinkList getSelection() const;
/*!
Set the element selection
*/
void setSelection(const BIMLinkList& elementIDs) const;
/*!
Clear the element selection
*/
void clearSelection() const;
/*!
Get an object by index
@param objID The object ID
@@ -0,0 +1,232 @@
#include "Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.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>
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 group object
@param groupData The API group representation
@return A new group object (nullptr on failure)
*/
Group::Shared makeGroup(const API_PropertyGroup& groupData) {
//NB: This function has been written to allow for the future possibility of different methods for constructing a group and/or
//failure to make one
return std::make_shared<Group>(groupData);
}
}
namespace speckle::database {
class ArchicadGroupDBaseEngine::Cache : public std::unordered_map<Guid, std::shared_ptr<Group>> {
public:
/*!
Default constructor
*/
Cache() { rebuild(); }
/*!
Rebuild the property group cache
*/
void rebuild() {
//Request all Archicad group groups
GS::Array<API_PropertyGroup> groups;
if (auto err = ACAPI_Property_GetPropertyGroups(groups); err != NoError)
return;
//Populate the group cache from the collected groups
for (auto iter = groups.Begin(); iter != groups.End(); ++iter)
if (auto propGroup = makeGroup(*iter); propGroup)
insert({propGroup->getBIMID(), propGroup});
}
};
}
/*--------------------------------------------------------------------
Constructor
id: The document storage identifier
schema: The document storage schema
--------------------------------------------------------------------*/
ArchicadGroupDBaseEngine::ArchicadGroupDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) :
ArchicadDBaseCore{id, std::move(schema)} {
} //ArchicadGroupDBaseEngine::ArchicadGroupDBaseEngine
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ArchicadGroupDBaseEngine::~ArchicadGroupDBaseEngine() {
} //ArchicadGroupDBaseEngine::~ArchicadGroupDBaseEngine
/*--------------------------------------------------------------------
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<Group> ArchicadGroupDBaseEngine::getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
if (!validateCache() || (tableID && (tableID != Group::propertyGroupTableID)))
return nullptr;
if (auto found = m_cache->find(objID); found != m_cache->end())
return std::make_unique<Group>(*found->second);
return nullptr;
} //ArchicadGroupDBaseEngine::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 ArchicadGroupDBaseEngine::getObjectCargo(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return nullptr; //TODO: Implement
} //ArchicadGroupDBaseEngine::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<Group> ArchicadGroupDBaseEngine::getObjects(std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadGroupDBaseEngine::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<Group> ArchicadGroupDBaseEngine::getObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadGroupDBaseEngine::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 ArchicadGroupDBaseEngine::write(const Group& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID,
std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadGroupDBaseEngine::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 ArchicadGroupDBaseEngine::erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadGroupDBaseEngine::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 ArchicadGroupDBaseEngine::erase(std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadGroupDBaseEngine::erase
/*--------------------------------------------------------------------
Get the database outline
return: The database outline
--------------------------------------------------------------------*/
ArchicadGroupDBaseEngine::Outline ArchicadGroupDBaseEngine::getOutline() const {
return {}; //TODO: Implement
} //ArchicadGroupDBaseEngine::getOutline
/*--------------------------------------------------------------------
Handle a project event
event: The project event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool ArchicadGroupDBaseEngine::handle(const event::ProjectEvent& event) {
using enum ProjectEvent::Type;
switch (event.getType()) {
case newDocument: case newAndReset: case open: case close: case quit:
//Reset the group cache on any event that changes the active project
m_cache.reset();
break;
default:
break;
}
return false;
} //ArchicadGroupDBaseEngine::handle
/*--------------------------------------------------------------------
Ensure the cache is current
return: True if the cache contains valid te groups
--------------------------------------------------------------------*/
bool ArchicadGroupDBaseEngine::validateCache() const {
if (!m_cache)
m_cache = std::make_unique<Cache>();
return !m_cache->empty();
} //ArchicadGroupDBaseEngine::validateCache
#endif //ARCHICAD
@@ -0,0 +1,136 @@
#ifndef SPECKLE_DATABASE_ARCHICAD_GROUP_DBASE_ENGINE
#define SPECKLE_DATABASE_ARCHICAD_GROUP_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/Group.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 groups in an Archicad project database (local file or cloud-based)
Property groups can be attached to property templates to support collections of types linked to a specific role
*/
class ArchicadGroupDBaseEngine : public ArchicadDBaseCore,
public active::database::DBaseEngine<record::property::Group, BIMRecordID, BIMRecordID, BIMRecordID> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<record::property::Group, BIMRecordID, BIMRecordID, BIMRecordID>;
using Group = record::property::Group;
using Filter = base::Filter;
using Outline = base::Outline;
// MARK: - Constructors
/*!
Constructor
@param id The document storage identifier
@param schema The document storage schema
*/
ArchicadGroupDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema);
ArchicadGroupDBaseEngine(const ArchicadGroupDBaseEngine&) = delete;
/*!
Destructor
*/
~ArchicadGroupDBaseEngine();
// MARK: - Functions (const)
/*!
Get an object by ID
@param objID The object ID
@param tableID Optional table ID (default selected based on record type)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested object (nullptr on failure)
*/
std::unique_ptr<Group> 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 (default selected based on record type)
@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 (default selected based on record type)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The requested objects (nullptr on failure)
*/
active::container::Vector<Group> 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 (default selected based on record type)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The filtered objects (nullptr on failure)
*/
active::container::Vector<Group> 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 (default selected based on record type)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
void write(const Group& 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 (default selected based on record type)
@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 (default selected based on record type)
@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_GROUP_DBASE_ENGINE
@@ -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 && (tableID != Template::propertyTemplateTableID)))
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 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 (default selected based on record type)
@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 (default selected based on record type)
@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 (default selected based on record type)
@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 (default selected based on record type)
@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 (default selected based on record type)
@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 (default selected based on record type)
@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 (default selected based on record type)
@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
+5 -1
View File
@@ -2,6 +2,8 @@
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Database/BIMGroupDatabase.h"
#include "Speckle/Database/BIMPropertyDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/SpeckleResource.h"
@@ -23,8 +25,10 @@ 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_group = std::make_unique<BIMGroupDatabase>();
m_property = std::make_unique<BIMPropertyDatabase>();
} //Project::Project
+21 -5
View File
@@ -7,6 +7,8 @@
namespace speckle::database {
class BIMAttributeDatabase;
class BIMElementDatabase;
class BIMGroupDatabase;
class BIMPropertyDatabase;
}
namespace speckle::environment {
@@ -59,12 +61,22 @@ namespace speckle::environment {
Get the account database
@return The account database
*/
const database::BIMAttributeDatabase* getAttributeDatabase() const { return m_attribute.get(); }
/*!
Get the element database
@return The element database
*/
const database::BIMElementDatabase* getElementDatabase() const { return m_element.get(); }
/*!
Get the account database
@return The account database
Get the group database
@return The group database
*/
const database::BIMAttributeDatabase* getAttributeDatabase() const { return m_attribute.get(); }
const database::BIMGroupDatabase* getGroupDatabase() const { return m_group.get(); }
/*!
Get the property database
@return The property database
*/
const database::BIMPropertyDatabase* getPropertyDatabase() const { return m_property.get(); }
// MARK: - Functions (mutating)
@@ -79,10 +91,14 @@ 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 group database
std::unique_ptr<database::BIMGroupDatabase> m_group;
///The BIM property database
std::unique_ptr<database::BIMPropertyDatabase> m_property;
};
}
@@ -126,7 +126,12 @@ namespace speckle::interfac::browser::bridge {
@return The number of parameters
*/
uint32_t parameterCount() const override { return Params; }
};
/*!
Set to the default package content
*/
void setDefault() override { T::setDefault(); }
};
}
@@ -30,6 +30,21 @@ namespace {
}
/*--------------------------------------------------------------------
Append a single face to the Mesh given by the vertices
--------------------------------------------------------------------*/
void Mesh::appendFace(const std::vector<double>& vertices) {
if (vertices.empty())
return;
m_vertices.insert(m_vertices.end(), vertices.begin(), vertices.end());
int lastVertexIndex = m_faces.empty() ? -1 : m_faces.back();
int faceSize = static_cast<int>(vertices.size() / 3);
m_faces.push_back(faceSize);
for (size_t i = 0; i < faceSize; i++)
m_faces.push_back(++lastVertexIndex);
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
+16 -1
View File
@@ -29,10 +29,19 @@ namespace speckle::primitive {
Mesh(active::measure::LengthType unit = active::measure::LengthType::metre) : base{utility::Guid{true}, utility::Guid{}, unit} {}
/*!
Constructor
@param unit The mesh unit type
@param material The mesh material
*/
Mesh(const ModelerAPI::Material& material,
active::measure::LengthType unit = active::measure::LengthType::metre) :
base{ utility::Guid{true}, utility::Guid{}, unit }, m_material{ material } {}
/*!
Constructor
@param unit The mesh unit type
@param vertices The mesh vertices
@param faces The mesh faces (the number of indices in the face followed by the vertex indices)
@param colors The mesh face colours
@param unit The mesh unit type
@param material The mesh material
*/
Mesh(std::vector<double>&& vertices, std::vector<int>&& faces, std::vector<int>&& colors, const ModelerAPI::Material& material,
active::measure::LengthType unit = active::measure::LengthType::metre) :
@@ -45,6 +54,12 @@ namespace speckle::primitive {
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "Objects.Geometry.Mesh"; }
/*!
Append a single face to the Mesh given by the vertices
@param vertices The vertices to append
*/
void appendFace(const std::vector<double>& vertices);
// MARK: - Serialisation
@@ -62,11 +62,6 @@ namespace speckle::record::attribute {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::record::attribute::Attribute"; }
/*!
Get the attribute name
@return The attribute name
@@ -67,11 +67,6 @@ namespace speckle::record::attribute {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::record::attribute::Storey"; }
#ifdef ARCHICAD
/*!
Get the (immutable) API attribute header data
@@ -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
+174
View File
@@ -0,0 +1,174 @@
#include "Speckle/Record/Element/Beam.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 Beam::Data {
public:
friend class Beam;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_BeamType>(elem.beam) } {}
Data(const Data& source) : root{ std::make_unique<API_BeamType>(*source.root) } {}
#endif
private:
std::unique_ptr<API_BeamType> root;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
segmentID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"segments"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Beam::Beam() {
} //Beam::Beam
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The element table ID (AC database, e.g. floor plan, 3D)
--------------------------------------------------------------------*/
Beam::Beam(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //Beam::Beam
#endif
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Beam::Beam(const Beam& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //Beam::Beam
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
Beam::~Beam() {}
#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& Beam::getHead() const {
return m_data->root->head;
} //Beam::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& Beam::getHead() {
return m_data->root->head;
} //Beam::getHead
/*--------------------------------------------------------------------
Load the element memo structure (elements must override according to requirements)
filter: Filter bits specifying memo requirements
--------------------------------------------------------------------*/
void Beam::loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const {
//Establish the memo filter for this element
if (!SegmentedBeam::isMemoLoaded())
filter |= SegmentedBeam::getPartFilter();
ModelElement::loadMemo(filter, memo);
//Receive the memo data into the element (when available)
if (memo) {
if (filter & SegmentedBeam::getPartFilter())
SegmentedBeam::receive(*memo);
}
SegmentedBeam::setMemoLoaded(true); //Always mark the data as loaded to prevent repeated attempts on error
} //Beam::loadMemo
#endif
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Beam::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[segmentID], segmentID, getSegmentCount(), std::nullopt }, //TODO: implement other fields
},
}.withType(&typeid(Beam)));
return base::fillInventory(inventory);
} //Beam::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Beam::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Beam))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case segmentID:
if (auto segment = getSegment(item.available); segment != nullptr) {
return Cargo::Unique{new PackageWrap{*segment}};
} else
return nullptr;
default:
return nullptr; //Requested an unknown index
}
} //Beam::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Beam::setDefault() {
base::setDefault();
m_data.reset();
} //Beam::setDefault
+137
View File
@@ -0,0 +1,137 @@
#ifndef SPECKLE_RECORD_ELEMENT_BEAM
#define SPECKLE_RECORD_ELEMENT_BEAM
#include "Speckle/Record/Element/BeamSegment.h"
#include "Speckle/Record/Element/ModelElement.h"
#include "Speckle/Record/Element/Interface/Assembly/Path.h"
#include "Speckle/Record/Element/Interface/SegmentedBeam.h"
namespace speckle::record::element {
class BeamSegment;
/*!
BIM beam class
*/
class Beam : public ModelElement, public SegmentedBeam, public assembly::Path {
public:
// MARK: - Types
using base = ModelElement;
///Unique pointer
using Unique = std::unique_ptr<Beam>;
///Shared pointer
using Shared = std::shared_ptr<Beam>;
///Optional
using Option = std::optional<Beam>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Beam();
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The beam element ID (AC database, e.g. floor plan, 3D)
*/
Beam(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
Beam(const Beam& source);
/*!
Destructor
*/
~Beam();
/*!
Object cloning
@return A clone of this object
*/
Beam* clonePtr() const override { return new Beam{*this}; }
// MARK: - Functions (const)
/*!
Get the BIM application parent table ID
@return The BIM table ID
*/
virtual database::BIMRecordID getTableID() const override { return ModelElement::getTableID(); }
/*!
Get the element body
@return nullptr (Beams don't explicitly have a 3D body - this comes from its child segments)
*/
virtual Body* getBody() const override { return nullptr; }
/*!
Get the number of segments in the path (elements must override according to requirements)
@return The segment count
*/
virtual size_t getSegmentCount() const override { return SegmentedBeam::getSegmentCount(); }
/*!
Get a segment from the path (elements must override according to requirements)
@param index The index of the required segment
@return The requested segment (nullptr on failure)
*/
virtual BeamSegment* getSegment(size_t index) const override { return SegmentedBeam::getSegment(index); }
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
const API_Elem_Head& getHead() const override;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
API_Elem_Head& getHead() override;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
protected:
/*!
Load the element memo structure (elements must override according to requirements)
@param filter Filter bits specifying memo requirements
*/
virtual void loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const override;
private:
class Data;
///The beam data
std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ELEMENT_BEAM
@@ -0,0 +1,159 @@
#include "Speckle/Record/Element/BeamSegment.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 <ACAPinc.h>
#endif
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 BeamSegment::Data {
public:
friend class BeamSegment;
#ifdef ARCHICAD
Data(const API_BeamSegmentType& seg) : root{ std::make_unique<API_BeamSegmentType>(seg) } {}
Data(const Data& source) : root{ std::make_unique<API_BeamSegmentType>(*source.root) } {}
private:
std::unique_ptr<API_BeamSegmentType> root;
#endif
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
BeamSegment::BeamSegment() {
} //BeamSegment::BeamSegment
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The element table ID (AC database, e.g. floor plan, 3D)
--------------------------------------------------------------------*/
BeamSegment::BeamSegment(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData.beamSegment);
} //BeamSegment::BeamSegment
/*--------------------------------------------------------------------
Constructor
segment: The segment element data
tableID: The parent table ID
cutOrigin: Cut at the segment origin
cutEnd: Cut at the segment end
scheme: The segment scheme
profile: The segment profile (nullptr = none)
--------------------------------------------------------------------*/
BeamSegment::BeamSegment(const API_BeamSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin,
const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme,
const API_AssemblySegmentProfileData* profile) :
base{segment.head.guid, tableID}, assembly::Segment{cutOrigin, cutEnd, scheme, profile} {
m_data = std::make_unique<Data>(segment);
} //BeamSegment::BeamSegment
#endif
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
BeamSegment::BeamSegment(const BeamSegment& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*source.m_data) : nullptr;
} //BeamSegment::BeamSegment
/*--------------------------------------------------------------------
Move constructor
source: The object to move
--------------------------------------------------------------------*/
BeamSegment::BeamSegment(BeamSegment&& source) noexcept : base{source} {
m_data = std::move(source.m_data);
} //BeamSegment::BeamSegment
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
BeamSegment::~BeamSegment() {}
#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& BeamSegment::getHead() const {
return m_data->root->head;
} //BeamSegment::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& BeamSegment::getHead() {
return m_data->root->head;
} //BeamSegment::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 BeamSegment::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
//TODO: Implement other fields as required
return base::fillInventory(inventory);
} //BeamSegment::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique BeamSegment::getCargo(const Inventory::Item& item) const {
//TODO: Implement other fields as required
return base::getCargo(item);
} //BeamSegment::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void BeamSegment::setDefault() {
m_data.reset();
} //BeamSegment::setDefault
@@ -0,0 +1,130 @@
#ifndef SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
#define SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
#include "Speckle/Record/Element/ModelElement.h"
#include "Speckle/Record/Element/Interface/Assembly/Segment.h"
namespace speckle::record::element {
class SegmentedBeam;
/*!
BIM beam class
*/
class BeamSegment : public ModelElement, public assembly::Segment {
public:
// MARK: - Types
using base = ModelElement;
///Unique pointer
using Unique = std::unique_ptr<BeamSegment>;
///Shared pointer
using Shared = std::shared_ptr<BeamSegment>;
///Optional
using Option = std::optional<BeamSegment>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
BeamSegment();
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
*/
BeamSegment(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
BeamSegment(const BeamSegment& source);
/*!
Move constructor
@param source The object to move
*/
BeamSegment(BeamSegment&& source) noexcept;
/*!
Destructor
*/
~BeamSegment();
/*!
Object cloning
@return A clone of this object
*/
BeamSegment* clonePtr() const override { return new BeamSegment{*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)
*/
const API_Elem_Head& getHead() const override;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
API_Elem_Head& getHead() override;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
protected:
friend class SegmentedBeam;
#ifdef ARCHICAD
/*!
Constructor
@param segment The segment element data
@param tableID The parent table ID
@param cutOrigin Cut at the segment origin
@param cutEnd Cut at the segment end
@param scheme The segment scheme
@param profile The segment profile (nullptr = none)
*/
BeamSegment(const API_BeamSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin,
const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme,
const API_AssemblySegmentProfileData* profile = nullptr);
#endif
private:
class Data;
///The beam data
std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
+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 -9
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
@@ -61,16 +61,11 @@ namespace speckle::record::element {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.Column"; }
/*!
Get the BIM application parent table ID
@return The BIM table ID
*/
virtual database::BIMRecordID getTableID() const override { return Element::getTableID(); }
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)
@@ -82,7 +82,7 @@ ColumnSegment::ColumnSegment(const API_ColumnSegmentType& segment, const speckle
source: The object to copy
--------------------------------------------------------------------*/
ColumnSegment::ColumnSegment(const ColumnSegment& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
m_data = source.m_data ? std::make_unique<Data>(*source.m_data) : nullptr;
} //ColumnSegment::ColumnSegment
@@ -91,7 +91,7 @@ ColumnSegment::ColumnSegment(const ColumnSegment& source) : base{ source } {
source: The object to move
--------------------------------------------------------------------*/
ColumnSegment::ColumnSegment(ColumnSegment&& source) : base{source} {
ColumnSegment::ColumnSegment(ColumnSegment&& source) noexcept : base{source} {
m_data = std::move(source.m_data);
} //ColumnSegment::ColumnSegment
@@ -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
@@ -49,7 +49,7 @@ namespace speckle::record::element {
Move constructor
@param source The object to move
*/
ColumnSegment(ColumnSegment&& source);
ColumnSegment(ColumnSegment&& source) noexcept;
/*!
Destructor
*/
@@ -64,11 +64,6 @@ namespace speckle::record::element {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.ColumnSegment"; }
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@@ -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,39 +28,34 @@ 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)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
virtual speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.GenericElement:Objects.BuiltElements.GenericElement"; }
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@@ -109,4 +101,4 @@ namespace speckle::record::element {
}
#endif //SPECKLE_RECORD_GENERIC_ELEMENT
#endif //SPECKLE_RECORD_DISPLAY_ELEMENT
@@ -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
}
} //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
@@ -64,11 +61,6 @@ namespace speckle::record::element {
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
virtual speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.Element"; }
/*!
Get the elmeent type name, e.g. "Wall", "Roof" etc
@return The type name
@@ -79,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
@@ -127,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,160 @@
#include "Speckle/Record/Element/Interface/SegmentedBeam.h"
#include "Speckle/Record/Element/BeamSegment.h"
#include "Speckle/Record/Element/Memo.h"
#include "Speckle/Record/Element/Interface/Assembly/Path.h"
#include "Speckle/Utility/BIMMemory.h"
using namespace active::serialise;
using namespace speckle::record::attribute;
using namespace speckle::record::element;
using namespace speckle::utility;
namespace speckle::record::element {
class SegmentedBeam::Data {
public:
friend class SegmentedBeam;
std::vector<BeamSegment> segments;
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
SegmentedBeam::SegmentedBeam() {
} //SegmentedBeam::SegmentedBeam
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
SegmentedBeam::SegmentedBeam(const SegmentedBeam& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //SegmentedBeam::SegmentedBeam
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
SegmentedBeam::~SegmentedBeam() {}
/*--------------------------------------------------------------------
Get the number of segments
return. The number of segments (0 on error)
--------------------------------------------------------------------*/
size_t SegmentedBeam::getSegmentCount() const {
confirmPart(getPartFilter());
return m_data ? m_data->segments.size() : 0;
} //SegmentedBeam::getSegmentCount
/*--------------------------------------------------------------------
Get a beam segment
index: The index of the required segment
return: The requested segment, nullptr on error
--------------------------------------------------------------------*/
BeamSegment* SegmentedBeam::getSegment(size_t index) const {
confirmPart(getPartFilter());
return (m_data && (index < m_data->segments.size())) ? &m_data->segments[index] : nullptr;
} //SegmentedBeam::getSegment
/*--------------------------------------------------------------------
Return the bits for the part filter required to load the data necessary to build this object
return: The required filter bits
--------------------------------------------------------------------*/
Part::filter_bits SegmentedBeam::getPartFilter() const {
#ifdef ARCHICAD
return APIMemoMask_BeamSegment | APIMemoMask_AssemblySegmentCut | APIMemoMask_AssemblySegmentScheme | APIMemoMask_AssemblySegmentProfile;
#endif
} //SegmentedBeam::getPartFilter
/*--------------------------------------------------------------------
Determine if the element memo content has been validated (elements must override according to requirements)
return: True if the element memo content is valid
--------------------------------------------------------------------*/
bool SegmentedBeam::isPartValid() const {
return m_data && !m_data->segments.empty();
} //SegmentedBeam::isPartValid
/*--------------------------------------------------------------------
Load the element memo structure (elements must override according to requirements)
filter: Filter bits specifying memo requirements
--------------------------------------------------------------------*/
void SegmentedBeam::loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const {
} //SegmentedBeam::loadMemo
/*--------------------------------------------------------------------
Send the element part back to a memo structure for storage (elements must override according to requirements)
memo: The memo to carry the data
return: True if the data was successfully sent
--------------------------------------------------------------------*/
bool SegmentedBeam::send(Memo* memo) const {
//TODO: Complete when required
return false;
} //SegmentedBeam::send
/*--------------------------------------------------------------------
Receive the element memo data from a memo structure (elements must override according to requirements)
memo: The memo carrying the data
return: True if the data was successfully received
--------------------------------------------------------------------*/
bool SegmentedBeam::receive(const Memo& memo) const {
#ifdef ARCHICAD
if (!memo || (memo.root()->beamSegments == nullptr))
return false;
if (m_data)
m_data->segments.clear();
else
m_data = std::make_unique<Data>();
//Confirm that required data is present in the memo
auto segmentPtr = memo.root()->beamSegments;
auto cutPtr = memo.root()->assemblySegmentCuts;
auto schemePtr = memo.root()->assemblySegmentSchemes;
auto profilePtr = memo.root()->assemblySegmentProfiles;
if ((segmentPtr == nullptr) || (cutPtr == nullptr) || (schemePtr == nullptr))
return false;
//Determine available item count
auto segmentCount = BIMMemory::getPtrSize(segmentPtr) / sizeof(API_BeamSegmentType);
auto cutCount = BIMMemory::getPtrSize(cutPtr) / sizeof(API_AssemblySegmentCutData);
auto schemeCount = BIMMemory::getPtrSize(schemePtr) / sizeof(API_AssemblySegmentSchemeData);
auto profileCount = BIMMemory::getPtrSize(profilePtr) / sizeof(API_AssemblySegmentProfileData);
if ((segmentCount == 0) || (cutCount != (segmentCount + 1)) || (schemeCount != segmentCount))
return false;
auto path = dynamic_cast<const assembly::Path*>(this);
for (size_t n = 0 ; n < segmentCount; ++n) {
const API_AssemblySegmentProfileData* thisProfile = nullptr;
for (size_t i = 0; i < profileCount; ++i) {
if (profilePtr[i].segmentIndex == n) {
thisProfile = profilePtr + i;
break;
}
}
m_data->segments.emplace_back(BeamSegment{segmentPtr[n], getTableID(), cutPtr[n], cutPtr[n + 1], schemePtr[n], thisProfile});
m_data->segments.back().setPath(path);
}
setMemoLoaded(true);
#endif
return true;
} //SegmentedBeam::receive
@@ -0,0 +1,103 @@
#ifndef SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
#define SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
#include "Speckle/Database/Identity/BIMRecordID.h"
#include "Speckle/Record/Element/Interface/Part.h"
namespace speckle::record::element {
class BeamSegment;
/*!
Interface for a beam type that is made up of consecutive segments
Note that the child segments use lazy loading to avoid high overheads when accessing data relevant to the parent beam only
*/
class SegmentedBeam : public Part {
public:
// MARK: - Types
using base = Part;
///Unique pointer
using Unique = std::unique_ptr<SegmentedBeam>;
///Shared pointer
using Shared = std::shared_ptr<SegmentedBeam>;
///Optional
using Option = std::optional<SegmentedBeam>;
// MARK: - Constructors
/*!
Default constructor
*/
SegmentedBeam();
/*!
Copy constructor
@param source The object to copy
*/
SegmentedBeam(const SegmentedBeam& source);
/*!
Destructor
*/
~SegmentedBeam();
// MARK: - Functions (const)
/*!
Get the BIM application parent table ID
@return The BIM table ID
*/
virtual database::BIMRecordID getTableID() const = 0;
/*!
Get the number of segments
@return The number of segments (0 on error)
*/
size_t getSegmentCount() const;
/*!
Get a beam segment
@param index The index of the required segment
@return The requested segment, nullptr on error
*/
BeamSegment* getSegment(size_t index) const;
// MARK: - Functions (mutating)
protected:
/*!
Return the bits for the part filter required to load the data necessary to build this object
@return The required filter bits */
filter_bits getPartFilter() const;
/*!
Determine if the element part content has been validated (elements must override according to requirements)
@return True if the element part content is valid
*/
bool isPartValid() const override;
/*!
Load the element memo structure (elements must override according to requirements)
@param filter Filter bits specifying memo requirements
*/
void loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const override;
/*!
Send the element part back to a memo structure for storage (elements must override according to requirements)
@param memo The memo to carry the data
@return True if the data was successfully sent
*/
bool send(Memo* memo) const override;
/*!
Receive the element memo data from a memo structure (elements must override according to requirements)
@param memo The memo carrying the data
@return True if the data was successfully received
*/
bool receive(const Memo& memo) const override;
private:
class Data;
///The segment data - mutable to support lazy loading
mutable std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
@@ -74,7 +74,9 @@ ColumnSegment* SegmentedColumn::getSegment(size_t index) const {
return: The required filter bits
--------------------------------------------------------------------*/
Part::filter_bits SegmentedColumn::getPartFilter() const {
#ifdef ARCHICAD
return APIMemoMask_ColumnSegment | APIMemoMask_AssemblySegmentCut | APIMemoMask_AssemblySegmentScheme | APIMemoMask_AssemblySegmentProfile;
#endif
} //SegmentedColumn::getPartFilter
@@ -0,0 +1,247 @@
#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/Record/Property/Wrapper/PropertiedWrapper.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::record::property;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::element {
class ModelElement::Data {
public:
friend class ModelElement;
#ifdef ARCHICAD
Data() {}
Data(const Data& source) : m_cache{std::make_unique<ModelElement::Body>(*source.m_cache)} {}
#endif
private:
std::unique_ptr<ModelElement::Body> m_cache;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
bodyID,
propertyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"displayValue"},
Identity{"properties"},
};
}
/*--------------------------------------------------------------------
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
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
ModelElement::ModelElement(const ModelElement& source) : base{source}, Classified{source}, Propertied{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_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();
// Map to collect meshes per material name
std::map<GS::UniString, primitive::Mesh> materialMeshMap;
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);
auto materialName = material.GetName();
if (materialMeshMap.find(materialName) == materialMeshMap.end()) {
materialMeshMap[materialName] = primitive::Mesh(material);
}
Int32 convexPolyCount = polygon.GetConvexPolygonCount();
for (Int32 convPolyIndex = 1; convPolyIndex <= convexPolyCount; ++convPolyIndex)
{
std::vector<double> vertices;
ModelerAPI::ConvexPolygon convexPolygon{};
polygon.GetConvexPolygon(convPolyIndex, &convexPolygon);
Int32 vertexCount = convexPolygon.GetVertexCount();
for (Int32 vertexIndex = 1; vertexIndex <= vertexCount; ++vertexIndex)
{
ModelerAPI::Vertex vertex{};
body.GetVertex(convexPolygon.GetVertexIndex(vertexIndex), &vertex);
// Collect vertices (as doubles for now, but should be changed to Vertex type)
vertices.push_back(vertex.x);
vertices.push_back(vertex.y);
vertices.push_back(vertex.z);
}
materialMeshMap[materialName].appendFace(std::move(vertices));
}
}
}
}
for (auto& [materialName, mesh] : materialMeshMap)
{
elementBody->push_back(std::move(mesh));
}
m_data = std::make_unique<Data>();
m_data->m_cache.reset(elementBody);
return m_data->m_cache.get();
#endif
} //ModelElement::getBody
/*--------------------------------------------------------------------
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 },
{ fieldID[propertyID], propertyID, element },
},
}.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;
case propertyID:
return std::make_unique<PropertiedWrapper>(*this);
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,94 @@
#ifndef SPECKLE_RECORD_MODEL_ELEMENT
#define SPECKLE_RECORD_MODEL_ELEMENT
#include "Speckle/Record/Classification/Classified.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Record/Property/Propertied.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 classify::Classified, public property::Propertied {
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);
/*!
Copy constructor
@param source The object to copy
*/
ModelElement(const ModelElement& source);
/*!
Destructor
*/
~ModelElement();
// 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;
// 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;
/*!
Set to the default package content
*/
void setDefault() override;
private:
class Data;
///The element data
mutable std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_MODEL_ELEMENT
@@ -0,0 +1,93 @@
#include "Speckle/Record/Property/Group.h"
#include "Speckle/Database/BIMPropertyDatabase.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"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Group::Group() {
} //Group::Group
/*--------------------------------------------------------------------
Constructor
ID: The template ID
--------------------------------------------------------------------*/
Group::Group(const database::BIMRecordID& ID) : base{ID, propertyGroupTableID} {
} //Group::Group
/*--------------------------------------------------------------------
Constructor
ID: The record ID
tableID: The parent table ID
unit: The record unit type
--------------------------------------------------------------------*/
Group::Group(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID) : base{ID, tableID} {
} //Group::Group
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
source: An Archicad property group to copy
--------------------------------------------------------------------*/
Group::Group(const API_PropertyGroup& source) : base{source.guid, propertyGroupTableID}, m_name(source.name), m_description(source.description) {
} //Group::Group
#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 Group::fillInventory(Inventory& inventory) const {
//Implement when required
return base::fillInventory(inventory);
} //Group::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Group::getCargo(const Inventory::Item& item) const {
//Implement when required
return base::getCargo(item);
} //Group::getCargo
+100
View File
@@ -0,0 +1,100 @@
#ifndef SPECKLE_RECORD_PROPERTY_GROUP
#define SPECKLE_RECORD_PROPERTY_GROUP
#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 group
Properties are typically associated with a group
Property groups are persisted in the BIM property database
*/
class Group : public speckle::database::BIMRecord {
public:
// MARK: - Types
using base = speckle::database::BIMRecord;
///Unique pointer
using Unique = std::unique_ptr<Group>;
///Shared pointer
using Shared = std::shared_ptr<Group>;
///Optional
using Option = std::optional<Group>;
// MARK: - Constants
///Identifier for a property group table
inline static utility::Guid propertyGroupTableID{utility::String{"cbe185dc-5011-4325-9651-1852056a04de"}};
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Group();
#ifdef ARCHICAD
/*!
Constructor
@param source An Archicad property group to copy
*/
Group(const API_PropertyGroup& source);
#endif
/*!
Constructor
@param ID The group ID
*/
Group(const database::BIMRecordID& ID);
/*!
Constructor
@param ID The record ID
@param tableID The parent table ID
*/
Group(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID);
// MARK: - Functions (const)
/*!
Get the group name
@return The group name
*/
speckle::utility::String getName() const { return m_name; }
// MARK: - Functions (mutating)
//TODO: Add methods as required
// 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:
///Name
speckle::utility::String m_name;
///Description
speckle::utility::String m_description;
};
}
#endif //SPECKLE_RECORD_PROPERTY_GROUP
@@ -0,0 +1,140 @@
#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;
/*--------------------------------------------------------------------
Get the attached properties
return: The attached properties
--------------------------------------------------------------------*/
const std::vector<Property>& Propertied::getProperties() const {
rebuild();
return *m_properties;
} //Propertied
/*--------------------------------------------------------------------
Get the number of attached properties
return: The property count
--------------------------------------------------------------------*/
Propertied::size_type Propertied::getPropertyCount() const {
rebuild();
return m_properties->size();
} //Propertied::getPropertyCount
/*--------------------------------------------------------------------
Get the number of attached properties passing a specified filter
filter: The property filter
return: The number of attached properties passing the filter
--------------------------------------------------------------------*/
Propertied::size_type Propertied::getPropertyCount(const Filter& filter) const {
rebuild();
size_type result = 0;
for (const auto& property : *m_properties)
if (filter(property))
++result;
return result;
} //Propertied::getPropertyCount
/*--------------------------------------------------------------------
Get a specified attached property
index: The index of the target property
return: The requested property
--------------------------------------------------------------------*/
const Property& Propertied::getProperty(size_type index) const {
rebuild();
return m_properties->at(index);
} //Propertied::getPropertyCount
/*--------------------------------------------------------------------
Get a specified attached property using a filter
filter: The property filter
index: The index of the target property (counting only properties passing the filter)
return: The requested property
--------------------------------------------------------------------*/
const Property& Propertied::getProperty(const Filter& filter, size_type index) const {
rebuild();
for (auto n = 0; n < m_properties->size(); ++n) {
if (filter((*m_properties)[n])) {
if (index == 0)
return (*m_properties)[n];
--index;
}
}
throw std::out_of_range("Out of bounds property access");
} //Propertied::getPropertyCount
/*--------------------------------------------------------------------
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;
#ifdef ARCHICAD
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});
}
}
#endif
return true;
} //Propertied::rebuild
@@ -0,0 +1,96 @@
#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
///Unary predicate for filtering properties
using Filter = std::function<bool(const Property&)>;
///Unique pointer
using Unique = std::unique_ptr<Propertied>;
///Shared pointer
using Shared = std::shared_ptr<Propertied>;
///Optional
using Option = std::optional<Propertied>;
///Size type for indexing etc
using size_type = typename std::size_t;
// MARK: - Constructors
/*!
Default constructor
*/
Propertied() {}
/*!
Copy constructor
@param source The object to copy
*/
Propertied(const Propertied& source) :
m_properties{source.m_properties ? std::make_unique<std::vector<Property>>(*source.m_properties) : nullptr} {}
/*!
Move constructor
@param source The object to move
*/
Propertied(Propertied&& source) noexcept : m_properties{std::move(source.m_properties)} {}
/*!
Destructor
*/
virtual ~Propertied() {}
// MARK: - Functions (const)
/*!
Get the number of attached properties
@return The property count
*/
size_type getPropertyCount() const;
/*!
Get the number of attached properties passing a specified filter
@param filter The property filter
@return The number of attached properties passing the filter
*/
size_type getPropertyCount(const Filter& filter) const;
/*!
Get a specified attached property
@param index The index of the target property
@return The requested property
*/
const Property& getProperty(size_type index) const;
/*!
Get a specified attached property using a filter
@param filter The property filter
@param index The index of the target property (counting only properties passing the filter)
@return The requested property
*/
const Property& getProperty(const Filter& filter, size_type index) 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,140 @@
#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>
/*--------------------------------------------------------------------
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
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Property::Property(const Property& source) :
m_setting{source.m_setting ? std::make_unique<Setting>(*source.m_setting) : nullptr}, m_template{source.m_template} {
} //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() {}
/*--------------------------------------------------------------------
Determine if the property has a defined value
return: True if a defined value is found
--------------------------------------------------------------------*/
bool Property::hasDefinedValue() const {
return m_setting && m_setting->hasDefinedValue();
} //Property::hasDefinedValue
/*--------------------------------------------------------------------
Determine if the property is null, e.g. zero, empty, undefined setting
return: True if the property setting is null
--------------------------------------------------------------------*/
bool Property::isNull() const {
return !m_setting || m_setting->isNull();
} //Setting::isNull
/*--------------------------------------------------------------------
Get the property name
return: The property name
--------------------------------------------------------------------*/
String Property::getName() const {
return m_template ? m_template->getName() : String{};
} //Property::getName
/*--------------------------------------------------------------------
Get the property group name. NB: This value is not cached in the object and drequires a database lookup - don't use casually
return: The property gorup name
--------------------------------------------------------------------*/
String Property::getGroupName() const {
return m_template ? m_template->getGroupName() : String{};
} //Property::getGroupName
/*--------------------------------------------------------------------
Get the property value as displayed in the UI
return: The property display value
--------------------------------------------------------------------*/
String Property::getDisplayValue() const {
return m_setting ? m_setting->getDisplayValue() : String{};
} //Property::getDisplayValue
/*--------------------------------------------------------------------
Get the property template ID
return: The property template ID (null if the property isn't linked to a template)
--------------------------------------------------------------------*/
Guid Property::getTemplateID() const {
return m_template ? m_template->getBIMID() : Guid{};
} //Property::getTemplateID
@@ -0,0 +1,118 @@
#ifndef SPECKLE_RECORD_PROPERTY
#define SPECKLE_RECORD_PROPERTY
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Utility/Guid.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:
// 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);
/*!
Copy constructor
@param source The object to copy
*/
Property(const Property& source);
/*!
Move constructor
@param source the property to move
*/
Property(Property&& source) noexcept;
/*!
Destructor
*/
~Property();
// MARK: - Functions (const)
/*!
Determine if the property has a defined value
@return True if a defined value is found
*/
bool hasDefinedValue() const;
/*!
Determine if the property is null, e.g. zero, empty, undefined setting
@return True if the property setting is null
*/
bool isNull() const;
/*!
Get the property name
@return The property name
*/
speckle::utility::String getName() const;
/*!
Get the property group name. NB: This value is not cached in the object and drequires a database lookup - don't use casually
@return The property gorup name
*/
speckle::utility::String getGroupName() const;
/*!
Get the property value as displayed in the UI
@return The property display value
*/
speckle::utility::String getDisplayValue() const;
/*!
Get the property template ID
@return The property template ID (null if the property isn't linked to a template)
*/
speckle::utility::Guid getTemplateID() const;
// MARK: - Functions (mutating)
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,144 @@
#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
/*--------------------------------------------------------------------
Determine if the setting has a defined value
return: True if a defined value is found
--------------------------------------------------------------------*/
bool Setting::hasDefinedValue() const {
for (const auto& value : m_values)
if (value.isDefined())
return true;
return false;
} //Setting::hasDefinedValue
/*--------------------------------------------------------------------
Determine if the setting is null, e.g. zero, empty, undefined
return: True if the setting is null
--------------------------------------------------------------------*/
bool Setting::isNull() const {
for (const auto& value : m_values)
if (!value.isNull())
return false;
return true;
} //Setting::isNull
/*--------------------------------------------------------------------
Get the setting value as displayed in the UI
return: The setting display value
--------------------------------------------------------------------*/
String Setting::getDisplayValue() const {
String result;
bool isFirst = true;
for (const auto& value : m_values) {
if (value.isDefined()) {
if (isFirst)
isFirst = false;
else
result += "; "; //Archicad separates value with a semi-colon - might need to revisit this in different contexts
result += value.getDisplayValue();
}
}
return result;
} //Setting::getDisplayValue
/*--------------------------------------------------------------------
Append a value to the setting
value: The value to append
--------------------------------------------------------------------*/
void Setting::append(Value&& value) {
m_values.emplace_back(value);
} //Setting::append
#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,154 @@
#ifndef SPECKLE_RECORD_PROPERTY_SETTING
#define SPECKLE_RECORD_PROPERTY_SETTING
#include "Speckle/Record/Property/Value.h"
#include "Speckle/Utility/String.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)
/*!
Determine if the setting is empty, i.e. has no values
@return True if the setting is empty
*/
bool empty() const { return m_values.empty(); }
/*!
Determine if the setting has a defined value
@return True if a defined value is found
*/
bool hasDefinedValue() const;
/*!
Determine if the setting is null, e.g. zero, empty, undefined
@return True if the setting is null
*/
bool isNull() const;
/*!
Get the setting value as displayed in the UI
@return The setting display value
*/
speckle::utility::String getDisplayValue() const;
// MARK: - Functions (mutating)
/*!
Append a value to the setting
@param value The value to append
*/
void append(Value&& value);
#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,266 @@
#include "Speckle/Record/Property/Template.h"
#include "Speckle/Database/BIMGroupDatabase.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, propertyTemplateTableID} {
} //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, propertyTemplateTableID},
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
/*--------------------------------------------------------------------
Get the property group name. NB: This value is not cached in the object and drequires a database lookup - don't use casually
return: The property gorup name
--------------------------------------------------------------------*/
String Template::getGroupName() const {
String result;
if (auto group = getGroup(); group)
result = group->getName();
return result;
} //Template::getGroupName
/*--------------------------------------------------------------------
Get the template group. NB: This value is not cached in the object and drequires a database lookup - don't use casually
return: The template group (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Group> Template::getGroup() const {
auto project = addon()->getActiveProject().lock();
return (project) ? project->getGroupDatabase()->getGroup(m_group) : nullptr;
} //Template::getGroup
#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:
return setting.receive(value.singleVariant, API_VariantStatusNormal, measure);
case Type::singleEnum:
if (auto enumValue = findEnumValue(Value{value.singleVariant.variant, API_VariantStatusNormal, measure}); enumValue) {
setting.append(std::move(*enumValue));
return true;
}
return false;
case Type::array:
return setting.receive(value.listVariant, API_VariantStatusNormal, measure);
case Type::arrayEnum:
for (const auto& val : value.listVariant.variants) {
if (auto enumValue = findEnumValue(Value{val, API_VariantStatusNormal, measure}); enumValue)
setting.append(std::move(*enumValue));
}
return !setting.empty();
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
/*--------------------------------------------------------------------
Find an enumerated value by key
key: The value key
return: The enum value paired with the specified key (nullopt on failure)
--------------------------------------------------------------------*/
Value::Option Template::findEnumValue(const Value& key) const {
if (key.getValue() != nullptr) {
if (auto iter = std::find_if(m_enumValues.begin(), m_enumValues.end(), [&key](const auto& value){
if (value.getKey() == nullptr)
return false;
return *key.getValue() == *value.getKey();
}); iter != m_enumValues.end())
return *iter;
}
return std::nullopt;
} //Template::findEnumValue
/*--------------------------------------------------------------------
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,214 @@
#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 Group;
class Setting;
/*!
Class defining the characteristics of a property template
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 template table
inline static utility::Guid propertyTemplateTableID{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 template group ID
@return The template group ID
*/
speckle::utility::String getGroupID() const { return m_group; }
/*!
Get the template group name. NB: This value is not cached in the object and drequires a database lookup - don't use casually
@return The template group name
*/
speckle::utility::String getGroupName() const;
/*!
Get the template group. NB: This value is not cached in the object and drequires a database lookup - don't use casually
@return The template group (nullptr on failure)
*/
std::unique_ptr<Group> getGroup() const;
/*!
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;
/*!
Find an enumerated value by key
@param key The value key
@return The enum value paired with the specified key (nullopt on failure)
*/
Value::Option findEnumValue(const Value& key) 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 measurement 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,211 @@
#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"
#include <array>
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);
break;
case API_PropertyRealValueType: {
//Ensure measured values are an appropriate type
switch (measure) {
case API_PropertyLengthMeasureType:
result = std::make_unique<active::setting::LengthValue>(source.doubleValue);
break;
case API_PropertyAreaMeasureType:
result = std::make_unique<active::setting::AreaValue>(source.doubleValue);
break;
case API_PropertyVolumeMeasureType:
result = std::make_unique<active::setting::VolumeValue>(source.doubleValue);
break;
case API_PropertyAngleMeasureType:
result = std::make_unique<active::setting::AngleValue>(source.doubleValue);
break;
default:
result = std::make_unique<active::setting::DoubleValue>(source.doubleValue);
break;
}
}
case API_PropertyStringValueType:
result = std::make_unique<active::setting::StringValue>(String{source.uniStringValue});
break;
case API_PropertyBooleanValueType:
result = std::make_unique<active::setting::BoolValue>(source.boolValue);
break;
case API_PropertyGuidValueType:
result = std::make_unique<active::setting::GuidValue>(Guid{source.guidValue});
break;
default:
result = std::make_unique<active::setting::NullValue>(); //TODO: Is this a possible/valid outcome?
break;
}
//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=
/*--------------------------------------------------------------------
Get the value as displayed in the UI
return: The value as displayed
--------------------------------------------------------------------*/
String Value::getDisplayValue() const {
return m_value ? m_value->operator active::utility::String() : String{};
} //Value::getDisplayValue
#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
+156
View File
@@ -0,0 +1,156 @@
#ifndef SPECKLE_RECORD_PROPERTY_VALUE
#define SPECKLE_RECORD_PROPERTY_VALUE
#include "Active/Setting/Values/Value.h"
#include "Speckle/Utility/String.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)
/*!
Determine if the value is defined (and good)
@return True if the value is defined
*/
bool isDefined() const { return m_value && (m_value->status == active::setting::Value::good); }
/*!
Determine if the value is null, e.g. zero, empty, undefined
@return True if the value is null
*/
virtual bool isNull() const { return !m_value || m_value->isNull(); }
/*!
Get the value as displayed in the UI
@return The value as displayed
*/
speckle::utility::String getDisplayValue() 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
@@ -0,0 +1,77 @@
#include "Speckle/Record/Property/Wrapper/PropertiedWrapper.h"
#include "Speckle/Record/Property/Propertied.h"
#include "Speckle/Record/Property/Wrapper/PropertyWrapper.h"
#include "Speckle/Utility/String.h"
#include <array>
using namespace active::serialise;
using namespace speckle::record::property;
using namespace speckle::utility;
using enum Entry::Type;
namespace {
///The indices of the package items
enum FieldIndex {
propertiesID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"Properties"},
};
}
/*--------------------------------------------------------------------
Constructor
propertied: Reference to a propertied object
--------------------------------------------------------------------*/
PropertiedWrapper::PropertiedWrapper(const Propertied& propertied) {
//Serialise only properties with a defined value
for (const auto& property : propertied.getProperties()) {
if (!property.isNull())
m_properties.push_back(std::reference_wrapper{const_cast<Property&>(property)});
}
} //PropertiedWrapper::PropertiedWrapper
/*--------------------------------------------------------------------
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 PropertiedWrapper::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[propertiesID], propertiesID, m_properties.size(), std::nullopt },
},
}.withType(&typeid(PropertiedWrapper)));
return true;
} //PropertiedWrapper::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique PropertiedWrapper::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(PropertiedWrapper))
return nullptr;
switch (item.index) {
case FieldIndex::propertiesID:
if (item.available < m_properties.size())
return std::make_unique<PropertyWrapper>(m_properties[item.available].get());
default:
return nullptr; //Requested an unknown index
}
} //PropertiedWrapper::getCargo
@@ -0,0 +1,50 @@
#ifndef SPECKLE_RECORD_PROPERTY_PROPERTIED_WRAPPER
#define SPECKLE_RECORD_PROPERTY_PROPERTIED_WRAPPER
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/String.h"
namespace speckle::record::property {
class Property;
class Propertied;
/*!
Wrapper for (de)seriliasing the contents of the Archicad Properties and Classification tab
*/
class PropertiedWrapper : public active::serialise::Package {
public:
// MARK: - Constructor
/*!
Constructor
@param propertied Reference to a propertied object
*/
PropertiedWrapper(const Propertied& propertied);
// MARK: - Functions (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:
using PropertyList = std::vector<std::reference_wrapper<Property>>;
//The wrapped properties
PropertyList m_properties;
};
}
#endif //SPECKLE_RECORD_PROPERTY_PROPERTIED_WRAPPER
@@ -0,0 +1,101 @@
#include "Speckle/Record/Property/Wrapper/PropertyWrapper.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Speckle/Record/Property/Property.h"
#include <array>
using namespace active::serialise;
using namespace speckle::record::property;
using namespace speckle::utility;
using enum Entry::Type;
namespace {
///Serialisation fields
enum FieldIndex {
nameID,
groupID,
valueID,
applicID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"name"},
Identity{"group"},
Identity{"value"},
Identity{"applicationID"},
};
}
// MARK: - Constructors
/*--------------------------------------------------------------------
Constructor
point: The point to wrap for (de)serialisation
--------------------------------------------------------------------*/
PropertyWrapper::PropertyWrapper(const Property& property) :
m_name{property.getName()}, m_groupName{property.getGroupName()}, m_displayValue{property.getDisplayValue()}, m_ID{property.getTemplateID()} {
} //PropertyWrapper::PropertyWrapper
/*--------------------------------------------------------------------
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 PropertyWrapper::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[nameID], nameID, element },
{ fieldID[groupID], groupID, element, !m_groupName.empty() },
{ fieldID[valueID], valueID, element },
{ fieldID[applicID], applicID, element, m_ID.operator bool() },
},
}.withType(&typeid(PropertyWrapper)));
return true;
} //PropertyWrapper::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique PropertyWrapper::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(PropertyWrapper))
return nullptr;
switch (item.index) {
case FieldIndex::nameID:
return std::make_unique<StringWrap>(m_name);
case FieldIndex::groupID:
return std::make_unique<StringWrap>(m_groupName);
case FieldIndex::valueID:
return std::make_unique<StringWrap>(m_displayValue);
case FieldIndex::applicID:
return std::make_unique<ValueWrap<Guid>>(m_ID);
default:
return nullptr; //Requested an unknown index
}
} //PropertyWrapper::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void PropertyWrapper::setDefault() {
m_name.clear();
m_groupName.clear();
m_displayValue.clear();
m_ID.clear();
} //PropertyWrapper::setDefault
@@ -0,0 +1,60 @@
#ifndef SPECKLE_RECORD_PROPERTY_WRAPPER
#define SPECKLE_RECORD_PROPERTY_WRAPPER
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
namespace speckle::record::property {
class Property;
/*!
Wrapper for (de)seriliasing the a property
*/
class PropertyWrapper : public active::serialise::Package {
public:
// MARK: - Constructor
/*!
Constructor
@param property Reference to a property object
*/
PropertyWrapper(const Property& property);
// MARK: - Functions (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;
//TODO: Add validation when we need to deserialise properties
private:
//The property name
utility::String m_name;
//The property group name
utility::String m_groupName;
//The property value (as displayed)
utility::String m_displayValue;
//The property (template) ID
utility::Guid m_ID;
};
}
#endif //SPECKLE_RECORD_PROPERTY_WRAPPER
@@ -0,0 +1,78 @@
#include "Speckle/Record/Property/Wrapper/PropsAndClassWrapper.h"
#include "Speckle/Record/Property/Wrapper/PropertiedWrapper.h"
#include "Speckle/Utility/String.h"
#include <array>
using namespace active::serialise;
using namespace speckle::record::property;
using namespace speckle::utility;
using enum Entry::Type;
namespace {
///The indices of the package items
enum FieldIndex {
propertiesID,
classificationID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"Classification"},
Identity{"Properties"},
};
} // namespace
// MARK: - Constructors
/*--------------------------------------------------------------------
Constructor
point: The point to wrap for (de)serialisation
--------------------------------------------------------------------*/
PropsAndClassWrapper::PropsAndClassWrapper(const Propertied& propertied) : m_property(const_cast<Propertied&>(propertied)) {}
/*--------------------------------------------------------------------
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 PropsAndClassWrapper::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[propertiesID], propertiesID, element },
//TODO: Implement object classifications
//{ fieldID[classificationID], classificationID, element },
},
}.withType(&typeid(PropsAndClassWrapper)));
return true;
} //PropsAndClassWrapper::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique PropsAndClassWrapper::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(PropsAndClassWrapper))
return nullptr;
switch (item.index) {
case FieldIndex::propertiesID:
return std::make_unique<PropertiedWrapper>(m_property.get());
case FieldIndex::classificationID:
return nullptr; //TODO: Implement object classifications
default:
return nullptr; //Requested an unknown index
}
} //PropsAndClassWrapper::getCargo
@@ -0,0 +1,47 @@
#ifndef SPECKLE_RECORD_PROPERTY_CLASS_WRAPPER
#define SPECKLE_RECORD_PROPERTY_CLASS_WRAPPER
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/String.h"
namespace speckle::record::property {
class Propertied;
/*!
Wrapper for (de)seriliasing the contents of the Archicad Properties and Classification tab
*/
class PropsAndClassWrapper : public active::serialise::Package {
public:
// MARK: - Constructor
/*!
Constructor
@param propertied Reference to a propertied object
*/
PropsAndClassWrapper(const Propertied& propertied);
// MARK: - Functions (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:
//Wrapper for the Properties section
std::reference_wrapper<Propertied> m_property;
};
}
#endif //SPECKLE_RECORD_PROPERTY_CLASS_WRAPPER
@@ -71,7 +71,7 @@ Cargo::Unique DetachedReference::getCargo(const Inventory::Item& item) const {
if (!m_reference)
throw; //TODO: Throw a more descriptive exception
}
std::make_unique<StringWrap>(*m_reference);
return std::make_unique<StringWrap>(*m_reference);
}
case speckTypeID:
return std::make_unique<StringWrap>(m_type);
+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
+201 -9
View File
@@ -66,9 +66,49 @@
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 */; };
21AE197B2CC7CE1A004DBCFC /* PropsAndClassWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19762CC7CE1A004DBCFC /* PropsAndClassWrapper.cpp */; };
21AE197C2CC7CE1A004DBCFC /* PropsAndClassWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19772CC7CE1A004DBCFC /* PropsAndClassWrapper.h */; };
21AE197F2CC7D265004DBCFC /* PropertiedWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE197D2CC7D265004DBCFC /* PropertiedWrapper.cpp */; };
21AE19802CC7D265004DBCFC /* PropertiedWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE197E2CC7D265004DBCFC /* PropertiedWrapper.h */; };
21AE19832CC7D517004DBCFC /* PropertyWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19812CC7D517004DBCFC /* PropertyWrapper.cpp */; };
21AE19842CC7D517004DBCFC /* PropertyWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19822CC7D517004DBCFC /* PropertyWrapper.h */; };
21AE19872CC7FF5F004DBCFC /* Group.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19852CC7FF5F004DBCFC /* Group.h */; };
21AE19882CC7FF5F004DBCFC /* Group.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19862CC7FF5F004DBCFC /* Group.cpp */; };
21AE198F2CC80541004DBCFC /* ArchicadGroupDBaseEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE198D2CC80541004DBCFC /* ArchicadGroupDBaseEngine.h */; };
21AE19902CC80541004DBCFC /* ArchicadGroupDBaseEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE198E2CC80541004DBCFC /* ArchicadGroupDBaseEngine.cpp */; };
21AE19932CC82866004DBCFC /* BIMGroupDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19912CC82866004DBCFC /* BIMGroupDatabase.cpp */; };
21AE19942CC82866004DBCFC /* BIMGroupDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19922CC82866004DBCFC /* BIMGroupDatabase.h */; };
21AE19A72CC8F1F8004DBCFC /* Beam.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19A12CC8F1F8004DBCFC /* Beam.cpp */; };
21AE19A82CC8F1F8004DBCFC /* BeamSegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19A42CC8F1F8004DBCFC /* BeamSegment.cpp */; };
21AE19A92CC8F1F8004DBCFC /* Beam.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19A52CC8F1F8004DBCFC /* Beam.h */; };
21AE19AA2CC8F1F8004DBCFC /* BeamSegment.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19A62CC8F1F8004DBCFC /* BeamSegment.h */; };
21AE19AD2CC8F214004DBCFC /* SegmentedBeam.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AE19AB2CC8F214004DBCFC /* SegmentedBeam.h */; };
21AE19AE2CC8F214004DBCFC /* SegmentedBeam.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AE19AC2CC8F214004DBCFC /* SegmentedBeam.cpp */; };
21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */; };
21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */; };
21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */; };
@@ -226,9 +266,49 @@
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>"; };
21AE19762CC7CE1A004DBCFC /* PropsAndClassWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropsAndClassWrapper.cpp; sourceTree = "<group>"; };
21AE19772CC7CE1A004DBCFC /* PropsAndClassWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropsAndClassWrapper.h; sourceTree = "<group>"; };
21AE197D2CC7D265004DBCFC /* PropertiedWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertiedWrapper.cpp; sourceTree = "<group>"; };
21AE197E2CC7D265004DBCFC /* PropertiedWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertiedWrapper.h; sourceTree = "<group>"; };
21AE19812CC7D517004DBCFC /* PropertyWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyWrapper.cpp; sourceTree = "<group>"; };
21AE19822CC7D517004DBCFC /* PropertyWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyWrapper.h; sourceTree = "<group>"; };
21AE19852CC7FF5F004DBCFC /* Group.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Group.h; sourceTree = "<group>"; };
21AE19862CC7FF5F004DBCFC /* Group.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Group.cpp; sourceTree = "<group>"; };
21AE198D2CC80541004DBCFC /* ArchicadGroupDBaseEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadGroupDBaseEngine.h; sourceTree = "<group>"; };
21AE198E2CC80541004DBCFC /* ArchicadGroupDBaseEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchicadGroupDBaseEngine.cpp; sourceTree = "<group>"; };
21AE19912CC82866004DBCFC /* BIMGroupDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMGroupDatabase.cpp; sourceTree = "<group>"; };
21AE19922CC82866004DBCFC /* BIMGroupDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMGroupDatabase.h; sourceTree = "<group>"; };
21AE19A12CC8F1F8004DBCFC /* Beam.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Beam.cpp; sourceTree = "<group>"; };
21AE19A42CC8F1F8004DBCFC /* BeamSegment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BeamSegment.cpp; sourceTree = "<group>"; };
21AE19A52CC8F1F8004DBCFC /* Beam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Beam.h; sourceTree = "<group>"; };
21AE19A62CC8F1F8004DBCFC /* BeamSegment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BeamSegment.h; sourceTree = "<group>"; };
21AE19AB2CC8F214004DBCFC /* SegmentedBeam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SegmentedBeam.h; sourceTree = "<group>"; };
21AE19AC2CC8F214004DBCFC /* SegmentedBeam.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentedBeam.cpp; 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>"; };
@@ -376,14 +456,24 @@
215F087A2CA18E1400CD343B /* Element */ = {
isa = PBXGroup;
children = (
21AE19A12CC8F1F8004DBCFC /* Beam.cpp */,
21AE19A52CC8F1F8004DBCFC /* Beam.h */,
21AE19A42CC8F1F8004DBCFC /* BeamSegment.cpp */,
21AE19A62CC8F1F8004DBCFC /* BeamSegment.h */,
21A0FBE82CBD6B1A0023F24E /* Column.cpp */,
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 +488,7 @@
215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */,
2196F2EA2CB4816B00450DFC /* Attribute */,
219246062CA2D22D00CF5703 /* Element */,
21A890C12CC171D80087E732 /* Property */,
);
path = ArchicadDBase;
sourceTree = "<group>";
@@ -552,6 +643,8 @@
21A0FC032CBE59A80023F24E /* Assembly */,
21A0FC102CBEE5C30023F24E /* Part.cpp */,
21A0FBE42CBD6B1A0023F24E /* Part.h */,
21AE19AC2CC8F214004DBCFC /* SegmentedBeam.cpp */,
21AE19AB2CC8F214004DBCFC /* SegmentedBeam.h */,
21A0FBFF2CBE59A80023F24E /* SegmentedColumn.cpp */,
21A0FC002CBE59A80023F24E /* SegmentedColumn.h */,
);
@@ -569,6 +662,59 @@
path = Assembly;
sourceTree = "<group>";
};
21A890C12CC171D80087E732 /* Property */ = {
isa = PBXGroup;
children = (
21AE198E2CC80541004DBCFC /* ArchicadGroupDBaseEngine.cpp */,
21AE198D2CC80541004DBCFC /* ArchicadGroupDBaseEngine.h */,
21A890BF2CC171D80087E732 /* ArchicadPropertyDBaseEngine.cpp */,
21A890C02CC171D80087E732 /* ArchicadPropertyDBaseEngine.h */,
);
path = Property;
sourceTree = "<group>";
};
21AE194E2CC273F1004DBCFC /* Property */ = {
isa = PBXGroup;
children = (
21AE19862CC7FF5F004DBCFC /* Group.cpp */,
21AE19852CC7FF5F004DBCFC /* Group.h */,
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 */,
21AE19782CC7CE1A004DBCFC /* Wrapper */,
);
path = Property;
sourceTree = "<group>";
};
21AE196D2CC64D37004DBCFC /* Classification */ = {
isa = PBXGroup;
children = (
21AE196B2CC64D37004DBCFC /* Classified.cpp */,
21AE196C2CC64D37004DBCFC /* Classified.h */,
);
path = Classification;
sourceTree = "<group>";
};
21AE19782CC7CE1A004DBCFC /* Wrapper */ = {
isa = PBXGroup;
children = (
21AE197D2CC7D265004DBCFC /* PropertiedWrapper.cpp */,
21AE197E2CC7D265004DBCFC /* PropertiedWrapper.h */,
21AE19812CC7D517004DBCFC /* PropertyWrapper.cpp */,
21AE19822CC7D517004DBCFC /* PropertyWrapper.h */,
21AE19762CC7CE1A004DBCFC /* PropsAndClassWrapper.cpp */,
21AE19772CC7CE1A004DBCFC /* PropsAndClassWrapper.h */,
);
path = Wrapper;
sourceTree = "<group>";
};
21AEF9C72CA818EA000B8681 /* Detached */ = {
isa = PBXGroup;
children = (
@@ -601,6 +747,10 @@
2196F2F72CB51ED400450DFC /* BIMAttributeDatabase.h */,
215F08932CA19AF800CD343B /* BIMElementDatabase.cpp */,
215F08942CA19AF800CD343B /* BIMElementDatabase.h */,
21AE19912CC82866004DBCFC /* BIMGroupDatabase.cpp */,
21AE19922CC82866004DBCFC /* BIMGroupDatabase.h */,
21AE19632CC2F702004DBCFC /* BIMPropertyDatabase.cpp */,
21AE19642CC2F702004DBCFC /* BIMPropertyDatabase.h */,
21D0BD272C86FC350077E104 /* Content */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BDB02C8F8AB60077E104 /* Storage */,
@@ -736,8 +886,10 @@
isa = PBXGroup;
children = (
2196F2EF2CB4823C00450DFC /* Attribute */,
215F087A2CA18E1400CD343B /* Element */,
21AE196D2CC64D37004DBCFC /* Classification */,
21F69F942C71087A008B6A06 /* Credentials */,
215F087A2CA18E1400CD343B /* Element */,
21AE194E2CC273F1004DBCFC /* Property */,
);
path = Record;
sourceTree = "<group>";
@@ -777,24 +929,32 @@
files = (
21A0FBF42CBD6B700023F24E /* Memo.h in Headers */,
215F088C2CA195EC00CD343B /* ArchicadDBaseCore.h in Headers */,
21AE19AD2CC8F214004DBCFC /* SegmentedBeam.h in Headers */,
21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */,
21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */,
21A0FBB52CBA5E380023F24E /* Str256.h in Headers */,
210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */,
21AE19872CC7FF5F004DBCFC /* Group.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 */,
21AE19A92CC8F1F8004DBCFC /* Beam.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 */,
21AE19802CC7D265004DBCFC /* PropertiedWrapper.h in Headers */,
21A0FC0B2CBE5E220023F24E /* Segment.h in Headers */,
215F088D2CA195EC00CD343B /* ArchicadElementDBaseEngine.h in Headers */,
2196F2F42CB483D600450DFC /* Finish.h in Headers */,
@@ -804,19 +964,31 @@
21D0BD2C2C86FC350077E104 /* Record.h in Headers */,
21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */,
215F087E2CA18E1400CD343B /* Element.h in Headers */,
21AE197C2CC7CE1A004DBCFC /* PropsAndClassWrapper.h in Headers */,
2196F2F92CB51ED400450DFC /* BIMAttributeDatabase.h in Headers */,
215F08562C99DA8D00CD343B /* Project.h in Headers */,
219245FF2CA2CC4300CF5703 /* BIMRecord.h in Headers */,
210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */,
21AE198F2CC80541004DBCFC /* ArchicadGroupDBaseEngine.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 */,
21AE19AA2CC8F1F8004DBCFC /* BeamSegment.h in Headers */,
21AE19942CC82866004DBCFC /* BIMGroupDatabase.h in Headers */,
21AE19542CC273F1004DBCFC /* Template.h in Headers */,
21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */,
21AE19842CC7D517004DBCFC /* PropertyWrapper.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;
@@ -947,12 +1119,16 @@
21F69FA62C733EDA008B6A06 /* BridgeArgument.cpp in Sources */,
21F69F682C6DFB01008B6A06 /* RunMethod.cpp in Sources */,
21F69F812C6FF3B0008B6A06 /* BridgeArgumentWrap.cpp in Sources */,
21AE197F2CC7D265004DBCFC /* PropertiedWrapper.cpp in Sources */,
215F088B2CA195EC00CD343B /* ArchicadDBaseCore.cpp in Sources */,
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */,
2196F2F02CB4823C00450DFC /* Attribute.cpp in Sources */,
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */,
215F08662C9B006800CD343B /* ProjectEvent.cpp in Sources */,
21AE19932CC82866004DBCFC /* BIMGroupDatabase.cpp in Sources */,
21AE19A72CC8F1F8004DBCFC /* Beam.cpp in Sources */,
21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */,
21AE197B2CC7CE1A004DBCFC /* PropsAndClassWrapper.cpp in Sources */,
21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */,
219246082CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp in Sources */,
2196F2E32CB05BAF00450DFC /* LengthUnit.cpp in Sources */,
@@ -960,10 +1136,15 @@
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 */,
21AE19902CC80541004DBCFC /* ArchicadGroupDBaseEngine.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 */,
21AE19A82CC8F1F8004DBCFC /* BeamSegment.cpp in Sources */,
21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */,
21A0FC062CBE59A80023F24E /* Path.cpp in Sources */,
2196F2F52CB483D600450DFC /* Finish.cpp in Sources */,
@@ -971,24 +1152,35 @@
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 */,
21AE19832CC7D517004DBCFC /* PropertyWrapper.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 */,
21AE19882CC7FF5F004DBCFC /* Group.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 */,
21AE19AE2CC8F214004DBCFC /* SegmentedBeam.cpp in Sources */,
21F69F962C71087A008B6A06 /* Account.cpp in Sources */,
21A0FBF82CBDB9A70023F24E /* BIMMemory.cpp in Sources */,
21A0FBF52CBD6B700023F24E /* Memo.cpp in Sources */,
+42 -2
View File
@@ -22,6 +22,8 @@
<ClInclude Include="Speckle\Database\AccountDatabase.h" />
<ClInclude Include="Speckle\Database\BIMAttributeDatabase.h" />
<ClInclude Include="Speckle\Database\BIMElementDatabase.h" />
<ClInclude Include="Speckle\Database\BIMGroupDatabase.h" />
<ClInclude Include="Speckle\Database\BIMPropertyDatabase.h" />
<ClInclude Include="Speckle\Database\Content\BIMRecord.h" />
<ClInclude Include="Speckle\Database\Content\Record.h" />
<ClInclude Include="Speckle\Database\Identity\BIMIndex.h" />
@@ -32,6 +34,8 @@
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Property\ArchicadGroupDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Property\ArchicadPropertyDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreEngine.h" />
<ClInclude Include="Speckle\Environment\Addon.h" />
@@ -67,19 +71,35 @@
<ClInclude Include="Speckle\Record\Attribute\Attribute.h" />
<ClInclude Include="Speckle\Record\Attribute\Finish.h" />
<ClInclude Include="Speckle\Record\Attribute\Storey.h" />
<ClInclude Include="Speckle\Record\Classification\Classified.h" />
<ClInclude Include="Speckle\Record\Credentials\Account.h" />
<ClInclude Include="Speckle\Record\Credentials\ServerInfo.h" />
<ClInclude Include="Speckle\Record\Credentials\ServerMigration.h" />
<ClInclude Include="Speckle\Record\Credentials\UserInfo.h" />
<ClInclude Include="Speckle\Record\Element\Beam.h" />
<ClInclude Include="Speckle\Record\Element\BeamSegment.h" />
<ClInclude Include="Speckle\Record\Element\Column.h" />
<ClInclude Include="Speckle\Record\Element\ColumnSegment.h" />
<ClInclude Include="Speckle\Record\Element\DrawingElement.h" />
<ClInclude Include="Speckle\Record\Element\Element.h" />
<ClInclude Include="Speckle\Record\Element\GenericElement.h" />
<ClInclude Include="Speckle\Record\Element\GenericDrawingElement.h" />
<ClInclude Include="Speckle\Record\Element\GenericModelElement.h" />
<ClInclude Include="Speckle\Record\Element\Interface\Assembly\Path.h" />
<ClInclude Include="Speckle\Record\Element\Interface\Assembly\Segment.h" />
<ClInclude Include="Speckle\Record\Element\Interface\Part.h" />
<ClInclude Include="Speckle\Record\Element\Interface\SegmentedBeam.h" />
<ClInclude Include="Speckle\Record\Element\Interface\SegmentedColumn.h" />
<ClInclude Include="Speckle\Record\Element\Memo.h" />
<ClInclude Include="Speckle\Record\Element\ModelElement.h" />
<ClInclude Include="Speckle\Record\Property\Group.h" />
<ClInclude Include="Speckle\Record\Property\Propertied.h" />
<ClInclude Include="Speckle\Record\Property\Property.h" />
<ClInclude Include="Speckle\Record\Property\Setting.h" />
<ClInclude Include="Speckle\Record\Property\Template.h" />
<ClInclude Include="Speckle\Record\Property\Value.h" />
<ClInclude Include="Speckle\Record\Property\Wrapper\PropertiedWrapper.h" />
<ClInclude Include="Speckle\Record\Property\Wrapper\PropertyWrapper.h" />
<ClInclude Include="Speckle\Record\Property\Wrapper\PropsAndClassWrapper.h" />
<ClInclude Include="Speckle\Serialise\Collection\FinishCollector.h" />
<ClInclude Include="Speckle\Serialise\Collection\FinishProxy.h" />
<ClInclude Include="Speckle\Serialise\Detached\DetachedReference.h" />
@@ -103,12 +123,16 @@
<ClCompile Include="Speckle\Database\AccountDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMAttributeDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMElementDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMGroupDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMPropertyDatabase.cpp" />
<ClCompile Include="Speckle\Database\Content\BIMRecord.cpp" />
<ClCompile Include="Speckle\Database\Content\Record.cpp" />
<ClCompile Include="Speckle\Database\Identity\BIMLink.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Property\ArchicadGroupDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Property\ArchicadPropertyDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.cpp" />
<ClCompile Include="Speckle\Environment\Addon.cpp" />
<ClCompile Include="Speckle\Environment\Platform.cpp" />
@@ -129,19 +153,35 @@
<ClCompile Include="Speckle\Record\Attribute\Attribute.cpp" />
<ClCompile Include="Speckle\Record\Attribute\Finish.cpp" />
<ClCompile Include="Speckle\Record\Attribute\Storey.cpp" />
<ClCompile Include="Speckle\Record\Classification\Classified.cpp" />
<ClCompile Include="Speckle\Record\Credentials\Account.cpp" />
<ClCompile Include="Speckle\Record\Credentials\ServerInfo.cpp" />
<ClCompile Include="Speckle\Record\Credentials\ServerMigration.cpp" />
<ClCompile Include="Speckle\Record\Credentials\UserInfo.cpp" />
<ClCompile Include="Speckle\Record\Element\Beam.cpp" />
<ClCompile Include="Speckle\Record\Element\BeamSegment.cpp" />
<ClCompile Include="Speckle\Record\Element\Column.cpp" />
<ClCompile Include="Speckle\Record\Element\ColumnSegment.cpp" />
<ClCompile Include="Speckle\Record\Element\DrawingElement.cpp" />
<ClCompile Include="Speckle\Record\Element\Element.cpp" />
<ClCompile Include="Speckle\Record\Element\GenericElement.cpp" />
<ClCompile Include="Speckle\Record\Element\GenericDrawingElement.cpp" />
<ClCompile Include="Speckle\Record\Element\GenericModelElement.cpp" />
<ClCompile Include="Speckle\Record\Element\Interface\Assembly\Path.cpp" />
<ClCompile Include="Speckle\Record\Element\Interface\Assembly\Segment.cpp" />
<ClCompile Include="Speckle\Record\Element\Interface\Part.cpp" />
<ClCompile Include="Speckle\Record\Element\Interface\SegmentedBeam.cpp" />
<ClCompile Include="Speckle\Record\Element\Interface\SegmentedColumn.cpp" />
<ClCompile Include="Speckle\Record\Element\Memo.cpp" />
<ClCompile Include="Speckle\Record\Element\ModelElement.cpp" />
<ClCompile Include="Speckle\Record\Property\Group.cpp" />
<ClCompile Include="Speckle\Record\Property\Propertied.cpp" />
<ClCompile Include="Speckle\Record\Property\Property.cpp" />
<ClCompile Include="Speckle\Record\Property\Setting.cpp" />
<ClCompile Include="Speckle\Record\Property\Template.cpp" />
<ClCompile Include="Speckle\Record\Property\Value.cpp" />
<ClCompile Include="Speckle\Record\Property\Wrapper\PropertiedWrapper.cpp" />
<ClCompile Include="Speckle\Record\Property\Wrapper\PropertyWrapper.cpp" />
<ClCompile Include="Speckle\Record\Property\Wrapper\PropsAndClassWrapper.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachedReference.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachedWrap.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachmentManager.cpp" />

Some files were not shown because too many files have changed in this diff Show More