From 18ca0318a73e33ce5c9bb3c6af062e0f352f27d0 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Thu, 14 Nov 2024 21:14:44 +0000 Subject: [PATCH 1/3] ReceiveBridge and Receive method classes added (no receive implementation yet) --- .../Connector.xcodeproj/project.pbxproj | 32 +++++++++++++ .../Browser/Bridge/Receive/Receive.cpp | 46 +++++++++++++++++++ .../Browser/Bridge/Receive/Receive.h | 39 ++++++++++++++++ .../Browser/Bridge/Receive/ReceiveBridge.cpp | 30 ++++++++++++ .../Browser/Bridge/Receive/ReceiveBridge.h | 29 ++++++++++++ .../Connector/Interface/ConnectorPalette.cpp | 2 + 6 files changed, 178 insertions(+) create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.cpp create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/Receive.h create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.cpp create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Receive/ReceiveBridge.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index ee9d1a3..c0381df 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -726,6 +726,14 @@ 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 */; }; 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 +1453,10 @@ 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 = ""; }; 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 +2797,17 @@ name = Archicad28; sourceTree = ""; }; + 21CE9B822CE69A230076522F /* Receive */ = { + isa = PBXGroup; + children = ( + 21CE9B7E2CE69A230076522F /* Receive.cpp */, + 21CE9B7F2CE69A230076522F /* Receive.h */, + 21CE9B802CE69A230076522F /* ReceiveBridge.cpp */, + 21CE9B812CE69A230076522F /* ReceiveBridge.h */, + ); + path = Receive; + sourceTree = ""; + }; 21D0BD5D2C89BFEA0077E104 /* Send */ = { isa = PBXGroup; children = ( @@ -2929,6 +2952,7 @@ 21F69F852C70D2C4008B6A06 /* Account */, 21B67CAB2C77329800FD64FC /* Base */, 21F69FB82C762EF0008B6A06 /* Config */, + 21CE9B822CE69A230076522F /* Receive */, 21D0BD5D2C89BFEA0077E104 /* Send */, 21A890B92CC15C540087E732 /* Selection */, 21B67CD82C78C83800FD64FC /* Test */, @@ -3376,6 +3400,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,6 +3427,7 @@ 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 */, 215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */, 21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */, @@ -3446,6 +3472,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,6 +3499,7 @@ 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 */, 21BD79B32CE23E4D00526AD1 /* FilterMover.cpp in Sources */, 21BD79B42CE23E4D00526AD1 /* ConnectorMenu.cpp in Sources */, @@ -3507,6 +3535,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,6 +3562,7 @@ 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 */, 21CE8AC52CE4F3370076522F /* FilterMover.cpp in Sources */, 21CE8AC62CE4F3370076522F /* ConnectorMenu.cpp in Sources */, @@ -3568,6 +3598,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,6 +3625,7 @@ 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 */, 21CE8E052CE5137C0076522F /* FilterMover.cpp in Sources */, 21CE8E062CE5137C0076522F /* ConnectorMenu.cpp in Sources */, 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/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); From d21f3da414bfeabc15d27b57ac3763c2000b6171 Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Wed, 20 Nov 2024 09:15:57 +0000 Subject: [PATCH 2/3] Prep for receive: - Database transactions added for write access to model - Attribute database write added (for layers, materials etc) User prompted to show layers when model card selection is not visible --- .../Connector.xcodeproj/project.pbxproj | 24 +- .../xcschemes/Connector-AC25-Debug.xcscheme | 2 +- .../xcschemes/Connector-AC25-EN-GB.xcscheme | 2 +- .../xcschemes/Connector-AC26-Debug.xcscheme | 2 +- .../xcschemes/Connector-AC26-EN-GB.xcscheme | 2 +- .../xcschemes/Connector-AC27-Debug.xcscheme | 2 +- .../Connector-AC27-EN-GB-Notarise.xcscheme | 2 +- .../xcschemes/Connector-AC27-EN_GB.xcscheme | 2 +- .../xcschemes/Connector-AC27-Test.xcscheme | 2 +- .../xcschemes/Connector-AC28-Debug.xcscheme | 2 +- .../xcschemes/Connector-AC28-EN-GB.xcscheme | 6 +- .../Connector/ConnectorResource.h | 2 + .../Connector/Database/ModelCardDatabase.cpp | 2 +- .../Connector/Database/ModelCardDatabase.h | 2 +- .../Connector/Event/ConnectorEventID.h | 6 +- .../Browser/Bridge/Base/AddModel.cpp | 6 +- .../Browser/Bridge/Base/UpdateModel.cpp | 6 +- .../Interface/Browser/Bridge/Send/Send.cpp | 2 +- .../Browser/Bridge/Send/SendBridge.cpp | 11 +- .../Browser/Bridge/Send/SendBridge.h | 4 + .../Filter/DirectSelectionSendFilter.cpp | 2 +- .../Model/Filter/DirectSelectionSendFilter.h | 10 +- .../Model/Filter/EverythingSendFilter.cpp | 2 +- .../Model/Filter/EverythingSendFilter.h | 12 +- .../Record/Model/Filter/SendFilter.cpp | 10 +- .../Record/Model/Filter/SendFilter.h | 11 +- .../Record/Model/ReceiverModelCard.cpp | 3 +- .../Record/Model/ReceiverModelCard.h | 8 +- .../Record/Model/SenderModelCard.cpp | 12 + .../Connector/Record/Model/SenderModelCard.h | 7 + .../Connector/Tool/ElementHighlighter.cpp | 122 ++++++++ .../Connector/Tool/ElementHighlighter.h | 28 ++ SpeckleConnector/RINT/Connector.grc | 7 + SpeckleLib/RINT/Speckle.grc | 5 + .../Speckle/Database/BIMAttributeDatabase.cpp | 4 +- .../Speckle/Database/BIMAttributeDatabase.h | 2 +- .../Speckle/Database/BIMElementDatabase.cpp | 9 +- .../Speckle/Database/BIMElementDatabase.h | 7 +- .../Speckle/Database/BIMGroupDatabase.cpp | 2 +- .../Speckle/Database/BIMGroupDatabase.h | 2 +- .../Speckle/Database/BIMPropertyDatabase.cpp | 2 +- .../Speckle/Database/BIMPropertyDatabase.h | 2 +- .../Speckle/Database/Identity/BIMLink.cpp | 25 +- .../Speckle/Database/Identity/BIMLink.h | 27 +- .../Speckle/Database/Identity/RecordID.h | 6 - .../ArchicadDBase/ArchicadDBaseCore.cpp | 14 +- .../Storage/ArchicadDBase/ArchicadDBaseCore.h | 9 + .../ArchicadAttributeDBaseEngine.cpp | 23 +- .../Attribute/ArchicadAttributeDBaseEngine.h | 6 +- .../Element/ArchicadElementDBaseEngine.cpp | 47 ++- .../Element/ArchicadElementDBaseEngine.h | 8 +- .../Property/ArchicadGroupDBaseEngine.cpp | 2 +- .../Property/ArchicadGroupDBaseEngine.h | 6 +- .../Property/ArchicadPropertyDBaseEngine.cpp | 2 +- .../Property/ArchicadPropertyDBaseEngine.h | 5 +- .../DocumentStore/DocumentStoreEngine.h | 7 +- SpeckleLib/Speckle/Environment/Addon.cpp | 45 +++ SpeckleLib/Speckle/Environment/Addon.h | 20 ++ SpeckleLib/Speckle/Environment/Host.cpp | 26 +- SpeckleLib/Speckle/Environment/Host.h | 11 + .../Event/Subscriber/ElementSubscriber.cpp | 8 +- .../Event/Subscriber/ElementSubscriber.h | 4 +- SpeckleLib/Speckle/Event/Type/ElementEvent.h | 7 +- .../Interface/Browser/Bridge/BrowserBridge.h | 2 +- .../Speckle/Record/Attribute/Attribute.h | 6 + SpeckleLib/Speckle/Record/Attribute/Layer.cpp | 275 ++++++++++++++++++ SpeckleLib/Speckle/Record/Attribute/Layer.h | 167 +++++++++++ SpeckleLib/Speckle/Record/Element/Element.cpp | 16 + SpeckleLib/Speckle/Record/Element/Element.h | 8 +- .../Filter/ElementVisibilityCollector.cpp | 21 ++ .../Filter/ElementVisibilityCollector.h | 56 ++++ SpeckleLib/Speckle/SpeckleResource.h | 5 + .../SpeckleLib.xcodeproj/project.pbxproj | 52 +++- .../xcschemes/SpeckleLib-AC25-Debug.xcscheme | 2 +- .../SpeckleLib-AC25-Release.xcscheme | 2 +- .../xcschemes/SpeckleLib-AC26-Debug.xcscheme | 2 +- .../SpeckleLib-AC26-Release.xcscheme | 2 +- .../xcschemes/SpeckleLib-AC27-Debug.xcscheme | 2 +- .../SpeckleLib-AC27-Release.xcscheme | 2 +- .../xcschemes/SpeckleLib-AC28-Debug.xcscheme | 2 +- .../SpeckleLib-AC28-Release.xcscheme | 2 +- 81 files changed, 1162 insertions(+), 128 deletions(-) create mode 100644 SpeckleConnector/Connector/Tool/ElementHighlighter.cpp create mode 100644 SpeckleConnector/Connector/Tool/ElementHighlighter.h create mode 100644 SpeckleLib/Speckle/Record/Attribute/Layer.cpp create mode 100644 SpeckleLib/Speckle/Record/Attribute/Layer.h create mode 100644 SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.cpp create mode 100644 SpeckleLib/Speckle/Record/Filter/ElementVisibilityCollector.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index c0381df..9236dd6 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -734,6 +734,10 @@ 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 */; }; @@ -1457,6 +1461,8 @@ 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 = ""; }; @@ -2808,6 +2814,15 @@ path = Receive; sourceTree = ""; }; + 21CE9B8D2CE75CFC0076522F /* Tool */ = { + isa = PBXGroup; + children = ( + 21CE9B8B2CE75CFC0076522F /* ElementHighlighter.cpp */, + 21CE9B8C2CE75CFC0076522F /* ElementHighlighter.h */, + ); + path = Tool; + sourceTree = ""; + }; 21D0BD5D2C89BFEA0077E104 /* Send */ = { isa = PBXGroup; children = ( @@ -2930,6 +2945,7 @@ 21F69F092C677BC0008B6A06 /* Event */, 21F69F0E2C677BC0008B6A06 /* Interface */, 21D0BDD82C9387E60077E104 /* Record */, + 21CE9B8D2CE75CFC0076522F /* Tool */, 21B67CBA2C774C6500FD64FC /* Version.h */, ); path = Connector; @@ -3122,7 +3138,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1530; + LastUpgradeCheck = 1610; TargetAttributes = { 219F30342C768F0A009834E9 = { CreatedOnToolsVersion = 15.3; @@ -3429,6 +3445,7 @@ 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 */, @@ -3501,6 +3518,7 @@ 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 */, @@ -3564,6 +3582,7 @@ 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 */, @@ -3627,6 +3646,7 @@ 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 */, @@ -3721,6 +3741,7 @@ "\"$(HEADER_PATH_5)/Frameworks\"", "\"$(HEADER_PATH_5)/Lib\"", ); + MACOSX_DEPLOYMENT_TARGET = 11.0; OTHER_CPLUSPLUSFLAGS = ( "-Wno-multichar", "-Wno-ctor-dtor-privacy", @@ -3785,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/ConnectorResource.h b/SpeckleConnector/Connector/ConnectorResource.h index 17e4482..aa4983f 100755 --- a/SpeckleConnector/Connector/ConnectorResource.h +++ b/SpeckleConnector/Connector/ConnectorResource.h @@ -29,6 +29,7 @@ enum TitleString { addonNameID = 1, addonDescriptionID, noStoreyID, + showLayersID, }; @@ -39,6 +40,7 @@ enum PromptString { //Information strings (in UI content, logging, reports) enum GeneralString { + 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/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/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/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..985bfa6 --- /dev/null +++ b/SpeckleConnector/Connector/Tool/ElementHighlighter.cpp @@ -0,0 +1,122 @@ +#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}; 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; + elementDatabase->findElements(collector, 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..58f0d09 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] */ "No objects were found to convert. Please update your publish filter!" +} + + '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..ffe00ca 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..d03b2d3 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..a71a5fe 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.getData(); + //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..c988a2e 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..130e4a0 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,36 @@ 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 && filter(*element)) + result.insert(elemID); + } + return result; } //ArchicadElementDBaseEngine::findObjects @@ -423,7 +446,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..468eaba 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..cf2ac31 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