Finishes incorporates all Archicad material properties
Serialisation wrapper for Archicad colour rgb colour
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#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
|
||||
@@ -22,14 +23,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<double>(attr.material.transpPc) / 100.0);
|
||||
roughness = 1.0 - (static_cast<double>(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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -57,35 +72,15 @@ namespace {
|
||||
#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
|
||||
|
||||
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<uint8_t>(std::round(alpha * 255.0));
|
||||
uint8_t r = static_cast<uint8_t>(std::round(red * 255.0));
|
||||
uint8_t g = static_cast<uint8_t>(std::round(green * 255.0));
|
||||
uint8_t b = static_cast<uint8_t>(std::round(blue * 255.0));
|
||||
|
||||
// Pack ARGB into a single 32-bit integer
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
int32_t ARGBToInt(double alpha, const API_RGBColor& color) {
|
||||
// Convert double (0.0 - 1.0) to uint8_t (0 - 255)
|
||||
uint8_t a = static_cast<uint8_t>(std::round(alpha * 255.0));
|
||||
uint8_t r = static_cast<uint8_t>(std::round(color.f_red * 255.0));
|
||||
uint8_t g = static_cast<uint8_t>(std::round(color.f_green * 255.0));
|
||||
uint8_t b = static_cast<uint8_t>(std::round(color.f_blue * 255.0));
|
||||
|
||||
// Pack ARGB into a single 32-bit integer
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
@@ -217,18 +212,20 @@ Cargo::Unique Finish::getCargo(const Inventory::Item& item) const {
|
||||
confirmData();
|
||||
using namespace active::serialise;
|
||||
switch (item.index) {
|
||||
case diffuseID: {
|
||||
auto opacity = 1.0 - m_data->root.transpPc;
|
||||
return std::make_unique<CargoHold<Int32Wrap, int32_t>>(ARGBToInt(opacity, m_data->root.surfaceRGB));
|
||||
}
|
||||
case diffuseID:
|
||||
#ifdef ARCHICAD
|
||||
return std::make_unique<ValueWrap<API_RGBColor>>(m_data->root.surfaceRGB);
|
||||
#endif
|
||||
case opacityID:
|
||||
return std::make_unique<CargoHold<DoubleWrap,double>>(1.0);
|
||||
return std::make_unique<DoubleWrap>(m_data->opacity);
|
||||
case emissiveID:
|
||||
return std::make_unique<CargoHold<Int32Wrap, int32_t>>(ARGBToInt(0.0, 0.0, 0.0, 0.0));
|
||||
#ifdef ARCHICAD
|
||||
return std::make_unique<ValueWrap<API_RGBColor>>(m_data->root.emissionRGB);
|
||||
#endif
|
||||
case metalnessID:
|
||||
return std::make_unique<CargoHold<DoubleWrap, double>>(1.0);
|
||||
return std::make_unique<DoubleWrap>(m_data->metalness);
|
||||
case roughnessID:
|
||||
return std::make_unique<CargoHold<DoubleWrap, double>>(1.0);
|
||||
return std::make_unique<DoubleWrap>(m_data->roughness);
|
||||
default:
|
||||
return nullptr; //Requested an unknown index
|
||||
}
|
||||
@@ -239,10 +236,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<short>(100 * (1.0 - m_data->opacity));
|
||||
m_data->root.shine = static_cast<short>(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
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
@@ -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:
|
||||
/*!
|
||||
|
||||
@@ -57,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<uint8_t>(std::round(alpha * 255.0));
|
||||
uint8_t r = static_cast<uint8_t>(std::round(red * 255.0));
|
||||
uint8_t g = static_cast<uint8_t>(std::round(green * 255.0));
|
||||
uint8_t b = static_cast<uint8_t>(std::round(blue * 255.0));
|
||||
|
||||
// Pack ARGB into a single 32-bit integer
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#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"
|
||||
|
||||
#include <APIdefs_base.h>
|
||||
|
||||
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<API_RGBColor> 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<double>(*intValue & 0xFF) / 255.0;
|
||||
*intValue >>= 8;
|
||||
result.f_green = static_cast<double>(*intValue & 0xFF) / 255.0;
|
||||
*intValue >>= 8;
|
||||
result.f_blue = static_cast<double>(*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<API_RGBColor>::read(const utility::String& source) {
|
||||
if (auto colour = convertToAPI_RGBColor(source); colour) {
|
||||
get() = *colour;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} //ValueWrap<API_RGBColor>::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<std::optional<API_RGBColor>>::read(const utility::String& source) {
|
||||
if (auto colour = convertToAPI_RGBColor(source); colour)
|
||||
get() = colour;
|
||||
return true;
|
||||
} //ValueWrap<API_RGBColor>::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<API_RGBColor>::write(utility::String& dest) const {
|
||||
dest = speckle::utility::String{(static_cast<uint32_t>(get().f_red * 255.0) << 24) |
|
||||
((static_cast<uint32_t>(get().f_green * 255.0)) << 16) |
|
||||
((static_cast<uint32_t>(get().f_blue * 255.0)) << 8)};
|
||||
return true;
|
||||
} //ValueWrap<API_RGBColor>::write
|
||||
|
||||
}
|
||||
|
||||
#endif //ARCHICAD
|
||||
#endif //SPECKLE_SERIALISE_ARCHICAD_RGB
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef SPECKLE_SERIALISE_LENGTH_UNIT
|
||||
#define SPECKLE_SERIALISE_LENGTH_UNIT
|
||||
#ifndef SPECKLE_SERIALISE_STR256
|
||||
#define SPECKLE_SERIALISE_STR256
|
||||
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
|
||||
@@ -12,10 +12,10 @@ namespace active::serialise {
|
||||
///NB: This is primarily for Archicad that still uses fixed 256-bytes char array strings in some contexts
|
||||
using Str256 = std::array<char, str256Size>;
|
||||
|
||||
// MARK: - Specialisations for bool
|
||||
// MARK: - Specialisations for Str256
|
||||
|
||||
/*!
|
||||
Import the object from the specified string (specialisation for bool)
|
||||
Import the object from the specified string (specialisation for Str256)
|
||||
@param source The string to read
|
||||
@return True if the data was successfully read
|
||||
*/
|
||||
@@ -23,11 +23,11 @@ namespace active::serialise {
|
||||
bool ValueWrap<Str256>::read(const utility::String& source) {
|
||||
source.writeUTF8(active::utility::BufferOut{get()});
|
||||
return true;
|
||||
} //ValueWrap<bool>::read
|
||||
} //ValueWrap<Str256>::read
|
||||
|
||||
|
||||
/*!
|
||||
Import the object from the specified string (specialisation for bool)
|
||||
Import the object from the specified string (specialisation for Str256)
|
||||
@param source The string to read
|
||||
@return True if the data was successfully read
|
||||
*/
|
||||
@@ -36,11 +36,11 @@ namespace active::serialise {
|
||||
base::get() = Str256{};
|
||||
source.writeUTF8(active::utility::BufferOut{*base::get()});
|
||||
return true;
|
||||
} //ValueWrap<bool>::read
|
||||
} //ValueWrap<Str256>::read
|
||||
|
||||
|
||||
/*!
|
||||
Export the object to the specified string (specialisation for bool)
|
||||
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
|
||||
*/
|
||||
@@ -48,8 +48,8 @@ namespace active::serialise {
|
||||
bool ValueWrap<Str256>::write(utility::String& dest) const {
|
||||
dest.assign(reinterpret_cast<const char*>(&get()), str256Size);
|
||||
return true;
|
||||
} //ValueWrap<bool>::write
|
||||
} //ValueWrap<Str256>::write
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_SERIALISE_LENGTH_UNIT
|
||||
#endif //SPECKLE_SERIALISE_STR256
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
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 */; };
|
||||
@@ -191,6 +192,7 @@
|
||||
21A0FB9F2CB880690023F24E /* FinishCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishCollector.h; sourceTree = "<group>"; };
|
||||
21A0FBA92CB9324A0023F24E /* FinishProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = "<group>"; };
|
||||
21A0FBB42CBA5E380023F24E /* Str256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Str256.h; sourceTree = "<group>"; };
|
||||
21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadRGB.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>"; };
|
||||
@@ -490,6 +492,7 @@
|
||||
21A0FBB12CBA5E0E0023F24E /* Types */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
21A0FBB92CBBC04C0023F24E /* ArchicadRGB.h */,
|
||||
21A0FBB42CBA5E380023F24E /* Str256.h */,
|
||||
2196F2DF2CB0566500450DFC /* Units */,
|
||||
);
|
||||
@@ -731,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 */,
|
||||
|
||||
Reference in New Issue
Block a user