Compare commits

..

13 Commits

Author SHA1 Message Date
Ralph Wessel 042a515dc4 Removed test code from palette 2024-10-03 17:54:01 +01:00
Ralph Wessel f5bb3dc454 Fix to element mesh face indices 2024-10-03 17:50:50 +01:00
Ralph Wessel f066b0ee02 Send bridge method injects the first selected element into the sent data for testing
Mesh vertices, faces and colours are all single arrays
2024-10-03 17:05:02 +01:00
Ralph Wessel 8dd00005b1 Element is a type of BIMRecord 2024-10-03 16:39:21 +01:00
Ralph Wessel 0592bcc947 BIMRecord is a type of Record (adds applicationID) 2024-10-03 16:31:58 +01:00
Ralph Wessel 76348c8fd1 Merge branch 'develop' into david/cnx-577-implement-mesh-class 2024-10-03 15:51:27 +01:00
Ralph Wessel 1a61608c42 Using preview interface for testing 2024-10-03 14:33:52 +01:00
Ralph Wessel 844ab3544b Commit working 2024-10-03 14:32:30 +01:00
Ralph Wessel 990a1ab9e1 Updated for VS 2024-10-03 13:48:22 +01:00
David Kekesi 6cf03010bd mesh export WIP 2024-10-03 14:39:09 +02:00
Ralph Wessel a0413d0d3a SendObject now holds and sends a Record 2024-10-03 13:12:57 +01:00
Ralph Wessel 8539129e7c SendObject now the owner of the object to be sent 2024-10-03 12:33:08 +01:00
Ralph Wessel 1a901b0a6c Send bridge is updated:
- total children removed
- rootObject replaces batches (sent as an object rather than a string)
2024-10-03 12:05:48 +01:00
15 changed files with 335 additions and 88 deletions
@@ -34,8 +34,8 @@
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E32CAB56E5000B8681 /* SendError.cpp */; };
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */; };
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9EE2CAB5720000B8681 /* SendObject.cpp */; };
21AEF9F32CAC12D1000B8681 /* SendManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9F02CAC12D1000B8681 /* SendManager.cpp */; };
21AEF9FA2CAC3897000B8681 /* ConversionResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */; };
21AEF9FD2CAD3FD8000B8681 /* GetSendSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */; };
21B67CA32C769CB400FD64FC /* libActiveLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69EF52C64FE91008B6A06 /* libActiveLib.a */; };
21B67CA42C769CB400FD64FC /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69ECD2C64C035008B6A06 /* libArchicad27.a */; };
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B67CA52C77329800FD64FC /* BaseBridge.cpp */; };
@@ -317,10 +317,10 @@
21AEF9E62CAB56E5000B8681 /* SendViaBrowserArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendViaBrowserArgs.h; sourceTree = "<group>"; };
21AEF9ED2CAB5720000B8681 /* SendObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendObject.h; sourceTree = "<group>"; };
21AEF9EE2CAB5720000B8681 /* SendObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendObject.cpp; sourceTree = "<group>"; };
21AEF9F02CAC12D1000B8681 /* SendManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendManager.cpp; sourceTree = "<group>"; };
21AEF9F12CAC12D1000B8681 /* SendManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendManager.h; sourceTree = "<group>"; };
21AEF9F82CAC3897000B8681 /* ConversionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionResult.h; sourceTree = "<group>"; };
21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionResult.cpp; sourceTree = "<group>"; };
21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSendSettings.cpp; sourceTree = "<group>"; };
21AEF9FC2CAD3FD8000B8681 /* GetSendSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetSendSettings.h; sourceTree = "<group>"; };
21B67CA52C77329800FD64FC /* BaseBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseBridge.cpp; sourceTree = "<group>"; };
21B67CA62C77329800FD64FC /* BaseBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseBridge.h; sourceTree = "<group>"; };
21B67CA72C77329800FD64FC /* GetSourceApplicationName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSourceApplicationName.cpp; sourceTree = "<group>"; };
@@ -975,15 +975,6 @@
path = Arg;
sourceTree = "<group>";
};
21AEF9F22CAC12D1000B8681 /* Serialise */ = {
isa = PBXGroup;
children = (
21AEF9F02CAC12D1000B8681 /* SendManager.cpp */,
21AEF9F12CAC12D1000B8681 /* SendManager.h */,
);
path = Serialise;
sourceTree = "<group>";
};
21B67CAB2C77329800FD64FC /* Base */ = {
isa = PBXGroup;
children = (
@@ -1071,6 +1062,8 @@
21AEF9E72CAB56E5000B8681 /* Arg */,
21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */,
21D0BD952C8F13F30077E104 /* GetSendFilters.h */,
21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */,
21AEF9FC2CAD3FD8000B8681 /* GetSendSettings.h */,
21D0BD8D2C8EE4490077E104 /* Send.cpp */,
21D0BD8A2C8EE4490077E104 /* Send.h */,
21D0BD5B2C89BFEA0077E104 /* SendBridge.cpp */,
@@ -1183,7 +1176,6 @@
21F69F092C677BC0008B6A06 /* Event */,
21F69F0E2C677BC0008B6A06 /* Interface */,
21D0BDD82C9387E60077E104 /* Record */,
21AEF9F22CAC12D1000B8681 /* Serialise */,
21B67CBA2C774C6500FD64FC /* Version.h */,
);
path = Connector;
@@ -1470,11 +1462,11 @@
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */,
2192460D2CA3469D00CF5703 /* RootCollection.cpp in Sources */,
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */,
21AEF9F32CAC12D1000B8681 /* SendManager.cpp in Sources */,
210CC8832C80E6A300610F58 /* TriggerEvent.cpp in Sources */,
21B67CEB2C78D27200FD64FC /* DocumentInfo.cpp in Sources */,
21B67CB92C774BFA00FD64FC /* GetConnectorVersion.cpp in Sources */,
21B67CD92C78C83800FD64FC /* TestBridge.cpp in Sources */,
21AEF9FD2CAD3FD8000B8681 /* GetSendSettings.cpp in Sources */,
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */,
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */,
21FF70492CA1A7F400AAD99A /* RecordCollection.cpp in Sources */,
@@ -1,6 +1,7 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include <array>
@@ -14,15 +15,13 @@ namespace {
///Serialisation fields
enum FieldIndex {
idID,
totChildID,
batchesID,
rootObjID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
Identity{"totalChildrenCount"},
Identity{"batches"},
Identity{"rootObject"},
};
}
@@ -39,8 +38,7 @@ bool SendObject::fillInventory(active::serialise::Inventory& inventory) const {
inventory.merge(Inventory{
{
{ fieldID[idID], idID, element },
{ fieldID[totChildID], totChildID, element },
{ fieldID[batchesID], batchesID, element },
{ fieldID[rootObjID], rootObjID, element },
},
}.withType(&typeid(SendObject)));
return true;
@@ -61,10 +59,10 @@ Cargo::Unique SendObject::getCargo(const active::serialise::Inventory::Item& ite
switch (item.index) {
case idID:
return std::make_unique<StringWrap>(id);
case totChildID:
return std::make_unique<Int32Wrap>(totalChildrenCount);
case batchesID:
return std::make_unique<ContainerWrap<std::vector<speckle::utility::String>>>(batches);
case rootObjID:
if (m_object)
return std::make_unique<PackageWrap>(*m_object);
return std::make_unique<NullPackage>();
default:
return nullptr; //Requested an unknown index
}
@@ -2,8 +2,8 @@
#define CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
@@ -13,24 +13,21 @@ namespace connector::interfac::browser::bridge {
*/
class SendObject final : public active::serialise::Package {
public:
using base = std::reference_wrapper<active::serialise::Package>;
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendObject() {}
Default constructor
@param object The object to send
*/
SendObject(std::unique_ptr<speckle::database::Record> object) : m_object{std::move(object)} { id = m_object->getID(); }
// MARK: - Public variables
///The root object id which should be used for creating the version
speckle::utility::String id = "1234asdasdsadsadsa";
///The total number of children
int32_t totalChildrenCount = 0;
///JSON batches for the root object and child (detached) objects
std::vector<speckle::utility::String> batches = { "[{\"speckle_type\": \"Base\", \"id\" : \"1234asdasdsadsadsa\"}]" }; // NOTE to Ralph: it will be stringified but like array of objects as in example
speckle::utility::String id;
// MARK: - Serialisation
@@ -46,6 +43,10 @@ namespace connector::interfac::browser::bridge {
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
///The object to send
std::unique_ptr<speckle::database::Record> m_object;
};
}
@@ -46,10 +46,11 @@ namespace {
modelCard: The model card to populate into the send info for the browser
account: The account linked to the send
object: The object to be sent
--------------------------------------------------------------------*/
SendViaBrowserArgs::SendViaBrowserArgs(const ModelCard& modelCard, const Account& account) :
SendViaBrowserArgs::SendViaBrowserArgs(const ModelCard& modelCard, const Account& account, SendObject&& object) :
modelCardID(modelCard.getID()), projectID(modelCard.getProjectID()), modelID(modelCard.getModelID()), token{account.getToken()},
serverURL{account.getServerURL()}, accountID{account.getID()} {
serverURL{account.getServerURL()}, accountID{account.getID()}, sendObject{std::move(object)} {
} //SendViaBrowserArgs::SendViaBrowserArgs
@@ -33,8 +33,9 @@ namespace connector::interfac::browser::bridge {
Constructor
@param modelCard The model card to populate into the send info for the browser
@param account The account linked to the send
@param object The object to be sent
*/
SendViaBrowserArgs(const connector::record::ModelCard& modelCard, const speckle::record::cred::Account& account);
SendViaBrowserArgs(const connector::record::ModelCard& modelCard, const speckle::record::cred::Account& account, SendObject&& object);
// MARK: - Public variables
@@ -8,11 +8,19 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h"
#include "Speckle/Database/AccountDatabase.h"
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Record/Credentials/Account.h"
#include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h"
#include "Speckle/Utility/Exception.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Record/Element/Element.h"
using namespace speckle::record::element;
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
@@ -45,6 +53,7 @@ void Send::run(const String& modelCardID) const {
std::make_unique<SendError>(connector()->getLocalString(errorString, modelCardNotFoundID), modelCardID));
return;
}
//Get the user account
auto accountDatabase = connector()->getAccountDatabase();
auto account = accountDatabase->getAccount(modelCard->getAccountID(), modelCard->getServerURL());
if (!account) {
@@ -59,9 +68,27 @@ void Send::run(const String& modelCardID) const {
std::make_unique<SendError>(connector()->getLocalString(errorString, noProjectOpenID), modelCardID));
return;
}
//We currently collect all detached object serialised data into a memory-based store - in future may be able to batch send and cache locally
DetachedMemoryStore detachedObjects;
auto result = std::make_unique<SendViaBrowserArgs>(*modelCard, *account);
//Collect targeted elements here
//NB: This is a testing placeholder
Element::Unique element;
if (auto project = connector::connector()->getActiveProject().lock(); project) {
auto elementDatabase = project->getElementDatabase();
auto selected = elementDatabase->getSelection();
for (const auto& link : selected)
if (element = elementDatabase->getElement(link); element)
break;
}
if (!element) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noSelectedModelItemsID), modelCardID));
return;
}
//Send the collected information
auto result = std::make_unique<SendViaBrowserArgs>(*modelCard, *account, SendObject{std::move(element)}); //NB: Using a placeholder object for now
getBridge()->sendEvent("sendByBrowser", std::move(result));
} //Send::run
@@ -1,6 +1,9 @@
#include "Connector/Interface/ConnectorPalette.h"
#include "Active/Event/Event.h"
#include "Active/Utility/String.h"
#include "Active/Serialise/JSON/JSONTransport.h"
#include "Active/Utility/BufferOut.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Event/ConnectorEventID.h"
#include "Connector/Interface/Browser/Bridge/Account/AccountBridge.h"
@@ -12,14 +15,6 @@
#include "Speckle/Event/Type/MenuEvent.h"
#include "Speckle/Interface/Browser/JSPortal.h"
#include "Speckle/Environment/Project.h"
#include "Connector/Connector.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include <ACAPinc.h>
#include <DGModule.hpp>
#include <DGBrowser.hpp>
@@ -214,7 +209,8 @@ void BrowserPalette::Hide() {
void BrowserPalette::InitBrowserControl() {
#ifdef TESTING_MODE
browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/test");
browser->LoadURL("https://deploy-preview-3180--boisterous-douhua-e3cefb.netlify.app/");
//browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/test");
#else
browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/");
#endif
@@ -1,11 +1,27 @@
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Utility/Guid.h"
#include <array>
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
applicID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"applicationId"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -13,12 +29,32 @@ using namespace speckle::utility;
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Record::fillInventory(active::serialise::Inventory& inventory) const {
bool BIMRecord::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{"id"}, active::database::record::FieldIndex::idIndex, element },
{ Identity{fieldID[applicID]}, applicID, element },
},
}.withType(&typeid(base)));
return true;
} //Record::fillInventory
}.withType(&typeid(BIMRecord)));
return base::fillInventory(inventory);
} //BIMRecord::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique BIMRecord::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(BIMRecord))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case applicID:
return std::make_unique<ValueWrap<BIMRecordID>>(m_applicationID);
default:
return nullptr; //Requested an unknown index
}
} //BIMRecord::getCargo
+28 -10
View File
@@ -1,7 +1,7 @@
#ifndef SPECKLE_DATABASE_RECORD
#define SPECKLE_DATABASE_RECORD
#ifndef SPECKLE_DATABASE_BIM_RECORD
#define SPECKLE_DATABASE_BIM_RECORD
#include "Active/Database/Content/Record.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
@@ -10,12 +10,12 @@ namespace speckle::database {
/*!
Base class for a database record
*/
class BIMRecord : public active::database::BIMRecord<BIMRecordID> {
class BIMRecord : public Record {
public:
// MARK: - Types
using base = active::database::BIMRecord<BIMRecordID>;
using base = Record;
///Unique pointer
using Unique = std::unique_ptr<BIMRecord>;
///Shared pointer
@@ -28,14 +28,12 @@ namespace speckle::database {
/*!
Default constructor
*/
BIMRecord() : base{active::utility::Guid{true}.operator active::utility::String(),
active::utility::Guid{true}.operator active::utility::String()} {} //TODO: Implement a better default for the ID
BIMRecord() : base{} {}
/*!
Constructor
@param ID The record ID
*/
BIMRecord(speckle::utility::String ID, speckle::utility::String::Option globID = std::nullopt) :
base{ID, globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
BIMRecord(speckle::utility::Guid ID) : base{}, m_applicationID{ID} {}
/*!
Destructor
*/
@@ -43,9 +41,19 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Get the BIM application ID
@return The BIM application ID
*/
BIMRecordID getBIMID() const { return m_applicationID; }
// MARK: - Functions (mutating)
/*!
Set the BIM application ID
@param ID The BIM application ID
*/
void setBIMID(const BIMRecordID& ID) { m_applicationID = ID; }
// MARK: - Serialisation
@@ -55,8 +63,18 @@ namespace speckle::database {
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
///The BIM application record ID
BIMRecordID m_applicationID;
};
}
#endif //SPECKLE_DATABASE_RECORD
#endif //SPECKLE_DATABASE_BIM_RECORD
+56 -1
View File
@@ -2,10 +2,28 @@
#include "Speckle/Utility/Guid.h"
#include <array>
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
speckleIDID,
speckleTypeID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
Identity{"speckle_type"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -17,8 +35,45 @@ bool Record::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{"id"}, active::database::record::FieldIndex::idIndex, element },
{ Identity{fieldID[speckleIDID]}, active::database::record::FieldIndex::idIndex, element },
},
}.withType(&typeid(base)));
inventory.merge(Inventory{
{
{ Identity{fieldID[speckleTypeID]}, speckleTypeID, element },
},
}.withType(&typeid(Record)));
return true;
} //Record::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Record::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Record))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case speckleTypeID:
//If the type is undefined, we're in a serialisation process and should populate it with whatever the object says it is
if (!m_type)
m_type = getSpeckleType();
return std::make_unique<StringWrap>(*m_type);
default:
return nullptr; //Requested an unknown index
}
} //Record::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Record::setDefault() {
//Ensure the content starts with an empty (defined) string for deserialisation so we can discover the incoming type
m_type = String{};
} //Record::setDefault
+24 -8
View File
@@ -27,22 +27,24 @@ namespace speckle::database {
/*!
Default constructor
*/
Record() : base{active::utility::Guid{true}.operator active::utility::String(),
active::utility::Guid{true}.operator active::utility::String()} {} //TODO: Implement a better default for the ID
/*!
Constructor
@param ID The record ID
@param globID The global ID
*/
Record(speckle::utility::String ID, speckle::utility::String::Option globID = std::nullopt) :
base{ID, globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
Record(speckle::utility::String::Option ID = std::nullopt, speckle::utility::String::Option globID = std::nullopt) :
base{ID.value_or(active::utility::Guid{true}.operator active::utility::String()),
globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
/*!
Destructor
*/
virtual ~Record() {}
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required, but "Base" is still considered a type on its own)
*/
virtual speckle::utility::String getSpeckleType() const { return "Base"; }
// MARK: - Functions (mutating)
@@ -55,6 +57,20 @@ namespace speckle::database {
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///Cache for the speckle type during serialisation operations
mutable speckle::utility::String::Option m_type;
};
}
+12 -5
View File
@@ -1,6 +1,8 @@
#include "Speckle/Primitive/Mesh/Mesh.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Inventory/Identity.h"
#include <array>
@@ -14,12 +16,14 @@ namespace {
enum FieldIndex {
vertexID,
faceID,
colorID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"vertices"},
Identity{"faces"},
Identity{"colors"},
};
}
@@ -35,8 +39,9 @@ bool Mesh::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
//{ fieldID[vertexID], vertexID, vertices::size(), std::nullopt, !vertices::empty() },
//{ fieldID[elementID], elementID, faces::size(), std::nullopt, !faces::empty() },
{ fieldID[vertexID], vertexID, element },
{ fieldID[faceID], faceID, element },
{ fieldID[colorID], colorID, element },
},
}.withType(&typeid(Mesh)));
return true;
@@ -55,10 +60,12 @@ Cargo::Unique Mesh::getCargo(const Inventory::Item& item) const {
return nullptr;
using namespace active::serialise;
switch (item.index) {
case vertexID:
return nullptr; //TODO: Implement vertices array
case vertexID:
return std::make_unique<ContainerWrap<std::vector<double>>>(vertices);
case faceID:
return nullptr; //TODO: Implement faces array
return std::make_unique<ContainerWrap<std::vector<int>>>(faces);
case colorID:
return std::make_unique<ContainerWrap<std::vector<int>>>(colors);
default:
return nullptr; //Requested an unknown index
}
+8 -1
View File
@@ -2,6 +2,7 @@
#define SPECKLE_PRIMITIVE_MESH
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
@@ -18,6 +19,9 @@ namespace speckle::primitive {
*/
Mesh() {}
Mesh(std::vector<double>&& vertices, std::vector<int>&& faces, std::vector<int>&& colors, utility::String units = "m")
: vertices{ std::move(vertices) }, faces{ std::move(faces) }, colors{ std::move(colors) }, units{ units } {}
// MARK: - Functions (const)
@@ -37,7 +41,10 @@ namespace speckle::primitive {
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
utility::String units;
};
}
+95 -3
View File
@@ -2,6 +2,7 @@
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Speckle/Primitive/Mesh/Mesh.h"
#include "Speckle/Utility/Guid.h"
@@ -10,6 +11,7 @@ using namespace speckle::record::element;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::element {
@@ -39,6 +41,14 @@ namespace {
Identity{"displayValue"},
};
void GetComponent(API_Component3D& component, API_3DTypeID typeId, Int32 index) {
component.header.typeID = typeId;
component.header.index = index;
if (ACAPI_ModelAccess_GetComponent(&component) != NoError) {
// TODO: throw
}
}
}
/*--------------------------------------------------------------------
@@ -53,7 +63,7 @@ Element::Element() {
elemData: Archicad element data
--------------------------------------------------------------------*/
Element::Element(const API_Element& elemData) {
Element::Element(const API_Element& elemData) : base{elemData.header.guid} {
m_data = std::make_unique<Data>(elemData);
} //Element::Element
@@ -63,7 +73,7 @@ Element::Element(const API_Element& elemData) {
source: The object to copy
--------------------------------------------------------------------*/
Element::Element(const Element& source) {
Element::Element(const Element& source) : base{source} {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //Element::Element
@@ -73,6 +83,81 @@ Element::Element(const Element& source) {
--------------------------------------------------------------------*/
Element::~Element() {}
Element::Body* Element::getBody() const {
if (m_data->m_cache) {
return m_data->m_cache.get();
}
auto elementBody = new Element::Body();
std::map<int, int> vertexIndexMap;
int currentVertexIndex = 0;
API_ElemInfo3D info3D = {};
if (ACAPI_ModelAccess_Get3DInfo(getHead(), &info3D) != NoError) {
// TODO: throw
}
for (Int32 ib = info3D.fbody; ib <= info3D.lbody; ib++) {
API_Component3D component = {};
GetComponent(component, API_BodyID, ib);
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
vertices.clear();
faces.clear();
colors.clear();
Int32 nPgon = component.body.nPgon;
for (Int32 ip = 1; ip <= nPgon; ip++) {
GetComponent(component, API_PgonID, ip);
Int32 fpedg = component.pgon.fpedg;
Int32 lpedg = component.pgon.lpedg;
Int32 faceSize = lpedg - fpedg + 1;
faces.push_back(faceSize);
for (Int32 ie = fpedg; ie <= lpedg; ie++)
{
GetComponent(component, API_PedgID, ie);
// TODO is this needed? need review, not sure how ACAPI_ModelAccess works
bool wasNegative = component.pedg.pedg < 0;
Int32 edgeIndex = std::abs(component.pedg.pedg);
GetComponent(component, API_EdgeID, edgeIndex);
// TODO is this needed? need review, not sure how ACAPI_ModelAccess works
Int32 vertexIndex = wasNegative ? component.edge.vert2 : component.edge.vert1;
/*auto materialIndex = component.pgon.iumat;
GetComponent(component, API_UmatID, materialIndex);
double R = component.umat.mater.surfaceRGB.f_red;
double G = component.umat.mater.surfaceRGB.f_green;
double B = component.umat.mater.surfaceRGB.f_blue;*/
// TODO: other material stuff
GetComponent(component, API_VertID, vertexIndex);
if (vertexIndexMap.find(vertexIndex) == vertexIndexMap.end()) {
faces.push_back(currentVertexIndex);
vertexIndexMap[vertexIndex] = currentVertexIndex++;
vertices.push_back(component.vert.x);
vertices.push_back(component.vert.y);
vertices.push_back(component.vert.z);
}
else {
faces.push_back(vertexIndexMap[vertexIndex]);
}
}
}
elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors)));
}
m_data->m_cache.reset(elementBody);
return m_data->m_cache.get();
}
/*--------------------------------------------------------------------
Get the (immutable) API element header data
@@ -125,7 +210,14 @@ Cargo::Unique Element::getCargo(const Inventory::Item& item) const {
using namespace active::serialise;
switch (item.index) {
case bodyID:
return nullptr; //TODO: implement
if (auto body = getBody(); body != nullptr)
{
//return std::make_unique<active::serialise::ContainerWrap>(*body);
return Cargo::Unique{ new active::serialise::ContainerWrap{ *body } };
}
else
return nullptr;
default:
return nullptr; //Requested an unknown index
}
+4 -4
View File
@@ -1,7 +1,7 @@
#ifndef SPECKLE_RECORD_ELEMENT
#define SPECKLE_RECORD_ELEMENT
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
@@ -13,7 +13,7 @@ namespace speckle::record::element {
/*!
Base BIM element class
*/
class Element : public speckle::database::Record {
class Element : public speckle::database::BIMRecord {
public:
///An element 3D body primitive
@@ -21,7 +21,7 @@ namespace speckle::record::element {
// MARK: - Types
using base = speckle::database::Record;
using base = speckle::database::BIMRecord;
///Unique pointer
using Unique = std::unique_ptr<Element>;
///Shared pointer
@@ -67,7 +67,7 @@ namespace speckle::record::element {
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
virtual Body* getBody() const { return nullptr; }
virtual Body* getBody() const;
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data