diff --git a/SpeckleConnector/Connector.vcxproj b/SpeckleConnector/Connector.vcxproj
index 96f0cbf..33d1e1d 100644
--- a/SpeckleConnector/Connector.vcxproj
+++ b/SpeckleConnector/Connector.vcxproj
@@ -175,6 +175,8 @@
+
+
@@ -206,6 +208,7 @@
+
@@ -234,6 +237,8 @@
+
+
@@ -268,6 +273,7 @@
+
diff --git a/SpeckleConnector/Connector.vcxproj.filters b/SpeckleConnector/Connector.vcxproj.filters
index 2e2ca28..bf46e71 100644
--- a/SpeckleConnector/Connector.vcxproj.filters
+++ b/SpeckleConnector/Connector.vcxproj.filters
@@ -74,6 +74,12 @@
{1d9a10c3-cac6-4b15-afb9-f117b99b3a24}
+
+ {896b7b9b-61d8-46e7-8432-cfbdab4918fb}
+
+
+ {f9330e8f-8242-4605-b25c-b1ba24451825}
+
@@ -98,9 +104,6 @@
-
- Connector
-
Connector\Interface
@@ -260,6 +263,18 @@
Connector\Interface\Browser\Bridge\Config
+
+ Connector\Interface\Browser\Bridge\Receive
+
+
+ Connector\Interface\Browser\Bridge\Receive
+
+
+ Connector\Tool
+
+
+ Connector
+
@@ -445,5 +460,14 @@
Connector\Interface\Browser\Bridge\Config
+
+ Connector\Interface\Browser\Bridge\Receive
+
+
+ Connector\Interface\Browser\Bridge\Receive
+
+
+ Connector\Tool
+
\ No newline at end of file
diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj
index ee9d1a3..9236dd6 100644
--- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj
+++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj
@@ -726,6 +726,18 @@
21CE9B7B2CE627640076522F /* GSProfiler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CE9AEE2CE627640076522F /* GSProfiler.framework */; };
21CE9B7C2CE627640076522F /* VBAttributeList.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CE9AEF2CE627640076522F /* VBAttributeList.framework */; };
21CE9B7D2CE627640076522F /* Property.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21CE9AF02CE627640076522F /* Property.framework */; };
+ 21CE9B832CE69A230076522F /* Receive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B7E2CE69A230076522F /* Receive.cpp */; };
+ 21CE9B842CE69A230076522F /* Receive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B7E2CE69A230076522F /* Receive.cpp */; };
+ 21CE9B852CE69A230076522F /* Receive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B7E2CE69A230076522F /* Receive.cpp */; };
+ 21CE9B862CE69A230076522F /* Receive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B7E2CE69A230076522F /* Receive.cpp */; };
+ 21CE9B872CE69A230076522F /* ReceiveBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */; };
+ 21CE9B882CE69A230076522F /* ReceiveBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */; };
+ 21CE9B892CE69A230076522F /* ReceiveBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */; };
+ 21CE9B8A2CE69A230076522F /* ReceiveBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */; };
+ 21CE9B8E2CE75CFC0076522F /* ElementHighlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */; };
+ 21CE9B8F2CE75CFC0076522F /* ElementHighlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */; };
+ 21CE9B902CE75CFC0076522F /* ElementHighlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */; };
+ 21CE9B912CE75CFC0076522F /* ElementHighlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */; };
21D0BD602C89BFEA0077E104 /* SendBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD5B2C89BFEA0077E104 /* SendBridge.cpp */; };
21D0BD672C89D7410077E104 /* AccountTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD642C89D7400077E104 /* AccountTests.cpp */; };
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD682C8A0DB40077E104 /* GetIsDevMode.cpp */; };
@@ -1445,6 +1457,12 @@
21CE9AEE2CE627640076522F /* GSProfiler.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GSProfiler.framework; path = "../../Archicad 26/Support/Frameworks/GSProfiler.framework"; sourceTree = ""; };
21CE9AEF2CE627640076522F /* VBAttributeList.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VBAttributeList.framework; path = "../../Archicad 26/Support/Frameworks/VBAttributeList.framework"; sourceTree = ""; };
21CE9AF02CE627640076522F /* Property.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Property.framework; path = "../../Archicad 26/Support/Frameworks/Property.framework"; sourceTree = ""; };
+ 21CE9B7E2CE69A230076522F /* Receive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Receive.cpp; sourceTree = ""; };
+ 21CE9B7F2CE69A230076522F /* Receive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Receive.h; sourceTree = ""; };
+ 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReceiveBridge.cpp; sourceTree = ""; };
+ 21CE9B812CE69A230076522F /* ReceiveBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReceiveBridge.h; sourceTree = ""; };
+ 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ElementHighlighter.cpp; sourceTree = ""; };
+ 21CE9B8C2CE75CFC0076522F /* ElementHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementHighlighter.h; sourceTree = ""; };
21D0BD5B2C89BFEA0077E104 /* SendBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendBridge.cpp; sourceTree = ""; };
21D0BD5C2C89BFEA0077E104 /* SendBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendBridge.h; sourceTree = ""; };
21D0BD642C89D7400077E104 /* AccountTests.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = AccountTests.cpp; sourceTree = ""; };
@@ -2785,6 +2803,26 @@
name = Archicad28;
sourceTree = "";
};
+ 21CE9B822CE69A230076522F /* Receive */ = {
+ isa = PBXGroup;
+ children = (
+ 21CE9B7E2CE69A230076522F /* Receive.cpp */,
+ 21CE9B7F2CE69A230076522F /* Receive.h */,
+ 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */,
+ 21CE9B812CE69A230076522F /* ReceiveBridge.h */,
+ );
+ path = Receive;
+ sourceTree = "";
+ };
+ 21CE9B8D2CE75CFC0076522F /* Tool */ = {
+ isa = PBXGroup;
+ children = (
+ 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */,
+ 21CE9B8C2CE75CFC0076522F /* ElementHighlighter.h */,
+ );
+ path = Tool;
+ sourceTree = "";
+ };
21D0BD5D2C89BFEA0077E104 /* Send */ = {
isa = PBXGroup;
children = (
@@ -2907,6 +2945,7 @@
21F69F092C677BC0008B6A06 /* Event */,
21F69F0E2C677BC0008B6A06 /* Interface */,
21D0BDD82C9387E60077E104 /* Record */,
+ 21CE9B8D2CE75CFC0076522F /* Tool */,
21B67CBA2C774C6500FD64FC /* Version.h */,
);
path = Connector;
@@ -2929,6 +2968,7 @@
21F69F852C70D2C4008B6A06 /* Account */,
21B67CAB2C77329800FD64FC /* Base */,
21F69FB82C762EF0008B6A06 /* Config */,
+ 21CE9B822CE69A230076522F /* Receive */,
21D0BD5D2C89BFEA0077E104 /* Send */,
21A890B92CC15C540087E732 /* Selection */,
21B67CD82C78C83800FD64FC /* Test */,
@@ -3098,7 +3138,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
- LastUpgradeCheck = 1530;
+ LastUpgradeCheck = 1610;
TargetAttributes = {
219F30342C768F0A009834E9 = {
CreatedOnToolsVersion = 15.3;
@@ -3376,6 +3416,7 @@
2199BB7E2CDD3FA800A4BEEC /* HighlightObjects.cpp in Sources */,
21D0BD602C89BFEA0077E104 /* SendBridge.cpp in Sources */,
21D0BD972C8F13F30077E104 /* GetSendFilters.cpp in Sources */,
+ 21CE9B882CE69A230076522F /* ReceiveBridge.cpp in Sources */,
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */,
2192460D2CA3469D00CF5703 /* ProjectCollection.cpp in Sources */,
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */,
@@ -3402,7 +3443,9 @@
2199BB552CDA4B1700A4BEEC /* ConnectorProject.cpp in Sources */,
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */,
21384BCD2CD2EE7400D4602B /* OpenUrl.cpp in Sources */,
+ 21CE9B842CE69A230076522F /* Receive.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
+ 21CE9B8F2CE75CFC0076522F /* ElementHighlighter.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */,
21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */,
@@ -3446,6 +3489,7 @@
21BD79952CE23E4D00526AD1 /* HighlightObjects.cpp in Sources */,
21BD79962CE23E4D00526AD1 /* SendBridge.cpp in Sources */,
21BD79972CE23E4D00526AD1 /* GetSendFilters.cpp in Sources */,
+ 21CE9B8A2CE69A230076522F /* ReceiveBridge.cpp in Sources */,
21BD79982CE23E4D00526AD1 /* BaseBridge.cpp in Sources */,
21BD79992CE23E4D00526AD1 /* ProjectCollection.cpp in Sources */,
21BD799A2CE23E4D00526AD1 /* GetIsDevMode.cpp in Sources */,
@@ -3472,7 +3516,9 @@
21BD79AF2CE23E4D00526AD1 /* ConnectorProject.cpp in Sources */,
21BD79B02CE23E4D00526AD1 /* SendObject.cpp in Sources */,
21BD79B12CE23E4D00526AD1 /* OpenUrl.cpp in Sources */,
+ 21CE9B862CE69A230076522F /* Receive.cpp in Sources */,
21BD79B22CE23E4D00526AD1 /* SayHi.cpp in Sources */,
+ 21CE9B912CE75CFC0076522F /* ElementHighlighter.cpp in Sources */,
21BD79B32CE23E4D00526AD1 /* FilterMover.cpp in Sources */,
21BD79B42CE23E4D00526AD1 /* ConnectorMenu.cpp in Sources */,
21BD79B52CE23E4D00526AD1 /* GetAccounts.cpp in Sources */,
@@ -3507,6 +3553,7 @@
21CE8AA72CE4F3370076522F /* HighlightObjects.cpp in Sources */,
21CE8AA82CE4F3370076522F /* SendBridge.cpp in Sources */,
21CE8AA92CE4F3370076522F /* GetSendFilters.cpp in Sources */,
+ 21CE9B892CE69A230076522F /* ReceiveBridge.cpp in Sources */,
21CE8AAA2CE4F3370076522F /* BaseBridge.cpp in Sources */,
21CE8AAB2CE4F3370076522F /* ProjectCollection.cpp in Sources */,
21CE8AAC2CE4F3370076522F /* GetIsDevMode.cpp in Sources */,
@@ -3533,7 +3580,9 @@
21CE8AC12CE4F3370076522F /* ConnectorProject.cpp in Sources */,
21CE8AC22CE4F3370076522F /* SendObject.cpp in Sources */,
21CE8AC32CE4F3370076522F /* OpenUrl.cpp in Sources */,
+ 21CE9B852CE69A230076522F /* Receive.cpp in Sources */,
21CE8AC42CE4F3370076522F /* SayHi.cpp in Sources */,
+ 21CE9B902CE75CFC0076522F /* ElementHighlighter.cpp in Sources */,
21CE8AC52CE4F3370076522F /* FilterMover.cpp in Sources */,
21CE8AC62CE4F3370076522F /* ConnectorMenu.cpp in Sources */,
21CE8AC72CE4F3370076522F /* GetAccounts.cpp in Sources */,
@@ -3568,6 +3617,7 @@
21CE8DE72CE5137C0076522F /* HighlightObjects.cpp in Sources */,
21CE8DE82CE5137C0076522F /* SendBridge.cpp in Sources */,
21CE8DE92CE5137C0076522F /* GetSendFilters.cpp in Sources */,
+ 21CE9B872CE69A230076522F /* ReceiveBridge.cpp in Sources */,
21CE8DEA2CE5137C0076522F /* BaseBridge.cpp in Sources */,
21CE8DEB2CE5137C0076522F /* ProjectCollection.cpp in Sources */,
21CE8DEC2CE5137C0076522F /* GetIsDevMode.cpp in Sources */,
@@ -3594,7 +3644,9 @@
21CE8E012CE5137C0076522F /* ConnectorProject.cpp in Sources */,
21CE8E022CE5137C0076522F /* SendObject.cpp in Sources */,
21CE8E032CE5137C0076522F /* OpenUrl.cpp in Sources */,
+ 21CE9B832CE69A230076522F /* Receive.cpp in Sources */,
21CE8E042CE5137C0076522F /* SayHi.cpp in Sources */,
+ 21CE9B8E2CE75CFC0076522F /* ElementHighlighter.cpp in Sources */,
21CE8E052CE5137C0076522F /* FilterMover.cpp in Sources */,
21CE8E062CE5137C0076522F /* ConnectorMenu.cpp in Sources */,
21CE8E072CE5137C0076522F /* GetAccounts.cpp in Sources */,
@@ -3689,6 +3741,7 @@
"\"$(HEADER_PATH_5)/Frameworks\"",
"\"$(HEADER_PATH_5)/Lib\"",
);
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
OTHER_CPLUSPLUSFLAGS = (
"-Wno-multichar",
"-Wno-ctor-dtor-privacy",
@@ -3753,6 +3806,7 @@
"\"$(HEADER_PATH_5)/Frameworks\"",
"\"$(HEADER_PATH_5)/Lib\"",
);
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
OTHER_CPLUSPLUSFLAGS = (
"-Wno-multichar",
"-Wno-ctor-dtor-privacy",
diff --git a/SpeckleConnector/Connector.xcodeproj/xcshareddata/xcschemes/Connector-AC25-Debug.xcscheme b/SpeckleConnector/Connector.xcodeproj/xcshareddata/xcschemes/Connector-AC25-Debug.xcscheme
index 19b567d..a6da887 100644
--- a/SpeckleConnector/Connector.xcodeproj/xcshareddata/xcschemes/Connector-AC25-Debug.xcscheme
+++ b/SpeckleConnector/Connector.xcodeproj/xcshareddata/xcschemes/Connector-AC25-Debug.xcscheme
@@ -1,6 +1,6 @@
@@ -55,7 +55,7 @@
diff --git a/SpeckleConnector/Connector/Connector.cpp b/SpeckleConnector/Connector/Connector.cpp
index 9321923..c63157b 100644
--- a/SpeckleConnector/Connector/Connector.cpp
+++ b/SpeckleConnector/Connector/Connector.cpp
@@ -4,12 +4,21 @@
#include "Connector/Environment/ConnectorProject.h"
#include "Connector/Interface/ConnectorMenu.h"
#include "Connector/Interface/ConnectorPalette.h"
+#include "Connector/Tool/ElementHighlighter.h"
#include "Speckle/Database/AccountDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Utility/String.h"
#include
+#ifdef WINDOWS
+ //NB: VS is ignoring template specialisations unless they are explicitly used in the top-level project
+#include "Active/Setting/Values/GuidValue.h"
+#include "Active/Setting/Values/TimeValue.h"
+#include "Active/Setting/Values/StringValue.h"
+using namespace active::setting;
+#endif
+
using namespace active::file;
using namespace active::environment;
using namespace connector;
@@ -42,6 +51,7 @@ namespace {
//Define the connector UI components
add();
add();
+ add();
}
// MARK: Functions (const)
@@ -84,6 +94,18 @@ namespace {
return std::nullopt;
return Directory{*appData, speckleDataDirName, true};
} //getAppDataDirectory
+
+#ifdef WINDOWS
+ //NB: VS is ignoring template specialisations unless they are explicitly used in the top-level project
+ void invokeSpecialisation() {
+ StringValue stringValue;
+ active::utility::String unusedString = stringValue;
+ GuidValue guidValue;
+ active::utility::Guid unusedGuid = guidValue;
+ TimeValue timeValue;
+ active::utility::Time unusedTime = timeValue;
+ }
+#endif
}
@@ -93,6 +115,9 @@ namespace {
name: The add-on name
--------------------------------------------------------------------*/
ConnectorAddon::ConnectorAddon(const speckle::utility::String& name) : Addon{name} {
+#ifdef WINDOWS
+ invokeSpecialisation();
+#endif
} //ConnectorAddon::ConnectorAddon
diff --git a/SpeckleConnector/Connector/ConnectorResource.h b/SpeckleConnector/Connector/ConnectorResource.h
index 17e4482..7a31c72 100755
--- a/SpeckleConnector/Connector/ConnectorResource.h
+++ b/SpeckleConnector/Connector/ConnectorResource.h
@@ -29,6 +29,7 @@ enum TitleString {
addonNameID = 1,
addonDescriptionID,
noStoreyID,
+ showLayersID,
};
@@ -44,6 +45,7 @@ enum GeneralString {
//Notification strings (advice displayed in alerts)
enum NotifyString {
+ showHiddenLayersID = 1,
};
diff --git a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp
index 9a2f0b3..032ac1f 100644
--- a/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp
+++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.cpp
@@ -96,7 +96,7 @@ Vector ModelCardDatabase::getCards() const {
card: The card to write
--------------------------------------------------------------------*/
-void ModelCardDatabase::write(const ModelCard& card) const {
+void ModelCardDatabase::write(ModelCard& card) const {
m_store->write(card);
} //ModelCardDatabase::write
diff --git a/SpeckleConnector/Connector/Database/ModelCardDatabase.h b/SpeckleConnector/Connector/Database/ModelCardDatabase.h
index 2f1e080..29a697b 100644
--- a/SpeckleConnector/Connector/Database/ModelCardDatabase.h
+++ b/SpeckleConnector/Connector/Database/ModelCardDatabase.h
@@ -43,7 +43,7 @@ namespace connector::database {
Write a card to storage
@param card The card to write
*/
- void write(const record::ModelCard& card) const;
+ void write(record::ModelCard& card) const;
/*!
Erase a card
@param cardID The ID of the card to erase
diff --git a/SpeckleConnector/Connector/Event/ConnectorEventID.h b/SpeckleConnector/Connector/Event/ConnectorEventID.h
index 6cad8aa..aebff0b 100755
--- a/SpeckleConnector/Connector/Event/ConnectorEventID.h
+++ b/SpeckleConnector/Connector/Event/ConnectorEventID.h
@@ -9,10 +9,14 @@
inline const active::utility::NameID toggleConnectorPaletteID{"toggleConnectorPalette"};
//Identifier for event signalling the connector palette has changed (state carried with event)
inline const active::utility::NameID reflectPaletteVisibilityID{"setConnectorMenuCheck"};
+ //Identifier for event signalling the that an attached list of elements should be highlighted
+inline const active::utility::NameID setElementHighlight{"setElementHighlight"};
// MARK: - Event setting identities
- //Identifier for event signalling the connector palette visibility state
+ //Identifier for setting carrying a menu state
inline const active::utility::NameID paletteVisibilityStateID{"menuCheckState"};
+ //Identifier for setting carrying a list of element links
+inline const active::utility::NameID recordLinks{"recordLinks"};
#endif //CONNECTOR_EVENT_ID
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp
index 741dc51..626c03b 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/AddModel.cpp
@@ -29,6 +29,8 @@ void AddModel::run(const ModelCard& card) const {
auto connectorProject = dynamic_cast(project.get());
if (!connectorProject)
return;
- if (auto modelCardDBase = connectorProject->getModelCardDatabase(); modelCardDBase != nullptr)
- modelCardDBase->write(card);
+ if (auto modelCardDBase = connectorProject->getModelCardDatabase(); modelCardDBase != nullptr) {
+ auto newCard = clone(card);
+ modelCardDBase->write(*newCard);
+ }
} //AddModel::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightModel.cpp
index 724aa59..ee6f7d3 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightModel.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightModel.cpp
@@ -1,7 +1,11 @@
+#include "Active/Setting/ValueSetting.h"
+#include "Active/Setting/Values/GuidValue.h"
+#include "Active/Event/Event.h"
#include "Connector/Interface/Browser/Bridge/Base/HighlightModel.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Environment/ConnectorProject.h"
+#include "Connector/Event/ConnectorEventID.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Connector/Record/Model/SenderModelCard.h"
@@ -12,6 +16,8 @@
#include "Speckle/Environment/Host.h"
#include "Speckle/Environment/Project.h"
+using namespace active::event;
+using namespace active::setting;
using namespace connector::environment;
using namespace connector::interfac::browser::bridge;
using namespace connector::record;
@@ -46,13 +52,9 @@ void HighlightModel::run(const String& modelCardID) const {
return;
}
if (auto senderCard = dynamic_cast(modelCard.get())) {
- auto modelCardSelection = senderCard->getFilter().getElementIDs();
- auto project = connector()->getActiveProject().lock();
- if (!project)
- return; // TODO: is this OK? should this throw?
- auto elementDatabase = project->getElementDatabase();
- elementDatabase->clearSelection();
- elementDatabase->setSelection(modelCardSelection);
- host()->zoomToFit(true);
+ ValueSetting elementIDs{recordLinks};
+ for (const auto& elementID : senderCard->getFilter().getElementIDs())
+ elementIDs.emplace_back(GuidValue{elementID});
+ connector()->publish(Event{setElementHighlight, { elementIDs }});
}
} //HighlightModel::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightObjects.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightObjects.cpp
index 1fa87ae..a977c74 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightObjects.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/HighlightObjects.cpp
@@ -1,12 +1,13 @@
#include "Connector/Interface/Browser/Bridge/Base/HighlightObjects.h"
+#include "Active/Setting/ValueSetting.h"
+#include "Active/Event/Event.h"
#include "Connector/Connector.h"
-#include "Connector/Environment/ConnectorProject.h"
-#include "Speckle/Database/BIMElementDatabase.h"
-#include "Speckle/Environment/Host.h"
-#include "Speckle/Environment/Project.h"
+#include "Connector/Event/ConnectorEventID.h"
-using namespace connector::environment;
+using namespace active::event;
+using namespace active::setting;
+using namespace connector;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::environment;
@@ -26,18 +27,5 @@ HighlightObjects::HighlightObjects() : BridgeMethod{"HighlightObjects", [&](cons
objectIDs: List of object IDs to be highlighted
--------------------------------------------------------------------*/
void HighlightObjects::run(const StringList& objectIDs) const {
- BIMLinkList objectSelection;
- for (const auto& text : objectIDs)
- if (Guid guid{text}; !guid.empty())
- objectSelection.emplace_back(guid);
- if (objectSelection.empty())
- return;
- auto project = connector()->getActiveProject().lock();
- auto connectorProject = dynamic_cast(project.get());
- if (!connectorProject)
- return;
- auto elementDatabase = project->getElementDatabase();
- elementDatabase->clearSelection();
- elementDatabase->setSelection(objectSelection);
- host()->zoomToFit(true);
+ connector()->publish(Event{setElementHighlight, { ValueSetting{objectIDs, recordLinks} }});
} //HighlightObjects::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp
index 6472d95..59c41e7 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/UpdateModel.cpp
@@ -36,6 +36,8 @@ void UpdateModel::run(const ModelCard& card) const {
auto connectorProject = dynamic_cast(project.get());
if (!connectorProject)
return;
- if (auto modelCardDBase = connectorProject->getModelCardDatabase(); modelCardDBase != nullptr)
- modelCardDBase->write(card);
+ if (auto modelCardDBase = connectorProject->getModelCardDatabase(); modelCardDBase != nullptr) {
+ auto newCard = clone(card);
+ modelCardDBase->write(*newCard);
+ }
} //UpdateModel::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.cpp
new file mode 100644
index 0000000..c25ac58
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.cpp
@@ -0,0 +1,46 @@
+#include "Connector/Interface/Browser/Bridge/Receive/Receive.h"
+
+#include "Active/Serialise/CargoHold.h"
+#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
+#include "Connector/Connector.h"
+#include "Connector/ConnectorResource.h"
+#include "Connector/Database/ModelCardDatabase.h"
+#include "Connector/Environment/ConnectorProject.h"
+#include "Connector/Record/Collection/ProjectCollection.h"
+#include "Connector/Record/Model/ReceiverModelCard.h"
+#include "Speckle/Database/AccountDatabase.h"
+#include "Speckle/Database/BIMElementDatabase.h"
+#include "Speckle/Database/Content/BIMRecord.h"
+#include "Speckle/Environment/Project.h"
+#include "Speckle/Environment/Host.h"
+#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
+#include "Speckle/Record/Credentials/Account.h"
+#include "Speckle/Record/Element/Element.h"
+#include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h"
+#include "Speckle/Utility/Exception.h"
+
+using namespace active::serialise;
+using namespace connector::environment;
+using namespace connector::interfac::browser::bridge;
+using namespace connector::record;
+using namespace speckle::database;
+using namespace speckle::environment;
+using namespace speckle::record::element;
+using namespace speckle::serialise;
+using namespace speckle::utility;
+
+/*--------------------------------------------------------------------
+ Default constructor
+ --------------------------------------------------------------------*/
+Receive::Receive() : BridgeMethod{"Receive", [&](const ReceiveArgs& args) {
+ run(args);
+}} {}
+
+
+/*--------------------------------------------------------------------
+ Receive a specified model
+
+ modelCardID: The ID of the model card identifying the objects to receive
+ --------------------------------------------------------------------*/
+void Receive::run(const String& modelCardID) const {
+} //Receive::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.h
new file mode 100644
index 0000000..a90b534
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.h
@@ -0,0 +1,39 @@
+#ifndef CONNECTOR_INTERFACE_BRIDGE_RECEIVE
+#define CONNECTOR_INTERFACE_BRIDGE_RECEIVE
+
+#include "Active/Serialise/CargoHold.h"
+#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
+#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
+
+namespace connector::interfac::browser::bridge {
+
+ ///Argument parameter for a string
+ using StringHold = active::serialise::CargoHold, speckle::utility::String>;
+ ///Argument type for this method
+ using ReceiveArgs = speckle::interfac::browser::bridge::JSArgType;
+
+ /*!
+ JS Function class to receive a specified model
+ */
+ class Receive : public speckle::interfac::browser::bridge::BridgeMethod {
+ public:
+
+ // MARK: - Constructors
+
+ /*!
+ Constructor
+ */
+ Receive();
+
+ // MARK: - Functions (const)
+
+ /*!
+ Receive a specified model
+ @param modelCardID The ID of the model card identifying the objects to receive
+ */
+ void run(const speckle::utility::String& modelCardID) const;
+ };
+
+}
+
+#endif //CONNECTOR_INTERFACE_BRIDGE_RECEIVE
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.cpp
new file mode 100644
index 0000000..659d817
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.cpp
@@ -0,0 +1,30 @@
+#include "Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h"
+#include "Connector/Interface/Browser/Bridge/Receive/Receive.h"
+#include "Connector/Connector.h"
+#include "Connector/ConnectorResource.h"
+#include "Connector/Database/ModelCardDatabase.h"
+#include "Connector/Environment/ConnectorProject.h"
+#include "Speckle/Event/Type/ElementEvent.h"
+#include "Speckle/Record/Element/Element.h"
+#include "Speckle/Database/BIMElementDatabase.h"
+#include "Speckle/Environment/Project.h"
+#include "Speckle/Database/Identity/RecordID.h"
+#include "Active/Serialise/CargoHold.h"
+#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
+#include "Connector/Record/Model/ReceiverModelCard.h"
+
+using namespace speckle::database;
+using namespace connector::environment;
+using namespace connector::interfac::browser::bridge;
+using namespace speckle::utility;
+using namespace speckle::event;
+using namespace active::serialise;
+using namespace connector::record;
+
+/*--------------------------------------------------------------------
+ Default constructor
+ --------------------------------------------------------------------*/
+ReceiveBridge::ReceiveBridge() : BrowserBridge{"receiveBinding"} {
+ //Add bridge methods
+ addMethod();
+} //ReceiveBridge::ReceiveBridge
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h
new file mode 100644
index 0000000..dbeac58
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h
@@ -0,0 +1,29 @@
+#ifndef CONNECTOR_INTERFACE_BRIDGE_RECEIVE_BRIDGE
+#define CONNECTOR_INTERFACE_BRIDGE_RECEIVE_BRIDGE
+
+#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
+
+namespace connector::interfac::browser::bridge {
+
+ /*!
+ A browser bridge to support receiving model data from a Speckle server
+ */
+ class ReceiveBridge : public speckle::interfac::browser::bridge::BrowserBridge {
+ public:
+
+ // MARK: - Types
+
+ using base = speckle::interfac::browser::bridge::BrowserBridge;
+
+ // MARK: - Constructors
+
+ using base::base;
+ /*!
+ Default constructor
+ */
+ ReceiveBridge();
+ };
+
+}
+
+#endif //CONNECTOR_INTERFACE_BRIDGE_RECEIVE_BRIDGE
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
index cb05aed..559cc96 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
@@ -24,7 +24,7 @@ SelectionBridge::SelectionBridge() : BrowserBridge{"selectionBinding"} {
--------------------------------------------------------------------*/
bool SelectionBridge::handle(const speckle::event::SelectionEvent& event) {
auto selectionInfo = std::make_unique();
- auto wrapped = std::make_unique>(std::move(selectionInfo));
+ auto wrapped = std::make_unique>(std::move(selectionInfo));
sendEvent("setSelection", std::move(wrapped));
return true;
} //SelectionBridge::handle
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp
index 397089f..93a681d 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp
@@ -76,7 +76,7 @@ void Send::run(const String& modelCardID) const {
}
//Get the selected elements from the modelcard
auto elementDatabase = project->getElementDatabase();
- ElementIDList selected{};
+ BIMRecordIDList selected{};
if (auto senderCard = dynamic_cast(modelCard.get()))
selected = senderCard->getFilter().getElementIDs();
//Build a collection from the selected elements
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp
index 6d8ae7e..bd96353 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp
@@ -59,10 +59,9 @@ bool SendBridge::handle(const ElementEvent& event) {
// POC: this is probably not efficient, should test, review and refactor it
RecordIDList expiredModelCardIds;
for (const auto& modelCard : modelCards) {
- if (auto senderCard = dynamic_cast(modelCard.get())) {
- auto modelCardSelection = senderCard->getFilter().getElementIDs();
- for (const auto& elemId : modelCardSelection) {
- if (std::find(m_changedElements.begin(), m_changedElements.end(), elemId) != m_changedElements.end()) {
+ if (auto senderCard = dynamic_cast(modelCard.get()); senderCard) {
+ for (const auto& recordID : m_changedElements) {
+ if (senderCard->contains(recordID)) {
expiredModelCardIds.push_back(modelCard->getID());
break;
}
@@ -76,8 +75,8 @@ bool SendBridge::handle(const ElementEvent& event) {
break;
}
case changeElem: case editElem: case deleteElem: {
- if (event.getElmentID())
- m_changedElements.push_back(*event.getElmentID());
+ if (event.getElementID())
+ m_changedElements.insert(*event.getElementID());
break;
}
default:
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.h
index 391cb57..47bf942 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.h
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.h
@@ -31,6 +31,10 @@ namespace connector::interfac::browser::bridge {
@return True if the event should be closed
*/
bool handle(const speckle::event::ElementEvent& event) override;
+
+ private:
+ ///List of changed element IDs
+ speckle::database::BIMRecordIDList m_changedElements;
};
}
diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
index 4f923e9..e8883f9 100644
--- a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
+++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
@@ -11,6 +11,7 @@
#include "Connector/Interface/Browser/Bridge/Account/AccountBridge.h"
#include "Connector/Interface/Browser/Bridge/Base/BaseBridge.h"
#include "Connector/Interface/Browser/Bridge/Config/ConfigBridge.h"
+#include "Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h"
#include "Connector/Interface/Browser/Bridge/Send/SendBridge.h"
#include "Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h"
#include "Connector/Interface/Browser/Bridge/Test/TestBridge.h"
@@ -213,6 +214,7 @@ BrowserPalette::BrowserPalette() :
}
}
install();
+ install();
if (auto ref = install(); ref) {
if (auto sendBridgeRef = std::dynamic_pointer_cast(ref); sendBridgeRef) {
connector::connector()->addWeak(sendBridgeRef);
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp
index b413ef4..3f22e2c 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp
+++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.cpp
@@ -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>(m_selectedElements, false, fieldID[selectedElemID].name);
+ return std::make_unique>(m_selectedElements, false, fieldID[selectedElemID].name);
default:
return nullptr; //Requested an unknown index
}
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h
index f2e64a5..3cb9d39 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h
+++ b/SpeckleConnector/Connector/Record/Model/Filter/DirectSelectionSendFilter.h
@@ -32,11 +32,17 @@ namespace connector::record {
// MARK: - Functions (const)
+ /*!
+ Determine if the send filter contains a specified record ID
+ @param recordID The record ID to search for
+ @return True if the filter contains the record ID
+ */
+ virtual bool contains(const speckle::database::BIMRecordID& recordID) const override { return m_selectedElements.contains(recordID); }
/*!
Get the filtered element IDs
@return The filter elements
*/
- const speckle::database::ElementIDList& getElementIDs() const override { return m_selectedElements; }
+ const speckle::database::BIMRecordIDList& getElementIDs() const override { return m_selectedElements; }
// MARK: - Serialisation
@@ -59,7 +65,7 @@ namespace connector::record {
private:
///A list of selected element IDs
- speckle::database::ElementIDList m_selectedElements;
+ speckle::database::BIMRecordIDList m_selectedElements;
};
}
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp
index 00a49aa..b5eb6eb 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp
+++ b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.cpp
@@ -58,7 +58,7 @@ Cargo::Unique EverythingSendFilter::getCargo(const Inventory::Item& item) const
using namespace active::serialise;
switch (item.index) {
case selectedElemID:
- return std::make_unique>(m_emptyList);
+ return std::make_unique>(m_emptyList);
default:
return nullptr; //Requested an unknown index
}
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h
index 4cd604e..da1eb51 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h
+++ b/SpeckleConnector/Connector/Record/Model/Filter/EverythingSendFilter.h
@@ -32,17 +32,23 @@ namespace connector::record {
// MARK: - Functions (const)
+ /*!
+ Determine if the send filter contains a specified record ID
+ @param recordID The record ID to search for
+ @return True if the filter contains the record ID
+ */
+ virtual bool contains(const speckle::database::BIMRecordID& recordID) const override { return true; }
/*!
Get the filtered element IDs
@return The filter elements
*/
- const speckle::database::ElementIDList& getElementIDs() const override { return m_emptyList; }
+ const speckle::database::BIMRecordIDList& 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 speckle::database::ElementIDList& changed) const override { return true; }
+ virtual bool checkExpiry(const speckle::database::BIMRecordIDList& changed) const override { return true; }
// MARK: - Serialisation
@@ -65,7 +71,7 @@ namespace connector::record {
private:
///Enables a const empty list to be returned
- speckle::database::ElementIDList m_emptyList;
+ speckle::database::BIMRecordIDList m_emptyList;
};
}
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp
index 8b42cc8..67ba1ca 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp
+++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.cpp
@@ -34,12 +34,10 @@ namespace {
return: True if the one of the changed elements is in the selection
--------------------------------------------------------------------*/
-bool SendFilter::checkExpiry(const ElementIDList& changed) const {
- ElementIDList intersect;
- ElementIDList mine{getElementIDs()}, theirs{changed};
- std::sort(mine.begin(), mine.end());
- std::sort(theirs.begin(), theirs.end());
- std::set_intersection (mine.begin(), mine.end(), theirs.begin(), theirs.end(), std::back_inserter(intersect));
+bool SendFilter::checkExpiry(const BIMRecordIDList& changed) const {
+ BIMRecordIDList intersect;
+ BIMRecordIDList mine{getElementIDs()}, theirs{changed};
+ std::set_intersection(mine.begin(), mine.end(), theirs.begin(), theirs.end(), std::inserter(intersect, intersect.begin()));
return !intersect.empty();
} //SendFilter::checkExpiry
diff --git a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h
index cedfc56..3f21839 100644
--- a/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h
+++ b/SpeckleConnector/Connector/Record/Model/Filter/SendFilter.h
@@ -4,6 +4,7 @@
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/Cloner.h"
#include "Speckle/Database/Identity/RecordID.h"
+#include "Speckle/Database/Identity/BIMRecordID.h"
#include "Speckle/Utility/String.h"
namespace connector::record {
@@ -55,17 +56,23 @@ namespace connector::record {
@return True if this is the default filter
*/
bool isDefault() const { return m_isDefault; };
+ /*!
+ Determine if the send filter contains a specified record ID
+ @param recordID The record ID to search for
+ @return True if the filter contains the record ID
+ */
+ virtual bool contains(const speckle::database::BIMRecordID& recordID) const = 0;
/*!
Get the filtered element IDs
@return The filter elements
*/
- virtual const speckle::database::ElementIDList& getElementIDs() const = 0;
+ virtual const speckle::database::BIMRecordIDList& 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 speckle::database::ElementIDList& changed) const;
+ virtual bool checkExpiry(const speckle::database::BIMRecordIDList& changed) const;
// MARK: - Serialisation
diff --git a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp
index 55bb8c8..17152bc 100644
--- a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp
+++ b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.cpp
@@ -2,6 +2,7 @@
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
+#include "Speckle/Database/Identity/BIMRecordID.h"
#include
@@ -81,7 +82,7 @@ Cargo::Unique ReceiverModelCard::getCargo(const Inventory::Item& item) const {
case warningDismissedID:
return std::make_unique(m_hasDismissedUpdateWarning);
case bakedObjectsID:
- return std::make_unique>(m_bakedObjectIDs);
+ return std::make_unique>(m_bakedObjectIDs);
default:
return nullptr; //Requested an unknown index
}
diff --git a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h
index e13acdb..9e369dd 100644
--- a/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h
+++ b/SpeckleConnector/Connector/Record/Model/ReceiverModelCard.h
@@ -1,7 +1,7 @@
#ifndef CONNECTOR_RECORD_RECEIVER_MODEL_CARD
#define CONNECTOR_RECORD_RECEIVER_MODEL_CARD
-#include "Speckle/Database/Identity/RecordID.h"
+#include "Speckle/Database/Identity/BIMRecordID.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, speckle::database::ElementIDList&& bakedObjects, const SettingList& settings) :
+ bool hasDimissedWarning, speckle::database::BIMRecordIDList&& 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 speckle::database::ElementIDList& getBakedObjectIDs() const { return m_bakedObjectIDs; }
+ const speckle::database::BIMRecordIDList& 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
- speckle::database::ElementIDList m_bakedObjectIDs;
+ speckle::database::BIMRecordIDList m_bakedObjectIDs;
};
}
diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp
index e122cc3..42dd8aa 100644
--- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp
+++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.cpp
@@ -61,6 +61,18 @@ SenderModelCard::~SenderModelCard() {
} //SenderModelCard::~SenderModelCard
+/*--------------------------------------------------------------------
+ Determine if the send filter contains a specified record ID
+
+ recordID: The record ID to search for
+
+ return: True if the filter contains the record ID
+ --------------------------------------------------------------------*/
+bool SenderModelCard::contains(const speckle::database::BIMRecordID& recordID) const {
+ return m_filter->contains(recordID);
+} //SenderModelCard::contains
+
+
/*--------------------------------------------------------------------
Fill an inventory with the package items
diff --git a/SpeckleConnector/Connector/Record/Model/SenderModelCard.h b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h
index 0b3e010..c802632 100644
--- a/SpeckleConnector/Connector/Record/Model/SenderModelCard.h
+++ b/SpeckleConnector/Connector/Record/Model/SenderModelCard.h
@@ -2,6 +2,7 @@
#define CONNECTOR_RECORD_SENDER_MODEL_CARD
#include "Connector/Record/Model/ModelCard.h"
+#include "Speckle/Database/Identity/BIMRecordID.h"
namespace connector::record {
@@ -46,6 +47,12 @@ namespace connector::record {
// MARK: - Functions (const)
+ /*!
+ Determine if the send filter contains a specified record ID
+ @param recordID The record ID to search for
+ @return True if the filter contains the record ID
+ */
+ bool contains(const speckle::database::BIMRecordID& recordID) const;
/*!
Get the filter applied when the model was sent
@return The model filter
diff --git a/SpeckleConnector/Connector/Tool/ElementHighlighter.cpp b/SpeckleConnector/Connector/Tool/ElementHighlighter.cpp
new file mode 100644
index 0000000..13fb5f9
--- /dev/null
+++ b/SpeckleConnector/Connector/Tool/ElementHighlighter.cpp
@@ -0,0 +1,123 @@
+#include "Connector/Tool/ElementHighlighter.h"
+
+#include "Active/Database/Transaction.h"
+#include "Active/Event/Event.h"
+#include "Connector/Connector.h"
+#include "Connector/ConnectorResource.h"
+#include "Connector/Environment/ConnectorProject.h"
+#include "Connector/Event/ConnectorEventID.h"
+#include "Speckle/Database/BIMAttributeDatabase.h"
+#include "Speckle/Database/BIMElementDatabase.h"
+#include "Speckle/Database/Identity/BIMLink.h"
+#include "Speckle/Environment/Host.h"
+#include "Speckle/Record/Filter/ElementVisibilityCollector.h"
+#include "Speckle/Utility/Guid.h"
+
+using namespace active::database;
+using namespace active::event;
+using namespace active::setting;
+using namespace connector;
+using namespace connector::environment;
+using namespace speckle::database;
+using namespace speckle::environment;
+using namespace speckle::record;
+using namespace speckle::utility;
+
+namespace {
+
+ /*!
+ Transaction to make a selection of layers visible
+ */
+ class ShowLayers : public Transaction {
+ public:
+ /*!
+ Constructor
+ @param project The target project
+ @param layers The layers in the project to be made visible
+ */
+ ShowLayers(Project::Shared project, ElementVisibilityCollector::Layers& layers) :
+ Transaction{connector::connector()->getLocalString(titleString, showLayersID)}, m_project{project}, m_layers{layers} {}
+
+ protected:
+
+ //MARK: - Functions (App management)
+
+ /*!
+ Perform the transaction. Database writes can be performed. NB: this function is not called if the prepare phase was unsuccessful)
+ @return True if the transaction was successfully performed
+ */
+ bool perform() override {
+ auto attributeDatabase = m_project->getAttributeDatabase();
+ for (auto& layer : m_layers) {
+ if (layer.second.isHidden()) {
+ layer.second.setHidden(false);
+ attributeDatabase->write(layer.second);
+ }
+ }
+ return true;
+ }
+
+ private:
+ ///The target project for showing layers
+ Project::Shared m_project;
+ ///The layers to be made visible
+ ElementVisibilityCollector::Layers& m_layers;
+ };
+
+}
+
+/*--------------------------------------------------------------------
+ Get the event subscription list
+
+ return: The subscription list (an empty list will put the subscriber into a suspended state)
+ --------------------------------------------------------------------*/
+Subscriber::Subscription ElementHighlighter::subscription() const {
+ return Subscription{setElementHighlight};
+} //ElementHighlighter::subscription
+
+
+/*--------------------------------------------------------------------
+ Receive a subscribed event
+
+ event: The incoming event
+
+ return: True if the event should be closed
+ --------------------------------------------------------------------*/
+bool ElementHighlighter::receive(const active::event::Event& event) {
+ //Collect the IDs of elements to be highlighted
+ ValueSetting* elementIDs = nullptr;
+ if (elementIDs = event.findValue(recordLinks); elementIDs == nullptr)
+ return false;
+ BIMLinkList elementSelection;
+ for (const auto& value : *elementIDs)
+ if (Guid guid{value->operator active::utility::Guid()}; guid)
+ elementSelection.emplace_back(guid);
+ if (elementSelection.empty())
+ return false;
+ auto project = connector()->getActiveProject().lock();
+ auto connectorProject = dynamic_cast(project.get());
+ if (!connectorProject)
+ return false;
+ auto elementDatabase = project->getElementDatabase();
+ //Collect the layers assigned to the model card elements
+ ElementVisibilityCollector collector;
+ BIMElementDatabase::Filter filter = [&collector](const speckle::record::element::Element& elem) { return collector(elem); };
+ elementDatabase->findElements(&filter, elementSelection);
+ //If any collected layers are hidden, the useer is prompted to show them (otherwise they may see nothing happen when a model card is clicked)
+ for (const auto& layer : collector.getLayers()) {
+ if (layer.second.isHidden()) {
+ //If a hidden layer is found, ask the user before taking any action
+ if (host()->displayConfirmation(addon()->getLocalString(notifyString, showHiddenLayersID))) {
+ //Run a transaction to ensure all layers are visible
+ ShowLayers showLayers{project, collector.getLayers()};
+ connector()->makeTransaction(showLayers);
+ }
+ break;
+ }
+ }
+ host()->makeModelViewActive();
+ elementDatabase->clearSelection();
+ elementDatabase->setSelection(elementSelection);
+ host()->zoomToFit(true);
+ return false;
+} //ElementHighlighter::receive
diff --git a/SpeckleConnector/Connector/Tool/ElementHighlighter.h b/SpeckleConnector/Connector/Tool/ElementHighlighter.h
new file mode 100644
index 0000000..b4b6d28
--- /dev/null
+++ b/SpeckleConnector/Connector/Tool/ElementHighlighter.h
@@ -0,0 +1,28 @@
+#ifndef CONNECTOR_ELEMENT_HIGHLIGHTER
+#define CONNECTOR_ELEMENT_HIGHLIGHTER
+
+#include "Active/Event/Subscriber.h"
+
+namespace connector {
+
+ class ElementHighlighter : public active::event::Subscriber {
+ public:
+ /*!
+ Get the event subscription list
+ @return The subscription list (an empty list will put the subscriber into a suspended state)
+ */
+ Subscription subscription() const override;
+
+ // MARK: - Functions (mutating)
+
+ /*!
+ Receive a subscribed event
+ @param event The incoming event
+ @return True if the event should be closed
+ */
+ bool receive(const active::event::Event& event) override;
+ };
+
+}
+
+#endif //CONNECTOR_ELEMENT_HIGHLIGHTER
diff --git a/SpeckleConnector/RINT/Connector.grc b/SpeckleConnector/RINT/Connector.grc
index 24aba3e..9e938ff 100644
--- a/SpeckleConnector/RINT/Connector.grc
+++ b/SpeckleConnector/RINT/Connector.grc
@@ -2,8 +2,15 @@
/* [ 1] */ "Speckle Connector"
/* [ 2] */ "Connector to share model content with Speckle"
/* [ 3] */ "No level"
+/* [ 4] */ "Show Layers"
}
+
+'STR#' 32602 "Notify strings" {
+/* [ 1] */ "Some elements published with the selected model card are on hidden layers - do you wish to make these layers visible?"
+}
+
+
'STR#' 32604 "Error strings" {
/* [ 1] */ "No objects were found to convert. Please update your publish filter!"
/* [ 2] */ "The specified model card cannot be found. Try another card or create a new one"
diff --git a/SpeckleLib/RINT/Speckle.grc b/SpeckleLib/RINT/Speckle.grc
index aa8eab1..0edb61a 100644
--- a/SpeckleLib/RINT/Speckle.grc
+++ b/SpeckleLib/RINT/Speckle.grc
@@ -2,4 +2,9 @@
/* [ 1] */ "Untitled"
/* [ 2] */ "Unknown"
/* [ 3] */ "Converting elements"
+/* [ 4] */ "Notification"
+/* [ 5] */ "Confirm"
+/* [ 6] */ "Yes"
+/* [ 7] */ "No"
+/* [ 8] */ "OK"
}
diff --git a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp
index 2fbf967..ad81693 100644
--- a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp
+++ b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.cpp
@@ -27,7 +27,7 @@ namespace speckle::database {
///Attribute database engine declaration
class BIMAttributeDatabase::Engine : public AttributeDatabaseEngine {
- using base = ArchicadAttributeDBaseEngine;
+ using base = AttributeDatabaseEngine;
using base::base;
};
@@ -102,7 +102,7 @@ Vector BIMAttributeDatabase::getAttributes() const {
attribute: The attribute to write
--------------------------------------------------------------------*/
-void BIMAttributeDatabase::write(const Attribute& attribute) const {
+void BIMAttributeDatabase::write(Attribute& attribute) const {
m_store->write(attribute);
} //BIMAttributeDatabase::write
diff --git a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h
index 17fe657..6ca63fc 100644
--- a/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h
+++ b/SpeckleLib/Speckle/Database/BIMAttributeDatabase.h
@@ -55,7 +55,7 @@ namespace speckle::database {
Write an attribute to storage
@param attribute The attribute to write
*/
- void write(const record::attribute::Attribute& attribute) const;
+ void write(record::attribute::Attribute& attribute) const;
/*!
Erase an attribute
@param attributeID The ID of the attribute to erase
diff --git a/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp b/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp
index 9837c54..408144f 100644
--- a/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp
+++ b/SpeckleLib/Speckle/Database/BIMElementDatabase.cpp
@@ -148,14 +148,15 @@ void BIMElementDatabase::clearSelection() const {
Find a filtered list of objects
filter: The object filter (nullptr = find all objects)
+ subset: A subset of the database content to search (specified by record ID)
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: A list containing IDs of found elements (empty if none found)
--------------------------------------------------------------------*/
-BIMRecordIDList BIMElementDatabase::findElements(const Filter& filter, std::optional tableID,
- std::optional documentID) const {
- return m_engine->findObjects(filter, tableID, documentID);
+BIMRecordIDList BIMElementDatabase::findElements(const Filter* filter, const BIMRecordIDList& subset, std::optional tableID,
+ std::optional documentID) const {
+ return m_engine->findObjects(filter, subset, tableID, documentID);
} //BIMElementDatabase::findElements
@@ -212,7 +213,7 @@ Memo::Unique BIMElementDatabase::getMemo(const BIMRecordID& elementID, Part::fil
element: The element to write
--------------------------------------------------------------------*/
-void BIMElementDatabase::write(const Element& element) const {
+void BIMElementDatabase::write(Element& element) const {
m_store->write(element);
} //BIMElementDatabase::write
diff --git a/SpeckleLib/Speckle/Database/BIMElementDatabase.h b/SpeckleLib/Speckle/Database/BIMElementDatabase.h
index 000612e..d1a692c 100644
--- a/SpeckleLib/Speckle/Database/BIMElementDatabase.h
+++ b/SpeckleLib/Speckle/Database/BIMElementDatabase.h
@@ -74,12 +74,13 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- BIMRecordIDList findElements(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
- std::optional documentID = std::nullopt) const;
+ BIMRecordIDList findElements(const Filter* filter = nullptr, const BIMRecordIDList& subset = {},
+ std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const;
/*!
Get a specified element
@param elementID The ID of the target element
@@ -114,7 +115,7 @@ namespace speckle::database {
Write an element to storage
@param element The element to write
*/
- void write(const record::element::Element& element) const;
+ void write(record::element::Element& element) const;
/*!
Erase an element
@param elementID The ID of the element to erase
diff --git a/SpeckleLib/Speckle/Database/BIMGroupDatabase.cpp b/SpeckleLib/Speckle/Database/BIMGroupDatabase.cpp
index 2b653a5..62e9460 100644
--- a/SpeckleLib/Speckle/Database/BIMGroupDatabase.cpp
+++ b/SpeckleLib/Speckle/Database/BIMGroupDatabase.cpp
@@ -114,7 +114,7 @@ Vector BIMGroupDatabase::getGroups() const {
group: The group to write
--------------------------------------------------------------------*/
-void BIMGroupDatabase::write(const Group& group) const {
+void BIMGroupDatabase::write(Group& group) const {
m_store->write(group);
} //BIMGroupDatabase::write
diff --git a/SpeckleLib/Speckle/Database/BIMGroupDatabase.h b/SpeckleLib/Speckle/Database/BIMGroupDatabase.h
index df18e4f..fdca3eb 100644
--- a/SpeckleLib/Speckle/Database/BIMGroupDatabase.h
+++ b/SpeckleLib/Speckle/Database/BIMGroupDatabase.h
@@ -57,7 +57,7 @@ namespace speckle::database {
Write an group to storage
@param group The group to write
*/
- void write(const record::property::Group& group) const;
+ void write(record::property::Group& group) const;
/*!
Erase an group
@param groupID The ID of the group to erase
diff --git a/SpeckleLib/Speckle/Database/BIMPropertyDatabase.cpp b/SpeckleLib/Speckle/Database/BIMPropertyDatabase.cpp
index 5456f62..d99f66f 100644
--- a/SpeckleLib/Speckle/Database/BIMPropertyDatabase.cpp
+++ b/SpeckleLib/Speckle/Database/BIMPropertyDatabase.cpp
@@ -126,7 +126,7 @@ std::vector> BIMPropertyDatabase::findTemplatesByClass
property: The property to write
--------------------------------------------------------------------*/
-void BIMPropertyDatabase::write(const Template& property) const {
+void BIMPropertyDatabase::write(Template& property) const {
m_store->write(property);
} //BIMPropertyDatabase::write
diff --git a/SpeckleLib/Speckle/Database/BIMPropertyDatabase.h b/SpeckleLib/Speckle/Database/BIMPropertyDatabase.h
index 8496c96..eec7aba 100644
--- a/SpeckleLib/Speckle/Database/BIMPropertyDatabase.h
+++ b/SpeckleLib/Speckle/Database/BIMPropertyDatabase.h
@@ -63,7 +63,7 @@ namespace speckle::database {
Write an property to storage
@param property The property to write
*/
- void write(const record::property::Template& property) const;
+ void write(record::property::Template& property) const;
/*!
Erase an property
@param propertyID The ID of the property to erase
diff --git a/SpeckleLib/Speckle/Database/Identity/BIMLink.cpp b/SpeckleLib/Speckle/Database/Identity/BIMLink.cpp
index 24c033c..a416269 100644
--- a/SpeckleLib/Speckle/Database/Identity/BIMLink.cpp
+++ b/SpeckleLib/Speckle/Database/Identity/BIMLink.cpp
@@ -13,9 +13,28 @@ 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
+#endif
-BIMLinkList::BIMLinkList(const ElementIDList& elementIDList) {
+
+/*--------------------------------------------------------------------
+ Constructor
+
+ elementIDList: BIM record IDs to populate the links
+ --------------------------------------------------------------------*/
+BIMLinkList::BIMLinkList(const BIMRecordIDList& elementIDList) {
for (const auto& id : elementIDList)
push_back(id);
-}
-#endif
+} //BIMLinkList::BIMLinkList
+
+
+/*--------------------------------------------------------------------
+ Conversion operator
+
+ return: A list of BIM record IDs from this list
+ --------------------------------------------------------------------*/
+BIMLinkList::operator BIMRecordIDList() const {
+ BIMRecordIDList result;
+ for (const auto& link : *this)
+ result.insert(BIMRecordID{link});
+ return result;
+} //BIMLinkList::operator BIMRecordIDList
diff --git a/SpeckleLib/Speckle/Database/Identity/BIMLink.h b/SpeckleLib/Speckle/Database/Identity/BIMLink.h
index 4eeb5b6..90ea960 100644
--- a/SpeckleLib/Speckle/Database/Identity/BIMLink.h
+++ b/SpeckleLib/Speckle/Database/Identity/BIMLink.h
@@ -41,18 +41,35 @@ namespace speckle::database {
#endif
};
- //A list of links to BIM records
- //using BIMLinkList = std::vector;
+ /*!
+ A list of links to BIM records
+ */
class BIMLinkList : public std::vector {
public:
-
+
+ // MARK: - Types
+
using base = std::vector;
-
+
+ // MARK: - Constructors
+
using base::base;
BIMLinkList() = default;
- BIMLinkList(const ElementIDList& elementIDList);
+ /*!
+ Constructor
+ @param elementIDList BIM record IDs to populate the links
+ */
+ BIMLinkList(const BIMRecordIDList& elementIDList);
+
+ // MARK: - Operators
+
+ /*!
+ Conversion operator
+ @return A list of BIM record IDs from this list
+ */
+ operator BIMRecordIDList() const;
};
}
diff --git a/SpeckleLib/Speckle/Database/Identity/RecordID.h b/SpeckleLib/Speckle/Database/Identity/RecordID.h
index 312ca44..2bc266e 100644
--- a/SpeckleLib/Speckle/Database/Identity/RecordID.h
+++ b/SpeckleLib/Speckle/Database/Identity/RecordID.h
@@ -15,12 +15,6 @@ namespace speckle::database {
//A list of record IDs
using RecordIDList = std::vector;
-
- //BIM element record identifier
- using ElementID = speckle::utility::Guid;
-
- //A list of element IDs
- using ElementIDList = std::vector;
}
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.cpp
index 5848954..cc1f741 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.cpp
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.cpp
@@ -33,7 +33,7 @@ namespace {
return: An equivalent status code
--------------------------------------------------------------------*/
- ArchicadDBaseCore::Status convertArchicadError(long acErrorCode) {
+ ArchicadDBaseCore::Status convertArchicadError(GSErrCode acErrorCode) {
using enum ArchicadDBaseCore::Status;
switch (acErrorCode) {
case NoError:
@@ -92,4 +92,16 @@ std::error_code ArchicadDBaseCore::makeError(ArchicadDBaseCore::Status code) {
return std::error_code(static_cast(code), instance);
} //ArchicadDBaseCore::makeError
+
+/*--------------------------------------------------------------------
+ Make an error code for ArchicadElementDBase processing
+
+ code: An Archicad API error code
+
+ return: An STL error code
+ --------------------------------------------------------------------*/
+std::error_code ArchicadDBaseCore::makeError(GSErrCode code) {
+ return makeError(convertArchicadError(code));
+} //ArchicadDBaseCore::makeError
+
#endif
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h
index fb6f0fa..dae78e2 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h
@@ -9,6 +9,8 @@
#include "Active/Utility/NameID.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
+#include
+
namespace speckle::database {
using ArchicadDBaseSchema = active::database::DBaseSchema<>;
@@ -35,9 +37,16 @@ namespace speckle::database {
/*!
Make an error code for ArchicadElementDBase processing
+ @param code An ArchicadDBaseCore status code
@return An STL error code
*/
static std::error_code makeError(ArchicadDBaseCore::Status code);
+ /*!
+ Make an error code for ArchicadElementDBase processing
+ @param code An Archicad API error code
+ @return An STL error code
+ */
+ static std::error_code makeError(GSErrCode code);
// MARK: - Constructors
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp
index ff23dbc..85d2e57 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.cpp
@@ -221,9 +221,26 @@ active::container::Vector ArchicadAttributeDBaseEngine::getObjects(co
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
-void ArchicadAttributeDBaseEngine::write(const Attribute& object, const BIMRecordID& objID, std::optional objDocID,
- std::optional tableID, std::optional documentID) const {
- //TODO: Implement
+void ArchicadAttributeDBaseEngine::write(Attribute& object, const BIMRecordID& objID, std::optional objDocID,
+ std::optional tableID, std::optional documentID) const {
+ auto attributeData = object.getDataOut();
+ //An record with no index has not been written (and needs to be created in the dbase)
+ GSErrCode status = NoError;
+#ifdef ServerMainVers_2700
+ if (attributeData.header.index.GenerateHashValue() == 0)
+#else
+ if (attributeData.header.index == 0)
+#endif
+ {
+ status = ACAPI_Attribute_CreateExt(&attributeData, nullptr); //TODO: Handle attribute extended definition
+ //Archicad assigns record guids - we need to capture this for the caller
+ object.setBIMID(attributeData.header.guid);
+ } else
+ status = ACAPI_Attribute_ModifyExt(&attributeData, nullptr);
+ if (status != NoError)
+ throw std::system_error(makeError(status));
+ //Archicad modifies record headers on write - need to capture this data for the caller
+ object.getHead() = attributeData.header;
} //ArchicadAttributeDBaseEngine::write
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h
index 6b13c59..cf66b6b 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h
@@ -55,11 +55,13 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
+ virtual ObjIDList findObjects(const Filter* filter = nullptr, const ObjIDList& subset = {},
+ std::optional tableID = std::nullopt,
std::optional documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by ID
@@ -101,7 +103,7 @@ namespace speckle::database {
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
- void write(const Attribute& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
+ void write(Attribute& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override;
/*!
Erase an object by index
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp
index a0a4353..ad00cef 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp
@@ -96,6 +96,21 @@ namespace {
} //setActiveTable
+ /*!
+ Find indices of all elements in an Archicad database. NB: It is assumed that the active database has already been set
+ @return A list of all element IDs in the active database
+ */
+ BIMRecordIDList getAllElementIDs() {
+ GS::Array found;
+ if ((ACAPI_Element_GetElemList({}, &found) != NoError) || found.IsEmpty())
+ return {};
+ BIMRecordIDList result;
+ for (const auto& item : found)
+ result.insert(item);
+ return result;
+ } //getAllElementIDs
+
+
/*!
Make a new element object
@param elementData The API element representation
@@ -287,28 +302,38 @@ void ArchicadElementDBaseEngine::setDefaultTable(const BIMRecordID& tableID) con
Find a filtered list of objects
filter: The object filter (nullptr = find all objects)
+ subset: A subset of the database content to search (specified by record ID)
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: A list containing IDs of found elements (empty if none found)
--------------------------------------------------------------------*/
-BIMRecordIDList ArchicadElementDBaseEngine::findObjects(const Filter& filter, std::optional tableID,
- std::optional documentID) const {
+BIMRecordIDList ArchicadElementDBaseEngine::findObjects(const Filter* filter, const BIMRecordIDList& subset, std::optional tableID,
+ std::optional documentID) const {
//Switch to the target table (when specified). Otherwise the currently active table will be used
if (tableID)
setActiveTable(*tableID);
//First check for no filter (in which case we return all objects)
if (filter == nullptr) {
- GS::Array found;
- if ((ACAPI_Element_GetElemList({}, &found) != NoError) || found.IsEmpty())
- return {};
- BIMRecordIDList result;
- for (const auto& item : found)
- result.insert(item);
- return result;
+ if (!subset.empty())
+ return subset;
+ return getAllElementIDs();
}
- //Implement other filtering as required - ideally identify characteristics supported by API, e.g. filter by type/renovation etc
- return {};
+ BIMRecordIDList buffer, result;
+ //Pick either all records or the specified subset
+ auto source = ⊂
+ if (subset.empty()) {
+ buffer = getAllElementIDs();
+ source = &buffer;
+ }
+ //Run the filter on the specified elements
+ for (const auto& elemID : *source) {
+ if (auto element = getObject(elemID); element) {
+ if ((*filter)(*element))
+ result.insert(elemID);
+ }
+ }
+ return result;
} //ArchicadElementDBaseEngine::findObjects
@@ -423,7 +448,7 @@ active::container::Vector ArchicadElementDBaseEngine::getObjects(const
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
-void ArchicadElementDBaseEngine::write(const Element& object, const BIMRecordID& objID, std::optional objDocID,
+void ArchicadElementDBaseEngine::write(Element& object, const BIMRecordID& objID, std::optional objDocID,
std::optional tableID, std::optional documentID) const {
} //ArchicadElementDBaseEngine::write
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h
index ef50f8c..a8679b5 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h
@@ -92,12 +92,14 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- virtual BIMRecordIDList findObjects(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
- std::optional documentID = std::nullopt) const override;
+ virtual BIMRecordIDList findObjects(const Filter* filter = nullptr, const BIMRecordIDList& subset = {},
+ std::optional tableID = std::nullopt,
+ std::optional documentID = std::nullopt) const override;
/*!
Get an object by index
@param objID The object ID
@@ -138,7 +140,7 @@ namespace speckle::database {
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
- void write(const Element& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
+ void write(Element& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override;
/*!
Erase an object by index
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.cpp
index 18b1123..d05b292 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.cpp
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.cpp
@@ -154,7 +154,7 @@ active::container::Vector ArchicadGroupDBaseEngine::getObjects(const Filt
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 objDocID,
+void ArchicadGroupDBaseEngine::write(Group& object, const BIMRecordID& objID, std::optional objDocID,
std::optional tableID, std::optional documentID) const {
//TODO: Implement
} //ArchicadGroupDBaseEngine::write
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.h
index 629ad0b..59c96c5 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.h
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadGroupDBaseEngine.h
@@ -50,11 +50,13 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
+ virtual ObjIDList findObjects(const Filter* filter = nullptr, const ObjIDList& subset = {},
+ std::optional tableID = std::nullopt,
std::optional documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by ID
@@ -96,7 +98,7 @@ namespace speckle::database {
@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 objDocID = std::nullopt,
+ void write(Group& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override;
/*!
Erase an object by index
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.cpp b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.cpp
index 27e9bd6..f5d77fe 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.cpp
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.cpp
@@ -178,7 +178,7 @@ active::container::Vector ArchicadPropertyDBaseEngine::getObjects(cons
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 objDocID,
+void ArchicadPropertyDBaseEngine::write(Template& object, const BIMRecordID& objID, std::optional objDocID,
std::optional tableID, std::optional documentID) const {
//TODO: Implement
} //ArchicadPropertyDBaseEngine::write
diff --git a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h
index 05a5d92..1cfa27b 100644
--- a/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h
+++ b/SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Property/ArchicadPropertyDBaseEngine.h
@@ -51,11 +51,12 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
+ virtual ObjIDList findObjects(const Filter* filter = nullptr, const ObjIDList& subset = {}, std::optional tableID = std::nullopt,
std::optional documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Find all property templates linked to specified classifications
@@ -103,7 +104,7 @@ namespace speckle::database {
@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 objDocID = std::nullopt,
+ void write(Template& object, const BIMRecordID& objID, std::optional objDocID = std::nullopt,
std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override;
/*!
Erase an object by index
diff --git a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h
index 92dd4d7..88bf31a 100644
--- a/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h
+++ b/SpeckleLib/Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h
@@ -63,11 +63,12 @@ namespace speckle::database {
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
+ @param subset A subset of the database content to search (specified by record ID)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
- virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional tableID = std::nullopt,
+ virtual ObjIDList findObjects(const Filter* filter = nullptr, const ObjIDList& subset = {}, std::optional tableID = std::nullopt,
std::optional documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by index
@@ -109,7 +110,7 @@ namespace speckle::database {
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
- void write(const Obj& object, const ObjID& objID, std::optional objDocID = std::nullopt,
+ void write(Obj& object, const ObjID& objID, std::optional objDocID = std::nullopt,
std::optional tableID = std::nullopt, std::optional documentID = std::nullopt) const override;
/*!
Erase an object by index
@@ -274,7 +275,7 @@ namespace speckle::database {
--------------------------------------------------------------------*/
template
requires DocumentStorable
- void DocumentStoreEngine::write(const Obj& object, const ObjID& objID, std::optional objDocID,
+ void DocumentStoreEngine::write(Obj& object, const ObjID& objID, std::optional objDocID,
std::optional tableID, std::optional documentID) const {
getCache()->write(object); //NB: In future we might support duplicating records if objID != obj.id
} //DocumentStoreEngine::write
diff --git a/SpeckleLib/Speckle/Environment/Addon.cpp b/SpeckleLib/Speckle/Environment/Addon.cpp
index f913940..0c46c22 100644
--- a/SpeckleLib/Speckle/Environment/Addon.cpp
+++ b/SpeckleLib/Speckle/Environment/Addon.cpp
@@ -1,5 +1,6 @@
#include "Speckle/Environment/Addon.h"
+#include "Active/Database/Transaction.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
@@ -10,6 +11,7 @@
#include
#endif
+using namespace active::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::utility;
@@ -228,3 +230,46 @@ std::shared_ptr Addon::makeProject() const {
auto project = new Project; //make_shared can't use protected constructor
return std::shared_ptr{project};
} //Addon::makeProject
+
+
+/*--------------------------------------------------------------------
+ Determine if a transaction can be started
+
+ return: True if a transaction can be started
+ --------------------------------------------------------------------*/
+bool Addon::canTransactionStart() const {
+ return true; //TODO: There are some situations where Archicad cannot accept perform a new transaction - add when determine essential
+} //Addon::canTransactionStart
+
+
+/*--------------------------------------------------------------------
+ Perform a transaction
+
+ transaction: The transaction to perform
+
+ return: True if the transaction was successfully performed
+ --------------------------------------------------------------------*/
+bool Addon::performTransaction(Transaction& transaction) const {
+ //If this is the opening transaction, we need to enclose it in a host undo session
+ if (isPerforming(transaction)) {
+#ifdef ARCHICAD
+ return ACAPI_CallUndoableCommand(String{transaction.getName()}, [&]() -> GSErrCode {
+ if (App::performTransaction(transaction))
+ return NoError;
+ return APIERR_COMMANDFAILED;
+ });
+#endif
+ }
+ return App::performTransaction(transaction);
+} //Addon::performTransaction
+
+
+/*--------------------------------------------------------------------
+ Finalise a transaction
+
+ transaction: The transaction to be finalised
+ wasPerformedSuccessfully: True if the transaction was successfully performed
+ --------------------------------------------------------------------*/
+void Addon::finaliseTransaction(Transaction& transaction, bool wasPerformedSuccessfully) const {
+
+} //Addon::finaliseTransaction
diff --git a/SpeckleLib/Speckle/Environment/Addon.h b/SpeckleLib/Speckle/Environment/Addon.h
index c329e7c..b3d46f3 100644
--- a/SpeckleLib/Speckle/Environment/Addon.h
+++ b/SpeckleLib/Speckle/Environment/Addon.h
@@ -103,6 +103,26 @@ namespace speckle::environment {
*/
virtual std::shared_ptr makeProject() const;
+ // MARK: - Functions (transactions)
+
+ /*!
+ Determine if a transaction can be started
+ @return True if a transaction can be started
+ */
+ bool canTransactionStart() const override;
+ /*!
+ Perform a transaction
+ @param transaction The transaction to perform
+ @return True if the transaction was successfully performed
+ */
+ bool performTransaction(active::database::Transaction& transaction) const override;
+ /*!
+ Finalise a transaction
+ @param transaction The transaction to be finalised
+ @param wasPerformedSuccessfully True if the transaction was successfully performed
+ */
+ void finaliseTransaction(active::database::Transaction& transaction, bool wasPerformedSuccessfully) const override;
+
private:
///The active project
std::shared_ptr m_activeProject;
diff --git a/SpeckleLib/Speckle/Environment/Host.cpp b/SpeckleLib/Speckle/Environment/Host.cpp
index 6046af7..9b1e0a7 100644
--- a/SpeckleLib/Speckle/Environment/Host.cpp
+++ b/SpeckleLib/Speckle/Environment/Host.cpp
@@ -1,5 +1,8 @@
#include "Speckle/Environment/Host.h"
+
#include "Active/Utility/Memory.h"
+#include "Speckle/Environment/Addon.h"
+#include "Speckle/SpeckleResource.h"
#ifdef ARCHICAD
#include "DG.h"
@@ -84,11 +87,32 @@ void Host::zoomToFit(bool isSelectionOnly) const {
--------------------------------------------------------------------*/
void Host::displayAlert(const String& message) const {
#ifdef ARCHICAD
- DGAlert(DG_INFORMATION, "Notification", message.data(), "", "OK");
+ DGAlert(DG_INFORMATION, addon()->getLocalString(titleStringLib, notifyDialogTitleID), message, "",
+ addon()->getLocalString(titleStringLib, okButtonTitleID));
#endif
} //Host::displayAlert
+/*--------------------------------------------------------------------
+ Display a confirmation dialog (prompting the user to pick one of two options)
+
+ question: The question text, e.g. "Do you wish to continue?"
+ positiveOption: The positive option text (nullopt = "Yes")
+ negativeOption: The negative option text (nullopt = "No")
+
+ return: True if the user picked the positive option
+ --------------------------------------------------------------------*/
+bool Host::displayConfirmation(const speckle::utility::String& question,
+ const speckle::utility::String::Option positiveOption,
+ const speckle::utility::String::Option negativeOption) const {
+#ifdef ARCHICAD
+ String positivePrompt{positiveOption.value_or(addon()->getLocalString(titleStringLib, positiveResponseTitleID))},
+ negativePrompt{positiveOption.value_or(addon()->getLocalString(titleStringLib, negativeResponseTitleID))};
+ return (DGAlert(DG_WARNING, addon()->getLocalString(titleStringLib, confirmDialogTitleID), question, String{}, positivePrompt, negativePrompt) == 1);
+#endif
+} //Host::displayConfirmation
+
+
/*--------------------------------------------------------------------
Get an object representing the parent process/application
diff --git a/SpeckleLib/Speckle/Environment/Host.h b/SpeckleLib/Speckle/Environment/Host.h
index 165db17..4c9904b 100644
--- a/SpeckleLib/Speckle/Environment/Host.h
+++ b/SpeckleLib/Speckle/Environment/Host.h
@@ -36,6 +36,17 @@ namespace speckle::environment {
@param message The alert message
*/
void displayAlert(const speckle::utility::String& message) const;
+ /*!
+ Display a confirmation dialog (prompting the user to pick one of two options)
+ @param question The question text, e.g. "Do you wish to continue?"
+ @param positiveOption The positive option text (nullopt = "Yes")
+ @param negativeOption The negative option text (nullopt = "No")
+
+ @return True if the user picked the positive option
+ */
+ bool displayConfirmation(const speckle::utility::String& question,
+ const speckle::utility::String::Option positiveOption = std::nullopt,
+ const speckle::utility::String::Option negativeOption = std::nullopt) const;
// MARK: Functions (mutating)
diff --git a/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.cpp
index c8d3b32..5ecebeb 100644
--- a/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.cpp
+++ b/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.cpp
@@ -33,16 +33,16 @@ namespace {
case APINotifyElement_New: {
// POC: Put this back once we decide to use Object Tracking
// ACAPI_Element_AttachObserver(elemType->elemHead.guid);
- addon()->publishExternal(ElementEvent{newElem, ElementID{elemType->elemHead.guid}});
+ addon()->publishExternal(ElementEvent{newElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Change: {
- addon()->publishExternal(ElementEvent{changeElem, ElementID{elemType->elemHead.guid}});
+ addon()->publishExternal(ElementEvent{changeElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Edit: {
- addon()->publishExternal(ElementEvent{editElem, ElementID{elemType->elemHead.guid}});
+ addon()->publishExternal(ElementEvent{editElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Delete: {
- addon()->publishExternal(ElementEvent{deleteElem, ElementID{ elemType->elemHead.guid}});
+ addon()->publishExternal(ElementEvent{deleteElem, BIMRecordID{ elemType->elemHead.guid}});
} break;
case APINotifyElement_BeginEvents:
addon()->publishExternal(ElementEvent{begin});
diff --git a/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.h
index 164213e..268be17 100644
--- a/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.h
+++ b/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.h
@@ -2,7 +2,7 @@
#define SPECKLE_EVENT_ELEMENT_CHANGED_SUBSCRIBER
#include "Active/Event/Subscriber.h"
-#include "Speckle/Database/Identity/RecordID.h"
+#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::event {
@@ -60,8 +60,6 @@ namespace speckle::event {
@return True if the event should be closed
*/
virtual bool handle(const ElementEvent& event) = 0;
-
- speckle::database::ElementIDList m_changedElements;
};
}
diff --git a/SpeckleLib/Speckle/Event/Type/ElementEvent.h b/SpeckleLib/Speckle/Event/Type/ElementEvent.h
index 31f0c9f..d56d4e0 100644
--- a/SpeckleLib/Speckle/Event/Type/ElementEvent.h
+++ b/SpeckleLib/Speckle/Event/Type/ElementEvent.h
@@ -5,6 +5,7 @@
#include "Active/Utility/Guid.h"
#include "Active/Utility/String.h"
+#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::event {
@@ -33,7 +34,7 @@ namespace speckle::event {
@param eventType An event type identifier
@param targetID The ID of the element targeted by the database transaction (nullopt = undefined, e.g. for a begin/end event)
*/
- ElementEvent(Type eventType, database::ElementID::Option targetID = std::nullopt) : Event{ID}, m_elementID{targetID}, m_eventType{eventType} {}
+ ElementEvent(Type eventType, database::BIMRecordID::Option targetID = std::nullopt) : Event{ID}, m_elementID{targetID}, m_eventType{eventType} {}
/*!
Copy constructor
@param source The object to copy
@@ -50,12 +51,12 @@ namespace speckle::event {
Get the ID of the database transaction target element
@return The target element ID (nullopt = no target, e.g. a begin/end event)
*/
- database::ElementID::Option getElmentID() const { return m_elementID; }
+ database::BIMRecordID::Option getElementID() const { return m_elementID; }
Type getEventType() const { return m_eventType; }
private:
///The ID of the target element (nullopt = undefined)
- database::ElementID::Option m_elementID;
+ database::BIMRecordID::Option m_elementID;
///The specific database operation performed
Type m_eventType;
};
diff --git a/SpeckleLib/Speckle/Interface/Browser/Bridge/BrowserBridge.h b/SpeckleLib/Speckle/Interface/Browser/Bridge/BrowserBridge.h
index 022a44d..ba4ce82 100644
--- a/SpeckleLib/Speckle/Interface/Browser/Bridge/BrowserBridge.h
+++ b/SpeckleLib/Speckle/Interface/Browser/Bridge/BrowserBridge.h
@@ -95,7 +95,7 @@ namespace speckle::interfac::browser::bridge {
}
private:
- ///List of methods supported by the bridge
+ ///Definition of a bridge method container
using BridgedMethods = std::vector>>;
///Methods supported by the bridge
std::unique_ptr m_methods = std::make_unique();
diff --git a/SpeckleLib/Speckle/Interface/Browser/JSFunction.h b/SpeckleLib/Speckle/Interface/Browser/JSFunction.h
index 0044ebf..5ad0b60 100644
--- a/SpeckleLib/Speckle/Interface/Browser/JSFunction.h
+++ b/SpeckleLib/Speckle/Interface/Browser/JSFunction.h
@@ -74,6 +74,8 @@ namespace speckle::interfac::browser {
//Process any returned result into the binding value type
auto processResult = [&, transport](Return* outgoing) -> typename Binding::ValueType {
if constexpr(!std::is_same::value) {
+ if (outgoing == nullptr)
+ throw; //NB: Throw a system exception here in future with a defined error
typename Binding::ValueType result;
transport.send(std::move(*outgoing), active::serialise::Identity{}, result);
return result;
diff --git a/SpeckleLib/Speckle/Record/Attribute/Attribute.h b/SpeckleLib/Speckle/Record/Attribute/Attribute.h
index ee4f684..372df5d 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Attribute.h
+++ b/SpeckleLib/Speckle/Record/Attribute/Attribute.h
@@ -4,6 +4,10 @@
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Utility/String.h"
+namespace speckle::database {
+ class ArchicadAttributeDBaseEngine;
+}
+
namespace speckle::record::attribute {
/*!
@@ -106,11 +110,18 @@ namespace speckle::record::attribute {
protected:
#ifdef ARCHICAD
+ friend class speckle::database::ArchicadAttributeDBaseEngine;
+
/*!
Get the attribute data from the host BIM application
@return The attribute data (for internal use to populate derived classes)
*/
API_Attribute getData() const;
+ /*!
+ Get the attribute data to be written to the database
+ @return The attribute data (for internal use to write to the database)
+ */
+ virtual API_Attribute getDataOut() const = 0;
#endif
};
diff --git a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp
index ac028a6..b9dc137 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp
+++ b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp
@@ -275,6 +275,20 @@ bool Finish::validate() {
} //Finish::validate
+/*--------------------------------------------------------------------
+ Get the attribute data to be written to the database
+
+ return: The attribute data (for internal use to write to the database)
+ --------------------------------------------------------------------*/
+API_Attribute Finish::getDataOut() const {
+ confirmData();
+ API_Attribute result;
+ active::utility::Memory::erase(result);
+ result.material = m_data->root;
+ return result;
+} //Finish::getDataOut
+
+
/*--------------------------------------------------------------------
Confirm the internal data, either loading from the BIM application or setting a default
--------------------------------------------------------------------*/
diff --git a/SpeckleLib/Speckle/Record/Attribute/Finish.h b/SpeckleLib/Speckle/Record/Attribute/Finish.h
index c1aaffd..e12b42a 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Finish.h
+++ b/SpeckleLib/Speckle/Record/Attribute/Finish.h
@@ -135,7 +135,14 @@ namespace speckle::record::attribute {
@return True if the data has been validated
*/
bool validate() override;
-
+
+ protected:
+ /*!
+ Get the attribute data to be written to the database
+ @return The attribute data (for internal use to write to the database)
+ */
+ API_Attribute getDataOut() const override;
+
private:
/*!
Confirm the internal data, either loading from the BIM application or setting a default
diff --git a/SpeckleLib/Speckle/Record/Attribute/Layer.cpp b/SpeckleLib/Speckle/Record/Attribute/Layer.cpp
new file mode 100644
index 0000000..a46e1a6
--- /dev/null
+++ b/SpeckleLib/Speckle/Record/Attribute/Layer.cpp
@@ -0,0 +1,293 @@
+#include "Speckle/Record/Attribute/Layer.h"
+
+#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
+#include "Active/Serialise/Management/Management.h"
+#include "Active/Serialise/CargoHold.h"
+#include "Active/Utility/BufferOut.h"
+#include "Speckle/Serialise/Types/ArchicadRGB.h"
+#include "Speckle/Utility/Guid.h"
+
+using namespace active::serialise;
+using namespace speckle::database;
+using namespace speckle::record::attribute;
+using namespace speckle::utility;
+
+#include
+#include
+
+namespace speckle::record::attribute {
+
+ ///Internal representation of a rendered layer on a 3D body, i.e. the surface colour/texture etc.
+ class Layer::Data {
+ public:
+#ifdef ARCHICAD
+ /*!
+ Constructor from Archicad surface material
+ @param attr An Archicad attribute
+ */
+ Data(const API_Attribute& attr) : root{attr.layer} {
+ isHidden = root.head.flags & APILay_Hidden;
+ isLocked = root.head.flags & APILay_Locked;
+ }
+
+ ///Archicad representation of a layer
+ API_LayerType root;
+#endif
+ ///True if the layer is hidden
+ bool isHidden = false;
+ ///True if the layer is locked
+ bool isLocked = false;
+ };
+
+}
+
+namespace {
+
+ ///Serialisation fields
+ enum FieldIndex {
+ hiddenID,
+ lockedID,
+ };
+
+ ///Serialisation field IDs
+ static std::array fieldID = {
+ Identity{"hidden"},
+ Identity{"locked"},
+ };
+
+}
+
+/*--------------------------------------------------------------------
+ Default constructor
+ --------------------------------------------------------------------*/
+Layer::Layer() {
+} //Layer::Layer
+
+
+/*--------------------------------------------------------------------
+ Constructor
+
+ ID: The attribute ID
+ --------------------------------------------------------------------*/
+Layer::Layer(const database::BIMRecordID& ID) : base{ID, Layer::table} {
+} //Layer::Layer
+
+
+#ifdef ARCHICAD
+/*--------------------------------------------------------------------
+ Constructor
+
+ attrData: Archicad attribute data
+ tableID: The ID of the parent table
+ --------------------------------------------------------------------*/
+Layer::Layer(const API_Attribute& attrData, const BIMRecordID& tableID) : base{attrData.header.guid, Layer::table} {
+ m_data = std::make_unique(attrData);
+ setUnit(std::nullopt); //Layeres have no unit
+}
+#endif
+
+
+/*--------------------------------------------------------------------
+ Copy constructor
+
+ source: The object to copy
+ --------------------------------------------------------------------*/
+Layer::Layer(const Layer& source) : base{source} {
+ m_data = source.m_data ? std::make_unique(*source.m_data) : nullptr;
+} //Layer::Layer
+
+
+/*--------------------------------------------------------------------
+ Destructor
+ --------------------------------------------------------------------*/
+Layer::~Layer() {}
+
+
+/*--------------------------------------------------------------------
+ Assignment operator
+
+ source: The object to assign
+
+ return: A reference to this
+ --------------------------------------------------------------------*/
+Layer& Layer::operator=(const Layer& source) {
+ if (this != &source) {
+ base::operator=(source);
+ m_data = source.m_data ? std::make_unique(*source.m_data) : nullptr;
+ }
+ return *this;
+} //Layer::operator=
+
+
+/*--------------------------------------------------------------------
+ Determine if the layer is hidden
+
+ return: True if the layer is hidden
+ --------------------------------------------------------------------*/
+bool Layer::isHidden() const {
+ confirmData();
+ return m_data->isHidden;
+} //Layer::isHidden
+
+
+/*--------------------------------------------------------------------
+ Determine if the layer is locked
+
+ return: True if the layer is locked
+ --------------------------------------------------------------------*/
+bool Layer::isLocked() const {
+ confirmData();
+ return m_data->isLocked;
+} //Layer::isLocked
+
+
+#ifdef ARCHICAD
+/*--------------------------------------------------------------------
+ Get the (immutable) API attribute header data
+
+ return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
+ --------------------------------------------------------------------*/
+const API_Attr_Head& Layer::getHead() const {
+ confirmData();
+ return m_data->root.head;
+} //Layer::getHead
+#endif
+
+
+/*--------------------------------------------------------------------
+ Set whether the layer is hidden
+
+ state: True if the layer is hidden
+ --------------------------------------------------------------------*/
+void Layer::setHidden(bool state) {
+ confirmData();
+ m_data->isHidden = state;
+#ifdef ARCHICAD
+ if (state)
+ m_data->root.head.flags |= APILay_Hidden;
+ else
+ m_data->root.head.flags &= ~APILay_Hidden;
+#endif
+} //Layer::setHidden
+
+
+/*--------------------------------------------------------------------
+ Set whether the layer is locked
+
+ state: True if the layer is locked
+ --------------------------------------------------------------------*/
+void Layer::setLocked(bool state) {
+ confirmData();
+ m_data->isLocked = state;
+#ifdef ARCHICAD
+ if (state)
+ m_data->root.head.flags |= APILay_Locked;
+ else
+ m_data->root.head.flags &= ~APILay_Locked;
+#endif
+} //Layer::setLocked
+
+
+#ifdef ARCHICAD
+/*--------------------------------------------------------------------
+ Get the (mutable) API attribute header data
+
+ return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
+ --------------------------------------------------------------------*/
+API_Attr_Head& Layer::getHead() {
+ confirmData();
+ return m_data->root.head;
+} //Layer::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 Layer::fillInventory(Inventory& inventory) const {
+ using enum Entry::Type;
+ inventory.merge(Inventory{
+ {
+ { fieldID[hiddenID], hiddenID, element },
+ { fieldID[lockedID], lockedID, element },
+ },
+ }.withType(&typeid(Layer)));
+ return base::fillInventory(inventory);
+} //Layer::fillInventory
+
+
+/*--------------------------------------------------------------------
+ Get the specified cargo
+
+ item: The inventory item to retrieve
+
+ return: The requested cargo (nullptr on failure)
+ --------------------------------------------------------------------*/
+Cargo::Unique Layer::getCargo(const Inventory::Item& item) const {
+ if (item.ownerType != &typeid(Layer))
+ return base::getCargo(item);
+ confirmData();
+ using namespace active::serialise;
+ switch (item.index) {
+ case hiddenID:
+ return std::make_unique(m_data->isHidden);
+ case lockedID:
+ return std::make_unique(m_data->isLocked);
+ default:
+ return nullptr; //Requested an unknown index
+ }
+} //Layer::getCargo
+
+
+/*--------------------------------------------------------------------
+ Set to the default package content
+ --------------------------------------------------------------------*/
+void Layer::setDefault() {
+ m_data->root = {};
+ m_data->isHidden = false;
+ m_data->isLocked = false;
+} //Layer::setDefault
+
+
+/*--------------------------------------------------------------------
+ Validate the cargo data
+
+ return: True if the data has been validated
+ --------------------------------------------------------------------*/
+bool Layer::validate() {
+#ifdef ARCHICAD
+ if (m_data->isHidden)
+ m_data->root.head.flags |= APILay_Hidden;
+ if (m_data->isLocked)
+ m_data->root.head.flags |= APILay_Locked;
+#endif
+ return true;
+} //Layer::validate
+
+
+/*--------------------------------------------------------------------
+ Get the attribute data to be written to the database
+
+ return: The attribute data (for internal use to write to the database)
+ --------------------------------------------------------------------*/
+API_Attribute Layer::getDataOut() const {
+ confirmData();
+ API_Attribute result;
+ active::utility::Memory::erase(result);
+ result.layer = m_data->root;
+ return result;
+} //Layer::getDataOut
+
+
+/*--------------------------------------------------------------------
+ Confirm the internal data, either loading from the BIM application or setting a default
+ --------------------------------------------------------------------*/
+void Layer::confirmData() const {
+ if (m_data)
+ return;
+ m_data = std::make_unique(getData());
+} //Layer::confirmData
diff --git a/SpeckleLib/Speckle/Record/Attribute/Layer.h b/SpeckleLib/Speckle/Record/Attribute/Layer.h
new file mode 100644
index 0000000..1c13719
--- /dev/null
+++ b/SpeckleLib/Speckle/Record/Attribute/Layer.h
@@ -0,0 +1,174 @@
+#ifndef SPECKLE_RECORD_ATTRIBUTE_LAYER
+#define SPECKLE_RECORD_ATTRIBUTE_LAYER
+
+#include "Speckle/Record/Attribute/Attribute.h"
+
+#ifdef ARCHICAD
+namespace ModelerAPI {
+ class Layer;
+}
+#endif
+
+namespace speckle::record::attribute {
+
+ /*!
+ Class to represent the rendered layer on a 3D body, i.e. the surface colour/texture etc.
+
+ In Archicad this attribute is represented by `API_LayerType`
+ */
+ class Layer : public Attribute {
+ public:
+
+ // MARK: - Types
+
+ using base = Attribute;
+ ///Unique pointer
+ using Unique = std::unique_ptr;
+ ///Shared pointer
+ using Shared = std::shared_ptr;
+ ///Optional
+ using Option = std::optional;
+
+ // MARK: - Constants
+
+#ifdef ARCHICAD
+ ///The layeres table identifier
+ static constexpr active::utility::Guid table{active::utility::Guid::fromInt(API_LayerID)};
+#endif
+
+ // MARK: - Constructors
+
+ using base::base;
+
+ /*!
+ Default constructor
+ */
+ Layer();
+ /*!
+ Constructor
+ @param ID The attribute ID
+ */
+ Layer(const database::BIMRecordID& ID);
+#ifdef ARCHICAD
+ /*!
+ Constructor
+ @param attrData Archicad attribute data
+ @param tableID The ID of the parent table
+ */
+ Layer(const API_Attribute& attrData, const database::BIMRecordID& tableID);
+#endif
+ /*!
+ Copy constructor
+ @param source The object to copy
+ */
+ Layer(const Layer& source);
+ /*!
+ Destructor
+ */
+ ~Layer();
+
+ /*!
+ Object cloning
+ @return A clone of this object
+ */
+ Layer* clonePtr() const override { return new Layer{*this}; }
+
+ // MARK: - Operators
+
+ /*!
+ Assignment operator
+ @param source The object to assign
+ @return A reference to this
+ */
+ Layer& operator=(const Layer& source);
+
+ // MARK: - Functions (const)
+
+ /*!
+ Determine if the layer is hidden
+ @return True if the layer is hidden
+ */
+ bool isHidden() const;
+ /*!
+ Determine if the layer is locked
+ @return True if the layer is locked
+ */
+ bool isLocked() const;
+ /*!
+ Get the speckle type identifier
+ @return The speckle type (relevant objects should override as required)
+ */
+ speckle::utility::String getSpeckleType() const override { return "Objects.Other.Layer"; }
+#ifdef ARCHICAD
+ /*!
+ Get the (immutable) API attribute header data
+ @return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
+ */
+ const API_Attr_Head& getHead() const override;
+#endif
+
+ // MARK: - Functions (mutating)
+
+ /*!
+ Set whether the layer is hidden
+ @param state True if the layer is hidden
+ */
+ void setHidden(bool state);
+ /*!
+ Set whether the layer is locked
+ @param state True if the layer is locked
+ */
+ void setLocked(bool state);
+#ifdef ARCHICAD
+ /*!
+ Get the (mutable) API attribute header data
+ @return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
+ */
+ API_Attr_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;
+ /*!
+ Validate the cargo data
+ @return True if the data has been validated
+ */
+ bool validate() override;
+
+ protected:
+ /*!
+ Get the attribute data to be written to the database
+ @return The attribute data (for internal use to write to the database)
+ */
+ API_Attribute getDataOut() const override;
+
+ private:
+ /*!
+ Confirm the internal data, either loading from the BIM application or setting a default
+ */
+ void confirmData() const;
+
+ class Data;
+ ///The attribute data - mutable to support lazy loading
+ mutable std::unique_ptr m_data;
+ };
+
+}
+
+#endif //SPECKLE_RECORD_ATTRIBUTE_LAYER
diff --git a/SpeckleLib/Speckle/Record/Attribute/Material.cpp b/SpeckleLib/Speckle/Record/Attribute/Material.cpp
index 13e6142..d623dcc 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Material.cpp
+++ b/SpeckleLib/Speckle/Record/Attribute/Material.cpp
@@ -186,6 +186,20 @@ void Material::setDefault() {
} //Material::setDefault
+/*--------------------------------------------------------------------
+ Get the attribute data to be written to the database
+
+ return: The attribute data (for internal use to write to the database)
+ --------------------------------------------------------------------*/
+API_Attribute Material::getDataOut() const {
+ confirmData();
+ API_Attribute result;
+ active::utility::Memory::erase(result);
+ result.buildingMaterial = m_data->root;
+ return result;
+} //Material::getDataOut
+
+
/*--------------------------------------------------------------------
Confirm the internal data, either loading from the BIM application or setting a default
--------------------------------------------------------------------*/
diff --git a/SpeckleLib/Speckle/Record/Attribute/Material.h b/SpeckleLib/Speckle/Record/Attribute/Material.h
index fd5b0f6..2273c28 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Material.h
+++ b/SpeckleLib/Speckle/Record/Attribute/Material.h
@@ -126,7 +126,14 @@ namespace speckle::record::attribute {
Set to the default package content
*/
void setDefault() override;
-
+
+ protected:
+ /*!
+ Get the attribute data to be written to the database
+ @return The attribute data (for internal use to write to the database)
+ */
+ API_Attribute getDataOut() const override;
+
private:
/*!
Confirm the internal data, either loading from the BIM application or setting a default
diff --git a/SpeckleLib/Speckle/Record/Attribute/Storey.cpp b/SpeckleLib/Speckle/Record/Attribute/Storey.cpp
index 69ec24b..f37921c 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Storey.cpp
+++ b/SpeckleLib/Speckle/Record/Attribute/Storey.cpp
@@ -185,6 +185,18 @@ void Storey::setDefault() {
} //Storey::setDefault
+/*--------------------------------------------------------------------
+ Get the attribute data to be written to the database
+
+ return: The attribute data (for internal use to write to the database)
+ --------------------------------------------------------------------*/
+API_Attribute Storey::getDataOut() const {
+ API_Attribute result;
+ active::utility::Memory::erase(result);
+ return result;
+} //Storey::getDataOut
+
+
/*--------------------------------------------------------------------
Confirm the internal data, either loading from the BIM application or setting a default
--------------------------------------------------------------------*/
diff --git a/SpeckleLib/Speckle/Record/Attribute/Storey.h b/SpeckleLib/Speckle/Record/Attribute/Storey.h
index e009eec..4ef24b5 100644
--- a/SpeckleLib/Speckle/Record/Attribute/Storey.h
+++ b/SpeckleLib/Speckle/Record/Attribute/Storey.h
@@ -104,6 +104,13 @@ namespace speckle::record::attribute {
*/
void setDefault() override;
+ protected:
+ /*!
+ Get the attribute data to be written to the database
+ @return The attribute data (for internal use to write to the database)
+ */
+ API_Attribute getDataOut() const override;
+
private:
/*!
Confirm the internal data, either loading from the BIM application or setting a default
diff --git a/SpeckleLib/Speckle/Record/Element/Element.cpp b/SpeckleLib/Speckle/Record/Element/Element.cpp
index 62430b4..6d04d50 100644
--- a/SpeckleLib/Speckle/Record/Element/Element.cpp
+++ b/SpeckleLib/Speckle/Record/Element/Element.cpp
@@ -160,6 +160,22 @@ Element::Element(Element&& source) : base{source} {
Element::~Element() {}
+/*--------------------------------------------------------------------
+ Get the element layer
+
+ return: The element layer (nullopt if not applicable to the element)
+ --------------------------------------------------------------------*/
+Layer::Option Element::getLayer() const {
+#ifdef ARCHICAD
+#ifdef ServerMainVers_2700
+ return Layer{ Guid::fromInt(getHead().layer.GenerateHashValue()) };
+#else
+ return Layer{ Guid::fromInt(getHead().layer) };
+#endif
+#endif
+} //Element::getLayer
+
+
/*--------------------------------------------------------------------
Get the element storey
diff --git a/SpeckleLib/Speckle/Record/Element/Element.h b/SpeckleLib/Speckle/Record/Element/Element.h
index 073019f..4740f65 100644
--- a/SpeckleLib/Speckle/Record/Element/Element.h
+++ b/SpeckleLib/Speckle/Record/Element/Element.h
@@ -2,8 +2,9 @@
#define SPECKLE_RECORD_ELEMENT
#include "Speckle/Database/Content/BIMRecord.h"
-#include "Speckle/Record/Element/Interface/Part.h"
+#include "Speckle/Record/Attribute/Layer.h"
#include "Speckle/Record/Attribute/Storey.h"
+#include "Speckle/Record/Element/Interface/Part.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
@@ -71,6 +72,11 @@ namespace speckle::record::element {
@return The type name
*/
virtual speckle::utility::String getTypeName() const;
+ /*!
+ Get the element layer
+ @return The element layer (nullopt if not applicable to the element)
+ */
+ record::attribute::Layer::Option getLayer() const;
/*!
Get the element storey
@return The element storey (nullopt if the element isn't linked to a storey)
diff --git a/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.cpp b/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.cpp
new file mode 100644
index 0000000..9e52274
--- /dev/null
+++ b/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.cpp
@@ -0,0 +1,21 @@
+#include "Speckle/Record/Filter/ElementVisibilityCollector.h"
+
+using namespace speckle::record;
+using namespace speckle::utility;
+
+/*--------------------------------------------------------------------
+ Apply the filter to a specified element
+
+ element: The target element
+
+ return: True if the element passed the filter. NB: Always false in this case - its role is data collection using a filter interface
+ --------------------------------------------------------------------*/
+bool ElementVisibilityCollector::operator()(const speckle::record::element::Element& element) const {
+ auto layer = element.getLayer();
+ if (layer)
+ m_layers.insert({layer->getBIMID(), *layer});
+ auto storey = element.getStorey();
+ if (storey)
+ m_storeys.insert({storey->getBIMID(), *storey});
+ return false;
+} //ElementVisibilityCollector::operator()
diff --git a/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.h b/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.h
new file mode 100644
index 0000000..42eeb53
--- /dev/null
+++ b/SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.h
@@ -0,0 +1,56 @@
+#ifndef CONNECTOR_ELEMENT_VISIBILTITY_COLLECTOR
+#define CONNECTOR_ELEMENT_VISIBILTITY_COLLECTOR
+
+#include "Speckle/Record/Attribute/Layer.h"
+#include "Speckle/Record/Attribute/Storey.h"
+#include "Speckle/Database/Storage/Element/ElementStorage.h"
+
+namespace speckle::record {
+
+ /*!
+ Element layer/storey collector
+
+ The collector uses a filter interface for easy integration with an element database, but does not actually provide any filtering behaviour
+ */
+ class ElementVisibilityCollector : public speckle::database::ElementStorage::Filter {
+ public:
+
+ // MARK: - Types
+
+ ///A set of layers
+ using Layers = std::unordered_map;
+ ///A set of storeys
+ using Storeys = std::unordered_map;
+
+ // MARK: - Operators
+
+ /*!
+ Apply the filter to a specified element
+ @param element The target element
+ @return True if the element passed the filter. NB: Always false in this case - its role is data collection using a filter interface
+ */
+ bool operator()(const speckle::record::element::Element& element) const;
+
+ // MARK: - Functions (const)
+
+ /*!
+ Get the layers collection from filtered elements
+ @return The collected layers
+ */
+ Layers& getLayers() const { return m_layers; }
+ /*!
+ Get the storeys collection from filtered elements
+ @return The collected storeys
+ */
+ Storeys& getStoreys() const { return m_storeys; }
+
+ private:
+ ///Layers collected from elements
+ mutable Layers m_layers;
+ ///Storeys collected from elements
+ mutable Storeys m_storeys;
+ };
+
+}
+
+#endif //CONNECTOR_ELEMENT_VISIBILTITY_COLLECTOR
diff --git a/SpeckleLib/Speckle/Serialise/JSBase/JSBaseTransport.cpp b/SpeckleLib/Speckle/Serialise/JSBase/JSBaseTransport.cpp
index 294a3da..b36d76f 100644
--- a/SpeckleLib/Speckle/Serialise/JSBase/JSBaseTransport.cpp
+++ b/SpeckleLib/Speckle/Serialise/JSBase/JSBaseTransport.cpp
@@ -397,7 +397,7 @@ namespace {
isWrapperTag = !identity.name.empty() && !inventory.begin()->identity().name.empty() && (inventory.begin()->identity() != identity);
}
auto sequence = inventory.sequence();
- auto container = destination;
+ auto container{destination};
if (isWrapperTag) {
auto containerType = cargo.entryType().value_or((inventory.size() == 1) && !(inventory.begin()->maximum() == 1) ?
Entry::Type::array : Entry::Type::element);
@@ -411,7 +411,7 @@ namespace {
destination = container;
}
for (auto& entry : sequence) {
- auto item = *entry.second;
+ auto item{*entry.second};
if (!item.required)
continue;
//Each cargo container may contain multiple export items
diff --git a/SpeckleLib/Speckle/SpeckleResource.h b/SpeckleLib/Speckle/SpeckleResource.h
index fe63be4..8454e8b 100755
--- a/SpeckleLib/Speckle/SpeckleResource.h
+++ b/SpeckleLib/Speckle/SpeckleResource.h
@@ -16,6 +16,11 @@ enum SpeckleTitleString {
untitledProjectID = 1,
unknownElementTypeID,
conversionProgressID,
+ notifyDialogTitleID,
+ confirmDialogTitleID,
+ positiveResponseTitleID,
+ negativeResponseTitleID,
+ okButtonTitleID,
};
diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj
index 9b3962f..48672c9 100644
--- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj
+++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj
@@ -722,6 +722,22 @@
21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */; };
21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */; };
21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDE42C943D3F0077E104 /* RecordID.h */; };
+ 21F0AE312CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */; };
+ 21F0AE322CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */; };
+ 21F0AE332CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */; };
+ 21F0AE342CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */; };
+ 21F0AE352CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */; };
+ 21F0AE362CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */; };
+ 21F0AE372CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */; };
+ 21F0AE382CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */; };
+ 21F0AE3D2CEB91F9003AD722 /* Layer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */; };
+ 21F0AE3E2CEB91F9003AD722 /* Layer.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE3B2CEB91F9003AD722 /* Layer.h */; };
+ 21F0AE3F2CEB91F9003AD722 /* Layer.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE3B2CEB91F9003AD722 /* Layer.h */; };
+ 21F0AE402CEB91F9003AD722 /* Layer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */; };
+ 21F0AE412CEB91F9003AD722 /* Layer.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE3B2CEB91F9003AD722 /* Layer.h */; };
+ 21F0AE422CEB91F9003AD722 /* Layer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */; };
+ 21F0AE432CEB91F9003AD722 /* Layer.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F0AE3B2CEB91F9003AD722 /* Layer.h */; };
+ 21F0AE442CEB91F9003AD722 /* Layer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */; };
21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; };
21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; };
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; };
@@ -965,6 +981,10 @@
21D0BDC32C9241940077E104 /* ProjectSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectSubscriber.h; sourceTree = ""; };
21D0BDC62C9245E40077E104 /* ProjectEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectEvent.h; sourceTree = ""; };
21D0BDE42C943D3F0077E104 /* RecordID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordID.h; sourceTree = ""; };
+ 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ElementVisibilityCollector.h; sourceTree = ""; };
+ 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ElementVisibilityCollector.cpp; sourceTree = ""; };
+ 21F0AE3B2CEB91F9003AD722 /* Layer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Layer.h; sourceTree = ""; };
+ 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Layer.cpp; sourceTree = ""; };
21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = ""; };
21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = ""; };
21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = ""; };
@@ -1180,8 +1200,8 @@
215F088A2CA195EC00CD343B /* ArchicadDBase */ = {
isa = PBXGroup;
children = (
- 215F08872CA195EC00CD343B /* ArchicadDBaseCore.cpp */,
215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */,
+ 215F08872CA195EC00CD343B /* ArchicadDBaseCore.cpp */,
2196F2EA2CB4816B00450DFC /* Attribute */,
219246062CA2D22D00CF5703 /* Element */,
21A890C12CC171D80087E732 /* Property */,
@@ -1297,6 +1317,8 @@
2196F2EE2CB4823C00450DFC /* Attribute.h */,
2196F2F32CB483D600450DFC /* Finish.cpp */,
2196F2F22CB483D600450DFC /* Finish.h */,
+ 21F0AE3C2CEB91F9003AD722 /* Layer.cpp */,
+ 21F0AE3B2CEB91F9003AD722 /* Layer.h */,
21384BEB2CD3EBE200D4602B /* Material.cpp */,
21384BEA2CD3EBE200D4602B /* Material.h */,
2196F3032CB57E7F00450DFC /* Storey.cpp */,
@@ -1531,6 +1553,15 @@
path = Storage;
sourceTree = "";
};
+ 21F0AE302CEB7045003AD722 /* Filter */ = {
+ isa = PBXGroup;
+ children = (
+ 21F0AE2F2CEB7045003AD722 /* ElementVisibilityCollector.cpp */,
+ 21F0AE2E2CEB7045003AD722 /* ElementVisibilityCollector.h */,
+ );
+ path = Filter;
+ sourceTree = "";
+ };
21F69F1A2C6A0FE2008B6A06 /* Browser */ = {
isa = PBXGroup;
children = (
@@ -1619,6 +1650,7 @@
21AE196D2CC64D37004DBCFC /* Classification */,
21F69F942C71087A008B6A06 /* Credentials */,
215F087A2CA18E1400CD343B /* Element */,
+ 21F0AE302CEB7045003AD722 /* Filter */,
21AE194E2CC273F1004DBCFC /* Property */,
);
path = Record;
@@ -1695,6 +1727,7 @@
21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */,
21384C192CD585A600D4602B /* Roof.h in Headers */,
21AE19802CC7D265004DBCFC /* PropertiedWrapper.h in Headers */,
+ 21F0AE3F2CEB91F9003AD722 /* Layer.h in Headers */,
21CE99132CE5EF670076522F /* StructuredStair.h in Headers */,
2199BB842CDE508800A4BEEC /* UserCancel.h in Headers */,
21A0FC0B2CBE5E220023F24E /* Segment.h in Headers */,
@@ -1729,6 +1762,7 @@
21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */,
21384BFC2CD52C7500D4602B /* Conversion.h in Headers */,
21CE99092CE563C60076522F /* Treads.h in Headers */,
+ 21F0AE372CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */,
21AE19842CC7D517004DBCFC /* PropertyWrapper.h in Headers */,
21A0FC052CBE59A80023F24E /* SegmentedColumn.h in Headers */,
21A0FC0F2CBE92F10023F24E /* ModelElement.h in Headers */,
@@ -1790,6 +1824,7 @@
21BD7A812CE23FA800526AD1 /* FinishCollector.h in Headers */,
21BD7A822CE23FA800526AD1 /* Roof.h in Headers */,
21BD7A832CE23FA800526AD1 /* PropertiedWrapper.h in Headers */,
+ 21F0AE3E2CEB91F9003AD722 /* Layer.h in Headers */,
21CE99152CE5EF670076522F /* StructuredStair.h in Headers */,
21BD7A842CE23FA800526AD1 /* UserCancel.h in Headers */,
21BD7A852CE23FA800526AD1 /* Segment.h in Headers */,
@@ -1824,6 +1859,7 @@
21BD7AA22CE23FA800526AD1 /* ArchicadRGB.h in Headers */,
21BD7AA32CE23FA800526AD1 /* Conversion.h in Headers */,
21CE990B2CE563C60076522F /* Treads.h in Headers */,
+ 21F0AE362CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */,
21BD7AA42CE23FA800526AD1 /* PropertyWrapper.h in Headers */,
21BD7AA52CE23FA800526AD1 /* SegmentedColumn.h in Headers */,
21BD7AA62CE23FA800526AD1 /* ModelElement.h in Headers */,
@@ -1885,6 +1921,7 @@
21CE8A012CE4F2860076522F /* FinishCollector.h in Headers */,
21CE8A022CE4F2860076522F /* Roof.h in Headers */,
21CE8A032CE4F2860076522F /* PropertiedWrapper.h in Headers */,
+ 21F0AE432CEB91F9003AD722 /* Layer.h in Headers */,
21CE99142CE5EF670076522F /* StructuredStair.h in Headers */,
21CE8A042CE4F2860076522F /* UserCancel.h in Headers */,
21CE8A052CE4F2860076522F /* Segment.h in Headers */,
@@ -1919,6 +1956,7 @@
21CE8A222CE4F2860076522F /* ArchicadRGB.h in Headers */,
21CE8A232CE4F2860076522F /* Conversion.h in Headers */,
21CE990A2CE563C60076522F /* Treads.h in Headers */,
+ 21F0AE332CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */,
21CE8A242CE4F2860076522F /* PropertyWrapper.h in Headers */,
21CE8A252CE4F2860076522F /* SegmentedColumn.h in Headers */,
21CE8A262CE4F2860076522F /* ModelElement.h in Headers */,
@@ -1980,6 +2018,7 @@
21CE8D432CE5134E0076522F /* FinishCollector.h in Headers */,
21CE8D442CE5134E0076522F /* Roof.h in Headers */,
21CE8D452CE5134E0076522F /* PropertiedWrapper.h in Headers */,
+ 21F0AE412CEB91F9003AD722 /* Layer.h in Headers */,
21CE99122CE5EF670076522F /* StructuredStair.h in Headers */,
21CE8D462CE5134E0076522F /* UserCancel.h in Headers */,
21CE8D472CE5134E0076522F /* Segment.h in Headers */,
@@ -2014,6 +2053,7 @@
21CE8D642CE5134E0076522F /* ArchicadRGB.h in Headers */,
21CE8D652CE5134E0076522F /* Conversion.h in Headers */,
21CE99082CE563C60076522F /* Treads.h in Headers */,
+ 21F0AE312CEB7045003AD722 /* ElementVisibilityCollector.h in Headers */,
21CE8D662CE5134E0076522F /* PropertyWrapper.h in Headers */,
21CE8D672CE5134E0076522F /* SegmentedColumn.h in Headers */,
21CE8D682CE5134E0076522F /* ModelElement.h in Headers */,
@@ -2113,7 +2153,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
- LastUpgradeCheck = 1510;
+ LastUpgradeCheck = 1610;
TargetAttributes = {
21379E072AE47A6400A1584C = {
CreatedOnToolsVersion = 15.0;
@@ -2179,6 +2219,7 @@
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */,
2196F2F02CB4823C00450DFC /* Attribute.cpp in Sources */,
21CE992D2CE622FC0076522F /* StairStructure.cpp in Sources */,
+ 21F0AE382CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */,
21384C032CD57CA500D4602B /* Wall.cpp in Sources */,
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */,
21CE98F12CE5539B0076522F /* StairRiser.cpp in Sources */,
@@ -2237,6 +2278,7 @@
21384BE82CD3DD6200D4602B /* MaterialQuantity.cpp in Sources */,
21AE19622CC2D358004DBCFC /* Setting.cpp in Sources */,
219351B32C62CC1A00E5A69C /* String.cpp in Sources */,
+ 21F0AE402CEB91F9003AD722 /* Layer.cpp in Sources */,
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */,
21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */,
21A0FC112CBEE5C30023F24E /* Part.cpp in Sources */,
@@ -2279,6 +2321,7 @@
21BD7ABC2CE23FA800526AD1 /* MenuSubscriber.cpp in Sources */,
21BD7ABD2CE23FA800526AD1 /* Attribute.cpp in Sources */,
21CE992F2CE622FC0076522F /* StairStructure.cpp in Sources */,
+ 21F0AE352CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */,
21BD7ABE2CE23FA800526AD1 /* Wall.cpp in Sources */,
21BD7ABF2CE23FA800526AD1 /* GetBindingsMethodNames.cpp in Sources */,
21CE98F32CE5539B0076522F /* StairRiser.cpp in Sources */,
@@ -2337,6 +2380,7 @@
21BD7AEF2CE23FA800526AD1 /* MaterialQuantity.cpp in Sources */,
21BD7AF02CE23FA800526AD1 /* Setting.cpp in Sources */,
21BD7AF12CE23FA800526AD1 /* String.cpp in Sources */,
+ 21F0AE3D2CEB91F9003AD722 /* Layer.cpp in Sources */,
21BD7AF22CE23FA800526AD1 /* Guid.cpp in Sources */,
21BD7AF32CE23FA800526AD1 /* BrowserBridge.cpp in Sources */,
21BD7AF42CE23FA800526AD1 /* Part.cpp in Sources */,
@@ -2379,6 +2423,7 @@
21CE8A3C2CE4F2860076522F /* MenuSubscriber.cpp in Sources */,
21CE8A3D2CE4F2860076522F /* Attribute.cpp in Sources */,
21CE992E2CE622FC0076522F /* StairStructure.cpp in Sources */,
+ 21F0AE342CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */,
21CE8A3E2CE4F2860076522F /* Wall.cpp in Sources */,
21CE8A3F2CE4F2860076522F /* GetBindingsMethodNames.cpp in Sources */,
21CE98F22CE5539B0076522F /* StairRiser.cpp in Sources */,
@@ -2437,6 +2482,7 @@
21CE8A6F2CE4F2860076522F /* MaterialQuantity.cpp in Sources */,
21CE8A702CE4F2860076522F /* Setting.cpp in Sources */,
21CE8A712CE4F2860076522F /* String.cpp in Sources */,
+ 21F0AE442CEB91F9003AD722 /* Layer.cpp in Sources */,
21CE8A722CE4F2860076522F /* Guid.cpp in Sources */,
21CE8A732CE4F2860076522F /* BrowserBridge.cpp in Sources */,
21CE8A742CE4F2860076522F /* Part.cpp in Sources */,
@@ -2479,6 +2525,7 @@
21CE8D7E2CE5134E0076522F /* MenuSubscriber.cpp in Sources */,
21CE8D7F2CE5134E0076522F /* Attribute.cpp in Sources */,
21CE992C2CE622FC0076522F /* StairStructure.cpp in Sources */,
+ 21F0AE322CEB7045003AD722 /* ElementVisibilityCollector.cpp in Sources */,
21CE8D802CE5134E0076522F /* Wall.cpp in Sources */,
21CE8D812CE5134E0076522F /* GetBindingsMethodNames.cpp in Sources */,
21CE98F02CE5539B0076522F /* StairRiser.cpp in Sources */,
@@ -2537,6 +2584,7 @@
21CE8DB12CE5134E0076522F /* MaterialQuantity.cpp in Sources */,
21CE8DB22CE5134E0076522F /* Setting.cpp in Sources */,
21CE8DB32CE5134E0076522F /* String.cpp in Sources */,
+ 21F0AE422CEB91F9003AD722 /* Layer.cpp in Sources */,
21CE8DB42CE5134E0076522F /* Guid.cpp in Sources */,
21CE8DB52CE5134E0076522F /* BrowserBridge.cpp in Sources */,
21CE8DB62CE5134E0076522F /* Part.cpp in Sources */,
diff --git a/SpeckleLib/SpeckleLib.xcodeproj/xcshareddata/xcschemes/SpeckleLib-AC25-Debug.xcscheme b/SpeckleLib/SpeckleLib.xcodeproj/xcshareddata/xcschemes/SpeckleLib-AC25-Debug.xcscheme
index 0a856dc..f793f40 100644
--- a/SpeckleLib/SpeckleLib.xcodeproj/xcshareddata/xcschemes/SpeckleLib-AC25-Debug.xcscheme
+++ b/SpeckleLib/SpeckleLib.xcodeproj/xcshareddata/xcschemes/SpeckleLib-AC25-Debug.xcscheme
@@ -1,6 +1,6 @@
+
@@ -162,6 +163,7 @@
+
@@ -228,6 +230,7 @@
+
@@ -267,6 +270,7 @@
+
diff --git a/SpeckleLib/SpeckleLib17.vcxproj.filters b/SpeckleLib/SpeckleLib17.vcxproj.filters
index 43351db..e79c0d8 100644
--- a/SpeckleLib/SpeckleLib17.vcxproj.filters
+++ b/SpeckleLib/SpeckleLib17.vcxproj.filters
@@ -128,6 +128,9 @@
{ccb4ca39-1960-4590-ad5a-8f9092924778}
+
+ {e6e7128b-795b-441c-9ea6-051c99a0343d}
+
@@ -502,6 +505,12 @@
Speckle\Record\Element\Interface
+
+ Speckle\Record\Attribute
+
+
+ Speckle\Record\Filter
+
@@ -783,6 +792,12 @@
Speckle\Record\Element\Interface
+
+ Speckle\Record\Attribute
+
+
+ Speckle\Record\Filter
+