Added FinishCollector interface as a serialisation manager to collect finishes from meshes as they are serialised
ProjectCollection is now a FinishCollector (accumulates the finishes to write the material proxies at the end)
This commit is contained in:
@@ -10,12 +10,22 @@
|
||||
#include "Speckle/Database/BIMElementDatabase.h"
|
||||
#include "Speckle/Record/Element/Element.h"
|
||||
|
||||
#ifdef ARCHICAD
|
||||
#include <ModelMaterial.hpp>
|
||||
#endif
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace connector::record;
|
||||
using namespace speckle::database;
|
||||
using namespace speckle::record::attribute;
|
||||
using namespace speckle::utility;
|
||||
|
||||
#ifdef ARCHICAD
|
||||
namespace connector::record {
|
||||
class ProjectCollection::FinishCache : public std::unordered_map<active::utility::Guid, Finish::Unique> {};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
///Serialisation fields
|
||||
@@ -32,6 +42,23 @@ namespace {
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Constructor
|
||||
|
||||
project: The source project
|
||||
--------------------------------------------------------------------*/
|
||||
ProjectCollection::ProjectCollection(speckle::environment::Project::Shared project) : base{project->getInfo().name, project} {
|
||||
m_finishes = std::make_unique<FinishCache>();
|
||||
} //ProjectCollection::ProjectCollection
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Destructor
|
||||
--------------------------------------------------------------------*/
|
||||
ProjectCollection::~ProjectCollection() {
|
||||
} //ProjectCollection::~ProjectCollection
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Add an element to the collection hierarchy
|
||||
|
||||
@@ -90,6 +117,25 @@ bool ProjectCollection::addMaterialProxy(const speckle::database::BIMIndex& mate
|
||||
} //ProjectCollection::addMaterialProxy
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*--------------------------------------------------------------------
|
||||
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
|
||||
|
||||
material: A material
|
||||
objectID: The object the material is applied to
|
||||
|
||||
return: True if the material proxy was added (false typically means the record already exists)
|
||||
--------------------------------------------------------------------*/
|
||||
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<Finish>(material);
|
||||
return m_finishes->insert({finishID, std::move(finish)}).second;
|
||||
} //ProjectCollection::addMaterialProxy
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Fill an inventory with the package items
|
||||
|
||||
@@ -126,11 +172,14 @@ Cargo::Unique ProjectCollection::getCargo(const Inventory::Item& item) const {
|
||||
if (item.available < m_finishProxies.size()) {
|
||||
auto iter = m_finishProxies.begin();
|
||||
std::advance(iter, item.available);
|
||||
if (auto attribute = m_project->getAttributeDatabase()->getAttribute(iter->first, iter->first.tableID); attribute) {
|
||||
if (auto finish = dynamic_cast<const Finish*>(attribute.get()); finish != nullptr) {
|
||||
auto proxy = std::make_unique<FinishProxy>(*finish, iter->second);
|
||||
return std::make_unique<WrappedProxy>(std::move(proxy));
|
||||
}
|
||||
const Finish* finish = nullptr;
|
||||
if (auto fin = m_finishes->find(iter->first); fin != m_finishes->end())
|
||||
finish = fin->second.get();
|
||||
else if (auto attribute = m_project->getAttributeDatabase()->getAttribute(iter->first, iter->first.tableID); attribute)
|
||||
finish = dynamic_cast<const Finish*>(attribute.get());
|
||||
if (finish != nullptr) {
|
||||
auto proxy = std::make_unique<FinishProxy>(*finish, iter->second);
|
||||
return std::make_unique<WrappedProxy>(std::move(proxy));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CONNECTOR_RECORD_ROOT_COLLECTiON
|
||||
|
||||
#include "Connector/Record/Collection/RecordCollection.h"
|
||||
#include "Speckle/Serialise/Collection/FinishCollector.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
@@ -20,7 +21,7 @@ namespace connector::record {
|
||||
- Other attributes, e.g. materials
|
||||
Add all this supplementary data to the root container as required
|
||||
*/
|
||||
class ProjectCollection : public RecordCollection {
|
||||
class ProjectCollection : public RecordCollection, public speckle::serialise::FinishCollector {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
@@ -33,7 +34,12 @@ namespace connector::record {
|
||||
Constructor
|
||||
@param project The source project
|
||||
*/
|
||||
ProjectCollection(speckle::environment::Project::Shared project) : base{project->getInfo().name, project} {}
|
||||
ProjectCollection(speckle::environment::Project::Shared project);
|
||||
ProjectCollection(const ProjectCollection&) = delete;
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
~ProjectCollection();
|
||||
|
||||
using base::base;
|
||||
|
||||
@@ -59,7 +65,16 @@ namespace connector::record {
|
||||
@param objectID The object the material is applied to
|
||||
@return True if the material proxy was added (false typically means the record already exists)
|
||||
*/
|
||||
bool addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID);
|
||||
bool addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID) override;
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
|
||||
@param material A material
|
||||
@param objectID The object the material is applied to
|
||||
@return True if the material proxy was added (false typically means the record already exists)
|
||||
*/
|
||||
bool addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) override;
|
||||
#endif
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
@@ -81,6 +96,11 @@ namespace connector::record {
|
||||
|
||||
///Finish proxies accumulated from meshes generated from the collection elements
|
||||
FinishProxies m_finishProxies;
|
||||
#ifdef ARCHICAD
|
||||
class FinishCache;
|
||||
///Finishes cached from ModelerAPI materials
|
||||
std::unique_ptr<FinishCache> m_finishes;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#include "Speckle/Record/Attribute/Finish.h"
|
||||
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Utility/BufferOut.h"
|
||||
#include "Speckle/Utility/Guid.h"
|
||||
|
||||
#ifdef ARCHICAD
|
||||
#include <ModelMaterial.hpp>
|
||||
#endif
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace speckle::database;
|
||||
using namespace speckle::record::attribute;
|
||||
@@ -37,6 +42,16 @@ namespace {
|
||||
Identity{"surfaceColour"},
|
||||
};
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Copy a ModelerAPI colour to an AC RGB 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
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
@@ -65,6 +80,31 @@ 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<Data>(attrData);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Constructor
|
||||
|
||||
material: A ModelerAPI material definition
|
||||
--------------------------------------------------------------------*/
|
||||
Finish::Finish(const ModelerAPI::Material& material) {
|
||||
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.material.mtype = static_cast<API_MaterTypeID>(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();
|
||||
copyModelerColor(material.GetSurfaceColor(), attr.material.surfaceRGB);
|
||||
copyModelerColor(material.GetSpecularColor(), attr.material.specularRGB);
|
||||
copyModelerColor(material.GetEmissionColor(), attr.material.emissionRGB);
|
||||
m_data = std::make_unique<Data>(attr);
|
||||
} //Finish::Finish
|
||||
#endif
|
||||
|
||||
|
||||
@@ -95,6 +135,7 @@ const API_Attr_Head& Finish::getHead() const {
|
||||
return m_data->root.head;
|
||||
} //Finish::getHead
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the (mutable) API attribute header data
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
#include "Speckle/Record/Attribute/Attribute.h"
|
||||
|
||||
#ifdef ARCHICAD
|
||||
namespace ModelerAPI {
|
||||
class Material;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace speckle::record::attribute {
|
||||
|
||||
/*!
|
||||
@@ -50,6 +56,11 @@ namespace speckle::record::attribute {
|
||||
@param tableID The ID of the parent table
|
||||
*/
|
||||
Finish(const API_Attribute& attrData, const database::BIMRecordID& tableID);
|
||||
/*!
|
||||
Constructor
|
||||
@param material A ModelerAPI material definition
|
||||
*/
|
||||
Finish(const ModelerAPI::Material& material);
|
||||
#endif
|
||||
/*!
|
||||
Copy constructor
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef SPECKLE_SERIALISE_FINISH_COLLECTOR
|
||||
#define SPECKLE_SERIALISE_FINISH_COLLECTOR
|
||||
|
||||
#include "Active/Serialise/Management/Manager.h"
|
||||
|
||||
#ifdef ARCHICAD
|
||||
namespace ModelerAPI {
|
||||
class Material;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace speckle::serialise {
|
||||
|
||||
/*!
|
||||
Collector for object finishes
|
||||
|
||||
Used as a serialisation manager to collect finishes from serialised objects
|
||||
*/
|
||||
class FinishCollector : public active::serialise::Manager {
|
||||
public:
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
virtual ~FinishCollector() {}
|
||||
|
||||
// MARK: - Functions (mutating)
|
||||
|
||||
/*!
|
||||
Add a material proxy record to the collection
|
||||
@param materialIndex The index of the material to add
|
||||
@param objectID The object the material is applied to
|
||||
@return True if the material proxy was added (false typically means the record already exists)
|
||||
*/
|
||||
virtual bool addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID) = 0;
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
|
||||
@param material A material
|
||||
@param objectID The object the material is applied to
|
||||
@return True if the material proxy was added (false typically means the record already exists)
|
||||
*/
|
||||
virtual bool addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_SERIALISE_FINISH_COLLECTOR
|
||||
@@ -64,7 +64,7 @@ Cargo::Unique DetachedReference::getCargo(const Inventory::Item& item) const {
|
||||
//If we don't have an allocated string for receiving a reference (from 'setDefault') then we need to create one
|
||||
if (!m_reference) {
|
||||
//Ask a manager to send the detached data and provide a reference
|
||||
auto detachmentManager = getManager<DetachmentManager>();
|
||||
auto detachmentManager = (management() == nullptr) ? nullptr : management()->get<DetachmentManager>();
|
||||
if (detachmentManager == nullptr)
|
||||
return nullptr; //TODO: Discuss if this is a serious error - possibly throwing an exception is warranted
|
||||
m_reference = detachmentManager->send(std::forward<Package&&>(base::get()), item.identity());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef SPECKLE_SERIALISE_DETACHMENT_MANAGER
|
||||
#define SPECKLE_SERIALISE_DETACHMENT_MANAGER
|
||||
|
||||
#include "Active/Serialise/Manager.h"
|
||||
#include "Active/Serialise/Management/Manager.h"
|
||||
#include "Active/Serialise/Transport.h"
|
||||
#include "Speckle/Database/Identity/RecordID.h"
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
2196F3042CB57E8000450DFC /* Storey.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F3022CB57E7F00450DFC /* Storey.h */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
@@ -186,6 +187,7 @@
|
||||
2196F3022CB57E7F00450DFC /* Storey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Storey.h; sourceTree = "<group>"; };
|
||||
2196F3032CB57E7F00450DFC /* Storey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Storey.cpp; sourceTree = "<group>"; };
|
||||
219712682BE7E2D500D9EF7E /* Serialisation.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Serialisation.md; sourceTree = "<group>"; };
|
||||
21A0FB9F2CB880690023F24E /* FinishCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishCollector.h; sourceTree = "<group>"; };
|
||||
21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = "<group>"; };
|
||||
21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = "<group>"; };
|
||||
21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachmentManager.h; sourceTree = "<group>"; };
|
||||
@@ -290,6 +292,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2167E27C2C49121F000827D3 /* CMakeLists.txt */,
|
||||
21A0FBA02CB880690023F24E /* Collection */,
|
||||
21AEF9C72CA818EA000B8681 /* Detached */,
|
||||
21F69F3A2C6B880B008B6A06 /* JSBase */,
|
||||
2196F2DF2CB0566500450DFC /* Units */,
|
||||
@@ -472,6 +475,14 @@
|
||||
path = SpeckleLibDoctest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
21A0FBA02CB880690023F24E /* Collection */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21A0FB9F2CB880690023F24E /* FinishCollector.h */,
|
||||
);
|
||||
path = Collection;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
21AEF9C72CA818EA000B8681 /* Detached */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -693,6 +704,7 @@
|
||||
21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */,
|
||||
210CC88F2C81A98500610F58 /* Guid64.h in Headers */,
|
||||
21AEF9DD2CAAA4EA000B8681 /* DetachedObjectStore.h in Headers */,
|
||||
21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */,
|
||||
215F088D2CA195EC00CD343B /* ArchicadElementDBaseEngine.h in Headers */,
|
||||
2196F2F42CB483D600450DFC /* Finish.h in Headers */,
|
||||
21B67D002C7CE15100FD64FC /* Exception.h in Headers */,
|
||||
|
||||
Reference in New Issue
Block a user