diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h index 601c330..662b2e3 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h @@ -43,6 +43,16 @@ namespace connector::interfac::browser::bridge { @return The requested cargo (nullptr on failure) */ Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Use a manager in (de)serialisation processes + @param management The management to use + */ + void useManagement(active::serialise::Management* management) const override { m_object->useManagement(management); } + /*! + Get the cargo management + @return The active management + */ + active::serialise::Management* management() const override { return m_object->management(); } private: ///The object to send diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h index c611732..71cef33 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h @@ -72,6 +72,16 @@ namespace connector::interfac::browser::bridge { @return The requested cargo (nullptr on failure) */ Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Use a manager in (de)serialisation processes + @param management The management to use + */ + void useManagement(active::serialise::Management* management) const override { sendObject.useManagement(management); } + /*! + Get the cargo management + @return The active management + */ + active::serialise::Management* management() const override { return sendObject.management(); } }; } diff --git a/SpeckleConnector/Connector/Record/Collection/FinishProxy.cpp b/SpeckleConnector/Connector/Record/Collection/FinishProxy.cpp index a4643fc..3979204 100644 --- a/SpeckleConnector/Connector/Record/Collection/FinishProxy.cpp +++ b/SpeckleConnector/Connector/Record/Collection/FinishProxy.cpp @@ -37,10 +37,10 @@ bool FinishProxy::fillInventory(active::serialise::Inventory& inventory) const { inventory.merge(Inventory{ { { fieldID[materialID], materialID, element }, - { fieldID[linkedMeshID], linkedMeshID, m_meshID.size(), std::nullopt }, + { fieldID[linkedMeshID], linkedMeshID, element }, }, }.withType(&typeid(FinishProxy))); - return true; + return base::fillInventory(inventory); } //FinishProxy::fillInventory @@ -53,13 +53,15 @@ bool FinishProxy::fillInventory(active::serialise::Inventory& inventory) const { --------------------------------------------------------------------*/ Cargo::Unique FinishProxy::getCargo(const active::serialise::Inventory::Item& item) const { if (item.ownerType != &typeid(FinishProxy)) - return nullptr; + return base::getCargo(item); using namespace active::serialise; switch (item.index) { case materialID: return std::make_unique(m_finish); - case linkedMeshID: - return std::make_unique>>(m_meshID); + case linkedMeshID: { + auto result = new ContainerWrap(m_meshID); + return Cargo::Unique{result}; + } default: return nullptr; //Requested an unknown index } diff --git a/SpeckleConnector/Connector/Record/Collection/FinishProxy.h b/SpeckleConnector/Connector/Record/Collection/FinishProxy.h index 19fba4a..3ad7b3e 100644 --- a/SpeckleConnector/Connector/Record/Collection/FinishProxy.h +++ b/SpeckleConnector/Connector/Record/Collection/FinishProxy.h @@ -1,7 +1,7 @@ #ifndef CONNECTOR_RECORD_COLLECTION_MATERIAL_PROXY #define CONNECTOR_RECORD_COLLECTION_MATERIAL_PROXY -#include "Active/Serialise/Package/Package.h" +#include "Speckle/Database/Content/BIMRecord.h" #include "Speckle/Record/Attribute/Finish.h" #include "Speckle/Utility/String.h" @@ -10,9 +10,11 @@ namespace connector::record { /*! A proxy record binding a surface finishes to meshes */ - class FinishProxy : public active::serialise::Package { + class FinishProxy : public speckle::database::BIMRecord { public: + using base = speckle::database::BIMRecord; + // MARK: - Constructors /*! @@ -21,8 +23,16 @@ namespace connector::record { @param meshID The list of mesh IDs the finish is applied to */ FinishProxy(const speckle::record::attribute::Finish& finish, const std::unordered_set& meshID) : - m_finish{finish} { std::copy(meshID.begin(), meshID.end(), std::back_inserter(m_meshID)); } + base{speckle::utility::Guid{true}, speckle::utility::Guid{}, std::nullopt}, m_finish{finish} { + std::copy(meshID.begin(), meshID.end(), std::back_inserter(m_meshID)); + } + /*! + 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) + */ + speckle::utility::String getSpeckleType() const override { return "Objects.Other.RenderMaterialProxy"; } + // MARK: - Serialisation /*! diff --git a/SpeckleConnector/Connector/Record/Collection/ProjectCollection.cpp b/SpeckleConnector/Connector/Record/Collection/ProjectCollection.cpp index 5ecbc69..3b46167 100644 --- a/SpeckleConnector/Connector/Record/Collection/ProjectCollection.cpp +++ b/SpeckleConnector/Connector/Record/Collection/ProjectCollection.cpp @@ -2,6 +2,7 @@ #include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Management/Management.h" #include "Active/Serialise/Package/Wrapper/PackageWrap.h" #include "Connector/Connector.h" #include "Connector/ConnectorResource.h" @@ -11,6 +12,7 @@ #include "Speckle/Record/Element/Element.h" #ifdef ARCHICAD +#include #include #endif @@ -47,8 +49,11 @@ namespace { project: The source project --------------------------------------------------------------------*/ -ProjectCollection::ProjectCollection(speckle::environment::Project::Shared project) : base{project->getInfo().name, project} { +ProjectCollection::ProjectCollection(speckle::environment::Project::Shared project) : base{project->getInfo().name, project}, + m_management{std::make_unique()} { + m_management->push_back(this); m_finishes = std::make_unique(); + base::useManagement(m_management.get()); } //ProjectCollection::ProjectCollection @@ -128,10 +133,12 @@ bool ProjectCollection::addMaterialProxy(const speckle::database::BIMIndex& mate --------------------------------------------------------------------*/ bool ProjectCollection::addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) { auto finishID = Guid::fromInt(material.GenerateHashValue()); - if (m_finishes->find(finishID) != m_finishes->end()) - return false; - auto finish = std::make_unique(material); - return m_finishes->insert({finishID, std::move(finish)}).second; + auto iter = m_finishes->find(finishID); + if (iter == m_finishes->end()) { + auto finish = std::make_unique(material); + iter = m_finishes->insert({ finishID, std::move(finish) }).first; + } + return addMaterialProxy(finishID, objectID); } //ProjectCollection::addMaterialProxy #endif @@ -148,7 +155,7 @@ bool ProjectCollection::fillInventory(active::serialise::Inventory& inventory) c base::fillInventory(inventory); inventory.merge(Inventory{ { - { Identity{fieldID[finishProxyID]}, finishProxyID, m_finishProxies.size(), std::nullopt }, + { Identity{fieldID[finishProxyID]}, finishProxyID, 100, std::nullopt }, }, }.withType(&typeid(ProjectCollection))); return true; diff --git a/SpeckleConnector/Connector/Record/Collection/ProjectCollection.h b/SpeckleConnector/Connector/Record/Collection/ProjectCollection.h index ddf287a..7d2f2c6 100644 --- a/SpeckleConnector/Connector/Record/Collection/ProjectCollection.h +++ b/SpeckleConnector/Connector/Record/Collection/ProjectCollection.h @@ -6,6 +6,10 @@ #include +namespace active::serialise { + class Management; +} + namespace speckle::record::element { class Element; } @@ -94,6 +98,7 @@ namespace connector::record { private: using FinishProxies = std::unordered_map>; + std::unique_ptr m_management; ///Finish proxies accumulated from meshes generated from the collection elements FinishProxies m_finishProxies; #ifdef ARCHICAD diff --git a/SpeckleLib/Speckle/Database/Content/BIMRecord.cpp b/SpeckleLib/Speckle/Database/Content/BIMRecord.cpp index dcc55d1..9f230d3 100644 --- a/SpeckleLib/Speckle/Database/Content/BIMRecord.cpp +++ b/SpeckleLib/Speckle/Database/Content/BIMRecord.cpp @@ -1,7 +1,7 @@ #include "Speckle/Database/Content/BIMRecord.h" #include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h" -#include "Speckle/Serialise/Units/LengthUnit.h" +#include "Speckle/Serialise/Types/Units/LengthUnit.h" #include "Speckle/Utility/Guid.h" #include @@ -23,7 +23,7 @@ namespace { ///Serialisation field IDs static std::array fieldID = { Identity{"applicationId"}, - Identity{"unit"}, + Identity{"units"}, }; } diff --git a/SpeckleLib/Speckle/Database/Content/BIMRecord.h b/SpeckleLib/Speckle/Database/Content/BIMRecord.h index a9964f3..aebd2be 100644 --- a/SpeckleLib/Speckle/Database/Content/BIMRecord.h +++ b/SpeckleLib/Speckle/Database/Content/BIMRecord.h @@ -39,7 +39,7 @@ namespace speckle::database { @param unit The record unit type */ BIMRecord(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID, - active::measure::LengthType unit = active::measure::LengthType::metre) : + std::optional unit = active::measure::LengthType::metre) : base{}, m_applicationID{ID}, m_applicationTableID{tableID}, m_unit{unit} {} /*! Destructor @@ -63,6 +63,11 @@ namespace speckle::database { @return The BIM record link */ BIMLink getBIMLink() const { return BIMLink{ BIMLink::base{m_applicationID, m_applicationTableID} }; } + /*! + Get the record unit type + @return The record unit type (nullopt if the record has no applicable unit type) + */ + std::optional getUnit() const { return m_unit; } // MARK: - Functions (mutating) @@ -76,6 +81,11 @@ namespace speckle::database { @param tableID The BIM table ID */ void setTableID(const BIMRecordID& tableID) { m_applicationTableID = tableID; } + /*! + Set the record unit type + @param unit The record unit type (nullopt if the record has no applicable unit type) + */ + void setUnit(std::optional unit) { m_unit = unit; } // MARK: - Serialisation diff --git a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp index 5251c28..23b0f83 100644 --- a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp +++ b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.cpp @@ -10,6 +10,7 @@ using namespace active::serialise; using namespace speckle::primitive; +using namespace speckle::serialise; namespace { @@ -18,7 +19,6 @@ namespace { vertexID, faceID, colorID, - proxyID, }; ///Serialisation field IDs @@ -26,7 +26,6 @@ namespace { Identity{"vertices"}, Identity{"faces"}, Identity{"colors"}, - Identity{"proxy"}, }; } @@ -45,7 +44,6 @@ bool Mesh::fillInventory(Inventory& inventory) const { { fieldID[vertexID], vertexID, element }, { fieldID[faceID], faceID, element }, { fieldID[colorID], colorID, element }, - { fieldID[proxyID], proxyID, element }, }, }.withType(&typeid(Mesh))); return base::fillInventory(inventory); @@ -65,15 +63,26 @@ Cargo::Unique Mesh::getCargo(const Inventory::Item& item) const { using namespace active::serialise; switch (item.index) { case vertexID: - return std::make_unique>>(vertices); + return std::make_unique>>(m_vertices); case faceID: - return std::make_unique>>(faces); + return std::make_unique>>(m_faces); case colorID: - return std::make_unique>>(colors); - case proxyID: - return nullptr; //Activate the following line when the mesh material is available to add to the collector - //return std::make_unique(getBIMID(), material); + return std::make_unique>>(m_colors); default: return nullptr; //Requested an unknown index } } //Mesh::getCargo + + +/*-------------------------------------------------------------------- + Use a manager in (de)serialisation processes + + management: The management to use + --------------------------------------------------------------------*/ +void Mesh::useManagement(Management* management) const { + //NB: This object only exists to populate the finish collection - it doesn't carry any serialisable content + if (management != nullptr) { + if (auto collector = management->get(); collector != nullptr) + collector->addMaterialProxy(m_material, getBIMID()); + } +} //Mesh::useManagement diff --git a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h index 93f2788..7c4853a 100644 --- a/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h +++ b/SpeckleLib/Speckle/Primitive/Mesh/Mesh.h @@ -4,6 +4,10 @@ #include "Speckle/Database/Content/BIMRecord.h" #include "Speckle/Utility/String.h" +#ifdef ARCHICAD +#include "ModelMaterial.hpp" +#endif + namespace speckle::primitive { /*! @@ -22,7 +26,7 @@ namespace speckle::primitive { Default constructor @param unit The mesh unit type */ - Mesh(active::measure::LengthType unit = active::measure::LengthType::metre) : base{unit} {} + Mesh(active::measure::LengthType unit = active::measure::LengthType::metre) : base{utility::Guid{true}, utility::Guid{}, unit} {} /*! Constructor @param vertices The mesh vertices @@ -30,9 +34,9 @@ namespace speckle::primitive { @param colors The mesh face colours @param unit The mesh unit type */ - Mesh(std::vector&& vertices, std::vector&& faces, std::vector&& colors, + Mesh(std::vector&& vertices, std::vector&& faces, std::vector&& colors, const ModelerAPI::Material& material, active::measure::LengthType unit = active::measure::LengthType::metre) : - base{unit}, vertices {std::move(vertices)}, faces{std::move(faces)}, colors{std::move(colors)} {} + base{utility::Guid{true}, utility::Guid{}, unit}, m_vertices{std::move(vertices)}, m_faces{std::move(faces)}, m_colors{std::move(colors)}, m_material{material} {} // MARK: - Functions (const) @@ -40,7 +44,7 @@ namespace speckle::primitive { Get the speckle type identifier @return The speckle type (relevant objects should override as required) */ - speckle::utility::String getSpeckleType() const override { return "speckle::primitive::Mesh"; } + speckle::utility::String getSpeckleType() const override { return "Objects.Geometry.Mesh"; } // MARK: - Serialisation @@ -56,11 +60,19 @@ namespace speckle::primitive { @return The requested cargo (nullptr on failure) */ active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; + /*! + Use a manager in (de)serialisation processes + @param management The management to use + */ + void useManagement(active::serialise::Management* management) const override; private: - std::vector vertices; - std::vector faces; - std::vector colors; + std::vector m_vertices; + std::vector m_faces; + std::vector m_colors; +#ifdef ARCHICAD + ModelerAPI::Material m_material; +#endif }; } diff --git a/SpeckleLib/Speckle/Record/Attribute/Attribute.cpp b/SpeckleLib/Speckle/Record/Attribute/Attribute.cpp index dba0b12..eece72d 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Attribute.cpp +++ b/SpeckleLib/Speckle/Record/Attribute/Attribute.cpp @@ -3,6 +3,7 @@ #include "Speckle/Database/BIMAttributeDatabase.h" #include "Speckle/Environment/Addon.h" #include "Speckle/Environment/Project.h" +#include "Speckle/Serialise/Types/Str256.h" using namespace active::serialise; using namespace speckle::database; @@ -77,8 +78,9 @@ Cargo::Unique Attribute::getCargo(const Inventory::Item& item) const { using namespace active::serialise; switch (item.index) { case nameID: - //return std::make_unique(*body); - return std::make_unique(getHead().name); +#ifdef ARCHICAD + return std::make_unique>(reinterpret_cast(getHead().name)); +#endif default: return nullptr; //Requested an unknown index } diff --git a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp index 448b9d4..86d45dd 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Finish.cpp +++ b/SpeckleLib/Speckle/Record/Attribute/Finish.cpp @@ -2,11 +2,14 @@ #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Active/Serialise/Management/Management.h" +#include "Active/Serialise/CargoHold.h" #include "Active/Utility/BufferOut.h" #include "Speckle/Serialise/Collection/FinishCollector.h" +#include "Speckle/Serialise/Types/ArchicadRGB.h" #include "Speckle/Utility/Guid.h" #ifdef ARCHICAD +#include #include #endif @@ -21,14 +24,28 @@ using namespace speckle::utility; namespace speckle::record::attribute { + ///Internal representation of a rendered finish on a 3D body, i.e. the surface colour/texture etc. class Finish::Data { public: #ifdef ARCHICAD - Data(const API_Attribute& attr) : root{attr.material} {} - Data(const Data& source) : root{source.root} {} + /*! + Constructor from Archicad surface material + @param attr An Archicad attribute + */ + Data(const API_Attribute& attr) : root{attr.material} { + opacity = 1.0 - (static_cast(attr.material.transpPc) / 100.0); + roughness = 1.0 - (static_cast(attr.material.shine) / 10000.0); + } + ///Archicad representation of a surface material API_MaterialType root; #endif + //Opacity (0.0 -> 1.0) + double opacity = 1.0; + //Roughness (0.0 -> 1.0) + double roughness = 0.0; + //Metalness (0.0 -> 1.0) + double metalness = 0.0; }; } @@ -37,23 +54,33 @@ namespace { ///Serialisation fields enum FieldIndex { - surfaceColourID, + diffuseID, + opacityID, + emissiveID, + metalnessID, + roughnessID, }; ///Serialisation field IDs static std::array fieldID = { - Identity{"surfaceColour"}, + Identity{"diffuse"}, + Identity{"opacity"}, + Identity{"emissive"}, + Identity{"metalness"}, + Identity{"roughness"}, }; #ifdef ARCHICAD /*! Copy a ModelerAPI colour to an AC RGB colour + @param modelColour The modeler API colour + @param colour The attribute API colour */ void copyModelerColor(const ModelerAPI::Color& modelColour, API_RGBColor& colour) { colour.f_red = modelColour.red; colour.f_green = modelColour.green; colour.f_blue = modelColour.blue; - } //copyModelerColor + } #endif } @@ -82,6 +109,7 @@ Finish::Finish(const database::BIMRecordID& ID) : base{ID, Finish::table} { --------------------------------------------------------------------*/ Finish::Finish(const API_Attribute& attrData, const BIMRecordID& tableID) : base{attrData.header.guid, Finish::table} { m_data = std::make_unique(attrData); + setUnit(std::nullopt); //Finishes have no unit } @@ -90,23 +118,25 @@ Finish::Finish(const API_Attribute& attrData, const BIMRecordID& tableID) : base material: A ModelerAPI material definition --------------------------------------------------------------------*/ -Finish::Finish(const ModelerAPI::Material& material) { +Finish::Finish(const ModelerAPI::Material& material) : base{Guid{Guid::fromInt(material.GenerateHashValue())}, Finish::table} { API_Attribute attr; active::utility::Memory::erase(attr); String{material.GetName()}.writeUTF8(active::utility::BufferOut{attr.header.name}); - attr.header.guid = Guid{Guid::fromInt(material.GenerateHashValue())}; + attr.header.guid = getBIMID(); attr.material.mtype = static_cast(material.GetType()); - attr.material.ambientPc = material.GetAmbientReflection(); - attr.material.diffusePc = material.GetDiffuseReflection(); - attr.material.specularPc = material.GetSpecularReflection(); - attr.material.transpPc = material.GetTransparency(); - attr.material.shine = material.GetShining(); - attr.material.transpAtt = material.GetTransparencyAttenuation(); - attr.material.emissionAtt = material.GetEmissionAttenuation(); + attr.material.ambientPc = static_cast(material.GetAmbientReflection() * 100); + attr.material.diffusePc = static_cast(material.GetDiffuseReflection() * 100); + attr.material.specularPc = static_cast(material.GetSpecularReflection() * 100); + attr.material.transpPc = static_cast(material.GetTransparency() * 100); + auto temp = material.GetShining(); + attr.material.shine = static_cast(material.GetShining() * 100); + attr.material.transpAtt = static_cast(material.GetTransparencyAttenuation() * 400); + attr.material.emissionAtt = static_cast(material.GetEmissionAttenuation() * 65535); copyModelerColor(material.GetSurfaceColor(), attr.material.surfaceRGB); copyModelerColor(material.GetSpecularColor(), attr.material.specularRGB); copyModelerColor(material.GetEmissionColor(), attr.material.emissionRGB); m_data = std::make_unique(attr); + setUnit(std::nullopt); //Finishes have no unit } //Finish::Finish #endif @@ -117,7 +147,7 @@ Finish::Finish(const ModelerAPI::Material& material) { source: The object to copy --------------------------------------------------------------------*/ Finish::Finish(const Finish& source) : base{source} { - m_data = source.m_data ? std::make_unique(*m_data) : nullptr; + m_data = source.m_data ? std::make_unique(*source.m_data) : nullptr; } //Finish::Finish @@ -162,7 +192,11 @@ bool Finish::fillInventory(Inventory& inventory) const { using enum Entry::Type; inventory.merge(Inventory{ { - { fieldID[surfaceColourID], surfaceColourID, element }, //TODO: implement other fields + { fieldID[diffuseID], diffuseID, element }, + { fieldID[opacityID], opacityID, element }, + { fieldID[emissiveID], emissiveID, element }, + { fieldID[metalnessID], metalnessID, element }, + { fieldID[roughnessID], roughnessID, element }, }, }.withType(&typeid(Finish))); return base::fillInventory(inventory); @@ -182,8 +216,20 @@ Cargo::Unique Finish::getCargo(const Inventory::Item& item) const { confirmData(); using namespace active::serialise; switch (item.index) { - case surfaceColourID: - return nullptr; //TODO: lookup surface colour + case diffuseID: +#ifdef ARCHICAD + return std::make_unique>(m_data->root.surfaceRGB); +#endif + case opacityID: + return std::make_unique(m_data->opacity); + case emissiveID: +#ifdef ARCHICAD + return std::make_unique>(m_data->root.emissionRGB); +#endif + case metalnessID: + return std::make_unique(m_data->metalness); + case roughnessID: + return std::make_unique(m_data->roughness); default: return nullptr; //Requested an unknown index } @@ -194,10 +240,26 @@ Cargo::Unique Finish::getCargo(const Inventory::Item& item) const { Set to the default package content --------------------------------------------------------------------*/ void Finish::setDefault() { - + m_data->root = {}; + m_data->opacity = 0.0; + m_data->roughness = 1.0; + m_data->metalness = 0.0; } //Finish::setDefault +/*-------------------------------------------------------------------- + Validate the cargo data + + return: True if the data has been validated + --------------------------------------------------------------------*/ +bool Finish::validate() { + m_data->root.transpPc = static_cast(100 * (1.0 - m_data->opacity)); + m_data->root.shine = static_cast(10000 * (1.0 - m_data->roughness)); + //NB: Archicad has no metalness value - currently discarded + return true; +} //Finish::validate + + /*-------------------------------------------------------------------- Confirm the internal data, either loading from the BIM application or setting a default --------------------------------------------------------------------*/ diff --git a/SpeckleLib/Speckle/Record/Attribute/Finish.h b/SpeckleLib/Speckle/Record/Attribute/Finish.h index 1c597f7..72fb19d 100644 --- a/SpeckleLib/Speckle/Record/Attribute/Finish.h +++ b/SpeckleLib/Speckle/Record/Attribute/Finish.h @@ -122,6 +122,11 @@ namespace speckle::record::attribute { Set to the default package content */ void setDefault() override; + /*! + Validate the cargo data + @return True if the data has been validated + */ + bool validate() override; private: /*! diff --git a/SpeckleLib/Speckle/Record/Element/Element.cpp b/SpeckleLib/Speckle/Record/Element/Element.cpp index d9ebf92..02fda04 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.cpp +++ b/SpeckleLib/Speckle/Record/Element/Element.cpp @@ -8,6 +8,7 @@ #include "Speckle/SpeckleResource.h" #include "Speckle/Utility/Guid.h" +#ifdef ARCHICAD #include "Sight.hpp" #include "Model.hpp" #include "ModelMaterial.hpp" @@ -15,6 +16,7 @@ #include "exp.h" #include "ModelMeshBody.hpp" #include "ConvexPolygon.hpp" +#endif using namespace active::serialise; using namespace speckle::environment; @@ -55,16 +57,6 @@ namespace { Identity{"displayValue"}, }; - int32_t ARGBToInt(double alpha, double red, double green, double blue) { - // Convert double (0.0 - 1.0) to uint8_t (0 - 255) - uint8_t a = static_cast(std::round(alpha * 255.0)); - uint8_t r = static_cast(std::round(red * 255.0)); - uint8_t g = static_cast(std::round(green * 255.0)); - uint8_t b = static_cast(std::round(blue * 255.0)); - - // Pack ARGB into a single 32-bit integer - return (a << 24) | (r << 16) | (g << 8) | b; - } } /*-------------------------------------------------------------------- @@ -204,13 +196,13 @@ Element::Body* Element::getBody() const { vertices.push_back(vertex.y); vertices.push_back(vertex.z); - double alpha = material.GetTransparency(); - ModelerAPI::Color color = material.GetSurfaceColor(); - colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue)); + //double alpha = material.GetTransparency(); + //ModelerAPI::Color color = material.GetSurfaceColor(); + //colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue)); faces.push_back(vertexIndex - 1); } - elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors))); + elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors), material)); } } } @@ -251,12 +243,11 @@ API_Elem_Head& Element::getHead() { --------------------------------------------------------------------*/ bool Element::fillInventory(Inventory& inventory) const { using enum Entry::Type; - auto body = getBody(); inventory.merge(Inventory{ { { fieldID[bodyID], bodyID, element }, //TODO: implement other fields }, - }.withType(&typeid(Element))); + }.withType(&typeid(Element))); return base::fillInventory(inventory); } //Element::fillInventory @@ -276,7 +267,7 @@ Cargo::Unique Element::getCargo(const Inventory::Item& item) const { case bodyID: if (auto body = getBody(); body != nullptr) { - return Cargo::Unique{ new active::serialise::ContainerWrap{ *body } }; + return Cargo::Unique{ new active::serialise::ContainerWrap{*body} }; } else return nullptr; diff --git a/SpeckleLib/Speckle/Serialise/Types/ArchicadRGB.h b/SpeckleLib/Speckle/Serialise/Types/ArchicadRGB.h new file mode 100644 index 0000000..83517a0 --- /dev/null +++ b/SpeckleLib/Speckle/Serialise/Types/ArchicadRGB.h @@ -0,0 +1,82 @@ +#ifndef SPECKLE_SERIALISE_ARCHICAD_RGB +#define SPECKLE_SERIALISE_ARCHICAD_RGB + +#ifdef ARCHICAD + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h" +#include "Active/Utility/BufferOut.h" + +#ifdef ARCHICAD +#include +#include +#endif + +namespace active::serialise { + + // MARK: - Specialisations for API_RGBColor + + /*! + Convert a string (encoding a 32-bit unsigned integer) to an Archicad RGB colour structure + @param source The source string to convert + @return The equivalent colour (nullopt on failure) + */ + std::optional convertToAPI_RGBColor(const utility::String& source) { + auto intValue = source.toUInt32(); + if (!intValue) + return std::nullopt; + API_RGBColor result{}; + *intValue >>= 8; + result.f_red = static_cast(*intValue & 0xFF) / 255.0; + *intValue >>= 8; + result.f_green = static_cast(*intValue & 0xFF) / 255.0; + *intValue >>= 8; + result.f_blue = static_cast(*intValue & 0xFF) / 255.0; + return result; + } + + /*! + Import the object from the specified string (specialisation for API_RGBColor) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap::read(const utility::String& source) { + if (auto colour = convertToAPI_RGBColor(source); colour) { + get() = *colour; + return true; + } + return false; + } //ValueWrap::read + + + /*! + Import the object from the specified string (specialisation for API_RGBColor) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap>::read(const utility::String& source) { + if (auto colour = convertToAPI_RGBColor(source); colour) + get() = colour; + return true; + } //ValueWrap::read + + + /*! + Export the object to the specified string (specialisation for API_RGBColor) + @param dest The string to write the data to + @return True if the data was successfully written + */ + template<> inline + bool ValueWrap::write(utility::String& dest) const { + dest = speckle::utility::String{(static_cast(get().f_red * 255.0) << 16) | + ((static_cast(get().f_green * 255.0)) << 8) | + ((static_cast(get().f_blue * 255.0)))}; + return true; + } //ValueWrap::write + +} + +#endif //ARCHICAD +#endif //SPECKLE_SERIALISE_ARCHICAD_RGB diff --git a/SpeckleLib/Speckle/Serialise/Types/Str256.h b/SpeckleLib/Speckle/Serialise/Types/Str256.h new file mode 100644 index 0000000..d6cfcae --- /dev/null +++ b/SpeckleLib/Speckle/Serialise/Types/Str256.h @@ -0,0 +1,65 @@ +#ifndef SPECKLE_SERIALISE_STR256 +#define SPECKLE_SERIALISE_STR256 + +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h" +#include "Active/Utility/BufferOut.h" + +namespace active::serialise { + + constexpr size_t str256Size = 256; + + ///NB: This is primarily for Archicad that still uses fixed 256-bytes char array strings in some contexts + using Str256 = std::array; + + // MARK: - Specialisations for Str256 + + /*! + Import the object from the specified string (specialisation for Str256) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap::read(const utility::String& source) { + source.writeUTF8(active::utility::BufferOut{get()}); + return true; + } //ValueWrap::read + + + /*! + Import the object from the specified string (specialisation for Str256) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap>::read(const utility::String& source) { + base::get() = Str256{}; + source.writeUTF8(active::utility::BufferOut{*base::get()}); + return true; + } //ValueWrap::read + + + /*! + Export the object to the specified string (specialisation for Str256) + @param dest The string to write the data to + @return True if the data was successfully written + */ + template<> inline + bool ValueWrap::write(utility::String& dest) const { + dest.assign(reinterpret_cast(&get()), str256Size); + return true; + } //ValueWrap::write + + + /*! + Get the serialisation type for the item value + @return The item value serialisation type (nullopt = unspecified, i.e. a default is acceptable) + */ + template<> inline + std::optional ValueWrap::type() const { + return Item::Type::text; + } //ValueWrap::type + +} + +#endif //SPECKLE_SERIALISE_STR256 diff --git a/SpeckleLib/Speckle/Serialise/Units/LengthUnit.cpp b/SpeckleLib/Speckle/Serialise/Types/Units/LengthUnit.cpp similarity index 93% rename from SpeckleLib/Speckle/Serialise/Units/LengthUnit.cpp rename to SpeckleLib/Speckle/Serialise/Types/Units/LengthUnit.cpp index bc71613..cd8fb9f 100644 --- a/SpeckleLib/Speckle/Serialise/Units/LengthUnit.cpp +++ b/SpeckleLib/Speckle/Serialise/Types/Units/LengthUnit.cpp @@ -1,4 +1,4 @@ -#include "Speckle/Serialise/Units/LengthUnit.h" +#include "Speckle/Serialise/Types/Units/LengthUnit.h" #include #include diff --git a/SpeckleLib/Speckle/Serialise/Units/LengthUnit.h b/SpeckleLib/Speckle/Serialise/Types/Units/LengthUnit.h similarity index 100% rename from SpeckleLib/Speckle/Serialise/Units/LengthUnit.h rename to SpeckleLib/Speckle/Serialise/Types/Units/LengthUnit.h diff --git a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj index 2a4d670..0781bc6 100644 --- a/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj +++ b/SpeckleLib/SpeckleLib.xcodeproj/project.pbxproj @@ -49,6 +49,8 @@ 2196F3052CB57E8000450DFC /* Storey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F3032CB57E7F00450DFC /* Storey.cpp */; }; 2199881E2BD833830035E5EA /* libArchicad27.a in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; }; 21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FB9F2CB880690023F24E /* FinishCollector.h */; }; + 21A0FBB52CBA5E380023F24E /* Str256.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBB42CBA5E380023F24E /* Str256.h */; }; + 21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */; }; 21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */; }; 21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */; }; 21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */; }; @@ -189,6 +191,8 @@ 219712682BE7E2D500D9EF7E /* Serialisation.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Serialisation.md; sourceTree = ""; }; 21A0FB9F2CB880690023F24E /* FinishCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishCollector.h; sourceTree = ""; }; 21A0FBA92CB9324A0023F24E /* FinishProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = ""; }; + 21A0FBB42CBA5E380023F24E /* Str256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Str256.h; sourceTree = ""; }; + 21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadRGB.h; sourceTree = ""; }; 21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = ""; }; 21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = ""; }; 21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachmentManager.h; sourceTree = ""; }; @@ -296,8 +300,8 @@ 21A0FBA02CB880690023F24E /* Collection */, 21AEF9C72CA818EA000B8681 /* Detached */, 21F69F3A2C6B880B008B6A06 /* JSBase */, - 2196F2DF2CB0566500450DFC /* Units */, 219712682BE7E2D500D9EF7E /* Serialisation.md */, + 21A0FBB12CBA5E0E0023F24E /* Types */, ); path = Serialise; sourceTree = ""; @@ -485,6 +489,16 @@ path = Collection; sourceTree = ""; }; + 21A0FBB12CBA5E0E0023F24E /* Types */ = { + isa = PBXGroup; + children = ( + 21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */, + 21A0FBB42CBA5E380023F24E /* Str256.h */, + 2196F2DF2CB0566500450DFC /* Units */, + ); + path = Types; + sourceTree = ""; + }; 21AEF9C72CA818EA000B8681 /* Detached */ = { isa = PBXGroup; children = ( @@ -694,6 +708,7 @@ 215F088C2CA195EC00CD343B /* ArchicadDBaseCore.h in Headers */, 21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */, 21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */, + 21A0FBB52CBA5E380023F24E /* Str256.h in Headers */, 210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */, 210CC8A02C81E34400610F58 /* Platform.h in Headers */, 219246132CA34DCE00CF5703 /* Mesh.h in Headers */, @@ -719,6 +734,7 @@ 210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */, 21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */, 2196F3042CB57E8000450DFC /* Storey.h in Headers */, + 21A0FBBC2CBBC04C0023F24E /* ArchicadRGB.h in Headers */, 21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */, 21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */, 2196F2EC2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h in Headers */, diff --git a/SpeckleLib/SpeckleLib17.vcxproj b/SpeckleLib/SpeckleLib17.vcxproj index 73d3154..6dc6cba 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj +++ b/SpeckleLib/SpeckleLib17.vcxproj @@ -80,7 +80,9 @@ - + + + @@ -127,7 +129,7 @@ - + @@ -283,6 +285,7 @@ true true TurnOffAllWarnings + false diff --git a/SpeckleLib/SpeckleLib17.vcxproj.filters b/SpeckleLib/SpeckleLib17.vcxproj.filters index 458d545..42974d7 100644 --- a/SpeckleLib/SpeckleLib17.vcxproj.filters +++ b/SpeckleLib/SpeckleLib17.vcxproj.filters @@ -83,9 +83,6 @@ {cb77e795-e8d8-4e31-9773-dd32beb694d3} - - {7d5ec9ba-bc7e-412c-9b14-16c37b183409} - {490a65bd-28e3-4282-bb33-67823e81e825} @@ -95,6 +92,12 @@ {b5733e9f-b72a-4162-9fc7-8feeec594e5b} + + {b992941c-66d5-4f16-89b2-82e27a22e229} + + + {7f43d4ea-b876-4587-a646-90eab81f7976} + @@ -277,9 +280,6 @@ Speckle\Serialise\Detached\Storage - - Speckle\Serialise\Units - Speckle\Database @@ -301,6 +301,15 @@ Speckle\Serialise\Collection + + Speckle\Serialise\Types + + + Speckle\Serialise\Types\Units + + + Speckle\Serialise\Types + @@ -411,9 +420,6 @@ Speckle\Serialise\Detached - - Speckle\Serialise\Units - Speckle\Database @@ -429,6 +435,9 @@ Speckle\Record\Attribute + + Speckle\Serialise\Types\Units +