diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp index 73c41b8..c4d5c3b 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp @@ -7,6 +7,8 @@ #include "Speckle/Interface/Browser/Bridge/BrowserBridge.h" #include "Speckle/Utility/Exception.h" +#include + using namespace active::serialise; using namespace connector::interfac::browser::bridge; using namespace speckle::utility; diff --git a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp index 6b63586..da74945 100644 --- a/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp +++ b/SpeckleConnector/Connector/Interface/ConnectorPalette.cpp @@ -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" @@ -15,10 +18,12 @@ #include "Speckle/Environment/Project.h" - #include "Connector/Connector.h" #include "Speckle/Database/BIMElementDatabase.h" +#include +#include +#include #include #include @@ -128,6 +133,31 @@ bool ConnectorPalette::start() { } //ConnectorPalette::start +static void Test() { + if (auto project = connector::connector()->getActiveProject().lock(); project) { + auto elementDatabase = project->getElementDatabase(); + auto selected = elementDatabase->getSelection(); + for (const auto& link : selected) { + auto element = elementDatabase->getElement(link); + active::utility::String output; + active::serialise::json::JSONTransport().send(std::forward(*element), active::serialise::Identity{}, output); + if (output.length() > 0) { + std::ofstream outFile("C:\\temp\\output.txt"); // Create an output file stream (opens file) + + // Check if the file opened successfully + if (outFile.is_open()) { + outFile << output.string(); + outFile.close(); + std::cout << "String written to file successfully." << std::endl; + } + else { + std::cerr << "Unable to open file." << std::endl; + } + } + } + } +} + /*-------------------------------------------------------------------- Receive a subscribed event @@ -136,6 +166,9 @@ bool ConnectorPalette::start() { return: True if the event should be closed --------------------------------------------------------------------*/ bool ConnectorPalette::receive(const active::event::Event& event) { + + Test(); + if (BrowserPalette::HasInstance() && BrowserPalette::GetInstance().IsVisible()) { BrowserPalette::GetInstance().Hide (); } else { diff --git a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp index ffe58ec..8b2d0de 100644 --- a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp +++ b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp @@ -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 @@ -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, vertices.size(), std::nullopt, !vertices.empty() }, + { fieldID[faceID], faceID, faces.size(), std::nullopt, !faces.empty() }, + { fieldID[colorID], colorID, colors.size(), std::nullopt, !colors.empty() }, }, }.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>>(vertices); case faceID: - return nullptr; //TODO: Implement faces array + return std::make_unique>>(faces); + case colorID: + return std::make_unique>>(colors); default: return nullptr; //Requested an unknown index } diff --git a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h index d440fc3..72035e2 100644 --- a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h +++ b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h @@ -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&& vertices, std::vector&& faces, std::vector&& 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 vertices; + std::vector faces; + std::vector colors; + utility::String units; }; } diff --git a/SpeckleLib/Speckle/Record/Element/Element.cpp b/SpeckleLib/Speckle/Record/Element/Element.cpp index 999cfe7..63b3cb2 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.cpp +++ b/SpeckleLib/Speckle/Record/Element/Element.cpp @@ -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 +#include 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 + } + } + } /*-------------------------------------------------------------------- @@ -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 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 vertices; + std::vector faces; + std::vector 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; + 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); + + faces.push_back(faceSize); + 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(*body); + return Cargo::Unique{ new active::serialise::ContainerWrap{ *body } }; + } + else + return nullptr; + default: return nullptr; //Requested an unknown index } diff --git a/SpeckleLib/Speckle/Record/Element/Element.h b/SpeckleLib/Speckle/Record/Element/Element.h index 068d495..ee478c9 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.h +++ b/SpeckleLib/Speckle/Record/Element/Element.h @@ -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