Material: Appearance Updates 2
Improves the use of the ShapeAppearance property for the Part workbench.
removes DiffuseColor property
adds Python compatibility using custom attributes
transitions DiffuseColor to ShapeAppearance on open
Improved UI elements for setting object appearance, and appearance per face
Lays the foundation for future texture support
This commit is contained in:
committed by
Chris Hennes
parent
c4d0f3ed97
commit
5feb963f9d
@@ -25,10 +25,26 @@
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <cstring>
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
#include "Application.h"
|
||||
#include "Material.h"
|
||||
|
||||
// Helper functions to consistently convert between float and long
|
||||
namespace
|
||||
{
|
||||
float fromPercent(long value)
|
||||
{
|
||||
return std::roundf(value) / 100.0F;
|
||||
}
|
||||
|
||||
long toPercent(float value)
|
||||
{
|
||||
return std::lround(100.0 * value);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
using namespace App;
|
||||
|
||||
|
||||
@@ -317,4 +333,47 @@ void Material::setType(MaterialType MatType)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
App::Material Material::getDefaultAppearance()
|
||||
{
|
||||
ParameterGrp::handle hGrp =
|
||||
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
|
||||
auto getColor = [hGrp](const char* parameter, App::Color& color) {
|
||||
uint32_t packed = color.getPackedRGB();
|
||||
packed = hGrp->GetUnsigned(parameter, packed);
|
||||
color.setPackedRGB(packed);
|
||||
};
|
||||
auto intRandom = [](int min, int max) -> int {
|
||||
static std::mt19937 generator;
|
||||
std::uniform_int_distribution<int> distribution(min, max);
|
||||
return distribution(generator);
|
||||
};
|
||||
|
||||
App::Material mat(App::Material::DEFAULT);
|
||||
mat.transparency = fromPercent(hGrp->GetInt("DefaultShapeTransparency", 0));
|
||||
long shininess = toPercent(mat.shininess);
|
||||
mat.shininess = fromPercent(hGrp->GetInt("DefaultShapeShininess", shininess));
|
||||
|
||||
// This is handled in the material code when using the object appearance
|
||||
bool randomColor = hGrp->GetBool("RandomColor", false);
|
||||
|
||||
// diffuse color
|
||||
if (randomColor) {
|
||||
float red = static_cast<float>(intRandom(0, 255)) / 255.0F;
|
||||
float green = static_cast<float>(intRandom(0, 255)) / 255.0F;
|
||||
float blue = static_cast<float>(intRandom(0, 255)) / 255.0F;
|
||||
mat.diffuseColor = App::Color(red, green, blue);
|
||||
}
|
||||
else {
|
||||
// Color = (204, 204, 230) = 3435980543UL
|
||||
getColor("DefaultShapeColor", mat.diffuseColor);
|
||||
}
|
||||
|
||||
getColor("DefaultAmbientColor", mat.ambientColor);
|
||||
getColor("DefaultEmissiveColor", mat.emissiveColor);
|
||||
getColor("DefaultSpecularColor", mat.specularColor);
|
||||
|
||||
return mat;
|
||||
}
|
||||
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
|
||||
|
||||
@@ -131,6 +131,8 @@ public:
|
||||
Color emissiveColor; /**< Defines the emissive color. */
|
||||
float shininess;
|
||||
float transparency;
|
||||
std::string image;
|
||||
std::string imagePath;
|
||||
std::string uuid;
|
||||
// NOLINTEND
|
||||
//@}
|
||||
@@ -145,6 +147,8 @@ public:
|
||||
&& diffuseColor == m.diffuseColor
|
||||
&& specularColor == m.specularColor
|
||||
&& emissiveColor == m.emissiveColor
|
||||
&& image == m.image
|
||||
&& image == m.imagePath
|
||||
&& uuid == m.uuid;
|
||||
// clang-format on
|
||||
}
|
||||
@@ -155,6 +159,8 @@ public:
|
||||
Material& operator=(const Material& other) = default;
|
||||
Material& operator=(Material&& other) = default;
|
||||
|
||||
static Material getDefaultAppearance();
|
||||
|
||||
private:
|
||||
MaterialType _matType;
|
||||
};
|
||||
|
||||
@@ -2579,6 +2579,8 @@ void PropertyMaterial::Save(Base::Writer& writer) const
|
||||
<< "\" emissiveColor=\"" << _cMat.emissiveColor.getPackedValue()
|
||||
<< "\" shininess=\"" << _cMat.shininess
|
||||
<< "\" transparency=\"" << _cMat.transparency
|
||||
<< "\" image=\"" << _cMat.image
|
||||
<< "\" imagePath=\"" << _cMat.imagePath
|
||||
<< "\" uuid=\"" << _cMat.uuid
|
||||
<< "\"/>" << std::endl;
|
||||
// clang-format on
|
||||
@@ -2596,6 +2598,12 @@ void PropertyMaterial::Restore(Base::XMLReader& reader)
|
||||
_cMat.emissiveColor.setPackedValue(reader.getAttributeAsUnsigned("emissiveColor"));
|
||||
_cMat.shininess = (float)reader.getAttributeAsFloat("shininess");
|
||||
_cMat.transparency = (float)reader.getAttributeAsFloat("transparency");
|
||||
if (reader.hasAttribute("image")) {
|
||||
_cMat.image = reader.getAttribute("image");
|
||||
}
|
||||
if (reader.hasAttribute("imagePath")) {
|
||||
_cMat.imagePath = reader.getAttribute("imagePath");
|
||||
}
|
||||
if (reader.hasAttribute("uuid")) {
|
||||
_cMat.uuid = reader.getAttribute("uuid");
|
||||
}
|
||||
@@ -2635,7 +2643,7 @@ TYPESYSTEM_SOURCE(App::PropertyMaterialList, App::PropertyLists)
|
||||
|
||||
PropertyMaterialList::PropertyMaterialList()
|
||||
{
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
}
|
||||
|
||||
PropertyMaterialList::~PropertyMaterialList() = default;
|
||||
@@ -2662,7 +2670,7 @@ void PropertyMaterialList::verifyIndex(int index) const
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyMaterialList::setSizeOne()
|
||||
void PropertyMaterialList::setMinimumSizeOne()
|
||||
{
|
||||
int size = getSize();
|
||||
if (size < 1) {
|
||||
@@ -2690,7 +2698,7 @@ void PropertyMaterialList::setValue()
|
||||
void PropertyMaterialList::setValue(const Material& mat)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setSize(1);
|
||||
for (auto& material : _lValueList) {
|
||||
material = mat;
|
||||
}
|
||||
@@ -2710,7 +2718,7 @@ void PropertyMaterialList::setValue(int index, const Material& mat)
|
||||
void PropertyMaterialList::setAmbientColor(const Color& col)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.ambientColor = col;
|
||||
}
|
||||
@@ -2720,7 +2728,7 @@ void PropertyMaterialList::setAmbientColor(const Color& col)
|
||||
void PropertyMaterialList::setAmbientColor(float r, float g, float b, float a)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.ambientColor.set(r, g, b, a);
|
||||
}
|
||||
@@ -2730,7 +2738,7 @@ void PropertyMaterialList::setAmbientColor(float r, float g, float b, float a)
|
||||
void PropertyMaterialList::setAmbientColor(uint32_t rgba)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.ambientColor.setPackedValue(rgba);
|
||||
}
|
||||
@@ -2770,7 +2778,7 @@ void PropertyMaterialList::setAmbientColor(int index, uint32_t rgba)
|
||||
void PropertyMaterialList::setDiffuseColor(const Color& col)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.diffuseColor = col;
|
||||
}
|
||||
@@ -2780,7 +2788,7 @@ void PropertyMaterialList::setDiffuseColor(const Color& col)
|
||||
void PropertyMaterialList::setDiffuseColor(float r, float g, float b, float a)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.diffuseColor.set(r, g, b, a);
|
||||
}
|
||||
@@ -2790,7 +2798,7 @@ void PropertyMaterialList::setDiffuseColor(float r, float g, float b, float a)
|
||||
void PropertyMaterialList::setDiffuseColor(uint32_t rgba)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.diffuseColor.setPackedValue(rgba);
|
||||
}
|
||||
@@ -2827,10 +2835,21 @@ void PropertyMaterialList::setDiffuseColor(int index, uint32_t rgba)
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyMaterialList::setDiffuseColors(const std::vector<App::Color>& colors)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSize(colors.size(), _lValueList[0]);
|
||||
|
||||
for (int i = 0; i < colors.size(); i++) {
|
||||
_lValueList[i].diffuseColor = colors[i];
|
||||
}
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyMaterialList::setSpecularColor(const Color& col)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.specularColor = col;
|
||||
}
|
||||
@@ -2840,7 +2859,7 @@ void PropertyMaterialList::setSpecularColor(const Color& col)
|
||||
void PropertyMaterialList::setSpecularColor(float r, float g, float b, float a)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.specularColor.set(r, g, b, a);
|
||||
}
|
||||
@@ -2850,7 +2869,7 @@ void PropertyMaterialList::setSpecularColor(float r, float g, float b, float a)
|
||||
void PropertyMaterialList::setSpecularColor(uint32_t rgba)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.specularColor.setPackedValue(rgba);
|
||||
}
|
||||
@@ -2890,7 +2909,7 @@ void PropertyMaterialList::setSpecularColor(int index, uint32_t rgba)
|
||||
void PropertyMaterialList::setEmissiveColor(const Color& col)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.emissiveColor = col;
|
||||
}
|
||||
@@ -2900,7 +2919,7 @@ void PropertyMaterialList::setEmissiveColor(const Color& col)
|
||||
void PropertyMaterialList::setEmissiveColor(float r, float g, float b, float a)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.emissiveColor.set(r, g, b, a);
|
||||
}
|
||||
@@ -2910,7 +2929,7 @@ void PropertyMaterialList::setEmissiveColor(float r, float g, float b, float a)
|
||||
void PropertyMaterialList::setEmissiveColor(uint32_t rgba)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.emissiveColor.setPackedValue(rgba);
|
||||
}
|
||||
@@ -2950,7 +2969,7 @@ void PropertyMaterialList::setEmissiveColor(int index, uint32_t rgba)
|
||||
void PropertyMaterialList::setShininess(float val)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.shininess = val;
|
||||
}
|
||||
@@ -2970,7 +2989,7 @@ void PropertyMaterialList::setShininess(int index, float val)
|
||||
void PropertyMaterialList::setTransparency(float val)
|
||||
{
|
||||
aboutToSetValue();
|
||||
setSizeOne();
|
||||
setMinimumSizeOne();
|
||||
for (auto& material : _lValueList) {
|
||||
material.transparency = val;
|
||||
}
|
||||
@@ -3039,12 +3058,12 @@ const Color& PropertyMaterialList::getEmissiveColor(int index) const
|
||||
|
||||
float PropertyMaterialList::getShininess() const
|
||||
{
|
||||
return _lValueList[0].transparency;
|
||||
return _lValueList[0].shininess;
|
||||
}
|
||||
|
||||
float PropertyMaterialList::getShininess(int index) const
|
||||
{
|
||||
return _lValueList[index].transparency;
|
||||
return _lValueList[index].shininess;
|
||||
}
|
||||
|
||||
float PropertyMaterialList::getTransparency() const
|
||||
@@ -3074,7 +3093,7 @@ void PropertyMaterialList::Save(Base::Writer& writer) const
|
||||
if (!writer.isForceXML()) {
|
||||
writer.Stream() << writer.ind() << "<MaterialList file=\""
|
||||
<< (getSize() ? writer.addFile(getName(), this) : "") << "\""
|
||||
<< " version=\"2\"/>"
|
||||
<< " version=\"3\"/>"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
@@ -3107,8 +3126,21 @@ void PropertyMaterialList::SaveDocFile(Base::Writer& writer) const
|
||||
str << it.emissiveColor.getPackedValue();
|
||||
str << it.shininess;
|
||||
str << it.transparency;
|
||||
// str << it.uuid.c_str();
|
||||
}
|
||||
|
||||
// Apply the latest changes last for backwards compatibility
|
||||
for (const auto& it : _lValueList) {
|
||||
writeString(str, it.image);
|
||||
writeString(str, it.imagePath);
|
||||
writeString(str, it.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string &value) const
|
||||
{
|
||||
uint32_t uCt = (uint32_t)value.size();
|
||||
str << uCt;
|
||||
str.write(value.c_str(), uCt);
|
||||
}
|
||||
|
||||
void PropertyMaterialList::RestoreDocFile(Base::Reader& reader)
|
||||
@@ -3120,11 +3152,20 @@ void PropertyMaterialList::RestoreDocFile(Base::Reader& reader)
|
||||
str >> count;
|
||||
RestoreDocFileV0(count, reader);
|
||||
}
|
||||
else if (formatVersion == Version_3) {
|
||||
// Default to the latest
|
||||
RestoreDocFileV3(reader);
|
||||
}
|
||||
else {
|
||||
int32_t version;
|
||||
str >> version;
|
||||
if (version < 0) {
|
||||
RestoreDocFileV1(reader);
|
||||
// This was a failed attempt at versioning, but is included
|
||||
// to support files created during development. In can be removed
|
||||
// in a future release once dev files are migrated.
|
||||
uint32_t count = 0;
|
||||
str >> count;
|
||||
RestoreDocFileV0(count, reader);
|
||||
}
|
||||
else {
|
||||
uint32_t uCt = static_cast<uint32_t>(version);
|
||||
@@ -3156,14 +3197,14 @@ void PropertyMaterialList::RestoreDocFileV0(uint32_t count, Base::Reader& reader
|
||||
setValues(values);
|
||||
}
|
||||
|
||||
void PropertyMaterialList::RestoreDocFileV1(Base::Reader& reader)
|
||||
void PropertyMaterialList::RestoreDocFileV3(Base::Reader& reader)
|
||||
{
|
||||
Base::InputStream str(reader);
|
||||
uint32_t count = 0;
|
||||
str >> count;
|
||||
std::vector<Material> values(count);
|
||||
uint32_t value {}; // must be 32 bit long
|
||||
float valueF {};
|
||||
uint32_t value; // must be 32 bit long
|
||||
float valueF;
|
||||
for (auto& it : values) {
|
||||
str >> value;
|
||||
it.ambientColor.setPackedValue(value);
|
||||
@@ -3177,12 +3218,29 @@ void PropertyMaterialList::RestoreDocFileV1(Base::Reader& reader)
|
||||
it.shininess = valueF;
|
||||
str >> valueF;
|
||||
it.transparency = valueF;
|
||||
// str >> valueS;
|
||||
// it.uuid = valueS;
|
||||
}
|
||||
for (auto& it : values) {
|
||||
readString(str, it.image);
|
||||
readString(str, it.imagePath);
|
||||
readString(str, it.uuid);
|
||||
}
|
||||
setValues(values);
|
||||
}
|
||||
|
||||
void PropertyMaterialList::readString(Base::InputStream& str,
|
||||
std::string& value)
|
||||
{
|
||||
uint32_t uCt;
|
||||
str >> uCt;
|
||||
|
||||
char *temp = new char[uCt];
|
||||
|
||||
str.read(temp, uCt);
|
||||
value.assign(temp, static_cast<std::size_t>(uCt));
|
||||
|
||||
delete [] temp;
|
||||
}
|
||||
|
||||
const char* PropertyMaterialList::getEditorName() const
|
||||
{
|
||||
if (testStatus(NoMaterialListEdit)) {
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
|
||||
namespace Base {
|
||||
class InputStream;
|
||||
class OutputStream;
|
||||
class Writer;
|
||||
}
|
||||
|
||||
@@ -1132,6 +1134,7 @@ public:
|
||||
void setDiffuseColor(int index, const Color& col);
|
||||
void setDiffuseColor(int index, float r, float g, float b, float a = 0.0F);
|
||||
void setDiffuseColor(int index, uint32_t rgba);
|
||||
void setDiffuseColors(const std::vector<App::Color>& colors);
|
||||
|
||||
void setSpecularColor(const Color& col);
|
||||
void setSpecularColor(float r, float g, float b, float a = 0.0F);
|
||||
@@ -1193,14 +1196,18 @@ private:
|
||||
enum Format {
|
||||
Version_0,
|
||||
Version_1,
|
||||
Version_2
|
||||
Version_2,
|
||||
Version_3
|
||||
};
|
||||
|
||||
void RestoreDocFileV0(uint32_t count, Base::Reader& reader);
|
||||
void RestoreDocFileV1(Base::Reader& reader);
|
||||
void RestoreDocFileV3(Base::Reader& reader);
|
||||
|
||||
void writeString(Base::OutputStream& str, const std::string &value) const;
|
||||
void readString(Base::InputStream& str, std::string& value);
|
||||
|
||||
void verifyIndex(int index) const;
|
||||
void setSizeOne();
|
||||
void setMinimumSizeOne();
|
||||
int resizeByOneIfNeeded(int index);
|
||||
|
||||
Format formatVersion {Version_0};
|
||||
|
||||
Reference in New Issue
Block a user