Files
speckle-cpp-connectors/SpeckleLib/Speckle/Event/Subscriber/ElementSubscriber.cpp
T
Ralph Wessel d21f3da414 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
2024-11-20 09:15:57 +00:00

111 lines
3.4 KiB
C++

#include "Speckle/Event/Subscriber/ElementSubscriber.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h"
#include "Speckle/Event/Type/ElementEvent.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
using namespace active::environment;
using namespace active::event;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
namespace {
using enum ElementEvent::Type;
#ifdef ARCHICAD
/*!
Callback for an Archicad element change
@param elemType Info about the last changed element
*/
GSErrCode __ACENV_CALL elementChangedCallback(const API_NotifyElementType* elemType) {
if (addon() == nullptr)
return NoError;
// POC: can we do this switch smater?
switch (elemType->notifID)
{
case APINotifyElement_New: {
// POC: Put this back once we decide to use Object Tracking
// ACAPI_Element_AttachObserver(elemType->elemHead.guid);
addon()->publishExternal(ElementEvent{newElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Change: {
addon()->publishExternal(ElementEvent{changeElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Edit: {
addon()->publishExternal(ElementEvent{editElem, BIMRecordID{elemType->elemHead.guid}});
} break;
case APINotifyElement_Delete: {
addon()->publishExternal(ElementEvent{deleteElem, BIMRecordID{ elemType->elemHead.guid}});
} break;
case APINotifyElement_BeginEvents:
addon()->publishExternal(ElementEvent{begin});
break;
case APINotifyElement_EndEvents: {
addon()->publishExternal(ElementEvent{end});
} break;
default:
break;
}
return NoError;
}
#endif
}
/*--------------------------------------------------------------------
Get the event subscription list
return: The subscription list (an empty list will put the subscriber into a suspended state)
--------------------------------------------------------------------*/
Subscriber::Subscription ElementSubscriber::subscription() const {
return { {ElementEvent::ID} };
} //ElementSubscriber::subscription
/*--------------------------------------------------------------------
Receive a subscribed event
event: The incoming event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool ElementSubscriber::receive(const Event& event) {
//Pass a menu event to the specified handler function
if (auto changeEvent = dynamic_cast<const ElementEvent*>(&event); changeEvent != nullptr)
return handle(*changeEvent);
return false;
} //ElementSubscriber::receive
/*--------------------------------------------------------------------
Start the participant operation
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool ElementSubscriber::start() {
#ifdef ARCHICAD
#ifdef ServerMainVers_2700
auto err = ACAPI_Element_InstallElementObserver(elementChangedCallback);
#else
auto err = ACAPI_Notify_InstallElementObserver(elementChangedCallback);
#endif
if (err != NoError)
return false;
#ifdef ServerMainVers_2700
return (ACAPI_Element_CatchNewElement(nullptr, elementChangedCallback) == NoError);
#else
return (ACAPI_Notify_CatchNewElement(nullptr, elementChangedCallback) == NoError);
#endif
#else
return false;
#endif
} //ElementSubscriber::start