diff --git a/SpeckleConnector/Connector.vcxproj b/SpeckleConnector/Connector.vcxproj
index acf33d4..245709b 100644
--- a/SpeckleConnector/Connector.vcxproj
+++ b/SpeckleConnector/Connector.vcxproj
@@ -114,6 +114,7 @@
+
@@ -169,6 +170,7 @@
+
diff --git a/SpeckleConnector/Connector.vcxproj.filters b/SpeckleConnector/Connector.vcxproj.filters
index 374c759..763dc5c 100644
--- a/SpeckleConnector/Connector.vcxproj.filters
+++ b/SpeckleConnector/Connector.vcxproj.filters
@@ -243,6 +243,9 @@
Connector\Interface\Browser\Bridge\Selection\Arg
+
+ Connector\Interface\Browser\Bridge\Selection
+
@@ -411,5 +414,8 @@
Connector\Interface\Browser\Bridge\Selection\Arg
+
+ Connector\Interface\Browser\Bridge\Selection
+
\ No newline at end of file
diff --git a/SpeckleConnector/Connector/Connector.cpp b/SpeckleConnector/Connector/Connector.cpp
index 23943be..4343b1e 100755
--- a/SpeckleConnector/Connector/Connector.cpp
+++ b/SpeckleConnector/Connector/Connector.cpp
@@ -1,6 +1,7 @@
#include "Active/File/Directory.h"
#include "ConnectorResource.h"
#include "Connector/Connector.h"
+#include "Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/ConnectorMenu.h"
#include "Connector/Interface/ConnectorPalette.h"
@@ -12,6 +13,7 @@ using namespace active::file;
using namespace active::environment;
using namespace connector;
using namespace connector::database;
+using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::utility;
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.cpp
index 42611d6..b7126b9 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.cpp
@@ -2,6 +2,14 @@
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
+#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
+
+#include "Connector/Connector.h"
+
+#include "Speckle/Database/BIMElementDatabase.h"
+#include "Speckle/Environment/Project.h"
+#include "Speckle/Record/Element/Element.h"
+using namespace speckle::record::element;
#include
@@ -12,16 +20,40 @@ namespace {
///Serialisation fields
enum FieldIndex {
+ selectedObjectIdsID,
summaryID,
};
///Serialisation field IDs
static std::array fieldID = {
+ Identity{"selectedObjectIds"},
Identity{"summary"},
};
}
+SelectionInfo::SelectionInfo() {
+ initialize();
+}
+
+void SelectionInfo::initialize() {
+ auto project = connector()->getActiveProject().lock();
+ if (!project) {
+ // TODO: handle
+ }
+
+ auto elementDatabase = project->getElementDatabase();
+ auto selected = elementDatabase->getSelection();
+
+ active::utility::String summary(selected.size());
+ summary += " objects selected.";
+ m_summary = summary;
+
+ for (const auto& link : selected) {
+ m_selectedElementIds.push_back(link);
+ }
+}
+
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -33,6 +65,7 @@ bool SelectionInfo::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
+ { fieldID[selectedObjectIdsID], selectedObjectIdsID, element },
{ fieldID[summaryID], summaryID, element },
},
}.withType(&typeid(SelectionInfo)));
@@ -52,8 +85,10 @@ Cargo::Unique SelectionInfo::getCargo(const Inventory::Item& item) const {
return nullptr;
using namespace active::serialise;
switch (item.index) {
+ case selectedObjectIdsID:
+ return std::make_unique>>(m_selectedElementIds);
case summaryID:
- return std::make_unique>(summary);
+ return std::make_unique>(m_summary);
default:
return nullptr; //Requested an unknown index
}
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h
index 2e81bea..12c9ec3 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h
@@ -21,10 +21,12 @@ namespace connector::interfac::browser::bridge {
/*!
Default constructor
*/
- SelectionInfo() = default;
+ SelectionInfo();
- active::utility::String summary = "Nothing is selected";
- std::vector selectedElementIds;
+ active::utility::String m_summary = "No objects selected";
+ std::vector m_selectedElementIds;
+
+ void initialize();
// MARK: - Serialisation
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/GetSelection.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/GetSelection.cpp
index fc239a7..6385c09 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/GetSelection.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/GetSelection.cpp
@@ -1,30 +1,10 @@
#include "Connector/Interface/Browser/Bridge/Selection/GetSelection.h"
-
#include "Active/Serialise/CargoHold.h"
-#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h"
-#include "Connector/Connector.h"
-#include "Connector/Record/Collection/ProjectCollection.h"
-
-#include "Speckle/Database/BIMElementDatabase.h"
-#include "Speckle/Environment/Project.h"
-#include "Speckle/Record/Element/Element.h"
-using namespace speckle::record::element;
-
-#include
-
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
-using namespace speckle::utility;
-using namespace connector::record;
-namespace {
-
- ///Return type for retrieving the current configuration
- using WrappedValue = CargoHold;
-
-}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
@@ -39,30 +19,6 @@ GetSelection::GetSelection() : BridgeMethod{"GetSelection", [&]() {
modelCardID: The ID of the model to send
--------------------------------------------------------------------*/
std::unique_ptr GetSelection::run() const {
-
auto selectionInfo = std::make_unique();
-
- auto project = connector()->getActiveProject().lock();
- if (!project) {
- // TODO
- }
-
- //Build a collection from the selected elements
- auto collection = std::make_unique(project);
- auto elementDatabase = project->getElementDatabase();
- auto selected = elementDatabase->getSelection();
-
- active::utility::String summary(selected.size());
- summary += " objects selected.";
-
- selectionInfo->summary = summary;
-
- for (const auto& link : selected) {
- if (auto element = elementDatabase->getElement(link); element) {
- collection->addElement(*element);
- selectionInfo->selectedElementIds.push_back(element->getBIMID());
- }
- }
-
- return std::make_unique(std::move(selectionInfo));
+ return std::make_unique>(std::move(selectionInfo));
} //GetSelection::run
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
index 5fa969f..f31cc98 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.cpp
@@ -1,7 +1,9 @@
#include "Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h"
-
#include "Connector/Interface/Browser/Bridge/Selection/GetSelection.h"
+#include "Active/Serialise/CargoHold.h"
+#include "Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h"
+using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
/*--------------------------------------------------------------------
@@ -11,3 +13,10 @@ SelectionBridge::SelectionBridge() : BrowserBridge{"selectionBinding"} {
//Add bridge methods
addMethod();
} //SelectionBridge::SelectionBridge
+
+bool SelectionBridge::handle(const speckle::event::SelectionEvent& event) {
+ auto selectionInfo = std::make_unique();
+ auto wrapped = std::make_unique>(std::move(selectionInfo));
+ sendEvent("setSelection", std::move(wrapped));
+ return true;
+}
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h
index 053fba2..a92f213 100644
--- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h
@@ -2,13 +2,15 @@
#define CONNECTOR_INTERFACE_BRIDGE_SELECTION_BRIDGE
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
+#include "Speckle/Event/Subscriber/SelectionSubscriber.h"
+#include "Speckle/Event/Type/SelectionEvent.h"
namespace connector::interfac::browser::bridge {
/*!
A browser bridge to support sending model data to a Speckle server
*/
- class SelectionBridge : public speckle::interfac::browser::bridge::BrowserBridge {
+ class SelectionBridge : public speckle::interfac::browser::bridge::BrowserBridge, public speckle::event::SelectionSubscriber {
public:
// MARK: - Types
@@ -22,6 +24,10 @@ namespace connector::interfac::browser::bridge {
Default constructor
*/
SelectionBridge();
+
+ protected:
+
+ bool handle(const speckle::event::SelectionEvent& event) override;
};
}
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.cpp
new file mode 100644
index 0000000..652b96d
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.cpp
@@ -0,0 +1,28 @@
+#include "Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.h"
+
+#include "Active/Event/Event.h"
+#include "Connector/ConnectorResource.h"
+#include "Connector/Event/ConnectorEventID.h"
+#include "Speckle/Environment/Addon.h"
+
+using namespace connector::interfac::browser::bridge;
+
+
+/*--------------------------------------------------------------------
+ Default constructor
+ --------------------------------------------------------------------*/
+SelectionChangeHandler::SelectionChangeHandler() {
+ int i = 0;
+} //SelectionChangeHandler::SelectionChangeHandler
+
+/*--------------------------------------------------------------------
+ Handle the menu selection
+
+ event: The menu event
+
+ return: True if the event should be closed
+ --------------------------------------------------------------------*/
+bool SelectionChangeHandler::handle(const speckle::event::SelectionEvent& event) {
+ int i = 0;
+ return true;
+}
diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.h
new file mode 100644
index 0000000..38cf52b
--- /dev/null
+++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Selection/SelectionChangeHandler.h
@@ -0,0 +1,28 @@
+#ifndef CONNECTOR_INTERFACE_BRIDGE_SELECTION_CHANGE_HANDLER
+#define CONNECTOR_INTERFACE_BRIDGE_SELECTION_CHANGE_HANDLER
+
+#include "Speckle/Event/Subscriber/SelectionSubscriber.h"
+#include "Speckle/Event/Type/SelectionEvent.h"
+
+namespace connector::interfac::browser::bridge {
+
+ /*!
+ Configuration settings class
+ */
+ class SelectionChangeHandler : public speckle::event::SelectionSubscriber {
+ public:
+ // MARK: - Constructors
+
+ /*!
+ Default constructor
+ */
+ SelectionChangeHandler();
+
+
+ protected:
+ bool handle(const speckle::event::SelectionEvent& event) override;
+ };
+
+}
+
+#endif //CONNECTOR_INTERFACE_BRIDGE_SELECTION_CHANGE_HANDLER
diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
index 0800691..da4a920 100644
--- a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
+++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp
@@ -4,6 +4,7 @@
#include "Active/Utility/String.h"
#include "Active/Serialise/JSON/JSONTransport.h"
#include "Active/Utility/BufferOut.h"
+#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Event/ConnectorEventID.h"
#include "Connector/Interface/Browser/Bridge/Account/AccountBridge.h"
@@ -77,9 +78,6 @@ namespace {
virtual void PanelResized(const DG::PanelResizeEvent& ev) override;
virtual void PanelCloseRequested(const DG::PanelCloseRequestEvent& ev, bool* accepted) override;
- static GS::Array GetSelectedElements();
- static void ModifySelection(const GS::UniString& elemGuidStr, SelectionModification modification);
-
static GSErrCode __ACENV_CALL PaletteControlCallBack(Int32 paletteId, API_PaletteMessageID messageID, GS::IntPtr param);
static GS::Ref instance;
@@ -171,7 +169,12 @@ BrowserPalette::BrowserPalette() :
install();
install();
install();
- install();
+ if (auto ref = install(); ref) {
+ if (auto selectionBridgeRef = std::dynamic_pointer_cast(ref); selectionBridgeRef) {
+ connector::connector()->addWeak(selectionBridgeRef);
+ selectionBridgeRef->start();
+ }
+ }
install();
InitBrowserControl();
}
@@ -245,31 +248,6 @@ void BrowserPalette::PanelCloseRequested(const DG::PanelCloseRequestEvent&, bool
*accepted = true;
}
-GS::Array BrowserPalette::GetSelectedElements() {
- API_SelectionInfo selectionInfo;
- GS::Array selNeigs;
- ACAPI_Selection_Get(&selectionInfo, &selNeigs, false, false);
- BMKillHandle((GSHandle*)&selectionInfo.marquee.coords);
-
- GS::Array selectedElements;
- for(const API_Neig& neig : selNeigs) {
- API_Elem_Head elemHead = {};
- elemHead.guid = neig.guid;
- ACAPI_Element_GetHeader(&elemHead);
-
- ElementInfo elemInfo;
- elemInfo.guidStr = APIGuidToString(elemHead.guid);
- ACAPI_Element_GetElemTypeName(elemHead.type, elemInfo.typeName);
- ACAPI_Element_GetElementInfoString(&elemHead.guid, &elemInfo.elemID);
- selectedElements.Push(elemInfo);
- }
- return selectedElements;
-}
-
-void BrowserPalette::ModifySelection(const GS::UniString& elemGuidStr, BrowserPalette::SelectionModification modification) {
- ACAPI_Selection_Select({ API_Neig(APIGuidFromString(elemGuidStr.ToCStr().Get())) }, modification == AddToSelection);
-}
-
GSErrCode __ACENV_CALL BrowserPalette::PaletteControlCallBack(Int32, API_PaletteMessageID messageID, GS::IntPtr param) {
switch(messageID) {
case APIPalMsg_OpenPalette:
diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp
index 48b5f04..c6925b4 100644
--- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp
+++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.cpp
@@ -69,12 +69,18 @@ bool SelectionSubscriber::receive(const Event& event) {
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool SelectionSubscriber::start() {
- if (m_isStarted)
- return true;
- m_isStarted = true;
#ifdef ARCHICAD
return (ACAPI_Notification_CatchSelectionChange(selectionCallback) == NoError);
#else
return false;
#endif
} //SelectionSubscriber::start
+
+/*--------------------------------------------------------------------
+ Stop participation (release resources etc)
+ --------------------------------------------------------------------*/
+void SelectionSubscriber::stop() {
+#ifdef ARCHICAD
+ ACAPI_Notification_CatchSelectionChange(nullptr);
+#endif
+}
diff --git a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h
index 975eb0c..a5595b0 100644
--- a/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h
+++ b/SpeckleLib/Speckle/Event/Subscriber/SelectionSubscriber.h
@@ -35,7 +35,7 @@ namespace speckle::event {
Get the event subscription list
@return The subscription list (an empty list will put the subscriber into a suspended state)
*/
- virtual Subscription subscription() const override;
+ Subscription subscription() const override;
// MARK: - Functions (mutating)
@@ -44,14 +44,21 @@ namespace speckle::event {
@param event The incoming event
@return True if the event should be closed
*/
- virtual bool receive(const active::event::Event& event) override;
-
- protected:
+ bool receive(const active::event::Event& event) override;
+
/*!
Start the participant operation
@return True if the participant is able to continue
*/
virtual bool start() override;
+
+ /*!
+ Stop participation (release resources etc)
+ */
+ void stop() override;
+
+ protected:
+
/*!
Handle the menu selection
@param event The menu event
diff --git a/SpeckleLib/Speckle/Event/Type/SelectionEvent.h b/SpeckleLib/Speckle/Event/Type/SelectionEvent.h
index 396f698..365f70f 100644
--- a/SpeckleLib/Speckle/Event/Type/SelectionEvent.h
+++ b/SpeckleLib/Speckle/Event/Type/SelectionEvent.h
@@ -24,7 +24,7 @@ namespace speckle::event {
Constructor
@param selected A link to a selected element (nullopt if the selection is empty)
*/
- SelectionEvent(speckle::database::BIMLink::Option selected) : m_selectedLink{selected} {}
+ SelectionEvent(speckle::database::BIMLink::Option selected) : Event{ ID }, m_selectedLink{selected} {}
/*!
Copy constructor
@param source The object to copy
diff --git a/SpeckleLib/Speckle/Interface/Browser/JSObject.h b/SpeckleLib/Speckle/Interface/Browser/JSObject.h
index 05732e6..46843e0 100644
--- a/SpeckleLib/Speckle/Interface/Browser/JSObject.h
+++ b/SpeckleLib/Speckle/Interface/Browser/JSObject.h
@@ -38,7 +38,7 @@ namespace speckle::interfac::browser {
*/
template
explicit JSObject(const speckle::utility::String& name, const std::initializer_list& items) : base{items}, m_name{name} {}
-
+ virtual ~JSObject() {}
// MARK: - Functions (const)
/*!
diff --git a/SpeckleLib/Speckle/Interface/Browser/JSPortal.h b/SpeckleLib/Speckle/Interface/Browser/JSPortal.h
index 14bcc26..159eeb7 100644
--- a/SpeckleLib/Speckle/Interface/Browser/JSPortal.h
+++ b/SpeckleLib/Speckle/Interface/Browser/JSPortal.h
@@ -48,14 +48,14 @@ namespace speckle::interfac::browser {
@param object The object to install
@return True if the object was successfully installed
*/
- bool install(std::shared_ptr> object);
+ std::shared_ptr> install(std::shared_ptr> object);
/*!
Install a JS function object
@return True if the object was successfully installed
@tparam T The type of object to install
*/
template requires std::is_base_of_v, T>
- bool install() { return install(std::make_shared()); }
+ std::shared_ptr> install() { return install(std::make_shared()); }
protected:
#ifdef ARCHICAD
@@ -101,12 +101,12 @@ namespace speckle::interfac::browser {
return: True if the object was successfully installed
--------------------------------------------------------------------*/
template
- bool JSPortal::install(std::shared_ptr> object) {
+ std::shared_ptr> JSPortal::install(std::shared_ptr> object) {
try {
#ifdef ARCHICAD
auto engine = getJSEngine();
if (!engine)
- return false;
+ return nullptr;
//Define the JS object
JS::Object* acObject = new JS::Object(object->getName());
//Add all the functions supported by this object
@@ -125,13 +125,13 @@ namespace speckle::interfac::browser {
if (engine->RegisterAsynchJSObject(acObject)) {
base::push_back(object);
object->setPortal(*this);
- return true;
+ return object;
}
#endif
} catch(...) {
///TODO: Need to discuss the best course of action to notify of a failure
}
- return false;
+ return nullptr;
} //JSPortal::install
}