From da457a34388dc9543c869f41490987f51c337c52 Mon Sep 17 00:00:00 2001 From: David Kekesi Date: Wed, 6 Nov 2024 11:51:29 +0100 Subject: [PATCH 1/5] subscribing all elements to element events --- .../Browser/Bridge/Base/BaseBridge.cpp | 35 ++++++++++++++++++- .../Browser/Bridge/Send/SendBridge.cpp | 16 --------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp index 6c9e660..2db15c8 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp @@ -11,8 +11,35 @@ #include "Connector/Interface/Browser/Bridge/Base/OpenUrl.h" #include "Speckle/Event/Type/ProjectEvent.h" +#include "Speckle/Environment/Project.h" +#include "Speckle/Record/Element/Element.h" +#include "Connector/Connector.h" +#include "Connector/ConnectorResource.h" +#include "Speckle/Database/Identity/RecordID.h" +#include "Speckle/Database/BIMElementDatabase.h" +#include "Connector/Record/Model/SenderModelCard.h" +#include "Connector/Record/Model/Filter/SendFilter.h" +#include "Connector/Database/ModelCardDatabase.h" + using namespace connector::interfac::browser::bridge; +namespace { +#ifdef ARCHICAD + void subscribeAllElementsToElementChangeEvents() + { + auto project = connector::connector()->getActiveProject().lock(); + if (!project) + return; + + auto elementDatabase = project->getElementDatabase(); + auto allElements = elementDatabase->findElements(); + + for (const auto& id : allElements) + ACAPI_Element_AttachObserver(id); + } +#endif +} + /*-------------------------------------------------------------------- Default constructor --------------------------------------------------------------------*/ @@ -28,6 +55,8 @@ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} { addMethod(); addMethod(); addMethod(); + + subscribeAllElementsToElementChangeEvents(); } //BaseBridge::BaseBridge /*-------------------------------------------------------------------- @@ -40,7 +69,11 @@ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} { bool BaseBridge::handle(const speckle::event::ProjectEvent& event) { using enum speckle::event::ProjectEvent::Type; switch (event.getType()) { - case open: case close: + case open: { + sendEvent("documentChanged"); + subscribeAllElementsToElementChangeEvents(); + } break; + case close: sendEvent("documentChanged"); break; default: diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp index 7188881..6d8ae7e 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/SendBridge.cpp @@ -32,22 +32,6 @@ SendBridge::SendBridge() : BrowserBridge{"sendBinding"} { addMethod(); addMethod(); addMethod(); - - // POC: do we have a better place to attach observer to elements? -#ifdef ARCHICAD - auto project = connector()->getActiveProject().lock(); - if (!project) { - // TODO: is this OK? should this throw? - return; - } - - auto elementDatabase = project->getElementDatabase(); - auto elements = elementDatabase->getElements(); - ElementIDList elementIds; - for (const auto& id : elementIds) { - ACAPI_Element_AttachObserver(id); - } -#endif } //SendBridge::SendBridge From 96759f7e9ef5d06553f9f4a0b6f4ee7038e39039 Mon Sep 17 00:00:00 2001 From: David Kekesi Date: Wed, 6 Nov 2024 19:43:01 +0100 Subject: [PATCH 2/5] very slow in a 3D view - attaching element observers to all elements --- .../Browser/Bridge/Base/BaseBridge.cpp | 7 +-- .../Connector/Interface/ConnectorPalette.cpp | 61 +++++++++++++++---- .../Connector/Interface/ConnectorPalette.h | 10 ++- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp index 2db15c8..1f29ee9 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp @@ -36,6 +36,8 @@ namespace { for (const auto& id : allElements) ACAPI_Element_AttachObserver(id); + + int i = 0; } #endif } @@ -69,13 +71,10 @@ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} { bool BaseBridge::handle(const speckle::event::ProjectEvent& event) { using enum speckle::event::ProjectEvent::Type; switch (event.getType()) { - case open: { + case open: { sendEvent("documentChanged"); subscribeAllElementsToElementChangeEvents(); } break; - case close: - sendEvent("documentChanged"); - break; default: break; } diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp index 9e63b78..76cc62b 100644 --- a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp +++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp @@ -17,6 +17,8 @@ #include "Speckle/Event/Type/MenuEvent.h" #include "Speckle/Interface/Browser/JSPortal.h" +#include "Speckle/Event/Type/ProjectEvent.h" + #include #include #include @@ -108,7 +110,9 @@ ConnectorPalette::ConnectorPalette() { return: The subscription list (an empty list will put the subscriber into a suspended state) --------------------------------------------------------------------*/ ConnectorPalette::Subscription ConnectorPalette::subscription() const { - return { {toggleConnectorPaletteID} }; + auto result = ProjectSubscriber::subscription(); + result.insert(toggleConnectorPaletteID); + return result; } //ConnectorPalette::subscription @@ -130,16 +134,49 @@ bool ConnectorPalette::start() { return: True if the event should be closed --------------------------------------------------------------------*/ bool ConnectorPalette::receive(const active::event::Event& event) { - if (BrowserPalette::HasInstance() && BrowserPalette::GetInstance().IsVisible()) { - BrowserPalette::GetInstance().Hide (); - } else { - if (!BrowserPalette::HasInstance()) - BrowserPalette::CreateInstance(); - BrowserPalette::GetInstance().Show(); + if (event == toggleConnectorPaletteID) { + if (BrowserPalette::HasInstance() && BrowserPalette::GetInstance().IsVisible()) { + BrowserPalette::GetInstance().Hide(); + } + else { + if (!BrowserPalette::HasInstance()) + BrowserPalette::CreateInstance(); + BrowserPalette::GetInstance().Show(); + } + return true; } - return true; + + return ProjectSubscriber::receive(event); + } //ConnectorPalette::receive +/*-------------------------------------------------------------------- + Handle a project event + + event: The project event + + return: True if the event should be closed + --------------------------------------------------------------------*/ +bool ConnectorPalette::handle(const speckle::event::ProjectEvent& event) { + using enum speckle::event::ProjectEvent::Type; + switch (event.getType()) { + case open: { + if (BrowserPalette::HasInstance() && !BrowserPalette::GetInstance().IsVisible()) { + BrowserPalette::GetInstance().Show(); + BrowserPalette::GetInstance().EnableItems(); + } + } break; + case close: { + if (BrowserPalette::HasInstance() && BrowserPalette::GetInstance().IsVisible()) { + BrowserPalette::GetInstance().Hide(); + } + } break; + default: + break; + } + return false; +} //ConnectorPalette::handle + //NB: Following is placeholder from GS example code - will be refactored to better suit our purposes @@ -282,11 +319,13 @@ GSErrCode __ACENV_CALL BrowserPalette::PaletteControlCallBack(Int32, API_Palette break; case APIPalMsg_HidePalette_End: - if(HasInstance() && !GetInstance().IsVisible()) + if (HasInstance() && !GetInstance().IsVisible()) + { GetInstance().Show(); + } break; - case APIPalMsg_DisableItems_Begin: + /*case APIPalMsg_DisableItems_Begin: if(HasInstance() && GetInstance().IsVisible()) GetInstance().DisableItems(); break; @@ -294,7 +333,7 @@ GSErrCode __ACENV_CALL BrowserPalette::PaletteControlCallBack(Int32, API_Palette case APIPalMsg_DisableItems_End: if(HasInstance() && GetInstance().IsVisible()) GetInstance().EnableItems(); - break; + break;*/ case APIPalMsg_IsPaletteVisible: *(reinterpret_cast(param)) = HasInstance() && GetInstance().IsVisible(); diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.h b/SpeckleConnector/Connector/Interface/ConnectorPalette.h index 289e243..b756242 100644 --- a/SpeckleConnector/Connector/Interface/ConnectorPalette.h +++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.h @@ -2,10 +2,11 @@ #define CONNECTOR_CONNECTOR_PALETTE #include "Active/Event/Subscriber.h" +#include "Speckle/Event/Subscriber/ProjectSubscriber.h" namespace connector { - class ConnectorPalette : public active::event::Subscriber { + class ConnectorPalette : public speckle::event::ProjectSubscriber { public: /*! Default constructor @@ -32,6 +33,13 @@ namespace connector { @return True if the event should be closed */ bool receive(const active::event::Event& event) override; + protected: + /*! + Handle the project events + @param event The project event + @return True if the event should be closed + */ + bool handle(const speckle::event::ProjectEvent& event) override; }; } From e612ed1192007d204933bdaeab818b87dd1a6f09 Mon Sep 17 00:00:00 2001 From: David Kekesi Date: Wed, 6 Nov 2024 20:18:36 +0100 Subject: [PATCH 3/5] attaching observer to all elements is too slow, commented out for now --- .../Interface/Browser/Bridge/Base/BaseBridge.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp index 1f29ee9..3f433ef 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp @@ -32,6 +32,8 @@ namespace { return; auto elementDatabase = project->getElementDatabase(); + //auto table = elementDatabase->getTables(speckle::database::ElementStorage::TableType::primary2D); + //auto allElements = elementDatabase->findElements(nullptr, *table.begin()); auto allElements = elementDatabase->findElements(); for (const auto& id : allElements) @@ -58,7 +60,9 @@ BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} { addMethod(); addMethod(); - subscribeAllElementsToElementChangeEvents(); + // POC: Attaching Observer to all elements is too slow, registration is commented out for now + // subscribeAllElementsToElementChangeEvents(); + } //BaseBridge::BaseBridge /*-------------------------------------------------------------------- @@ -73,7 +77,8 @@ bool BaseBridge::handle(const speckle::event::ProjectEvent& event) { switch (event.getType()) { case open: { sendEvent("documentChanged"); - subscribeAllElementsToElementChangeEvents(); + // POC: Attaching Observer to all elements is too slow, registration is commented out for now + // subscribeAllElementsToElementChangeEvents(); } break; default: break; From 0e0dc7da2dda339b37ed803bd506b7275ac3ae01 Mon Sep 17 00:00:00 2001 From: David Kekesi Date: Wed, 6 Nov 2024 20:24:03 +0100 Subject: [PATCH 4/5] switching to 3D window before send operation implemented --- .../Connector/Interface/Browser/Bridge/Send/Send.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp index bf0cadf..6fcc6c9 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp @@ -44,6 +44,11 @@ Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) { modelCardID: The ID of the model card identifying the objects to send --------------------------------------------------------------------*/ void Send::run(const String& modelCardID) const { + + // we currently rely on the ModelerAPI instead of the ModelAccessAPI + // we have to open a 3D window to get the Mesh data of the model elements + ACAPI_View_ShowAllIn3D(); + //Get the active project auto project = connector()->getActiveProject().lock(); if (!project) { From a6f15e9a53bf480493bb23319a6d279bb6944d41 Mon Sep 17 00:00:00 2001 From: David Kekesi Date: Wed, 6 Nov 2024 20:34:46 +0100 Subject: [PATCH 5/5] review comments fixed --- .../Interface/Browser/Bridge/Base/BaseBridge.cpp | 2 -- .../Connector/Interface/Browser/Bridge/Send/Send.cpp | 2 ++ .../Connector/Interface/ConnectorPalette.cpp | 10 ---------- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp index 3f433ef..4c5f125 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Base/BaseBridge.cpp @@ -38,8 +38,6 @@ namespace { for (const auto& id : allElements) ACAPI_Element_AttachObserver(id); - - int i = 0; } #endif } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp index 6fcc6c9..59813f7 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp @@ -45,9 +45,11 @@ Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) { --------------------------------------------------------------------*/ void Send::run(const String& modelCardID) const { +#ifdef ARCHICAD // we currently rely on the ModelerAPI instead of the ModelAccessAPI // we have to open a 3D window to get the Mesh data of the model elements ACAPI_View_ShowAllIn3D(); +#endif //Get the active project auto project = connector()->getActiveProject().lock(); diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp index 76cc62b..5dd0408 100644 --- a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp +++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp @@ -325,16 +325,6 @@ GSErrCode __ACENV_CALL BrowserPalette::PaletteControlCallBack(Int32, API_Palette } break; - /*case APIPalMsg_DisableItems_Begin: - if(HasInstance() && GetInstance().IsVisible()) - GetInstance().DisableItems(); - break; - - case APIPalMsg_DisableItems_End: - if(HasInstance() && GetInstance().IsVisible()) - GetInstance().EnableItems(); - break;*/ - case APIPalMsg_IsPaletteVisible: *(reinterpret_cast(param)) = HasInstance() && GetInstance().IsVisible(); break;