From 5feb963f9d0376952eede16cd44e7b2fbde72e44 Mon Sep 17 00:00:00 2001 From: David Carter Date: Sat, 1 Jun 2024 18:26:38 -0400 Subject: [PATCH] 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 --- src/App/Material.cpp | 59 ++++ src/App/Material.h | 6 + src/App/PropertyStandard.cpp | 112 +++++-- src/App/PropertyStandard.h | 13 +- src/Base/Stream.cpp | 12 + src/Base/Stream.h | 4 + src/Gui/Application.h | 2 +- src/Gui/DlgMaterialProperties.ui | 126 ++++---- src/Gui/DlgMaterialPropertiesImp.cpp | 274 +++++++++++++----- src/Gui/DlgMaterialPropertiesImp.h | 28 +- src/Gui/ViewProviderGeometryObject.cpp | 137 +++++---- src/Gui/ViewProviderGeometryObject.h | 21 +- src/Gui/ViewProviderGeometryObjectPyImp.cpp | 2 +- .../ViewProviderFemConstraintOnBoundary.cpp | 8 +- src/Mod/Import/Gui/ExportOCAFGui.cpp | 6 +- src/Mod/Import/Gui/ImportOCAFGui.cpp | 2 +- src/Mod/Material/App/Materials.cpp | 74 +++-- src/Mod/Material/App/Materials.h | 1 + src/Mod/Material/Gui/AppearancePreview.cpp | 91 +++++- src/Mod/Material/Gui/AppearancePreview.h | 14 + src/Mod/Material/Gui/DlgDisplayProperties.ui | 4 +- .../Material/Gui/DlgDisplayPropertiesImp.cpp | 65 +---- .../Material/Gui/DlgDisplayPropertiesImp.h | 3 +- src/Mod/Material/Gui/DlgMaterialImp.cpp | 1 - src/Mod/Material/Gui/MaterialTreeWidget.cpp | 17 +- src/Mod/Material/Gui/MaterialsEditor.cpp | 110 +++++-- src/Mod/Material/Gui/MaterialsEditor.h | 2 + src/Mod/Material/Gui/PreCompiled.h | 8 +- .../Models/Rendering/TextureRendering.yml | 3 +- src/Mod/MeshPart/Gui/Tessellation.cpp | 2 +- src/Mod/Part/Gui/AppPartGui.cpp | 109 ++++--- src/Mod/Part/Gui/CMakeLists.txt | 17 +- src/Mod/Part/Gui/Command.cpp | 2 +- src/Mod/Part/Gui/DlgProjectionOnSurface.cpp | 50 ++-- src/Mod/Part/Gui/ReferenceHighlighter.cpp | 32 ++ src/Mod/Part/Gui/ReferenceHighlighter.h | 9 + ...FaceColors.cpp => TaskFaceAppearances.cpp} | 132 +++++---- ...TaskFaceColors.h => TaskFaceAppearances.h} | 21 +- ...skFaceColors.ui => TaskFaceAppearances.ui} | 111 +++---- src/Mod/Part/Gui/ViewProvider.cpp | 28 ++ src/Mod/Part/Gui/ViewProvider.h | 5 + src/Mod/Part/Gui/ViewProviderBoolean.cpp | 74 ++--- src/Mod/Part/Gui/ViewProviderCompound.cpp | 20 +- src/Mod/Part/Gui/ViewProviderExt.cpp | 216 +++++++++----- src/Mod/Part/Gui/ViewProviderExt.h | 26 +- src/Mod/Part/Gui/ViewProviderExtPy.xml | 17 ++ src/Mod/Part/Gui/ViewProviderExtPyImp.cpp | 73 +++++ src/Mod/Part/Gui/ViewProviderMirror.cpp | 42 +-- src/Mod/PartDesign/Gui/ViewProviderBody.cpp | 7 +- .../PartDesign/Gui/ViewProviderDressUp.cpp | 16 +- src/Mod/PartDesign/Gui/ViewProviderDressUp.h | 2 +- .../Gui/ViewProviderShapeBinder.cpp | 14 +- .../PartDesign/Gui/ViewProviderShapeBinder.h | 2 +- src/Mod/Surface/Gui/TaskFilling.cpp | 11 +- src/Mod/Surface/Gui/TaskSections.cpp | 11 +- 55 files changed, 1540 insertions(+), 714 deletions(-) rename src/Mod/Part/Gui/{TaskFaceColors.cpp => TaskFaceAppearances.cpp} (77%) rename src/Mod/Part/Gui/{TaskFaceColors.h => TaskFaceAppearances.h} (81%) rename src/Mod/Part/Gui/{TaskFaceColors.ui => TaskFaceAppearances.ui} (54%) create mode 100644 src/Mod/Part/Gui/ViewProviderExtPy.xml create mode 100644 src/Mod/Part/Gui/ViewProviderExtPyImp.cpp diff --git a/src/App/Material.cpp b/src/App/Material.cpp index 389e2e94c1..af399dcc32 100644 --- a/src/App/Material.cpp +++ b/src/App/Material.cpp @@ -25,10 +25,26 @@ #ifndef _PreComp_ #include +#include #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 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(intRandom(0, 255)) / 255.0F; + float green = static_cast(intRandom(0, 255)) / 255.0F; + float blue = static_cast(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) diff --git a/src/App/Material.h b/src/App/Material.h index ba22b510e5..e578d00b62 100644 --- a/src/App/Material.h +++ b/src/App/Material.h @@ -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; }; diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 4395623fc2..e2ee13c103 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -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& 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() << "" + << " 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(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 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(uCt)); + + delete [] temp; +} + const char* PropertyMaterialList::getEditorName() const { if (testStatus(NoMaterialListEdit)) { diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index 60978ecb53..d013400a33 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -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& 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}; diff --git a/src/Base/Stream.cpp b/src/Base/Stream.cpp index eb9a8743fb..f95a4fa722 100644 --- a/src/Base/Stream.cpp +++ b/src/Base/Stream.cpp @@ -150,6 +150,12 @@ OutputStream& OutputStream::operator<<(double d) return *this; } +OutputStream& OutputStream::write(const char* s, int n) +{ + _out.write(s, n); + return *this; +} + InputStream::InputStream(std::istream& rin) : _in(rin) {} @@ -246,6 +252,12 @@ InputStream& InputStream::operator>>(double& d) return *this; } +InputStream& InputStream::read(char* s, int n) +{ + _in.read(s, n); + return *this; +} + // ---------------------------------------------------------------------- ByteArrayOStreambuf::ByteArrayOStreambuf(QByteArray& ba) diff --git a/src/Base/Stream.h b/src/Base/Stream.h index 8b816b2754..94055cb118 100644 --- a/src/Base/Stream.h +++ b/src/Base/Stream.h @@ -95,6 +95,8 @@ public: OutputStream& operator<<(float f); OutputStream& operator<<(double d); + OutputStream& write(const char* s, int n); + OutputStream(const OutputStream&) = delete; OutputStream(OutputStream&&) = delete; void operator=(const OutputStream&) = delete; @@ -126,6 +128,8 @@ public: InputStream& operator>>(float& f); InputStream& operator>>(double& d); + InputStream& read(char* s, int n); + explicit operator bool() const { // test if _Ipfx succeeded diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 8f7fb3195e..bbb1aa2258 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -271,7 +271,7 @@ protected: std::make_pair(QT_TRANSLATE_NOOP("EditMode", "Color"), QT_TRANSLATE_NOOP("EditMode", "The object will have the color of its individual faces " - "editable with the Part FaceColors command"))}, + "editable with the Part FaceAppearances command"))}, }; int userEditMode = userEditModes.begin()->first; diff --git a/src/Gui/DlgMaterialProperties.ui b/src/Gui/DlgMaterialProperties.ui index 7cb7b98860..f0b56befd4 100644 --- a/src/Gui/DlgMaterialProperties.ui +++ b/src/Gui/DlgMaterialProperties.ui @@ -41,62 +41,6 @@ 6 - - - - Ambient color: - - - - - - - - - - - - - - Diffuse color: - - - - - - - - - - - - - - Emissive color: - - - - - - - - - - - - - - Specular color: - - - - - - - - - - @@ -149,6 +93,76 @@ + + + + Diffuse color: + + + + + + + + + + + + + + + + + + + + + Specular color: + + + + + + + + + + + + + + Ambient color: + + + + + + + + + + + + + + Emissive color: + + + + + + + Reset + + + + + + + Default + + + diff --git a/src/Gui/DlgMaterialPropertiesImp.cpp b/src/Gui/DlgMaterialPropertiesImp.cpp index 20e4bcb5a7..305b41c0ae 100644 --- a/src/Gui/DlgMaterialPropertiesImp.cpp +++ b/src/Gui/DlgMaterialPropertiesImp.cpp @@ -22,8 +22,11 @@ #include "PreCompiled.h" +#include +#include #include +#include "Application.h" #include "DlgMaterialPropertiesImp.h" #include "ui_DlgMaterialProperties.h" #include "ViewProvider.h" @@ -46,11 +49,12 @@ DlgMaterialPropertiesImp::DlgMaterialPropertiesImp(const std::string& mat, QWidg : QDialog(parent, fl) , ui(new Ui_DlgMaterialProperties) , material(mat) + , updateColors(true) { ui->setupUi(this); setupConnections(); - if (material != "ShapeMaterial") { + if (material != "ShapeAppearance") { ui->textLabel1->hide(); ui->diffuseColor->hide(); } @@ -68,6 +72,8 @@ DlgMaterialPropertiesImp::~DlgMaterialPropertiesImp() = default; void DlgMaterialPropertiesImp::setupConnections() { + Base::Console().Log("DlgMaterialPropertiesImp::setupConnections()\n"); + connect(ui->ambientColor, &ColorButton::changed, this, &DlgMaterialPropertiesImp::onAmbientColorChanged); connect(ui->diffuseColor, &ColorButton::changed, @@ -78,6 +84,10 @@ void DlgMaterialPropertiesImp::setupConnections() this, &DlgMaterialPropertiesImp::onSpecularColorChanged); connect(ui->shininess, qOverload(&QSpinBox::valueChanged), this, &DlgMaterialPropertiesImp::onShininessValueChanged); + connect(ui->buttonReset, &QPushButton::clicked, + this, &DlgMaterialPropertiesImp::onButtonReset); + connect(ui->buttonDefault, &QPushButton::clicked, + this, &DlgMaterialPropertiesImp::onButtonDefault); } QColor DlgMaterialPropertiesImp::diffuseColor() const @@ -85,24 +95,54 @@ QColor DlgMaterialPropertiesImp::diffuseColor() const return ui->diffuseColor->color(); } +App::Material DlgMaterialPropertiesImp::getMaterial() +{ + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto& materials = ShapeAppearance->getValues(); + auto mat = materials[0]; + + mat.setType(App::Material::USER_DEFINED); + + // Reset any texture data + mat.image = ""; + mat.imagePath = ""; + mat.uuid = ""; + + return mat; + } + } + + return App::Material::getDefaultAppearance(); +} + +App::Color DlgMaterialPropertiesImp::getColor(const QColor& color) const +{ + float r = (float)color.red() / 255.0F; + float g = (float)color.green() / 255.0F; + float b = (float)color.blue() / 255.0F; + + return App::Color(r, g, b); +} + /** * Sets the ambient color. */ void DlgMaterialPropertiesImp::onAmbientColorChanged() { - QColor col = ui->ambientColor->color(); - float r = (float)col.red() / 255.0f; - float g = (float)col.green() / 255.0f; - float b = (float)col.blue() / 255.0f; - App::Color ambient(r, g, b); + if (updateColors) { + App::Color ambient = getColor(ui->ambientColor->color()); - for (std::vector::iterator it= Objects.begin(); it != Objects.end(); ++it) { - App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - mat.ambientColor = ambient; - ShapeMaterial->setValue(mat); + for (std::vector::iterator it= Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + mat.ambientColor = ambient; + ShapeAppearance->setValue(mat); + } } } } @@ -112,19 +152,17 @@ void DlgMaterialPropertiesImp::onAmbientColorChanged() */ void DlgMaterialPropertiesImp::onDiffuseColorChanged() { - QColor col = ui->diffuseColor->color(); - float r = (float)col.red() / 255.0f; - float g = (float)col.green() / 255.0f; - float b = (float)col.blue() / 255.0f; - App::Color diffuse(r, g, b); + if (updateColors) { + App::Color diffuse = getColor(ui->diffuseColor->color()); - for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { - App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - mat.diffuseColor = diffuse; - ShapeMaterial->setValue(mat); + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + mat.diffuseColor = diffuse; + ShapeAppearance->setValue(mat); + } } } } @@ -134,19 +172,17 @@ void DlgMaterialPropertiesImp::onDiffuseColorChanged() */ void DlgMaterialPropertiesImp::onEmissiveColorChanged() { - QColor col = ui->emissiveColor->color(); - float r = (float)col.red() / 255.0f; - float g = (float)col.green() / 255.0f; - float b = (float)col.blue() / 255.0f; - App::Color emissive(r, g, b); + if (updateColors) { + App::Color emissive = getColor(ui->emissiveColor->color()); - for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { - App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - mat.emissiveColor = emissive; - ShapeMaterial->setValue(mat); + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + mat.emissiveColor = emissive; + ShapeAppearance->setValue(mat); + } } } } @@ -156,19 +192,17 @@ void DlgMaterialPropertiesImp::onEmissiveColorChanged() */ void DlgMaterialPropertiesImp::onSpecularColorChanged() { - QColor col = ui->specularColor->color(); - float r = (float)col.red() / 255.0f; - float g = (float)col.green() / 255.0f; - float b = (float)col.blue() / 255.0f; - App::Color specular(r, g, b); + if (updateColors) { + App::Color specular = getColor(ui->specularColor->color()); - for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { - App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - mat.specularColor = specular; - ShapeMaterial->setValue(mat); + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + mat.specularColor = specular; + ShapeAppearance->setValue(mat); + } } } } @@ -178,14 +212,63 @@ void DlgMaterialPropertiesImp::onSpecularColorChanged() */ void DlgMaterialPropertiesImp::onShininessValueChanged(int sh) { - float shininess = (float)sh / 100.0f; + if (updateColors) { + float shininess = (float)sh / 100.0F; + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + mat.shininess = shininess; + ShapeAppearance->setValue(mat); + } + } + } +} + +/** + * Reset the colors to the Coin3D defaults + */ +void DlgMaterialPropertiesImp::onButtonReset(bool checked) +{ for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - mat.shininess = shininess; - ShapeMaterial->setValue(mat); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = getMaterial(); + + App::Color defaultAmbient(0.2, 0.2, 0.2); + App::Color defaultDiffuse(0.8, 0.8, 0.8); + App::Color black(0, 0, 0); + + mat.ambientColor = defaultAmbient; + mat.diffuseColor = defaultDiffuse; + mat.emissiveColor = black; + mat.specularColor = black; + mat.shininess = 0.2; + ShapeAppearance->setValue(mat); + + setButtonColors(); + break; + } + } +} + +/** + * Reset the colors to the current default + */ +void DlgMaterialPropertiesImp::onButtonDefault(bool checked) +{ + for (std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { + App::Property* prop = (*it)->getPropertyByName(material.c_str()); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto mat = App::Material::getDefaultAppearance(); + + ShapeAppearance->setValue(mat); + + setButtonColors(); + break; } } } @@ -197,33 +280,82 @@ void DlgMaterialPropertiesImp::setViewProviders(const std::vector::iterator it = Objects.begin(); it != Objects.end(); ++it) { App::Property* prop = (*it)->getPropertyByName(material.c_str()); - if (prop && prop->isDerivedFrom()) { - auto ShapeMaterial = static_cast(prop); - App::Material mat = ShapeMaterial->getValue(); - int r = int(mat.ambientColor.r * 255.0f); - int g = int(mat.ambientColor.g * 255.0f); - int b = int(mat.ambientColor.b * 255.0f); + if (prop && prop->isDerivedFrom()) { + auto ShapeAppearance = static_cast(prop); + auto& materials = ShapeAppearance->getValues(); + auto& mat = materials[0]; + int r = int(mat.ambientColor.r * 255.0F); + int g = int(mat.ambientColor.g * 255.0F); + int b = int(mat.ambientColor.b * 255.0F); ui->ambientColor->setColor(QColor(r, g, b)); - r = int(mat.diffuseColor.r * 255.0f); - g = int(mat.diffuseColor.g * 255.0f); - b = int(mat.diffuseColor.b * 255.0f); + r = int(mat.diffuseColor.r * 255.0F); + g = int(mat.diffuseColor.g * 255.0F); + b = int(mat.diffuseColor.b * 255.0F); ui->diffuseColor->setColor(QColor(r, g, b)); - r = int(mat.emissiveColor.r * 255.0f); - g = int(mat.emissiveColor.g * 255.0f); - b = int(mat.emissiveColor.b * 255.0f); + r = int(mat.emissiveColor.r * 255.0F); + g = int(mat.emissiveColor.g * 255.0F); + b = int(mat.emissiveColor.b * 255.0F); ui->emissiveColor->setColor(QColor(r, g, b)); - r = int(mat.specularColor.r * 255.0f); - g = int(mat.specularColor.g * 255.0f); - b = int(mat.specularColor.b * 255.0f); + r = int(mat.specularColor.r * 255.0F); + g = int(mat.specularColor.g * 255.0F); + b = int(mat.specularColor.b * 255.0F); ui->specularColor->setColor(QColor(r, g, b)); ui->shininess->blockSignals(true); - ui->shininess->setValue((int)(100.0f * (mat.shininess + 0.001f))); + ui->shininess->setValue((int)(100.0f * (mat.shininess + 0.001F))); ui->shininess->blockSignals(false); break; } } } +/** + * Constructs a Gui::Dialog::DlgFaceMaterialPropertiesImp as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + * + * The dialog will by default be modeless, unless you set 'modal' to + * true to construct a modal dialog. + * + * This differs from Gui::Dialog::DlgMaterialPropertiesImp in that it does not update + * the underlying object. This is undesirable when we're updating only a single face. + */ +DlgFaceMaterialPropertiesImp::DlgFaceMaterialPropertiesImp(const std::string& mat, + QWidget* parent, + Qt::WindowFlags fl) + : DlgMaterialPropertiesImp(mat, parent, fl) +{ + Base::Console().Log("DlgFaceMaterialPropertiesImp::DlgFaceMaterialPropertiesImp()\n"); + + // Override the base class on this. Otherwise the whole object changes + updateColors = false; +} + +/** + * Destroys the object and frees any allocated resources + */ +DlgFaceMaterialPropertiesImp::~DlgFaceMaterialPropertiesImp() = default; + +App::Material DlgFaceMaterialPropertiesImp::getCustomAppearance() const +{ + App::Material material; + material.setType(App::Material::USER_DEFINED); + + material.ambientColor = getColor(ui->ambientColor->color()); + material.diffuseColor = getColor(ui->diffuseColor->color()); + material.emissiveColor = getColor(ui->emissiveColor->color()); + material.specularColor = getColor(ui->specularColor->color()); + material.shininess = (float)ui->shininess->value() / 100.0F; + + return material; +} + #include "moc_DlgMaterialPropertiesImp.cpp" diff --git a/src/Gui/DlgMaterialPropertiesImp.h b/src/Gui/DlgMaterialPropertiesImp.h index 8d1e4b458c..385a4c0259 100644 --- a/src/Gui/DlgMaterialPropertiesImp.h +++ b/src/Gui/DlgMaterialPropertiesImp.h @@ -28,6 +28,12 @@ #include #include +namespace App +{ +class Color; +class Material; +} + namespace Gui { class ViewProvider; @@ -48,18 +54,36 @@ public: void setViewProviders(const std::vector&); QColor diffuseColor() const; -private: +protected: void setupConnections(); + App::Material getMaterial(); + App::Color getColor(const QColor& color) const; void onAmbientColorChanged(); void onDiffuseColorChanged(); void onEmissiveColorChanged(); void onSpecularColorChanged(); void onShininessValueChanged(int); + void onButtonReset(bool checked); + void onButtonDefault(bool checked); + void setButtonColors(); -private: +protected: std::unique_ptr ui; std::string material; std::vector Objects; + bool updateColors; +}; + +class GuiExport DlgFaceMaterialPropertiesImp: public DlgMaterialPropertiesImp +{ + Q_OBJECT + +public: + explicit DlgFaceMaterialPropertiesImp(const std::string& mat, + QWidget* parent = nullptr, + Qt::WindowFlags fl = Qt::WindowFlags()); + ~DlgFaceMaterialPropertiesImp() override; + App::Material getCustomAppearance() const; }; } // namespace Dialog diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index 661d6be980..3f8d7dd5c1 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include #include @@ -35,12 +34,14 @@ #include #include #include +#include #endif #include #include #include +#include #include "Application.h" #include "Document.h" @@ -56,12 +57,12 @@ using namespace Gui; namespace { float fromPercent(long value) { - return static_cast(value) / 100.0F; + return std::roundf(value) / 100.0F; } long toPercent(float value) { - return static_cast(100.0 * value + 0.5); + return std::lround(100.0 * value); } } @@ -71,7 +72,7 @@ const App::PropertyIntegerConstraint::Constraints intPercent = {0, 100, 5}; ViewProviderGeometryObject::ViewProviderGeometryObject() { - App::Material mat = getUserDefinedMaterial(); + App::Material mat = App::Material::getDefaultAppearance(); long initialTransparency = toPercent(mat.transparency); static const char* dogroup = "Display Options"; @@ -95,10 +96,29 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() Selectable.setValue(isSelectionEnabled()); + pcSwitchAppearance = new SoSwitch; + pcSwitchAppearance->ref(); + pcSwitchTexture = new SoSwitch; + pcSwitchTexture->ref(); + pcShapeMaterial = new SoMaterial; - setSoMaterial(mat); + setCoinAppearance(mat); pcShapeMaterial->ref(); + pcShapeTexture2D = new SoTexture2; + pcShapeTexture2D->ref(); + + pcTextureGroup3D = new SoGroup; + pcTextureGroup3D->ref(); + + // Materials go first, with textured faces drawing over them + pcSwitchAppearance->addChild(pcShapeMaterial); + pcSwitchAppearance->addChild(pcSwitchTexture); + pcSwitchTexture->addChild(pcShapeTexture2D); + pcSwitchTexture->addChild(pcTextureGroup3D); + pcSwitchAppearance->whichChild.setValue(0); + pcSwitchTexture->whichChild.setValue(SO_SWITCH_NONE); + pcBoundingBox = new Gui::SoFCBoundingBox; pcBoundingBox->ref(); @@ -110,54 +130,15 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() ViewProviderGeometryObject::~ViewProviderGeometryObject() { + pcSwitchAppearance->unref(); + pcSwitchTexture->unref(); pcShapeMaterial->unref(); + pcShapeTexture2D->unref(); + pcTextureGroup3D->unref(); pcBoundingBox->unref(); pcBoundColor->unref(); } -App::Material ViewProviderGeometryObject::getUserDefinedMaterial() -{ - 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 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(intRandom(0, 255)) / 255.0F; - float green = static_cast(intRandom(0, 255)) / 255.0F; - float blue = static_cast(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; -} - bool ViewProviderGeometryObject::isSelectionEnabled() const { ParameterGrp::handle hGrp = @@ -187,12 +168,14 @@ void ViewProviderGeometryObject::onChanged(const App::Property* prop) if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange)) { getObject()->touch(true); } - const App::Material& Mat = ShapeAppearance[0]; long value = toPercent(ShapeAppearance.getTransparency()); if (value != Transparency.getValue()) { Transparency.setValue(value); } - setSoMaterial(Mat); + if (ShapeAppearance.getSize() == 1) { + const App::Material& Mat = ShapeAppearance[0]; + setCoinAppearance(Mat); + } } else if (prop == &BoundingBox) { showBoundingBox(BoundingBox.getValue()); @@ -288,14 +271,33 @@ unsigned long ViewProviderGeometryObject::getBoundColor() const return bbcol; } -void ViewProviderGeometryObject::setSoMaterial(const App::Material& source) +void ViewProviderGeometryObject::setCoinAppearance(const App::Material& source) { +#if 0 + if (!source.image.empty()) { + Base::Console().Log("setCoinAppearance(Texture)\n"); + activateTexture2D(); + + QByteArray by = QByteArray::fromBase64(QString::fromStdString(source.image).toUtf8()); + auto image = QImage::fromData(by, "PNG"); //.scaled(64, 64, Qt::KeepAspectRatio); + + SoSFImage texture; + Gui::BitmapFactory().convert(image, texture); + pcShapeTexture2D->image = texture; + } else { + Base::Console().Log("setCoinAppearance(Material)\n"); + activateMaterial(); + } +#endif + activateMaterial(); + + // Always set the material for items such as lines that don't support textures pcShapeMaterial->ambientColor.setValue(source.ambientColor.r, - source.ambientColor.g, - source.ambientColor.b); + source.ambientColor.g, + source.ambientColor.b); pcShapeMaterial->diffuseColor.setValue(source.diffuseColor.r, - source.diffuseColor.g, - source.diffuseColor.b); + source.diffuseColor.g, + source.diffuseColor.b); pcShapeMaterial->specularColor.setValue(source.specularColor.r, source.specularColor.g, source.specularColor.b); @@ -306,6 +308,31 @@ void ViewProviderGeometryObject::setSoMaterial(const App::Material& source) pcShapeMaterial->transparency.setValue(source.transparency); } +void ViewProviderGeometryObject::activateMaterial() +{ + pcSwitchAppearance->whichChild.setValue(0); + pcSwitchTexture->whichChild.setValue(SO_SWITCH_NONE); +} + +void ViewProviderGeometryObject::activateTexture2D() +{ + pcSwitchAppearance->whichChild.setValue(1); + pcSwitchTexture->whichChild.setValue(0); +} + +void ViewProviderGeometryObject::activateTexture3D() +{ + pcSwitchAppearance->whichChild.setValue(1); + pcSwitchTexture->whichChild.setValue(1); +} + +void ViewProviderGeometryObject::activateMixed3D() +{ + pcSwitchAppearance->whichChild.setValue(SO_SWITCH_ALL); + pcSwitchTexture->whichChild.setValue(1); +} + + namespace { float getBoundBoxFontSize() diff --git a/src/Gui/ViewProviderGeometryObject.h b/src/Gui/ViewProviderGeometryObject.h index 44ef6dc80a..5a8b4134e6 100644 --- a/src/Gui/ViewProviderGeometryObject.h +++ b/src/Gui/ViewProviderGeometryObject.h @@ -30,6 +30,7 @@ class SoPickedPointList; class SoSwitch; class SoSensor; +class SoTexture2; class SbVec2s; class SoBaseColor; @@ -58,7 +59,6 @@ public: // Display properties App::PropertyPercent Transparency; - // App::PropertyMaterial ShapeMaterial; // Default appearance and physical properties App::PropertyMaterialList ShapeAppearance; // May be different from material App::PropertyBool BoundingBox; App::PropertyBool Selectable; @@ -108,13 +108,30 @@ protected: void handleChangedPropertyName(Base::XMLReader& reader, const char* TypeName, const char* PropName) override; + void setCoinAppearance(const App::Material& source); + + /** + * Select which appearance type is active + * + */ + /** Material only */ + void activateMaterial(); + /** 2D Texture */ + void activateTexture2D(); + /** 3D texture only */ + void activateTexture3D(); + /** Mix of material and 3D textures */ + void activateMixed3D(); private: - void setSoMaterial(const App::Material& source); bool isSelectionEnabled() const; protected: + SoSwitch* pcSwitchAppearance {nullptr}; + SoSwitch* pcSwitchTexture {nullptr}; SoMaterial* pcShapeMaterial {nullptr}; + SoTexture2* pcShapeTexture2D {nullptr}; + SoGroup* pcTextureGroup3D {nullptr}; SoFCBoundingBox* pcBoundingBox {nullptr}; SoSwitch* pcBoundSwitch {nullptr}; SoBaseColor* pcBoundColor {nullptr}; diff --git a/src/Gui/ViewProviderGeometryObjectPyImp.cpp b/src/Gui/ViewProviderGeometryObjectPyImp.cpp index c7dfba3af8..76d83f1df7 100644 --- a/src/Gui/ViewProviderGeometryObjectPyImp.cpp +++ b/src/Gui/ViewProviderGeometryObjectPyImp.cpp @@ -71,7 +71,7 @@ PyObject* ViewProviderGeometryObjectPy::getCustomAttributes(const char* attr) co PyObject* ViewProviderGeometryObjectPy::getUserDefinedMaterial() { - App::Material mat = ViewProviderGeometryObject::getUserDefinedMaterial(); + App::Material mat = App::Material::getDefaultAppearance(); return new App::MaterialPy(new App::Material(mat)); } diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintOnBoundary.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintOnBoundary.cpp index 51ece8c417..18d168b5a3 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintOnBoundary.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintOnBoundary.cpp @@ -94,7 +94,7 @@ void ViewProviderFemConstraintOnBoundary::highlightReferences(const bool on) else if (subSet.second[0].find("Face") != std::string::npos) { // make sure original colors are remembered if (originalFaceColors[base].empty()) { - originalFaceColors[base] = vp->DiffuseColor.getValues(); + originalFaceColors[base] = vp->ShapeAppearance.getDiffuseColors(); } std::vector colors = originalFaceColors[base]; @@ -104,7 +104,7 @@ void ViewProviderFemConstraintOnBoundary::highlightReferences(const bool on) base->Shape.getValue(), colors.empty() ? ShapeAppearance.getDiffuseColor() : colors[0]); highlighter.getFaceColors(subSet.second, colors); - vp->DiffuseColor.setValues(colors); + vp->ShapeAppearance.setDiffuseColors(colors); } } else { @@ -117,7 +117,7 @@ void ViewProviderFemConstraintOnBoundary::highlightReferences(const bool on) originalLineColors[base].clear(); } else if (!originalFaceColors[base].empty()) { - vp->DiffuseColor.setValues(originalFaceColors[base]); + vp->ShapeAppearance.setDiffuseColors(originalFaceColors[base]); originalFaceColors[base].clear(); } } @@ -164,7 +164,7 @@ void ViewProviderFemConstraintOnBoundary::highlightReferences(const bool on) continue; } - vp->DiffuseColor.setValues(ogPair.second); + vp->ShapeAppearance.setDiffuseColors(ogPair.second); ogPair.second.clear(); } } diff --git a/src/Mod/Import/Gui/ExportOCAFGui.cpp b/src/Mod/Import/Gui/ExportOCAFGui.cpp index b56d1d9688..db20afa4e5 100644 --- a/src/Mod/Import/Gui/ExportOCAFGui.cpp +++ b/src/Mod/Import/Gui/ExportOCAFGui.cpp @@ -39,10 +39,6 @@ void ExportOCAFGui::findColors(Part::Feature* part, std::vector& col { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part); if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { - colors = static_cast(vp)->DiffuseColor.getValues(); - if (colors.empty()) { - colors.push_back( - static_cast(vp)->ShapeAppearance.getDiffuseColor()); - } + colors = static_cast(vp)->ShapeAppearance.getDiffuseColors(); } } diff --git a/src/Mod/Import/Gui/ImportOCAFGui.cpp b/src/Mod/Import/Gui/ImportOCAFGui.cpp index cd594a2123..154e1297fb 100644 --- a/src/Mod/Import/Gui/ImportOCAFGui.cpp +++ b/src/Mod/Import/Gui/ImportOCAFGui.cpp @@ -54,7 +54,7 @@ void ImportOCAFGui::applyFaceColors(Part::Feature* part, const std::vectorTransparency.setValue(100 * colors.front().a); } else { - vp->DiffuseColor.setValues(colors); + vp->ShapeAppearance.setDiffuseColors(colors); } } diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index 5192328211..5727a3a690 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -333,6 +333,11 @@ void MaterialProperty::setString(const QString& value) _valuePtr->setValue(QVariant(value)); } +void MaterialProperty::setString(const std::string& value) +{ + _valuePtr->setValue(QVariant(QString::fromStdString(value))); +} + void MaterialProperty::setBoolean(bool value) { _valuePtr->setValue(QVariant(value)); @@ -1545,13 +1550,21 @@ Material& Material::operator=(const App::Material& other) addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic); } - getAppearanceProperty(QString::fromLatin1("AmbientColor"))->setColor(other.ambientColor); - getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->setColor(other.diffuseColor); - getAppearanceProperty(QString::fromLatin1("SpecularColor"))->setColor(other.specularColor); - getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->setColor(other.emissiveColor); - getAppearanceProperty(QString::fromLatin1("Shininess"))->setFloat(other.shininess); - getAppearanceProperty(QString::fromLatin1("Transparency"))->setFloat(other.transparency); - // std::string uuid; + getAppearanceProperty(QLatin1String("AmbientColor"))->setColor(other.ambientColor); + getAppearanceProperty(QLatin1String("DiffuseColor"))->setColor(other.diffuseColor); + getAppearanceProperty(QLatin1String("SpecularColor"))->setColor(other.specularColor); + getAppearanceProperty(QLatin1String("EmissiveColor"))->setColor(other.emissiveColor); + getAppearanceProperty(QLatin1String("Shininess"))->setFloat(other.shininess); + getAppearanceProperty(QLatin1String("Transparency"))->setFloat(other.transparency); + + if (!other.image.empty() || !other.imagePath.empty()) { + if (!hasAppearanceModel(ModelUUIDs::ModelUUID_Rendering_Texture)) { + addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture); + } + + getAppearanceProperty(QLatin1String("TextureImage"))->setString(other.image); + getAppearanceProperty(QLatin1String("TexturePath"))->setString(other.imagePath); + } return *this; } @@ -1641,33 +1654,46 @@ App::Material Material::getMaterialAppearance() const App::Material material(App::Material::DEFAULT); bool custom = false; - if (hasAppearanceProperty(QString::fromLatin1("AmbientColor"))) { - material.ambientColor = - getAppearanceProperty(QString::fromLatin1("AmbientColor"))->getColor(); + if (hasAppearanceProperty(QLatin1String("AmbientColor"))) { + material.ambientColor = getAppearanceProperty(QLatin1String("AmbientColor"))->getColor(); custom = true; } - if (hasAppearanceProperty(QString::fromLatin1("DiffuseColor"))) { - material.diffuseColor = - getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->getColor(); + if (hasAppearanceProperty(QLatin1String("DiffuseColor"))) { + material.diffuseColor = getAppearanceProperty(QLatin1String("DiffuseColor"))->getColor(); custom = true; } - if (hasAppearanceProperty(QString::fromLatin1("SpecularColor"))) { - material.specularColor = - getAppearanceProperty(QString::fromLatin1("SpecularColor"))->getColor(); + if (hasAppearanceProperty(QLatin1String("SpecularColor"))) { + material.specularColor = getAppearanceProperty(QLatin1String("SpecularColor"))->getColor(); custom = true; } - if (hasAppearanceProperty(QString::fromLatin1("EmissiveColor"))) { - material.emissiveColor = - getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->getColor(); + if (hasAppearanceProperty(QLatin1String("EmissiveColor"))) { + material.emissiveColor = getAppearanceProperty(QLatin1String("EmissiveColor"))->getColor(); custom = true; } - if (hasAppearanceProperty(QString::fromLatin1("Shininess"))) { - material.shininess = getAppearanceProperty(QString::fromLatin1("Shininess"))->getFloat(); + if (hasAppearanceProperty(QLatin1String("Shininess"))) { + material.shininess = getAppearanceProperty(QLatin1String("Shininess"))->getFloat(); custom = true; } - if (hasAppearanceProperty(QString::fromLatin1("Transparency"))) { - material.transparency = - getAppearanceProperty(QString::fromLatin1("Transparency"))->getFloat(); + if (hasAppearanceProperty(QLatin1String("Transparency"))) { + material.transparency = getAppearanceProperty(QLatin1String("Transparency"))->getFloat(); + custom = true; + } + if (hasAppearanceProperty(QLatin1String("TextureImage"))) { + auto property = getAppearanceProperty(QLatin1String("TextureImage")); + if (!property->isNull()) { + Base::Console().Log("Has 'TextureImage'\n"); + material.image = property->getString().toStdString(); + } + + custom = true; + } + else if (hasAppearanceProperty(QLatin1String("TexturePath"))) { + auto property = getAppearanceProperty(QLatin1String("TexturePath")); + if (!property->isNull()) { + Base::Console().Log("Has 'TexturePath'\n"); + material.imagePath = property->getString().toStdString(); + } + custom = true; } diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index 1b5630d2b1..7f88aaf963 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -116,6 +116,7 @@ public: void setValue(const QString& value); void setValue(const std::shared_ptr& value); void setString(const QString& value); + void setString(const std::string& value); void setBoolean(bool value); void setBoolean(int value); void setBoolean(const QString& value); diff --git a/src/Mod/Material/Gui/AppearancePreview.cpp b/src/Mod/Material/Gui/AppearancePreview.cpp index b0351a8773..c72f1c3879 100644 --- a/src/Mod/Material/Gui/AppearancePreview.cpp +++ b/src/Mod/Material/Gui/AppearancePreview.cpp @@ -21,15 +21,23 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#endif +#include +#include +#include #include #include #include #include +#include +#include +#endif + +#include #include #include +#include #include "AppearancePreview.h" @@ -123,11 +131,24 @@ AppearancePreview::AppearancePreview(QWidget* parent) // setBackground(); setEnabledNaviCube(false); - auto root = dynamic_cast(getSceneGraph()); + _group = dynamic_cast(getSceneGraph()); + _group->ref(); + + _switch = new SoSwitch(); + _switch->ref(); _material = new SoMaterial(); _material->ref(); - root->addChild(_material); - root->addChild(new SoSphere()); + _texture = new SoTexture2(); + _texture->ref(); + _environment = new SoTextureCoordinateEnvironment(); + _environment->ref(); + + _switch->addChild(_material); + _switch->addChild(_texture); + _switch->whichChild.setValue(0); + + _group->addChild(_switch); + _group->addChild(new SoSphere()); setCameraType(SoOrthographicCamera::getClassTypeId()); setViewDirection(SbVec3f(1, 1, -5)); @@ -136,8 +157,30 @@ AppearancePreview::AppearancePreview(QWidget* parent) AppearancePreview::~AppearancePreview() { + if (_switch) { + if (_switch->findChild(_material) > -1) { + _switch->removeChild(_material); + } + if (_switch->findChild(_texture) > -1) { + _switch->removeChild(_texture); + } + } + if (_group) { + if (_group->findChild(_switch) > -1) { + _group->removeChild(_switch); + } + } + + _group->unref(); + _group = nullptr; + _switch->unref(); + _switch = nullptr; _material->unref(); _material = nullptr; + _texture->unref(); + _texture = nullptr; + _environment->unref(); + _environment = nullptr; } void AppearancePreview::applySettings() @@ -148,8 +191,19 @@ void AppearancePreview::applySettings() viewSettings->applySettings(); } +void AppearancePreview::setCoinTexture() +{ + _switch->whichChild.setValue(1); +} + +void AppearancePreview::setCoinMaterial() +{ + _switch->whichChild.setValue(0); +} + void AppearancePreview::setAmbientColor(const QColor& color) { + setCoinMaterial(); _material->ambientColor.setValue( SbColor(color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0)); _material->ambientColor.setDefault(false); @@ -157,6 +211,7 @@ void AppearancePreview::setAmbientColor(const QColor& color) void AppearancePreview::setDiffuseColor(const QColor& color) { + setCoinMaterial(); _material->diffuseColor.setValue( SbColor(color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0)); _material->diffuseColor.setDefault(false); @@ -164,6 +219,7 @@ void AppearancePreview::setDiffuseColor(const QColor& color) void AppearancePreview::setSpecularColor(const QColor& color) { + setCoinMaterial(); _material->specularColor.setValue( SbColor(color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0)); _material->specularColor.setDefault(false); @@ -171,6 +227,7 @@ void AppearancePreview::setSpecularColor(const QColor& color) void AppearancePreview::setEmissiveColor(const QColor& color) { + setCoinMaterial(); _material->emissiveColor.setValue( SbColor(color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0)); _material->emissiveColor.setDefault(false); @@ -178,48 +235,74 @@ void AppearancePreview::setEmissiveColor(const QColor& color) void AppearancePreview::setShininess(double value) { + setCoinMaterial(); _material->shininess.setValue(value); _material->shininess.setDefault(false); } void AppearancePreview::setTransparency(double value) { + setCoinMaterial(); _material->transparency.setValue(value); _material->transparency.setDefault(false); } +void AppearancePreview::setTexture(const QImage& image) +{ + setCoinTexture(); + + SoSFImage texture; + Gui::BitmapFactory().convert(image, texture); + _texture->image = texture; +} + +void AppearancePreview::setTextureScaling(double scale) +{} + void AppearancePreview::resetAmbientColor() { + setCoinMaterial(); _material->ambientColor.deleteValues(0); _material->ambientColor.setDefault(true); } void AppearancePreview::resetDiffuseColor() { + setCoinMaterial(); _material->diffuseColor.deleteValues(0); _material->diffuseColor.setDefault(true); } void AppearancePreview::resetSpecularColor() { + setCoinMaterial(); _material->specularColor.deleteValues(0); _material->specularColor.setDefault(true); } void AppearancePreview::resetEmissiveColor() { + setCoinMaterial(); _material->emissiveColor.deleteValues(0); _material->emissiveColor.setDefault(true); } void AppearancePreview::resetShininess() { + setCoinMaterial(); _material->shininess.deleteValues(0); _material->shininess.setDefault(true); } void AppearancePreview::resetTransparency() { + setCoinMaterial(); _material->transparency.deleteValues(0); _material->transparency.setDefault(true); } + +void AppearancePreview::resetTexture() +{} + +void AppearancePreview::resetTextureScaling() +{} diff --git a/src/Mod/Material/Gui/AppearancePreview.h b/src/Mod/Material/Gui/AppearancePreview.h index cbf4a71b2b..115670cf7b 100644 --- a/src/Mod/Material/Gui/AppearancePreview.h +++ b/src/Mod/Material/Gui/AppearancePreview.h @@ -26,7 +26,11 @@ #include #include +class SoGroup; class SoMaterial; +class SoSwitch; +class SoTexture2; +class SoTextureCoordinateEnvironment; namespace MatGui { @@ -57,6 +61,8 @@ public: void setEmissiveColor(const QColor& color); void setShininess(double value); void setTransparency(double value); + void setTexture(const QImage& image); + void setTextureScaling(double scale); void resetAmbientColor(); void resetDiffuseColor(); @@ -64,12 +70,20 @@ public: void resetEmissiveColor(); void resetShininess(); void resetTransparency(); + void resetTexture(); + void resetTextureScaling(); private: + SoSeparator* _group; + SoSwitch* _switch; SoMaterial* _material; + SoTexture2* _texture; + SoTextureCoordinateEnvironment* _environment; std::unique_ptr viewSettings; void applySettings(); + void setCoinTexture(); + void setCoinMaterial(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/DlgDisplayProperties.ui b/src/Mod/Material/Gui/DlgDisplayProperties.ui index fd80c1d23d..ae637d1bc9 100644 --- a/src/Mod/Material/Gui/DlgDisplayProperties.ui +++ b/src/Mod/Material/Gui/DlgDisplayProperties.ui @@ -369,7 +369,7 @@ - Shape Appearance: + Custom Appearance @@ -401,7 +401,7 @@ - + ... diff --git a/src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp b/src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp index eb68612826..92dcadb41b 100644 --- a/src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp +++ b/src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp @@ -167,7 +167,6 @@ DlgDisplayPropertiesImp::DlgDisplayPropertiesImp(bool floating, QWidget* parent, std::vector views = getSelection(); setDisplayModes(views); - setMaterial(views); setColorPlot(views); setShapeAppearance(views); setLineColor(views); @@ -276,10 +275,10 @@ void DlgDisplayPropertiesImp::setupConnections() qOverload(&QSpinBox::valueChanged), this, &DlgDisplayPropertiesImp::onSpinLineTransparencyValueChanged); - connect(d->ui.buttonUserDefinedMaterial, + connect(d->ui.buttonCustomAppearance, &Gui::ColorButton::clicked, this, - &DlgDisplayPropertiesImp::onButtonUserDefinedMaterialClicked); + &DlgDisplayPropertiesImp::onbuttonCustomAppearanceClicked); connect(d->ui.buttonColorPlot, &Gui::ColorButton::clicked, this, @@ -309,7 +308,6 @@ void DlgDisplayPropertiesImp::OnChange(Gui::SelectionSingleton::SubjectType& rCa || Reason.Type == Gui::SelectionChanges::ClrSelection) { std::vector views = getSelection(); setDisplayModes(views); - setMaterial(views); setColorPlot(views); setShapeAppearance(views); setLineColor(views); @@ -357,15 +355,10 @@ void DlgDisplayPropertiesImp::slotChangedObject(const Gui::ViewProvider& obj, } } else if (prop.isDerivedFrom()) { - //auto& value = static_cast(prop).getValue(); if (prop_name == "ShapeAppearance") { - // Base::Console().Log("slotChangeObject(ShapeAppearance)\n"); - // bool blocked = d->ui.buttonColor->blockSignals(true); - // auto color = value.diffuseColor; - // d->ui.buttonColor->setColor(QColor((int)(255.0f * color.r), - // (int)(255.0f * color.g), - // (int)(255.0f * color.b))); - // d->ui.buttonColor->blockSignals(blocked); + auto& values = static_cast(prop).getValues(); + auto& material = values[0]; + d->ui.widgetMaterial->setMaterial(QString::fromStdString(material.uuid)); } } else if (prop.isDerivedFrom()) { @@ -419,10 +412,10 @@ void DlgDisplayPropertiesImp::reject() /** * Opens a dialog that allows to modify the 'ShapeMaterial' property of all selected view providers. */ -void DlgDisplayPropertiesImp::onButtonUserDefinedMaterialClicked() +void DlgDisplayPropertiesImp::onbuttonCustomAppearanceClicked() { std::vector Provider = getSelection(); - Gui::Dialog::DlgMaterialPropertiesImp dlg("ShapeMaterial", this); + Gui::Dialog::DlgMaterialPropertiesImp dlg("ShapeAppearance", this); dlg.setViewProviders(Provider); dlg.exec(); @@ -586,25 +579,6 @@ void DlgDisplayPropertiesImp::setDisplayModes(const std::vector& views) -{ - Q_UNUSED(views); - // bool material = false; - // App::Material mat = App::Material(App::Material::DEFAULT); - // for (auto view : views) { - // if (auto* prop = - // dynamic_cast(view->getPropertyByName("ShapeMaterial"))) { - // mat = prop->getValue(); - // material = mat.uuid.empty(); - // if (!material) { - // d->ui.widgetMaterial->setMaterial(QString::fromStdString(mat.uuid)); - // } - // break; - // } - // } - // d->ui.buttonUserDefinedMaterial->setEnabled(material); -} - void DlgDisplayPropertiesImp::setColorPlot(const std::vector& views) { bool material = false; @@ -627,16 +601,13 @@ void DlgDisplayPropertiesImp::setShapeAppearance(const std::vector(view->getPropertyByName("ShapeAppearance"))) { + material = true; mat = prop->getValues()[0]; - material = mat.uuid.empty(); - if (!material) { - d->ui.widgetMaterial->setMaterial(QString::fromStdString(mat.uuid)); - } + d->ui.widgetMaterial->setMaterial(QString::fromStdString(mat.uuid)); break; } } - // d->ui.buttonUserDefinedMaterial->setEnabled(material); - d->ui.buttonUserDefinedMaterial->setEnabled(true); + d->ui.buttonCustomAppearance->setEnabled(material); } void DlgDisplayPropertiesImp::setLineColor(const std::vector& views) @@ -694,21 +665,7 @@ void DlgDisplayPropertiesImp::onMaterialSelected( for (auto it : Provider) { if (auto* prop = dynamic_cast( it->getPropertyByName("ShapeAppearance"))) { - App::Material mat; - mat.ambientColor = - material->getAppearanceProperty(QString::fromLatin1("AmbientColor"))->getColor(); - mat.diffuseColor = - material->getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->getColor(); - mat.emissiveColor = - material->getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->getColor(); - mat.specularColor = - material->getAppearanceProperty(QString::fromLatin1("SpecularColor"))->getColor(); - mat.shininess = - material->getAppearanceProperty(QString::fromLatin1("Shininess"))->getFloat(); - mat.transparency = - material->getAppearanceProperty(QString::fromLatin1("Transparency"))->getFloat(); - mat.uuid = material->getUUID().toStdString(); - prop->setValue(mat); + prop->setValue(material->getMaterialAppearance()); } } } diff --git a/src/Mod/Material/Gui/DlgDisplayPropertiesImp.h b/src/Mod/Material/Gui/DlgDisplayPropertiesImp.h index d16b2aea88..2d94004b3b 100644 --- a/src/Mod/Material/Gui/DlgDisplayPropertiesImp.h +++ b/src/Mod/Material/Gui/DlgDisplayPropertiesImp.h @@ -75,7 +75,7 @@ private Q_SLOTS: void onButtonPointColorChanged(); void onSpinLineWidthValueChanged(int); void onSpinLineTransparencyValueChanged(int); - void onButtonUserDefinedMaterialClicked(); + void onbuttonCustomAppearanceClicked(); void onButtonColorPlotClicked(); void onMaterialSelected(const std::shared_ptr& material); @@ -87,7 +87,6 @@ private: void setupFilters(); void slotChangedObject(const Gui::ViewProvider&, const App::Property& Prop); void setDisplayModes(const std::vector&); - void setMaterial(const std::vector&); void setColorPlot(const std::vector&); void setShapeAppearance(const std::vector&); void setLineColor(const std::vector&); diff --git a/src/Mod/Material/Gui/DlgMaterialImp.cpp b/src/Mod/Material/Gui/DlgMaterialImp.cpp index e82813ea00..c970752e64 100644 --- a/src/Mod/Material/Gui/DlgMaterialImp.cpp +++ b/src/Mod/Material/Gui/DlgMaterialImp.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/src/Mod/Material/Gui/MaterialTreeWidget.cpp b/src/Mod/Material/Gui/MaterialTreeWidget.cpp index 6e3a2eb494..398b46779f 100644 --- a/src/Mod/Material/Gui/MaterialTreeWidget.cpp +++ b/src/Mod/Material/Gui/MaterialTreeWidget.cpp @@ -285,9 +285,19 @@ QModelIndex MaterialTreeWidget::findInTree(const QString& uuid) void MaterialTreeWidget::setMaterial(const QString& uuid) { - if (uuid.isEmpty() || uuid == m_uuid) { + if (uuid == m_uuid) { return; } + + if (uuid.isEmpty()) { + // Nothing is selected + QItemSelectionModel* selectionModel = m_materialTree->selectionModel(); + selectionModel->clear(); + m_material->clear(); + + return; + } + updateMaterial(uuid); // Now select the material in the tree @@ -634,6 +644,11 @@ void MaterialTreeWidget::onSelectMaterial(const QItemSelection& selected, { Q_UNUSED(deselected); + if (selected.isEmpty()) { + m_uuid.clear(); + return; + } + // Get the UUID before changing the underlying data model QString uuid; auto model = dynamic_cast(m_materialTree->model()); diff --git a/src/Mod/Material/Gui/MaterialsEditor.cpp b/src/Mod/Material/Gui/MaterialsEditor.cpp index 582600b6db..c1679de989 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.cpp +++ b/src/Mod/Material/Gui/MaterialsEditor.cpp @@ -89,7 +89,7 @@ void MaterialsEditor::setup() Gui::WaitCursor wc; ui->setupUi(this); - _warningIcon = QIcon(QString::fromStdString(":/icons/Warning.svg")); + _warningIcon = QIcon(QLatin1String(":/icons/Warning.svg")); getFavorites(); getRecents(); @@ -108,7 +108,7 @@ void MaterialsEditor::setup() resize(width, height); - ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg"))); + ui->buttonURL->setIcon(QIcon(QLatin1String(":/icons/internet-web-browser.svg"))); connect(ui->standardButtons->button(QDialogButtonBox::Ok), &QPushButton::clicked, @@ -491,7 +491,7 @@ void MaterialsEditor::setMaterialDefaults() const char* name = App::licenseItems.at(index).at(App::posnOfFullName); // const char* url = App::licenseItems.at(index).at(App::posnOfUrl); // std::string licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); - _material->setLicense(QString::fromStdString(name)); + _material->setLicense(QLatin1String(name)); // Empty materials will have no parent _materialManager.dereference(_material); @@ -894,54 +894,120 @@ void MaterialsEditor::refreshMaterialTree() fillMaterialTree(); } -void MaterialsEditor::updatePreview() const +bool MaterialsEditor::updateTexturePreview() const { - if (_material->hasAppearanceProperty(QString::fromStdString("AmbientColor"))) { - QString color = _material->getAppearanceValueString(QString::fromStdString("AmbientColor")); + bool hasImage = false; + QImage image; + double scaling = 99.0; + if (_material->hasModel(Materials::ModelUUIDs::ModelUUID_Rendering_Texture)) { + // First try loading an embedded image + try { + auto property = _material->getAppearanceProperty(QLatin1String("TextureImage")); + if (!property->isNull()) { + // Base::Console().Log("Has 'TextureImage'\n"); + auto propertyValue = property->getString(); + if (!propertyValue.isEmpty()) { + QByteArray by = QByteArray::fromBase64(propertyValue.toUtf8()); + image = QImage::fromData(by, "PNG"); //.scaled(64, 64, Qt::KeepAspectRatio); + hasImage = true; + } + } + } + catch (const Materials::PropertyNotFound&) { + } + + // If no embedded image, load from a path + if (!hasImage) { + try { + auto property = _material->getAppearanceProperty(QLatin1String("TexturePath")); + if (!property->isNull()) { + // Base::Console().Log("Has 'TexturePath'\n"); + auto filePath = property->getString(); + if (!image.load(filePath)) { + Base::Console().Log("Unable to load image '%s'\n", + filePath.toStdString().c_str()); + // return; // ??? + } + hasImage = true; + } + } + catch (const Materials::PropertyNotFound&) { + } + } + + // Apply any scaling + try { + auto property = _material->getAppearanceProperty(QLatin1String("TextureScaling")); + if (!property->isNull()) { + scaling = property->getFloat(); + // Base::Console().Log("Has 'TextureScaling' = %g\n", scaling); + } + } + catch (const Materials::PropertyNotFound&) { + } + + if (hasImage) { + _rendered->setTexture(image); + } + } + + return hasImage; +} + +bool MaterialsEditor::updateMaterialPreview() const +{ + if (_material->hasAppearanceProperty(QLatin1String("AmbientColor"))) { + QString color = _material->getAppearanceValueString(QLatin1String("AmbientColor")); _rendered->setAmbientColor(getColorHash(color, 255)); } else { _rendered->resetAmbientColor(); } - if (_material->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { - QString color = _material->getAppearanceValueString(QString::fromStdString("DiffuseColor")); + if (_material->hasAppearanceProperty(QLatin1String("DiffuseColor"))) { + QString color = _material->getAppearanceValueString(QLatin1String("DiffuseColor")); _rendered->setDiffuseColor(getColorHash(color, 255)); } else { _rendered->resetDiffuseColor(); } - if (_material->hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { - QString color = - _material->getAppearanceValueString(QString::fromStdString("SpecularColor")); + if (_material->hasAppearanceProperty(QLatin1String("SpecularColor"))) { + QString color = _material->getAppearanceValueString(QLatin1String("SpecularColor")); _rendered->setSpecularColor(getColorHash(color, 255)); } else { _rendered->resetSpecularColor(); } - if (_material->hasAppearanceProperty(QString::fromStdString("EmissiveColor"))) { - QString color = - _material->getAppearanceValueString(QString::fromStdString("EmissiveColor")); + if (_material->hasAppearanceProperty(QLatin1String("EmissiveColor"))) { + QString color = _material->getAppearanceValueString(QLatin1String("EmissiveColor")); _rendered->setEmissiveColor(getColorHash(color, 255)); } else { _rendered->resetEmissiveColor(); } - if (_material->hasAppearanceProperty(QString::fromStdString("Shininess"))) { - double value = - _material->getAppearanceValue(QString::fromStdString("Shininess")).toDouble(); + if (_material->hasAppearanceProperty(QLatin1String("Shininess"))) { + double value = _material->getAppearanceValue(QLatin1String("Shininess")).toDouble(); _rendered->setShininess(value); } else { _rendered->resetShininess(); } - if (_material->hasAppearanceProperty(QString::fromStdString("Transparency"))) { - double value = - _material->getAppearanceValue(QString::fromStdString("Transparency")).toDouble(); + if (_material->hasAppearanceProperty(QLatin1String("Transparency"))) { + double value = _material->getAppearanceValue(QLatin1String("Transparency")).toDouble(); _rendered->setTransparency(value); } else { _rendered->resetTransparency(); } + + return true; +} + +void MaterialsEditor::updatePreview() const +{ + if (updateTexturePreview()) { + return; + } + updateMaterialPreview(); } QString MaterialsEditor::getColorHash(const QString& colorString, int colorRange) @@ -1108,12 +1174,12 @@ QString MaterialsEditor::libraryPath(const std::shared_ptr& QString path; auto library = material->getLibrary(); if (library) { - path = QString::fromStdString("/%1/%2") + path = QString::fromLatin1("/%1/%2") .arg(material->getLibrary()->getName()) .arg(material->getDirectory()); } else { - path = QString::fromStdString("%1").arg(material->getDirectory()); + path = QString::fromLatin1("%1").arg(material->getDirectory()); } return path; diff --git a/src/Mod/Material/Gui/MaterialsEditor.h b/src/Mod/Material/Gui/MaterialsEditor.h index f5311d58e0..9d27f86b9b 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.h +++ b/src/Mod/Material/Gui/MaterialsEditor.h @@ -152,6 +152,8 @@ private: void onInheritNew(bool checked); void setMaterialDefaults(); + bool updateTexturePreview() const; + bool updateMaterialPreview() const; void updatePreview() const; static QString getColorHash(const QString& colorString, int colorRange = 255); diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 9d0d6c1884..2b1db3466b 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -61,10 +61,10 @@ #include #endif -// // Inventor includes OpenGL -// #ifndef __InventorAll__ -// # include -// #endif +// Inventor includes OpenGL +#ifndef __InventorAll__ +# include +#endif #endif //_PreComp_ diff --git a/src/Mod/Material/Resources/Models/Rendering/TextureRendering.yml b/src/Mod/Material/Resources/Models/Rendering/TextureRendering.yml index 49fbec7a9d..0d581ebce0 100644 --- a/src/Mod/Material/Resources/Models/Rendering/TextureRendering.yml +++ b/src/Mod/Material/Resources/Models/Rendering/TextureRendering.yml @@ -35,8 +35,9 @@ AppearanceModel: Type: 'File' Units: '' URL: '' - Description: "Path to file containing a texture image. Only used if TextureImage is unpopulated" + Description: "Path to file containing a texture image. Only used if Texture Image is unpopulated" TextureImage: + DisplayName: "Texture Image" Type: 'Image' Units: '' URL: '' diff --git a/src/Mod/MeshPart/Gui/Tessellation.cpp b/src/Mod/MeshPart/Gui/Tessellation.cpp index 134ad2969e..edb02c878e 100644 --- a/src/Mod/MeshPart/Gui/Tessellation.cpp +++ b/src/Mod/MeshPart/Gui/Tessellation.cpp @@ -378,7 +378,7 @@ void Tessellation::setFaceColors(int method, App::Document* doc, App::DocumentOb auto svp = Base::freecad_dynamic_cast( Gui::Application::Instance->getViewProvider(obj)); if (vpmesh && svp) { - std::vector diff_col = svp->DiffuseColor.getValues(); + std::vector diff_col = svp->ShapeAppearance.getDiffuseColors(); if (ui->groupsFaceColors->isChecked()) { diff_col = getUniqueColors(diff_col); } diff --git a/src/Mod/Part/Gui/AppPartGui.cpp b/src/Mod/Part/Gui/AppPartGui.cpp index a1895fe0e9..519a449fc0 100644 --- a/src/Mod/Part/Gui/AppPartGui.cpp +++ b/src/Mod/Part/Gui/AppPartGui.cpp @@ -1,25 +1,25 @@ /*************************************************************************** -* Copyright (c) 2002 Juergen Riegel * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Lesser General Public License (LGPL) * -* as published by the Free Software Foundation; either version 2 of * -* the License, or (at your option) any later version. * -* for detail see the LICENCE text file. * -* * -* FreeCAD is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Lesser General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with FreeCAD; if not, write to the Free Software * -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -* USA * -* * -***************************************************************************/ + * Copyright (c) 2002 Juergen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License (LGPL) * + * as published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * for detail see the LICENCE text file. * + * * + * FreeCAD is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with FreeCAD; if not, write to the Free Software * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * USA * + * * + ***************************************************************************/ #include "PreCompiled.h" @@ -92,13 +92,15 @@ void loadPartResource() Gui::Translator::instance()->refresh(); } -namespace PartGui { -class Module : public Py::ExtensionModule +namespace PartGui +{ +class Module: public Py::ExtensionModule { public: - Module() : Py::ExtensionModule("PartGui") + Module() + : Py::ExtensionModule("PartGui") { - initialize("This module is the PartGui module."); // register with Python + initialize("This module is the PartGui module."); // register with Python } private: @@ -106,10 +108,11 @@ private: PyObject* initModule() { - return Base::Interpreter().addModule(new Module);; + return Base::Interpreter().addModule(new Module); + ; } -} // namespace PartGui +} // namespace PartGui PyMOD_INIT_FUNC(PartGui) { @@ -123,7 +126,7 @@ PyMOD_INIT_FUNC(PartGui) Base::Interpreter().runString("import Part"); Base::Interpreter().runString("import MatGui"); } - catch(const Base::Exception& e) { + catch (const Base::Exception& e) { PyErr_SetString(PyExc_ImportError, e.what()); PyMOD_Return(nullptr); } @@ -137,13 +140,15 @@ PyMOD_INIT_FUNC(PartGui) Gui::BitmapFactory().addPath(QString::fromLatin1(":/icons/parametric")); Gui::BitmapFactory().addPath(QString::fromLatin1(":/icons/tools")); - static struct PyModuleDef pAttachEngineTextsModuleDef = { - PyModuleDef_HEAD_INIT, - "AttachEngineResources", - "AttachEngineResources", -1, - AttacherGui::AttacherGuiPy::Methods, - nullptr, nullptr, nullptr, nullptr - }; + static struct PyModuleDef pAttachEngineTextsModuleDef = {PyModuleDef_HEAD_INIT, + "AttachEngineResources", + "AttachEngineResources", + -1, + AttacherGui::AttacherGuiPy::Methods, + nullptr, + nullptr, + nullptr, + nullptr}; PyObject* pAttachEngineTextsModule = PyModule_Create(&pAttachEngineTextsModuleDef); Py_INCREF(pAttachEngineTextsModule); @@ -220,23 +225,31 @@ PyMOD_INIT_FUNC(PartGui) CreateSimplePartCommands(); CreateParamPartCommands(); CreatePartSelectCommands(); - try{ - Py::Object ae = Base::Interpreter().runStringObject("__import__('AttachmentEditor.Commands').Commands"); - Py::Module(partGuiModule).setAttr(std::string("AttachmentEditor"),ae); - } catch (Base::PyException &err){ + try { + Py::Object ae = + Base::Interpreter().runStringObject("__import__('AttachmentEditor.Commands').Commands"); + Py::Module(partGuiModule).setAttr(std::string("AttachmentEditor"), ae); + } + catch (Base::PyException& err) { err.ReportException(); } // register preferences pages - Gui::Dialog::DlgPreferencesImp::setGroupData("Part/Part Design", "Part design", QObject::tr("Part and Part Design workbench")); - (void)new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); - (void)new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); - (void)new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); - (void)new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "Import-Export")); - (void)new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "Import-Export")); - Gui::ViewProviderBuilder::add( - Part::PropertyPartShape::getClassTypeId(), - PartGui::ViewProviderPart::getClassTypeId()); + Gui::Dialog::DlgPreferencesImp::setGroupData("Part/Part Design", + "Part design", + QObject::tr("Part and Part Design workbench")); + (void)new Gui::PrefPageProducer( + QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); + (void)new Gui::PrefPageProducer( + QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); + (void)new Gui::PrefPageProducer( + QT_TRANSLATE_NOOP("QObject", "Part/Part Design")); + (void)new Gui::PrefPageProducer( + QT_TRANSLATE_NOOP("QObject", "Import-Export")); + (void)new Gui::PrefPageProducer( + QT_TRANSLATE_NOOP("QObject", "Import-Export")); + Gui::ViewProviderBuilder::add(Part::PropertyPartShape::getClassTypeId(), + PartGui::ViewProviderPart::getClassTypeId()); // add resources and reloads the translators loadPartResource(); diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index 9b4e372468..a2899609a6 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -31,6 +31,8 @@ list(APPEND PartGui_LIBS ${QtConcurrent_LIBRARIES} ) +generate_from_xml(ViewProviderExtPy) + set (Part_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Resources/Part_translation.qrc) qt_find_and_add_translation(QM_SRCS "Resources/translations/*_*.ts" ${CMAKE_CURRENT_BINARY_DIR}/Resources/translations) @@ -61,7 +63,7 @@ set(PartGui_UIC_SRCS DlgProjectionOnSurface.ui SectionCutting.ui ShapeFromMesh.ui - TaskFaceColors.ui + TaskFaceAppearances.ui TaskShapeBuilder.ui TaskLoft.ui TaskOffset.ui @@ -69,9 +71,16 @@ set(PartGui_UIC_SRCS TaskAttacher.ui ) +SET(Python_SRCS + ViewProviderExtPy.xml + ViewProviderExtPyImp.cpp +) +SOURCE_GROUP("Python" FILES ${Python_SRCS}) + SET(PartGui_SRCS ${PartGui_QRC_SRCS} ${PartGui_UIC_HDRS} + ${Python_SRCS} AppPartGui.cpp AttacherTexts.h AttacherTexts.cpp @@ -224,9 +233,9 @@ SET(PartGui_SRCS SectionCutting.ui ShapeFromMesh.cpp ShapeFromMesh.h - TaskFaceColors.cpp - TaskFaceColors.h - TaskFaceColors.ui + TaskFaceAppearances.cpp + TaskFaceAppearances.h + TaskFaceAppearances.ui TaskShapeBuilder.cpp TaskShapeBuilder.h TaskShapeBuilder.ui diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 4290cf30c7..d8a44a2885 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -2112,7 +2112,7 @@ void CmdColorPerFace::activated(int iMsg) return; PartGui::ViewProviderPartExt* vp = dynamic_cast(Gui::Application::Instance->getViewProvider(sel.front())); if (vp) - vp->changeFaceColors(); + vp->changeFaceAppearances(); } bool CmdColorPerFace::isActive() diff --git a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp index 9f99c21468..8dd5b95069 100644 --- a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp +++ b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp @@ -720,34 +720,38 @@ void PartGui::DlgProjectionOnSurface::higlight_object(Part::Feature* iCurrentObj auto vp = dynamic_cast( Gui::Application::Instance->getViewProvider(iCurrentObject)); if (vp) { - std::vector colors; - App::Color defaultColor; + App::Color aColor; + aColor.setPackedValue(iColor); if (currentShapeType == TopAbs_FACE) { - colors = vp->DiffuseColor.getValues(); - defaultColor = vp->ShapeAppearance.getDiffuseColor(); + std::vector colors = vp->ShapeAppearance.getValues(); + App::Color defaultColor = vp->ShapeAppearance.getDiffuseColor(); + + if (static_cast(colors.size()) != anIndices.Extent()) { + colors.resize(anIndices.Extent(), vp->ShapeAppearance[0]); + } + + if (iHighlight) { + colors.at(index - 1).diffuseColor = aColor; + } + else { + colors.at(index - 1).diffuseColor = defaultColor; + } + vp->ShapeAppearance.setValues(colors); } else if (currentShapeType == TopAbs_EDGE) { - colors = vp->LineColorArray.getValues(); - defaultColor = vp->LineColor.getValue(); - } + std::vector colors = vp->LineColorArray.getValues(); + App::Color defaultColor = vp->LineColor.getValue(); - if (static_cast(colors.size()) != anIndices.Extent()) { - colors.resize(anIndices.Extent(), defaultColor); - } + if (static_cast(colors.size()) != anIndices.Extent()) { + colors.resize(anIndices.Extent(), defaultColor); + } - if (iHighlight) { - App::Color aColor; - aColor.setPackedValue(iColor); - colors.at(index - 1) = aColor; - } - else { - colors.at(index - 1) = defaultColor; - } - if (currentShapeType == TopAbs_FACE) { - vp->DiffuseColor.setValues(colors); - } - else if (currentShapeType == TopAbs_EDGE) { - vp->LineColorArray.setValues(colors); + if (iHighlight) { + colors.at(index - 1) = aColor; + } + else { + colors.at(index - 1) = defaultColor; + } } } } diff --git a/src/Mod/Part/Gui/ReferenceHighlighter.cpp b/src/Mod/Part/Gui/ReferenceHighlighter.cpp index a42d50bc7e..9d2692f9ce 100644 --- a/src/Mod/Part/Gui/ReferenceHighlighter.cpp +++ b/src/Mod/Part/Gui/ReferenceHighlighter.cpp @@ -210,6 +210,17 @@ void ReferenceHighlighter::getFaceColor(const std::string& element, std::vector< colors[pos] = elementColor; } +void ReferenceHighlighter::getFaceColor(const std::string& element, + std::vector& materials) const +{ + int idx = std::stoi(element.substr(4)) - 1; + assert(idx >= 0); + std::size_t pos = std::size_t(idx); + if (pos < materials.size()) { + materials[pos].diffuseColor = elementColor; + } +} + void ReferenceHighlighter::getFaceColors(const std::vector& elements, std::vector& colors) const { @@ -226,3 +237,24 @@ void ReferenceHighlighter::getFaceColors(const std::vector& element std::fill(colors.begin(), colors.end(), objectColor); } } + +void ReferenceHighlighter::getFaceMaterials(const std::vector& elements, + std::vector& materials) const +{ + App::Material defaultMaterial; + materials.resize(fMap.Extent(), defaultMaterial); + + if (!elements.empty()) { + for (const std::string& e : elements) { + if (boost::starts_with(e, "Face")) { + getFaceColor(e, materials); + } + } + } + else { + for (auto& material : materials) { + material.diffuseColor = objectColor; + } + // std::fill(materials.begin(), materials.end(), objectColor); + } +} diff --git a/src/Mod/Part/Gui/ReferenceHighlighter.h b/src/Mod/Part/Gui/ReferenceHighlighter.h index de501c032b..507e383776 100644 --- a/src/Mod/Part/Gui/ReferenceHighlighter.h +++ b/src/Mod/Part/Gui/ReferenceHighlighter.h @@ -79,6 +79,14 @@ public: */ void getFaceColors(const std::vector& elements, std::vector& colors) const; + /*! + * \brief getFaceMaterials + * \param elements The sub-element names. If this list is empty \a materials will be filled with + * the default color. \param materials The size of the \a materials array is equal to the number + * of faces of the shape + */ + void getFaceMaterials(const std::vector& elements, + std::vector& materials) const; private: void getVertexColor(const std::string& element, std::vector& colors) const; @@ -89,6 +97,7 @@ private: void getEdgeColorsOfWire(const std::string& element, std::vector& colors) const; void getEdgeColorsOfFace(const std::string& element, std::vector& colors) const; void getFaceColor(const std::string& element, std::vector& colors) const; + void getFaceColor(const std::string& element, std::vector& materials) const; private: App::Color defaultColor; diff --git a/src/Mod/Part/Gui/TaskFaceColors.cpp b/src/Mod/Part/Gui/TaskFaceAppearances.cpp similarity index 77% rename from src/Mod/Part/Gui/TaskFaceColors.cpp rename to src/Mod/Part/Gui/TaskFaceAppearances.cpp index 4ab51e6923..6361067533 100644 --- a/src/Mod/Part/Gui/TaskFaceColors.cpp +++ b/src/Mod/Part/Gui/TaskFaceAppearances.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -54,8 +55,10 @@ #include #include -#include "TaskFaceColors.h" -#include "ui_TaskFaceColors.h" +#include + +#include "TaskFaceAppearances.h" +#include "ui_TaskFaceAppearances.h" #include "SoBrepFaceSet.h" #include "ViewProviderExt.h" @@ -84,23 +87,23 @@ namespace PartGui { }; } -class FaceColors::Private +class FaceAppearances::Private { public: using Connection = boost::signals2::connection; - Ui_TaskFaceColors* ui; + Ui_TaskFaceAppearances* ui; QPointer view; ViewProviderPartExt* vp; App::DocumentObject* obj; Gui::Document* doc; - std::vector perface; + std::vector perface; QSet index; bool boxSelection; Connection connectDelDoc; Connection connectDelObj; Connection connectUndoDoc; - explicit Private(ViewProviderPartExt* vp) : ui(new Ui_TaskFaceColors()), view(nullptr), vp(vp) + explicit Private(ViewProviderPartExt* vp) : ui(new Ui_TaskFaceAppearances()), view(nullptr), vp(vp) { obj = vp->getObject(); doc = Gui::Application::Instance->getDocument(obj->getDocument()); @@ -113,9 +116,7 @@ public: xp.Next(); } - std::vector current = vp->DiffuseColor.getValues(); - if (current.empty()) - current.push_back(vp->ShapeAppearance.getDiffuseColor()); + std::vector current = vp->ShapeAppearance.getValues(); perface = current; perface.resize(mapOfShape.Extent(), perface.front()); @@ -220,7 +221,7 @@ public: polygon.Add(Base::Vector2d(it[0], it[1])); } - FaceColors* self = static_cast(ud); + FaceAppearances* self = static_cast(ud); self->d->view = nullptr; if (self->d->obj && self->d->obj->isDerivedFrom()) { cb->setHandled(); @@ -235,9 +236,9 @@ public: } }; -/* TRANSLATOR PartGui::TaskFaceColors */ +/* TRANSLATOR PartGui::TaskFaceAppearances */ -FaceColors::FaceColors(ViewProviderPartExt* vp, QWidget* parent) +FaceAppearances::FaceAppearances(ViewProviderPartExt* vp, QWidget* parent) : d(new Private(vp)) { Q_UNUSED(parent); @@ -245,23 +246,22 @@ FaceColors::FaceColors(ViewProviderPartExt* vp, QWidget* parent) setupConnections(); d->ui->groupBox->setTitle(QString::fromUtf8(vp->getObject()->Label.getValue())); - d->ui->colorButton->setDisabled(true); - d->ui->colorButton->setAllowTransparency(true); + d->ui->buttonCustomAppearance->setDisabled(true); FaceSelection* gate = new FaceSelection(d->vp->getObject()); Gui::Selection().addSelectionGate(gate); //NOLINTBEGIN d->connectDelDoc = Gui::Application::Instance->signalDeleteDocument.connect(std::bind - (&FaceColors::slotDeleteDocument, this, sp::_1)); + (&FaceAppearances::slotDeleteDocument, this, sp::_1)); d->connectDelObj = Gui::Application::Instance->signalDeletedObject.connect(std::bind - (&FaceColors::slotDeleteObject, this, sp::_1)); + (&FaceAppearances::slotDeleteObject, this, sp::_1)); d->connectUndoDoc = d->doc->signalUndoDocument.connect(std::bind - (&FaceColors::slotUndoDocument, this, sp::_1)); + (&FaceAppearances::slotUndoDocument, this, sp::_1)); //NOLINTEND } -FaceColors::~FaceColors() +FaceAppearances::~FaceAppearances() { if (d->view) { d->view->stopSelection(); @@ -276,17 +276,23 @@ FaceColors::~FaceColors() delete d; } -void FaceColors::setupConnections() +void FaceAppearances::setupConnections() { - connect(d->ui->colorButton, &Gui::ColorButton::changed, - this, &FaceColors::onColorButtonChanged); connect(d->ui->defaultButton, &QPushButton::clicked, - this, &FaceColors::onDefaultButtonClicked); + this, &FaceAppearances::onDefaultButtonClicked); connect(d->ui->boxSelection, &QPushButton::toggled, - this, &FaceColors::onBoxSelectionToggled); + this, &FaceAppearances::onBoxSelectionToggled); + connect(d->ui->widgetMaterial, + &MatGui::MaterialTreeWidget::materialSelected, + this, + &FaceAppearances::onMaterialSelected); + connect(d->ui->buttonCustomAppearance, + &QPushButton::clicked, + this, + &FaceAppearances::onButtonCustomAppearanceClicked); } -void FaceColors::slotUndoDocument(const Gui::Document& Doc) +void FaceAppearances::slotUndoDocument(const Gui::Document& Doc) { if (d->doc == &Doc) { d->doc->resetEdit(); @@ -294,19 +300,19 @@ void FaceColors::slotUndoDocument(const Gui::Document& Doc) } } -void FaceColors::slotDeleteDocument(const Gui::Document& Doc) +void FaceAppearances::slotDeleteDocument(const Gui::Document& Doc) { if (d->doc == &Doc) Gui::Control().closeDialog(); } -void FaceColors::slotDeleteObject(const Gui::ViewProvider& obj) +void FaceAppearances::slotDeleteObject(const Gui::ViewProvider& obj) { if (d->vp == &obj) Gui::Control().closeDialog(); } -void FaceColors::onBoxSelectionToggled(bool checked) +void FaceAppearances::onBoxSelectionToggled(bool checked) { Gui::View3DInventor* view = qobject_cast(Gui::getMainWindow()->activeWindow()); // toggle the button state and feature @@ -330,28 +336,26 @@ void FaceColors::onBoxSelectionToggled(bool checked) } } -void FaceColors::onDefaultButtonClicked() +void FaceAppearances::onDefaultButtonClicked() { - std::fill(d->perface.begin(), d->perface.end(), d->vp->ShapeAppearance.getDiffuseColor()); - d->vp->DiffuseColor.setValues(d->perface); + std::fill(d->perface.begin(), d->perface.end(), d->vp->ShapeAppearance[0]); + d->vp->ShapeAppearance.setValues(d->perface); } -void FaceColors::onColorButtonChanged() +void FaceAppearances::onMaterialSelected(const std::shared_ptr& material) { if (!d->index.isEmpty()) { - QColor color = d->ui->colorButton->color(); for (int it : d->index) { - // alpha of App::Color is contrary to the one of QColor - d->perface[it].set(color.redF(), color.greenF(), color.blueF(), (1.0 - color.alphaF())); + d->perface[it] = material->getMaterialAppearance(); } - d->vp->DiffuseColor.setValues(d->perface); + d->vp->ShapeAppearance.setValues(d->perface); // new color has been applied, unselect so that users can see this onSelectionChanged(Gui::SelectionChanges::ClrSelection); Gui::Selection().clearSelection(); } } -void FaceColors::onSelectionChanged(const Gui::SelectionChanges& msg) +void FaceAppearances::onSelectionChanged(const Gui::SelectionChanges& msg) { // no object selected in the combobox or no sub-element was selected if (!msg.pSubName) @@ -366,11 +370,10 @@ void FaceColors::onSelectionChanged(const Gui::SelectionChanges& msg) if (docname == msg.pDocName && objname == msg.pObjectName) { int index = std::atoi(msg.pSubName + 4) - 1; d->index.insert(index); - const App::Color& faceColor = d->perface[index]; + const App::Color& faceColor = d->perface[index].diffuseColor; QColor color; // alpha of App::Color is contrary to the one of QColor color.setRgbF(faceColor.r, faceColor.g, faceColor.b, (1.0 - faceColor.a)); - d->ui->colorButton->setColor(color); selection_changed = true; } } @@ -394,7 +397,7 @@ void FaceColors::onSelectionChanged(const Gui::SelectionChanges& msg) } } -void FaceColors::updatePanel() +void FaceAppearances::updatePanel() { QString faces = QString::fromLatin1("["); int size = d->index.size(); @@ -412,16 +415,39 @@ void FaceColors::updatePanel() } d->ui->labelElement->setText(faces); - d->ui->colorButton->setDisabled(d->index.isEmpty()); + d->ui->buttonCustomAppearance->setDisabled(d->index.isEmpty()); } -void FaceColors::open() +/** + * Opens a dialog that allows to modify the 'ShapeMaterial' property of all selected view providers. + */ +void FaceAppearances::onButtonCustomAppearanceClicked() +{ + std::vector Provider; + Provider.push_back(d->vp); + Gui::Dialog::DlgFaceMaterialPropertiesImp dlg("ShapeAppearance", this); + dlg.setViewProviders(Provider); + dlg.exec(); + + // Set the face appearance + if (!d->index.isEmpty()) { + for (int it : d->index) { + d->perface[it] = dlg.getCustomAppearance(); + } + d->vp->ShapeAppearance.setValues(d->perface); + // new color has been applied, unselect so that users can see this + onSelectionChanged(Gui::SelectionChanges::ClrSelection); + Gui::Selection().clearSelection(); + } +} + +void FaceAppearances::open() { Gui::Document* doc = Gui::Application::Instance->getDocument(d->vp->getObject()->getDocument()); doc->openCommand(QT_TRANSLATE_NOOP("Command", "Change face colors")); } -bool FaceColors::accept() +bool FaceAppearances::accept() { Gui::Document* doc = Gui::Application::Instance->getDocument(d->vp->getObject()->getDocument()); doc->commitCommand(); @@ -429,7 +455,7 @@ bool FaceColors::accept() return true; } -bool FaceColors::reject() +bool FaceAppearances::reject() { Gui::Document* doc = Gui::Application::Instance->getDocument(d->vp->getObject()->getDocument()); doc->abortCommand(); @@ -437,7 +463,7 @@ bool FaceColors::reject() return true; } -void FaceColors::changeEvent(QEvent* e) +void FaceAppearances::changeEvent(QEvent* e) { QWidget::changeEvent(e); if (e->type() == QEvent::LanguageChange) { @@ -446,33 +472,33 @@ void FaceColors::changeEvent(QEvent* e) } -/* TRANSLATOR PartGui::TaskFaceColors */ +/* TRANSLATOR PartGui::TaskFaceAppearances */ -TaskFaceColors::TaskFaceColors(ViewProviderPartExt* vp) +TaskFaceAppearances::TaskFaceAppearances(ViewProviderPartExt* vp) { - widget = new FaceColors(vp); + widget = new FaceAppearances(vp); addTaskBox(widget); } -TaskFaceColors::~TaskFaceColors() = default; +TaskFaceAppearances::~TaskFaceAppearances() = default; -void TaskFaceColors::open() +void TaskFaceAppearances::open() { widget->open(); } -void TaskFaceColors::clicked(int) +void TaskFaceAppearances::clicked(int) { } -bool TaskFaceColors::accept() +bool TaskFaceAppearances::accept() { return widget->accept(); } -bool TaskFaceColors::reject() +bool TaskFaceAppearances::reject() { return widget->reject(); } -#include "moc_TaskFaceColors.cpp" +#include "moc_TaskFaceAppearances.cpp" diff --git a/src/Mod/Part/Gui/TaskFaceColors.h b/src/Mod/Part/Gui/TaskFaceAppearances.h similarity index 81% rename from src/Mod/Part/Gui/TaskFaceColors.h rename to src/Mod/Part/Gui/TaskFaceAppearances.h index 929ab1fce3..c83a431c0e 100644 --- a/src/Mod/Part/Gui/TaskFaceColors.h +++ b/src/Mod/Part/Gui/TaskFaceAppearances.h @@ -31,17 +31,21 @@ namespace Gui { class ViewProvider; } +namespace Materials { + class Material; +} + namespace PartGui { class ViewProviderPartExt; -class FaceColors : public QWidget, public Gui::SelectionObserver +class FaceAppearances : public QWidget, public Gui::SelectionObserver { Q_OBJECT public: - explicit FaceColors(ViewProviderPartExt* vp, QWidget* parent = nullptr); - ~FaceColors() override; + explicit FaceAppearances(ViewProviderPartExt* vp, QWidget* parent = nullptr); + ~FaceAppearances() override; void open(); bool accept(); @@ -49,9 +53,10 @@ public: private: void setupConnections(); - void onColorButtonChanged(); + void onMaterialSelected(const std::shared_ptr& material); void onDefaultButtonClicked(); void onBoxSelectionToggled(bool checked); + void onButtonCustomAppearanceClicked(); protected: void onSelectionChanged(const Gui::SelectionChanges& msg) override; @@ -66,13 +71,13 @@ private: Private* d; }; -class TaskFaceColors : public Gui::TaskView::TaskDialog +class TaskFaceAppearances : public Gui::TaskView::TaskDialog { Q_OBJECT public: - explicit TaskFaceColors(ViewProviderPartExt* vp); - ~TaskFaceColors() override; + explicit TaskFaceAppearances(ViewProviderPartExt* vp); + ~TaskFaceAppearances() override; public: void open() override; @@ -84,7 +89,7 @@ public: { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } private: - FaceColors* widget; + FaceAppearances* widget; }; } //namespace PartGui diff --git a/src/Mod/Part/Gui/TaskFaceColors.ui b/src/Mod/Part/Gui/TaskFaceAppearances.ui similarity index 54% rename from src/Mod/Part/Gui/TaskFaceColors.ui rename to src/Mod/Part/Gui/TaskFaceAppearances.ui index dbe93fe3f7..08f64a1527 100644 --- a/src/Mod/Part/Gui/TaskFaceColors.ui +++ b/src/Mod/Part/Gui/TaskFaceAppearances.ui @@ -1,17 +1,17 @@ - PartGui::TaskFaceColors - + PartGui::TaskFaceAppearances + 0 0 247 - 143 + 219 - Set color per face + Set appearance per face @@ -26,57 +26,57 @@ Group box - - - - - - 0 - 0 - - - - Faces: - - + + + + + + + + 0 + 0 + + + + Faces: + + + + + + + [] + + + + - - - - [] - - + + + + + + - - - - - 146 - 0 - - - - - 160 - 16777215 - - - + + + + + + ... + + + + + + + Custom Appearance + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + @@ -136,9 +136,10 @@ by dragging a selection rectangle in the 3D view - Gui::ColorButton - QPushButton -
Gui/Widgets.h
+ MatGui::MaterialTreeWidget + QWidget +
Mod/Material/Gui/MaterialTreeWidget.h
+ 1
diff --git a/src/Mod/Part/Gui/ViewProvider.cpp b/src/Mod/Part/Gui/ViewProvider.cpp index 00c9082186..7f17c6ee22 100644 --- a/src/Mod/Part/Gui/ViewProvider.cpp +++ b/src/Mod/Part/Gui/ViewProvider.cpp @@ -71,6 +71,20 @@ void ViewProviderPart::applyColor(const Part::ShapeHistory& hist, } } +void ViewProviderPart::applyMaterial(const Part::ShapeHistory& hist, + const App::PropertyMaterialList& colBase, + std::vector& colBool) +{ + std::map>::const_iterator jt; + // apply color from modified faces + for (jt = hist.shapeMap.begin(); jt != hist.shapeMap.end(); ++jt) { + std::vector::const_iterator kt; + for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { + colBool[*kt] = colBase[jt->first]; + } + } +} + void ViewProviderPart::applyTransparency(const float& transparency, std::vector& colors) { @@ -85,6 +99,20 @@ void ViewProviderPart::applyTransparency(const float& transparency, } } +void ViewProviderPart::applyTransparency(const float& transparency, std::vector& colors) +{ + if (transparency != 0.0) { + // transparency has been set object-wide + std::vector::iterator j; + for (j = colors.begin(); j != colors.end(); ++j) { + // transparency hasn't been set for this face + if (j->transparency == 0.0) { + j->transparency = transparency / 100.0; // transparency comes in percent + } + } + } +} + // ---------------------------------------------------------------------------- void ViewProviderShapeBuilder::buildNodes(const App::Property* , std::vector& ) const diff --git a/src/Mod/Part/Gui/ViewProvider.h b/src/Mod/Part/Gui/ViewProvider.h index 6426c9ae16..dae2d2ef29 100644 --- a/src/Mod/Part/Gui/ViewProvider.h +++ b/src/Mod/Part/Gui/ViewProvider.h @@ -57,8 +57,13 @@ protected: void applyColor(const Part::ShapeHistory& hist, const std::vector& colBase, std::vector& colBool); + void applyMaterial(const Part::ShapeHistory& hist, + const App::PropertyMaterialList& colBase, + std::vector& colBool); void applyTransparency(const float& transparency, std::vector& colors); + void applyTransparency(const float& transparency, + std::vector& colors); }; } // namespace PartGui diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index faeb6b2eb8..df8ebf5383 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -100,27 +100,27 @@ void ViewProviderBoolean::updateData(const App::Property* prop) auto vpTool = dynamic_cast( Gui::Application::Instance->getViewProvider(objTool)); if (vpBase && vpTool) { - std::vector colBase = vpBase->DiffuseColor.getValues(); - std::vector colTool = vpTool->DiffuseColor.getValues(); - std::vector colBool; - colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor()); - applyTransparency(vpBase->Transparency.getValue(),colBase); - applyTransparency(vpTool->Transparency.getValue(),colTool); + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]); + vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue()); + vpTool->ShapeAppearance.setTransparency(vpTool->Transparency.getValue()); - if (static_cast(colBase.size()) == baseMap.Extent()) { - applyColor(hist[0], colBase, colBool); + if (static_cast(vpBase->ShapeAppearance.getSize()) == baseMap.Extent()) { + applyMaterial(hist[0], vpBase->ShapeAppearance, colBool); } - else if (!colBase.empty() && colBase[0] != this->ShapeAppearance.getDiffuseColor()) { - colBase.resize(baseMap.Extent(), colBase[0]); - applyColor(hist[0], colBase, colBool); + else if (vpBase->ShapeAppearance.getSize() > 0 + && vpBase->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpBase->ShapeAppearance.setSize(baseMap.Extent(), vpBase->ShapeAppearance[0]); + applyMaterial(hist[0], vpBase->ShapeAppearance, colBool); } - if (static_cast(colTool.size()) == toolMap.Extent()) { - applyColor(hist[1], colTool, colBool); + if (static_cast(vpTool->ShapeAppearance.getSize()) == toolMap.Extent()) { + applyMaterial(hist[1], vpTool->ShapeAppearance, colBool); } - else if (!colTool.empty() && colTool[0] != this->ShapeAppearance.getDiffuseColor()) { - colTool.resize(toolMap.Extent(), colTool[0]); - applyColor(hist[1], colTool, colBool); + else if (vpTool->ShapeAppearance.getSize() > 0 + && vpTool->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpTool->ShapeAppearance.setSize(toolMap.Extent(), vpTool->ShapeAppearance[0]); + applyMaterial(hist[1], vpTool->ShapeAppearance, colBool); } // If the view provider has set a transparency then override the values @@ -129,7 +129,7 @@ void ViewProviderBoolean::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), colBool); } - this->DiffuseColor.setValues(colBool); + this->ShapeAppearance.setValues(colBool); } } } @@ -186,8 +186,8 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop) TopTools_IndexedMapOfShape boolMap; TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); - std::vector colBool; - colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor()); + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]); int index=0; for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { @@ -201,14 +201,14 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop) auto vpBase = dynamic_cast(Gui::Application::Instance->getViewProvider(objBase)); if (vpBase) { - std::vector colBase = vpBase->DiffuseColor.getValues(); - applyTransparency(vpBase->Transparency.getValue(),colBase); - if (static_cast(colBase.size()) == baseMap.Extent()) { - applyColor(hist[index], colBase, colBool); + vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue()); + if (static_cast(vpBase->ShapeAppearance.getSize()) == baseMap.Extent()) { + applyMaterial(hist[index], vpBase->ShapeAppearance, colBool); } - else if (!colBase.empty() && colBase[0] != this->ShapeAppearance.getDiffuseColor()) { - colBase.resize(baseMap.Extent(), colBase[0]); - applyColor(hist[index], colBase, colBool); + else if (vpBase->ShapeAppearance.getSize() > 0 + && vpBase->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpBase->ShapeAppearance.setSize(baseMap.Extent(), vpBase->ShapeAppearance[0]); + applyMaterial(hist[index], vpBase->ShapeAppearance, colBool); } } } @@ -219,7 +219,7 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), colBool); } - this->DiffuseColor.setValues(colBool); + this->ShapeAppearance.setValues(colBool); } else if (prop->isDerivedFrom()) { std::vector pShapes = static_cast(prop)->getValues(); @@ -321,8 +321,8 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop) TopTools_IndexedMapOfShape boolMap; TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); - std::vector colBool; - colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor()); + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]); int index=0; for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { @@ -336,14 +336,14 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop) auto vpBase = dynamic_cast(Gui::Application::Instance->getViewProvider(objBase)); if (vpBase) { - std::vector colBase = vpBase->DiffuseColor.getValues(); - applyTransparency(vpBase->Transparency.getValue(),colBase); - if (static_cast(colBase.size()) == baseMap.Extent()) { - applyColor(hist[index], colBase, colBool); + vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue()); + if (static_cast(vpBase->ShapeAppearance.getSize()) == baseMap.Extent()) { + applyMaterial(hist[index], vpBase->ShapeAppearance, colBool); } - else if (!colBase.empty() && colBase[0] != this->ShapeAppearance.getDiffuseColor()) { - colBase.resize(baseMap.Extent(), colBase[0]); - applyColor(hist[index], colBase, colBool); + else if (vpBase->ShapeAppearance.getSize() > 0 + && vpBase->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpBase->ShapeAppearance.setSize(baseMap.Extent(), vpBase->ShapeAppearance[0]); + applyMaterial(hist[index], vpBase->ShapeAppearance, colBool); } } } @@ -354,7 +354,7 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), colBool); } - this->DiffuseColor.setValues(colBool); + this->ShapeAppearance.setValues(colBool); } else if (prop->isDerivedFrom()) { std::vector pShapes = static_cast(prop)->getValues(); diff --git a/src/Mod/Part/Gui/ViewProviderCompound.cpp b/src/Mod/Part/Gui/ViewProviderCompound.cpp index d0094e7ac0..9754362524 100644 --- a/src/Mod/Part/Gui/ViewProviderCompound.cpp +++ b/src/Mod/Part/Gui/ViewProviderCompound.cpp @@ -95,8 +95,8 @@ void ViewProviderCompound::updateData(const App::Property* prop) TopTools_IndexedMapOfShape compMap; TopExp::MapShapes(compShape, TopAbs_FACE, compMap); - std::vector compCol; - compCol.resize(compMap.Extent(), this->ShapeAppearance.getDiffuseColor()); + std::vector compCol; + compCol.resize(compMap.Extent(), this->ShapeAppearance[0]); int index=0; for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { @@ -111,14 +111,14 @@ void ViewProviderCompound::updateData(const App::Property* prop) auto vpBase = dynamic_cast(Gui::Application::Instance->getViewProvider(objBase)); if (vpBase) { - std::vector baseCol = vpBase->DiffuseColor.getValues(); - applyTransparency(vpBase->Transparency.getValue(),baseCol); - if (static_cast(baseCol.size()) == baseMap.Extent()) { - applyColor(hist[index], baseCol, compCol); + vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue()); + if (static_cast(vpBase->ShapeAppearance.getSize()) == baseMap.Extent()) { + applyMaterial(hist[index], vpBase->ShapeAppearance, compCol); } - else if (!baseCol.empty() && baseCol[0] != this->ShapeAppearance.getDiffuseColor()) { - baseCol.resize(baseMap.Extent(), baseCol[0]); - applyColor(hist[index], baseCol, compCol); + else if (vpBase->ShapeAppearance.getSize() > 0 + && vpBase->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpBase->ShapeAppearance.setSize(baseMap.Extent(), vpBase->ShapeAppearance[0]); + applyMaterial(hist[index], vpBase->ShapeAppearance, compCol); } } } @@ -129,7 +129,7 @@ void ViewProviderCompound::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), compCol); } - this->DiffuseColor.setValues(compCol); + this->ShapeAppearance.setValues(compCol); } else if (prop->isDerivedFrom()) { const std::vector& pBases = static_cast(prop)->getValues(); diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 36eb1d65e2..38140df7de 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -66,6 +66,7 @@ # include # include # include +# include # include #endif @@ -86,10 +87,11 @@ #include #include "ViewProviderExt.h" +#include "ViewProviderPartExtPy.h" #include "SoBrepEdgeSet.h" #include "SoBrepFaceSet.h" #include "SoBrepPointSet.h" -#include "TaskFaceColors.h" +#include "TaskFaceAppearances.h" FC_LOG_LEVEL_INIT("Part", true, true) @@ -100,12 +102,12 @@ using namespace PartGui; namespace { float fromPercent(long value) { - return static_cast(value) / 100.0F; + return std::roundf(value) / 100.0F; } long toPercent(float value) { - return static_cast(100.0 * value + 0.5); + return std::lround(100.0 * value); } } @@ -175,7 +177,6 @@ ViewProviderPartExt::ViewProviderPartExt() ADD_PROPERTY_TYPE(LineColor, (lmat.diffuseColor), osgroup, App::Prop_None, "Set object line color."); ADD_PROPERTY_TYPE(PointColor, (vmat.diffuseColor), osgroup, App::Prop_None, "Set object point color"); ADD_PROPERTY_TYPE(PointColorArray, (PointColor.getValue()), osgroup, App::Prop_None, "Object point color array."); - ADD_PROPERTY_TYPE(DiffuseColor,(ShapeAppearance.getDiffuseColors()), osgroup, App::Prop_None, "Object diffuse color."); ADD_PROPERTY_TYPE(LineColorArray,(LineColor.getValue()), osgroup, App::Prop_None, "Object line color array."); ADD_PROPERTY_TYPE(LineWidth,(lwidth), osgroup, App::Prop_None, "Set object line width."); LineWidth.setConstraints(&sizeRange); @@ -196,6 +197,16 @@ ViewProviderPartExt::ViewProviderPartExt() ADD_PROPERTY_TYPE(DrawStyle,((long int)0), osgroup, App::Prop_None, "Defines the style of the edges in the 3D view."); DrawStyle.setEnums(DrawStyleEnums); + // This is needed to restore old DiffuseColor values since the restore + // function is asynchronous + App::PropertyColor noColor; + ADD_PROPERTY_TYPE(_diffuseColor, + (noColor.getValue()), + osgroup, + App::Prop_NoPersist, + "Object diffuse color."); + _diffuseColor.setStatus(App::Property::PropHidden, true); + coords = new SoCoordinate3(); coords->ref(); faceset = new SoBrepFaceSet(); @@ -210,6 +221,14 @@ ViewProviderPartExt::ViewProviderPartExt() nodeset = new SoBrepPointSet(); nodeset->ref(); + // Support for textured faces + pcShapeTexture3D = new SoTexture3; + pcShapeTexture3D->ref(); + pcShapeCoordinates = new SoCoordinate3; + pcShapeCoordinates->ref(); + pcShapeFaceset = new SoIndexedFaceSet; + pcShapeFaceset->ref(); + pcFaceBind = new SoMaterialBinding(); pcFaceBind->ref(); @@ -261,6 +280,19 @@ ViewProviderPartExt::~ViewProviderPartExt() normb->unref(); lineset->unref(); nodeset->unref(); + + pcShapeTexture3D->unref(); + pcShapeCoordinates->unref(); + pcShapeFaceset->unref(); +} + +PyObject* ViewProviderPartExt::getPyObject() +{ + if (!pyViewObject) { + pyViewObject = new ViewProviderPartExtPy(this); + } + pyViewObject->IncRef(); + return pyViewObject; } void ViewProviderPartExt::onChanged(const App::Property* prop) @@ -328,29 +360,20 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) else if (prop == &LineColorArray) { setHighlightedEdges(LineColorArray.getValues()); } - else if (prop == &DiffuseColor) { - setHighlightedFaces(DiffuseColor.getValues()); + else if (prop == &_diffuseColor) { + // Used to load the old DiffuseColor values asynchronously + ShapeAppearance.setDiffuseColors(_diffuseColor.getValues()); + ShapeAppearance.setTransparency(Transparency.getValue() / 100.0f); } else if (prop == &ShapeAppearance) { - pcFaceBind->value = SoMaterialBinding::OVERALL; + setHighlightedFaces(ShapeAppearance); ViewProviderGeometryObject::onChanged(prop); - // While restoring a document do not override the - // DiffuseColor that has already been restored - if (!isRestoring()) { - App::Color c = ShapeAppearance.getDiffuseColor(); - c.a = fromPercent(Transparency.getValue()); - DiffuseColor.setValue(c); - } } else if (prop == &Transparency) { const App::Material& Mat = ShapeAppearance[0]; long value = toPercent(Mat.transparency); if (value != Transparency.getValue()) { float trans = fromPercent(Transparency.getValue()); - auto colors = DiffuseColor.getValues(); - for (auto &c : colors) - c.a = trans; - DiffuseColor.setValues(colors); App::PropertyContainer* parent = ShapeAppearance.getContainer(); ShapeAppearance.setContainer(nullptr); @@ -380,12 +403,12 @@ void ViewProviderPartExt::onChanged(const App::Property* prop) updateVisual(); // updateVisual() may not be triggered by any change (e.g. // triggered by an external object through forceUpdate()). And - // since DiffuseColor is not changed here either, do not falsely set + // since ShapeAppearance is not changed here either, do not falsely set // the document modified status Base::ObjectStatusLocker guard( - App::Property::NoModify, &DiffuseColor); + App::Property::NoModify, &ShapeAppearance); // The material has to be checked again (#0001736) - onChanged(&DiffuseColor); + onChanged(&ShapeAppearance); } } @@ -444,7 +467,10 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat) // just faces with no edges or points pcFlatRoot->addChild(pShapeHints); pcFlatRoot->addChild(pcFaceBind); - pcFlatRoot->addChild(pcShapeMaterial); + pcFlatRoot->addChild(pcSwitchAppearance); + pcTextureGroup3D->addChild(pcShapeTexture3D); + pcTextureGroup3D->addChild(pcShapeCoordinates); + pcTextureGroup3D->addChild(pcShapeFaceset); SoDrawStyle* pcFaceStyle = new SoDrawStyle(); pcFaceStyle->style = SoDrawStyle::FILLED; pcFlatRoot->addChild(pcFaceStyle); @@ -599,69 +625,89 @@ std::vector ViewProviderPartExt::getSelectionShape(const char* / return {}; } -void ViewProviderPartExt::setHighlightedFaces(const std::vector& colors) +void ViewProviderPartExt::setHighlightedFaces(const std::vector& materials) { - if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange)) - getObject()->touch(true); - - Gui::SoUpdateVBOAction action; - action.apply(this->faceset); - - int size = static_cast(colors.size()); - if (size > 1 && size == this->faceset->partIndex.getNum()) { - pcFaceBind->value = SoMaterialBinding::PER_PART; - pcShapeMaterial->diffuseColor.setNum(size); - pcShapeMaterial->transparency.setNum(size); - SbColor* ca = pcShapeMaterial->diffuseColor.startEditing(); - float *t = pcShapeMaterial->transparency.startEditing(); - for (int i = 0; i < size; i++) { - ca[i].setValue(colors[i].r, colors[i].g, colors[i].b); - t[i] = colors[i].a; - } - pcShapeMaterial->diffuseColor.finishEditing(); - pcShapeMaterial->transparency.finishEditing(); - } - else if (colors.size() == 1) { - pcFaceBind->value = SoMaterialBinding::OVERALL; - pcShapeMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b); - pcShapeMaterial->transparency = Transparency.getValue()/100.f; - } -} - -void ViewProviderPartExt::setHighlightedFaces(const std::vector& colors) -{ - int size = static_cast(colors.size()); + int size = static_cast(materials.size()); if (size > 1 && size == this->faceset->partIndex.getNum()) { pcFaceBind->value = SoMaterialBinding::PER_PART; + activateMaterial(); pcShapeMaterial->diffuseColor.setNum(size); pcShapeMaterial->ambientColor.setNum(size); pcShapeMaterial->specularColor.setNum(size); pcShapeMaterial->emissiveColor.setNum(size); + pcShapeMaterial->shininess.setNum(size); SbColor* dc = pcShapeMaterial->diffuseColor.startEditing(); SbColor* ac = pcShapeMaterial->ambientColor.startEditing(); SbColor* sc = pcShapeMaterial->specularColor.startEditing(); SbColor* ec = pcShapeMaterial->emissiveColor.startEditing(); + float* sh = pcShapeMaterial->shininess.startEditing(); for (int i = 0; i < size; i++) { - dc[i].setValue(colors[i].diffuseColor.r, colors[i].diffuseColor.g, colors[i].diffuseColor.b); - ac[i].setValue(colors[i].ambientColor.r, colors[i].ambientColor.g, colors[i].ambientColor.b); - sc[i].setValue(colors[i].specularColor.r, colors[i].specularColor.g, colors[i].specularColor.b); - ec[i].setValue(colors[i].emissiveColor.r, colors[i].emissiveColor.g, colors[i].emissiveColor.b); + dc[i].setValue(materials[i].diffuseColor.r, materials[i].diffuseColor.g, materials[i].diffuseColor.b); + ac[i].setValue(materials[i].ambientColor.r, materials[i].ambientColor.g, materials[i].ambientColor.b); + sc[i].setValue(materials[i].specularColor.r, materials[i].specularColor.g, materials[i].specularColor.b); + ec[i].setValue(materials[i].emissiveColor.r, materials[i].emissiveColor.g, materials[i].emissiveColor.b); + sh[i] = materials[i].shininess; } pcShapeMaterial->diffuseColor.finishEditing(); pcShapeMaterial->ambientColor.finishEditing(); pcShapeMaterial->specularColor.finishEditing(); pcShapeMaterial->emissiveColor.finishEditing(); + pcShapeMaterial->shininess.finishEditing(); } - else if (colors.size() == 1) { + else if (size == 1) { pcFaceBind->value = SoMaterialBinding::OVERALL; - pcShapeMaterial->diffuseColor.setValue(colors[0].diffuseColor.r, colors[0].diffuseColor.g, colors[0].diffuseColor.b); - pcShapeMaterial->ambientColor.setValue(colors[0].ambientColor.r, colors[0].ambientColor.g, colors[0].ambientColor.b); - pcShapeMaterial->specularColor.setValue(colors[0].specularColor.r, colors[0].specularColor.g, colors[0].specularColor.b); - pcShapeMaterial->emissiveColor.setValue(colors[0].emissiveColor.r, colors[0].emissiveColor.g, colors[0].emissiveColor.b); + setCoinAppearance(materials[0]); + } +} + +void ViewProviderPartExt::setHighlightedFaces(const App::PropertyMaterialList& appearance) +{ + int size = static_cast(appearance.getSize()); + if (size > 1 && size == this->faceset->partIndex.getNum()) { + pcFaceBind->value = SoMaterialBinding::PER_PART; + activateMaterial(); + + pcShapeMaterial->diffuseColor.setNum(size); + pcShapeMaterial->ambientColor.setNum(size); + pcShapeMaterial->specularColor.setNum(size); + pcShapeMaterial->emissiveColor.setNum(size); + pcShapeMaterial->shininess.setNum(size); + + SbColor* dc = pcShapeMaterial->diffuseColor.startEditing(); + SbColor* ac = pcShapeMaterial->ambientColor.startEditing(); + SbColor* sc = pcShapeMaterial->specularColor.startEditing(); + SbColor* ec = pcShapeMaterial->emissiveColor.startEditing(); + float* sh = pcShapeMaterial->shininess.startEditing(); + + for (int i = 0; i < size; i++) { + dc[i].setValue(appearance.getDiffuseColor(i).r, + appearance.getDiffuseColor(i).g, + appearance.getDiffuseColor(i).b); + ac[i].setValue(appearance.getAmbientColor(i).r, + appearance.getAmbientColor(i).g, + appearance.getAmbientColor(i).b); + sc[i].setValue(appearance.getSpecularColor(i).r, + appearance.getSpecularColor(i).g, + appearance.getSpecularColor(i).b); + ec[i].setValue(appearance.getEmissiveColor(i).r, + appearance.getEmissiveColor(i).g, + appearance.getEmissiveColor(i).b); + sh[i] = appearance.getShininess(i); + } + + pcShapeMaterial->diffuseColor.finishEditing(); + pcShapeMaterial->ambientColor.finishEditing(); + pcShapeMaterial->specularColor.finishEditing(); + pcShapeMaterial->emissiveColor.finishEditing(); + pcShapeMaterial->shininess.finishEditing(); + } + else if (size == 1) { + pcFaceBind->value = SoMaterialBinding::OVERALL; + setCoinAppearance(appearance[0]); } } @@ -678,18 +724,21 @@ std::map ViewProviderPartExt::getElementColors(const cha } if(boost::starts_with(element,"Face")) { - auto size = DiffuseColor.getSize(); + auto size = ShapeAppearance.getSize(); if(element[4]=='*') { auto color = ShapeAppearance.getDiffuseColor(); color.a = Transparency.getValue()/100.0f; bool singleColor = true; for(int i=0;i ViewProviderPartExt::getElementColors(const cha }else{ int idx = atoi(element+4); if(idx>0 && idx<=size) - ret[element] = DiffuseColor[idx-1]; + ret[element] = ShapeAppearance.getDiffuseColor(idx - 1); else ret[element] = ShapeAppearance.getDiffuseColor(); if(size==1) @@ -753,7 +802,8 @@ std::map ViewProviderPartExt::getElementColors(const cha void ViewProviderPartExt::unsetHighlightedFaces() { - DiffuseColor.touch(); + // DiffuseColor.touch(); + ShapeAppearance.touch(); Transparency.touch(); } @@ -875,7 +925,7 @@ void ViewProviderPartExt::finishRestoring() // and currently sets a single color. // In case DiffuseColor has defined multiple colors they will // be passed to the scene graph now. - DiffuseColor.touch(); + ShapeAppearance.touch(); Gui::ViewProviderGeometryObject::finishRestoring(); } @@ -883,11 +933,11 @@ void ViewProviderPartExt::setupContextMenu(QMenu* menu, QObject* receiver, const { QIcon iconObject = mergeGreyableOverlayIcons(Gui::BitmapFactory().pixmap("Part_ColorFace.svg")); Gui::ViewProviderGeometryObject::setupContextMenu(menu, receiver, member); - QAction* act = menu->addAction(iconObject, QObject::tr("Set colors..."), receiver, member); + QAction* act = menu->addAction(iconObject, QObject::tr("Set appearance per face..."), receiver, member); act->setData(QVariant((int)ViewProvider::Color)); } -bool ViewProviderPartExt::changeFaceColors() +bool ViewProviderPartExt::changeFaceAppearances() { Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); if (dlg) { @@ -896,7 +946,7 @@ bool ViewProviderPartExt::changeFaceColors() } Gui::Selection().clearSelection(); - Gui::Control().showDialog(new TaskFaceColors(this)); + Gui::Control().showDialog(new TaskFaceAppearances(this)); return true; } @@ -906,7 +956,7 @@ bool ViewProviderPartExt::setEdit(int ModNum) // When double-clicking on the item for this pad the // object unsets and sets its edit mode without closing // the task panel - return changeFaceColors(); + return changeFaceAppearances(); } else { return Gui::ViewProviderGeometryObject::setEdit(ModNum); @@ -1321,7 +1371,8 @@ void ViewProviderPartExt::updateVisual() VisualTouched = false; // The material has to be checked again - setHighlightedFaces(DiffuseColor.getValues()); + // setHighlightedFaces(DiffuseColor.getValues()); + setHighlightedFaces(ShapeAppearance); setHighlightedEdges(LineColorArray.getValues()); setHighlightedPoints(PointColorArray.getValue()); } @@ -1336,3 +1387,18 @@ void ViewProviderPartExt::forceUpdate(bool enable) { --forceUpdateCount; } + +void ViewProviderPartExt::handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) +{ + if (strcmp(PropName, "DiffuseColor") == 0 + && strcmp(TypeName, App::PropertyColorList::getClassTypeId().getName()) == 0) { + + // PropertyColorLists are loaded asynchronously as they're stored in separate files + _diffuseColor.Restore(reader); + } + else { + Gui::ViewProviderGeometryObject::handleChangedPropertyName(reader, TypeName, PropName); + } +} diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index 85ccf105ef..249cae1d2f 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -52,6 +52,7 @@ class SoNormal; class SoNormalBinding; class SoMaterialBinding; class SoIndexedLineSet; +class SoTexture3; namespace PartGui { @@ -85,8 +86,8 @@ public: App::PropertyColor LineColor; App::PropertyMaterial LineMaterial; App::PropertyColorList LineColorArray; - // Faces (Gui::ViewProviderGeometryObject::ShapeColor and Gui::ViewProviderGeometryObject::ShapeMaterial apply) - App::PropertyColorList DiffuseColor; + // Faces (Gui::ViewProviderGeometryObject::ShapeAppearance and Gui::ViewProviderGeometryObject::ShapeMaterial apply) + // App::PropertyColorList DiffuseColor; void attach(App::DocumentObject *) override; void setDisplayMode(const char* ModeName) override; @@ -95,7 +96,7 @@ public: /// Update the view representation void reload(); /// If no other task is pending it opens a dialog to allow to change face colors - bool changeFaceColors(); + bool changeFaceAppearances(); void updateData(const App::Property*) override; @@ -125,8 +126,8 @@ public: * This group of methods do the highlighting of elements. */ //@{ - void setHighlightedFaces(const std::vector& colors); - void setHighlightedFaces(const std::vector& colors); + void setHighlightedFaces(const std::vector& materials); + void setHighlightedFaces(const App::PropertyMaterialList& appearance); void unsetHighlightedFaces(); void setHighlightedEdges(const std::vector& colors); void unsetHighlightedEdges(); @@ -151,6 +152,9 @@ public: //@{ void setupContextMenu(QMenu*, QObject*, const char*) override; + /// Get the python wrapper for that ViewProvider + PyObject* getPyObject() override; + protected: bool setEdit(int ModNum) override; void unsetEdit(int ModNum) override; @@ -161,6 +165,9 @@ protected: void onChanged(const App::Property* prop) override; bool loadParameter(); void updateVisual(); + void handleChangedPropertyName(Base::XMLReader& reader, + const char* TypeName, + const char* PropName) override; // nodes for the data representation SoMaterialBinding * pcFaceBind; @@ -179,6 +186,11 @@ protected: SoBrepEdgeSet * lineset; SoBrepPointSet * nodeset; + // Used to support per face textures + SoTexture3 * pcShapeTexture3D; + SoCoordinate3 * pcShapeCoordinates; + SoIndexedFaceSet * pcShapeFaceset; + bool VisualTouched; bool NormalsFromUV; @@ -190,6 +202,10 @@ private: static App::PropertyQuantityConstraint::Constraints angDeflectionRange; static const char* LightingEnums[]; static const char* DrawStyleEnums[]; + + // This is needed to restore old DiffuseColor values since the restore + // function is asynchronous + App::PropertyColorList _diffuseColor; }; } diff --git a/src/Mod/Part/Gui/ViewProviderExtPy.xml b/src/Mod/Part/Gui/ViewProviderExtPy.xml new file mode 100644 index 0000000000..76b9602ab4 --- /dev/null +++ b/src/Mod/Part/Gui/ViewProviderExtPy.xml @@ -0,0 +1,17 @@ + + + + + + This is the ViewProvider geometry class + + + diff --git a/src/Mod/Part/Gui/ViewProviderExtPyImp.cpp b/src/Mod/Part/Gui/ViewProviderExtPyImp.cpp new file mode 100644 index 0000000000..c25b83a270 --- /dev/null +++ b/src/Mod/Part/Gui/ViewProviderExtPyImp.cpp @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#include +#endif + +#include +#include + +#include "ViewProviderExt.h" +#include "ViewProviderPartExtPy.h" + +#include "ViewProviderPartExtPy.cpp" + + +using namespace PartGui; + +// returns a string which represents the object e.g. when printed in python +std::string ViewProviderPartExtPy::representation() const +{ + std::stringstream str; + str << ""; + + return str.str(); +} + +PyObject* ViewProviderPartExtPy::getCustomAttributes(const char* attr) const +{ + ViewProviderPartExt* vp = getViewProviderPartExtPtr(); + if (strcmp(attr, "DiffuseColor") == 0) { + // Get the color properties + App::PropertyColorList prop; + prop.setValues(vp->ShapeAppearance.getDiffuseColors()); + return prop.getPyObject(); + } + return nullptr; +} + +int ViewProviderPartExtPy::setCustomAttributes(const char* attr, PyObject* obj) +{ + ViewProviderPartExt* vp = getViewProviderPartExtPtr(); + if (strcmp(attr, "DiffuseColor") == 0) { + // Set the color properties + App::PropertyColorList prop; + prop.setPyObject(obj); + vp->ShapeAppearance.setDiffuseColors(prop.getValues()); + return 1; + } + return 0; +} diff --git a/src/Mod/Part/Gui/ViewProviderMirror.cpp b/src/Mod/Part/Gui/ViewProviderMirror.cpp index eec50b2641..df93218245 100644 --- a/src/Mod/Part/Gui/ViewProviderMirror.cpp +++ b/src/Mod/Part/Gui/ViewProviderMirror.cpp @@ -263,17 +263,18 @@ void ViewProviderFillet::updateData(const App::Property* prop) auto vpBase = dynamic_cast(Gui::Application::Instance->getViewProvider(objBase)); if (vpBase) { - std::vector colBase = vpBase->DiffuseColor.getValues(); - std::vector colFill; - colFill.resize(fillMap.Extent(), vpBase->ShapeAppearance.getDiffuseColor()); - applyTransparency(vpBase->Transparency.getValue(),colBase); + // std::vector colBase = vpBase->DiffuseColor.getValues(); + std::vector colFill; + colFill.resize(fillMap.Extent(), vpBase->ShapeAppearance[0]); + vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue()); - if (static_cast(colBase.size()) == baseMap.Extent()) { - applyColor(hist[0], colBase, colFill); + if (static_cast(vpBase->ShapeAppearance.getSize()) == baseMap.Extent()) { + applyMaterial(hist[0], vpBase->ShapeAppearance, colFill); } - else if (!colBase.empty() && colBase[0] != this->ShapeAppearance.getDiffuseColor()) { - colBase.resize(baseMap.Extent(), colBase[0]); - applyColor(hist[0], colBase, colFill); + else if (vpBase->ShapeAppearance.getSize() > 0 + && vpBase->ShapeAppearance[0] != this->ShapeAppearance[0]) { + vpBase->ShapeAppearance.setSize(baseMap.Extent(), vpBase->ShapeAppearance[0]); + applyMaterial(hist[0], vpBase->ShapeAppearance, colFill); } // If the view provider has set a transparency then override the values @@ -282,7 +283,7 @@ void ViewProviderFillet::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), colFill); } - this->DiffuseColor.setValues(colFill); + this->ShapeAppearance.setValues(colFill); } } } @@ -373,17 +374,18 @@ void ViewProviderChamfer::updateData(const App::Property* prop) auto vpBase = dynamic_cast(Gui::Application::Instance->getViewProvider(objBase)); if (vpBase) { - std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); - std::vector colCham; - colCham.resize(chamMap.Extent(), static_cast(vpBase)->ShapeAppearance.getDiffuseColor()); - applyTransparency(static_cast(vpBase)->Transparency.getValue(),colBase); + // std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + auto& colBase = static_cast(vpBase)->ShapeAppearance; + std::vector colCham; + colCham.resize(chamMap.Extent(), colBase[0]); + colBase.setTransparency(static_cast(vpBase)->Transparency.getValue()); - if (static_cast(colBase.size()) == baseMap.Extent()) { - applyColor(hist[0], colBase, colCham); + if (static_cast(colBase.getSize()) == baseMap.Extent()) { + applyMaterial(hist[0], colBase, colCham); } - else if (!colBase.empty() && colBase[0] != this->ShapeAppearance.getDiffuseColor()) { - colBase.resize(baseMap.Extent(), colBase[0]); - applyColor(hist[0], colBase, colCham); + else if (colBase.getSize() > 0 && colBase[0] != this->ShapeAppearance[0]) { + colBase.setSize(baseMap.Extent(), colBase[0]); + applyMaterial(hist[0], colBase, colCham); } // If the view provider has set a transparency then override the values @@ -392,7 +394,7 @@ void ViewProviderChamfer::updateData(const App::Property* prop) applyTransparency(Transparency.getValue(), colCham); } - this->DiffuseColor.setValues(colCham); + this->ShapeAppearance.setValues(colCham); } } } diff --git a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp index 68f47a28f5..13c469a898 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp @@ -255,11 +255,11 @@ void ViewProviderBody::updateData(const App::Property* prop) } void ViewProviderBody::copyColorsfromTip(App::DocumentObject* tip) { - // update DiffuseColor + // update ShapeAppearance Gui::ViewProvider* vptip = Gui::Application::Instance->getViewProvider(tip); if (vptip && vptip->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) { - auto colors = static_cast(vptip)->DiffuseColor.getValues(); - this->DiffuseColor.setValues(colors); + auto materials = static_cast(vptip)->ShapeAppearance.getValues(); + this->ShapeAppearance.setValues(materials); } } @@ -426,7 +426,6 @@ void ViewProviderBody::unifyVisualProperty(const App::Property* prop) { if (prop == &Visibility || prop == &Selectable || prop == &DisplayModeBody || - prop == &DiffuseColor || prop == &PointColorArray || prop == &LineColorArray) { return; diff --git a/src/Mod/PartDesign/Gui/ViewProviderDressUp.cpp b/src/Mod/PartDesign/Gui/ViewProviderDressUp.cpp index 4f1aa54ef4..19b9b757bc 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDressUp.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDressUp.cpp @@ -100,13 +100,13 @@ void ViewProviderDressUp::highlightReferences(const bool on) std::vector edges = pcDressUp->Base.getSubValuesStartsWith("Edge"); if (on) { - if (!faces.empty() && originalFaceColors.empty()) { - originalFaceColors = vp->DiffuseColor.getValues(); - std::vector colors = originalFaceColors; + if (!faces.empty() && originalFaceMaterials.empty()) { + originalFaceMaterials = vp->ShapeAppearance.getValues(); + std::vector materials = originalFaceMaterials; PartGui::ReferenceHighlighter highlighter(base->Shape.getValue(), ShapeAppearance.getDiffuseColor()); - highlighter.getFaceColors(faces, colors); - vp->DiffuseColor.setValues(colors); + highlighter.getFaceMaterials(faces, materials); + vp->ShapeAppearance.setValues(materials); } if (!edges.empty() && originalLineColors.empty()) { originalLineColors = vp->LineColorArray.getValues(); @@ -117,9 +117,9 @@ void ViewProviderDressUp::highlightReferences(const bool on) vp->LineColorArray.setValues(colors); } } else { - if (!faces.empty() && !originalFaceColors.empty()) { - vp->DiffuseColor.setValues(originalFaceColors); - originalFaceColors.clear(); + if (!faces.empty() && !originalFaceMaterials.empty()) { + vp->ShapeAppearance.setValues(originalFaceMaterials); + originalFaceMaterials.clear(); } if (!edges.empty() && !originalLineColors.empty()) { vp->LineColorArray.setValues(originalLineColors); diff --git a/src/Mod/PartDesign/Gui/ViewProviderDressUp.h b/src/Mod/PartDesign/Gui/ViewProviderDressUp.h index d04adae269..3c5ff435c9 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDressUp.h +++ b/src/Mod/PartDesign/Gui/ViewProviderDressUp.h @@ -60,7 +60,7 @@ protected: bool setEdit(int ModNum) override; private: - std::vector originalFaceColors; + std::vector originalFaceMaterials; std::vector originalLineColors; }; diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp index 8c4da52827..5743261360 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp @@ -161,9 +161,9 @@ void ViewProviderShapeBinder::highlightReferences(bool on) lcolors.resize(eMap.Extent(), svp->LineColor.getValue()); TopExp::MapShapes(static_cast(obj)->Shape.getValue(), TopAbs_FACE, eMap); - originalFaceColors = svp->DiffuseColor.getValues(); - std::vector fcolors = originalFaceColors; - fcolors.resize(eMap.Extent(), svp->ShapeAppearance.getDiffuseColor()); + originalFaceAppearance = svp->ShapeAppearance.getValues(); + std::vector fcolors = originalFaceAppearance; + fcolors.resize(eMap.Extent(), svp->ShapeAppearance[0]); for (const std::string& e : subs) { // Note: stoi may throw, but it strictly shouldn't happen @@ -177,11 +177,11 @@ void ViewProviderShapeBinder::highlightReferences(bool on) int idx = std::stoi(e.substr(4)) - 1; assert(idx >= 0); if (idx < static_cast(fcolors.size())) - fcolors[idx] = App::Color(1.0, 0.0, 1.0); // magenta + fcolors[idx].diffuseColor = App::Color(1.0, 0.0, 1.0); // magenta } } svp->LineColorArray.setValues(lcolors); - svp->DiffuseColor.setValues(fcolors); + svp->ShapeAppearance.setValues(fcolors); } } else { @@ -189,8 +189,8 @@ void ViewProviderShapeBinder::highlightReferences(bool on) svp->LineColorArray.setValues(originalLineColors); originalLineColors.clear(); - svp->DiffuseColor.setValues(originalFaceColors); - originalFaceColors.clear(); + svp->ShapeAppearance.setValues(originalFaceAppearance); + originalFaceAppearance.clear(); } } } diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h index 3037b3e862..9a1836afe4 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.h @@ -48,7 +48,7 @@ protected: private: std::vector originalLineColors; - std::vector originalFaceColors; + std::vector originalFaceAppearance; }; diff --git a/src/Mod/Surface/Gui/TaskFilling.cpp b/src/Mod/Surface/Gui/TaskFilling.cpp index e11b52db56..03ca409b83 100644 --- a/src/Mod/Surface/Gui/TaskFilling.cpp +++ b/src/Mod/Surface/Gui/TaskFilling.cpp @@ -161,22 +161,23 @@ void ViewProviderFilling::highlightReferences(ShapeType type, const References& break; case ViewProviderFilling::Face: if (on) { - std::vector colors; + std::vector materials; TopTools_IndexedMapOfShape fMap; TopExp::MapShapes(base->Shape.getValue(), TopAbs_FACE, fMap); - colors.resize(fMap.Extent(), svp->ShapeAppearance.getDiffuseColor()); + materials.resize(fMap.Extent(), svp->ShapeAppearance[0]); for (const auto& jt : it.second) { std::size_t idx = static_cast(std::stoi(jt.substr(4)) - 1); // check again that the index is in range because it's possible that // the sub-names are invalid - if (idx < colors.size()) { - colors[idx] = App::Color(1.0, 0.0, 1.0); // magenta + if (idx < materials.size()) { + materials[idx].diffuseColor = + App::Color(1.0, 0.0, 1.0); // magenta } } - svp->setHighlightedFaces(colors); + svp->setHighlightedFaces(materials); } else { svp->unsetHighlightedFaces(); diff --git a/src/Mod/Surface/Gui/TaskSections.cpp b/src/Mod/Surface/Gui/TaskSections.cpp index e1e93be19e..d7ee73aa54 100644 --- a/src/Mod/Surface/Gui/TaskSections.cpp +++ b/src/Mod/Surface/Gui/TaskSections.cpp @@ -161,22 +161,23 @@ void ViewProviderSections::highlightReferences(ShapeType type, const References& break; case ViewProviderSections::Face: if (on) { - std::vector colors; + std::vector materials; TopTools_IndexedMapOfShape fMap; TopExp::MapShapes(base->Shape.getValue(), TopAbs_FACE, fMap); - colors.resize(fMap.Extent(), svp->ShapeAppearance.getDiffuseColor()); + materials.resize(fMap.Extent(), svp->ShapeAppearance[0]); for (const auto& jt : it.second) { std::size_t idx = static_cast(std::stoi(jt.substr(4)) - 1); // check again that the index is in range because it's possible that // the sub-names are invalid - if (idx < colors.size()) { - colors[idx] = App::Color(1.0, 0.0, 1.0); // magenta + if (idx < materials.size()) { + materials[idx].diffuseColor = + App::Color(1.0, 0.0, 1.0); // magenta } } - svp->setHighlightedFaces(colors); + svp->setHighlightedFaces(materials); } else { svp->unsetHighlightedFaces();