Material: Appearance Updates 2

Improves the use of the ShapeAppearance property for the Part workbench.

    removes DiffuseColor property
        adds Python compatibility using custom attributes
        transitions DiffuseColor to ShapeAppearance on open
    Improved UI elements for setting object appearance, and appearance per face
    Lays the foundation for future texture support
This commit is contained in:
David Carter
2024-06-01 18:26:38 -04:00
committed by Chris Hennes
parent c4d0f3ed97
commit 5feb963f9d
55 changed files with 1540 additions and 714 deletions

View File

@@ -25,10 +25,26 @@
#ifndef _PreComp_
#include <cstring>
#include <random>
#endif
#include "Application.h"
#include "Material.h"
// Helper functions to consistently convert between float and long
namespace
{
float fromPercent(long value)
{
return std::roundf(value) / 100.0F;
}
long toPercent(float value)
{
return std::lround(100.0 * value);
}
} // namespace
using namespace App;
@@ -317,4 +333,47 @@ void Material::setType(MaterialType MatType)
break;
}
}
App::Material Material::getDefaultAppearance()
{
ParameterGrp::handle hGrp =
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
auto getColor = [hGrp](const char* parameter, App::Color& color) {
uint32_t packed = color.getPackedRGB();
packed = hGrp->GetUnsigned(parameter, packed);
color.setPackedRGB(packed);
};
auto intRandom = [](int min, int max) -> int {
static std::mt19937 generator;
std::uniform_int_distribution<int> distribution(min, max);
return distribution(generator);
};
App::Material mat(App::Material::DEFAULT);
mat.transparency = fromPercent(hGrp->GetInt("DefaultShapeTransparency", 0));
long shininess = toPercent(mat.shininess);
mat.shininess = fromPercent(hGrp->GetInt("DefaultShapeShininess", shininess));
// This is handled in the material code when using the object appearance
bool randomColor = hGrp->GetBool("RandomColor", false);
// diffuse color
if (randomColor) {
float red = static_cast<float>(intRandom(0, 255)) / 255.0F;
float green = static_cast<float>(intRandom(0, 255)) / 255.0F;
float blue = static_cast<float>(intRandom(0, 255)) / 255.0F;
mat.diffuseColor = App::Color(red, green, blue);
}
else {
// Color = (204, 204, 230) = 3435980543UL
getColor("DefaultShapeColor", mat.diffuseColor);
}
getColor("DefaultAmbientColor", mat.ambientColor);
getColor("DefaultEmissiveColor", mat.emissiveColor);
getColor("DefaultSpecularColor", mat.specularColor);
return mat;
}
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)

View File

@@ -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;
};

View File

@@ -2579,6 +2579,8 @@ void PropertyMaterial::Save(Base::Writer& writer) const
<< "\" emissiveColor=\"" << _cMat.emissiveColor.getPackedValue()
<< "\" shininess=\"" << _cMat.shininess
<< "\" transparency=\"" << _cMat.transparency
<< "\" image=\"" << _cMat.image
<< "\" imagePath=\"" << _cMat.imagePath
<< "\" uuid=\"" << _cMat.uuid
<< "\"/>" << std::endl;
// clang-format on
@@ -2596,6 +2598,12 @@ void PropertyMaterial::Restore(Base::XMLReader& reader)
_cMat.emissiveColor.setPackedValue(reader.getAttributeAsUnsigned("emissiveColor"));
_cMat.shininess = (float)reader.getAttributeAsFloat("shininess");
_cMat.transparency = (float)reader.getAttributeAsFloat("transparency");
if (reader.hasAttribute("image")) {
_cMat.image = reader.getAttribute("image");
}
if (reader.hasAttribute("imagePath")) {
_cMat.imagePath = reader.getAttribute("imagePath");
}
if (reader.hasAttribute("uuid")) {
_cMat.uuid = reader.getAttribute("uuid");
}
@@ -2635,7 +2643,7 @@ TYPESYSTEM_SOURCE(App::PropertyMaterialList, App::PropertyLists)
PropertyMaterialList::PropertyMaterialList()
{
setSizeOne();
setMinimumSizeOne();
}
PropertyMaterialList::~PropertyMaterialList() = default;
@@ -2662,7 +2670,7 @@ void PropertyMaterialList::verifyIndex(int index) const
}
}
void PropertyMaterialList::setSizeOne()
void PropertyMaterialList::setMinimumSizeOne()
{
int size = getSize();
if (size < 1) {
@@ -2690,7 +2698,7 @@ void PropertyMaterialList::setValue()
void PropertyMaterialList::setValue(const Material& mat)
{
aboutToSetValue();
setSizeOne();
setSize(1);
for (auto& material : _lValueList) {
material = mat;
}
@@ -2710,7 +2718,7 @@ void PropertyMaterialList::setValue(int index, const Material& mat)
void PropertyMaterialList::setAmbientColor(const Color& col)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.ambientColor = col;
}
@@ -2720,7 +2728,7 @@ void PropertyMaterialList::setAmbientColor(const Color& col)
void PropertyMaterialList::setAmbientColor(float r, float g, float b, float a)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.ambientColor.set(r, g, b, a);
}
@@ -2730,7 +2738,7 @@ void PropertyMaterialList::setAmbientColor(float r, float g, float b, float a)
void PropertyMaterialList::setAmbientColor(uint32_t rgba)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.ambientColor.setPackedValue(rgba);
}
@@ -2770,7 +2778,7 @@ void PropertyMaterialList::setAmbientColor(int index, uint32_t rgba)
void PropertyMaterialList::setDiffuseColor(const Color& col)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.diffuseColor = col;
}
@@ -2780,7 +2788,7 @@ void PropertyMaterialList::setDiffuseColor(const Color& col)
void PropertyMaterialList::setDiffuseColor(float r, float g, float b, float a)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.diffuseColor.set(r, g, b, a);
}
@@ -2790,7 +2798,7 @@ void PropertyMaterialList::setDiffuseColor(float r, float g, float b, float a)
void PropertyMaterialList::setDiffuseColor(uint32_t rgba)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.diffuseColor.setPackedValue(rgba);
}
@@ -2827,10 +2835,21 @@ void PropertyMaterialList::setDiffuseColor(int index, uint32_t rgba)
hasSetValue();
}
void PropertyMaterialList::setDiffuseColors(const std::vector<App::Color>& colors)
{
aboutToSetValue();
setSize(colors.size(), _lValueList[0]);
for (int i = 0; i < colors.size(); i++) {
_lValueList[i].diffuseColor = colors[i];
}
hasSetValue();
}
void PropertyMaterialList::setSpecularColor(const Color& col)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.specularColor = col;
}
@@ -2840,7 +2859,7 @@ void PropertyMaterialList::setSpecularColor(const Color& col)
void PropertyMaterialList::setSpecularColor(float r, float g, float b, float a)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.specularColor.set(r, g, b, a);
}
@@ -2850,7 +2869,7 @@ void PropertyMaterialList::setSpecularColor(float r, float g, float b, float a)
void PropertyMaterialList::setSpecularColor(uint32_t rgba)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.specularColor.setPackedValue(rgba);
}
@@ -2890,7 +2909,7 @@ void PropertyMaterialList::setSpecularColor(int index, uint32_t rgba)
void PropertyMaterialList::setEmissiveColor(const Color& col)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.emissiveColor = col;
}
@@ -2900,7 +2919,7 @@ void PropertyMaterialList::setEmissiveColor(const Color& col)
void PropertyMaterialList::setEmissiveColor(float r, float g, float b, float a)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.emissiveColor.set(r, g, b, a);
}
@@ -2910,7 +2929,7 @@ void PropertyMaterialList::setEmissiveColor(float r, float g, float b, float a)
void PropertyMaterialList::setEmissiveColor(uint32_t rgba)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.emissiveColor.setPackedValue(rgba);
}
@@ -2950,7 +2969,7 @@ void PropertyMaterialList::setEmissiveColor(int index, uint32_t rgba)
void PropertyMaterialList::setShininess(float val)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.shininess = val;
}
@@ -2970,7 +2989,7 @@ void PropertyMaterialList::setShininess(int index, float val)
void PropertyMaterialList::setTransparency(float val)
{
aboutToSetValue();
setSizeOne();
setMinimumSizeOne();
for (auto& material : _lValueList) {
material.transparency = val;
}
@@ -3039,12 +3058,12 @@ const Color& PropertyMaterialList::getEmissiveColor(int index) const
float PropertyMaterialList::getShininess() const
{
return _lValueList[0].transparency;
return _lValueList[0].shininess;
}
float PropertyMaterialList::getShininess(int index) const
{
return _lValueList[index].transparency;
return _lValueList[index].shininess;
}
float PropertyMaterialList::getTransparency() const
@@ -3074,7 +3093,7 @@ void PropertyMaterialList::Save(Base::Writer& writer) const
if (!writer.isForceXML()) {
writer.Stream() << writer.ind() << "<MaterialList file=\""
<< (getSize() ? writer.addFile(getName(), this) : "") << "\""
<< " version=\"2\"/>"
<< " version=\"3\"/>"
<< std::endl;
}
}
@@ -3107,8 +3126,21 @@ void PropertyMaterialList::SaveDocFile(Base::Writer& writer) const
str << it.emissiveColor.getPackedValue();
str << it.shininess;
str << it.transparency;
// str << it.uuid.c_str();
}
// Apply the latest changes last for backwards compatibility
for (const auto& it : _lValueList) {
writeString(str, it.image);
writeString(str, it.imagePath);
writeString(str, it.uuid);
}
}
void PropertyMaterialList::writeString(Base::OutputStream& str, const std::string &value) const
{
uint32_t uCt = (uint32_t)value.size();
str << uCt;
str.write(value.c_str(), uCt);
}
void PropertyMaterialList::RestoreDocFile(Base::Reader& reader)
@@ -3120,11 +3152,20 @@ void PropertyMaterialList::RestoreDocFile(Base::Reader& reader)
str >> count;
RestoreDocFileV0(count, reader);
}
else if (formatVersion == Version_3) {
// Default to the latest
RestoreDocFileV3(reader);
}
else {
int32_t version;
str >> version;
if (version < 0) {
RestoreDocFileV1(reader);
// This was a failed attempt at versioning, but is included
// to support files created during development. In can be removed
// in a future release once dev files are migrated.
uint32_t count = 0;
str >> count;
RestoreDocFileV0(count, reader);
}
else {
uint32_t uCt = static_cast<uint32_t>(version);
@@ -3156,14 +3197,14 @@ void PropertyMaterialList::RestoreDocFileV0(uint32_t count, Base::Reader& reader
setValues(values);
}
void PropertyMaterialList::RestoreDocFileV1(Base::Reader& reader)
void PropertyMaterialList::RestoreDocFileV3(Base::Reader& reader)
{
Base::InputStream str(reader);
uint32_t count = 0;
str >> count;
std::vector<Material> values(count);
uint32_t value {}; // must be 32 bit long
float valueF {};
uint32_t value; // must be 32 bit long
float valueF;
for (auto& it : values) {
str >> value;
it.ambientColor.setPackedValue(value);
@@ -3177,12 +3218,29 @@ void PropertyMaterialList::RestoreDocFileV1(Base::Reader& reader)
it.shininess = valueF;
str >> valueF;
it.transparency = valueF;
// str >> valueS;
// it.uuid = valueS;
}
for (auto& it : values) {
readString(str, it.image);
readString(str, it.imagePath);
readString(str, it.uuid);
}
setValues(values);
}
void PropertyMaterialList::readString(Base::InputStream& str,
std::string& value)
{
uint32_t uCt;
str >> uCt;
char *temp = new char[uCt];
str.read(temp, uCt);
value.assign(temp, static_cast<std::size_t>(uCt));
delete [] temp;
}
const char* PropertyMaterialList::getEditorName() const
{
if (testStatus(NoMaterialListEdit)) {

View File

@@ -38,6 +38,8 @@
namespace Base {
class InputStream;
class OutputStream;
class Writer;
}
@@ -1132,6 +1134,7 @@ public:
void setDiffuseColor(int index, const Color& col);
void setDiffuseColor(int index, float r, float g, float b, float a = 0.0F);
void setDiffuseColor(int index, uint32_t rgba);
void setDiffuseColors(const std::vector<App::Color>& colors);
void setSpecularColor(const Color& col);
void setSpecularColor(float r, float g, float b, float a = 0.0F);
@@ -1193,14 +1196,18 @@ private:
enum Format {
Version_0,
Version_1,
Version_2
Version_2,
Version_3
};
void RestoreDocFileV0(uint32_t count, Base::Reader& reader);
void RestoreDocFileV1(Base::Reader& reader);
void RestoreDocFileV3(Base::Reader& reader);
void writeString(Base::OutputStream& str, const std::string &value) const;
void readString(Base::InputStream& str, std::string& value);
void verifyIndex(int index) const;
void setSizeOne();
void setMinimumSizeOne();
int resizeByOneIfNeeded(int index);
Format formatVersion {Version_0};

View File

@@ -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)

View File

@@ -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

View File

@@ -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;

View File

@@ -41,62 +41,6 @@
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Ambient color:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::ColorButton" name="ambientColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="textLabel1">
<property name="text">
<string>Diffuse color:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::ColorButton" name="diffuseColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Emissive color:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::ColorButton" name="emissiveColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="textLabel3">
<property name="text">
<string>Specular color:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::ColorButton" name="specularColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<layout class="QHBoxLayout">
<property name="spacing">
@@ -149,6 +93,76 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="textLabel1">
<property name="text">
<string>Diffuse color:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::ColorButton" name="ambientColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::ColorButton" name="emissiveColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="textLabel3">
<property name="text">
<string>Specular color:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::ColorButton" name="diffuseColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Ambient color:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::ColorButton" name="specularColor">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Emissive color:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="buttonReset">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="buttonDefault">
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -22,8 +22,11 @@
#include "PreCompiled.h"
#include <App/Color.h>
#include <App/Material.h>
#include <App/PropertyStandard.h>
#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<int>(&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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it= Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(prop);
App::Material mat = ShapeMaterial->getValue();
mat.ambientColor = ambient;
ShapeMaterial->setValue(mat);
for (std::vector<ViewProvider*>::iterator it= Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(prop);
App::Material mat = ShapeMaterial->getValue();
mat.diffuseColor = diffuse;
ShapeMaterial->setValue(mat);
for (std::vector<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(prop);
App::Material mat = ShapeMaterial->getValue();
mat.emissiveColor = emissive;
ShapeMaterial->setValue(mat);
for (std::vector<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(prop);
App::Material mat = ShapeMaterial->getValue();
mat.specularColor = specular;
ShapeMaterial->setValue(mat);
for (std::vector<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(prop);
App::Material mat = ShapeMaterial->getValue();
mat.shininess = shininess;
ShapeMaterial->setValue(mat);
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(prop);
auto mat = App::Material::getDefaultAppearance();
ShapeAppearance->setValue(mat);
setButtonColors();
break;
}
}
}
@@ -197,33 +280,82 @@ void DlgMaterialPropertiesImp::setViewProviders(const std::vector<Gui::ViewProvi
{
Objects = Obj;
setButtonColors();
}
/**
* Sets the button colors to match the current material settings.
*/
void DlgMaterialPropertiesImp::setButtonColors()
{
for (std::vector<ViewProvider*>::iterator it = Objects.begin(); it != Objects.end(); ++it) {
App::Property* prop = (*it)->getPropertyByName(material.c_str());
if (prop && prop->isDerivedFrom<App::PropertyMaterial>()) {
auto ShapeMaterial = static_cast<App::PropertyMaterial*>(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<App::PropertyMaterialList>()) {
auto ShapeAppearance = static_cast<App::PropertyMaterialList*>(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"

View File

@@ -28,6 +28,12 @@
#include <memory>
#include <vector>
namespace App
{
class Color;
class Material;
}
namespace Gui
{
class ViewProvider;
@@ -48,18 +54,36 @@ public:
void setViewProviders(const std::vector<Gui::ViewProvider*>&);
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_DlgMaterialProperties> ui;
std::string material;
std::vector<Gui::ViewProvider*> 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

View File

@@ -23,7 +23,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <random>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/actions/SoRayPickAction.h>
#include <Inventor/actions/SoSearchAction.h>
@@ -35,12 +34,14 @@
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/nodes/SoTexture2.h>
#endif
#include <Inventor/nodes/SoResetTransform.h>
#include <App/GeoFeature.h>
#include <App/PropertyGeo.h>
#include <Gui/BitmapFactory.h>
#include "Application.h"
#include "Document.h"
@@ -56,12 +57,12 @@ using namespace Gui;
namespace {
float fromPercent(long value)
{
return static_cast<float>(value) / 100.0F;
return std::roundf(value) / 100.0F;
}
long toPercent(float value)
{
return static_cast<long>(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<int> distribution(min, max);
return distribution(generator);
};
App::Material mat(App::Material::DEFAULT);
mat.transparency = fromPercent(hGrp->GetInt("DefaultShapeTransparency", 0));
long shininess = toPercent(mat.shininess);
mat.shininess = fromPercent(hGrp->GetInt("DefaultShapeShininess", shininess));
// This is handled in the material code when using the object appearance
bool randomColor = hGrp->GetBool("RandomColor", false);
// diffuse color
if (randomColor) {
float red = static_cast<float>(intRandom(0, 255)) / 255.0F;
float green = static_cast<float>(intRandom(0, 255)) / 255.0F;
float blue = static_cast<float>(intRandom(0, 255)) / 255.0F;
mat.diffuseColor = App::Color(red, green, blue);
}
else {
// Color = (204, 204, 230) = 3435980543UL
getColor("DefaultShapeColor", mat.diffuseColor);
}
getColor("DefaultAmbientColor", mat.ambientColor);
getColor("DefaultEmissiveColor", mat.emissiveColor);
getColor("DefaultSpecularColor", mat.specularColor);
return mat;
}
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()

View File

@@ -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};

View File

@@ -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));
}

View File

@@ -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<App::Color> 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();
}
}

View File

@@ -39,10 +39,6 @@ void ExportOCAFGui::findColors(Part::Feature* part, std::vector<App::Color>& col
{
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
colors = static_cast<PartGui::ViewProviderPartExt*>(vp)->DiffuseColor.getValues();
if (colors.empty()) {
colors.push_back(
static_cast<PartGui::ViewProviderPart*>(vp)->ShapeAppearance.getDiffuseColor());
}
colors = static_cast<PartGui::ViewProviderPartExt*>(vp)->ShapeAppearance.getDiffuseColors();
}
}

View File

@@ -54,7 +54,7 @@ void ImportOCAFGui::applyFaceColors(Part::Feature* part, const std::vector<App::
vp->Transparency.setValue(100 * colors.front().a);
}
else {
vp->DiffuseColor.setValues(colors);
vp->ShapeAppearance.setDiffuseColors(colors);
}
}

View File

@@ -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;
}

View File

@@ -116,6 +116,7 @@ public:
void setValue(const QString& value);
void setValue(const std::shared_ptr<MaterialValue>& 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);

View File

@@ -21,15 +21,23 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <QImage>
#include <QImageReader>
#include <Inventor/nodes/SoGroup.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoOrthographicCamera.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/nodes/SoTexture2.h>
#endif
#include <Inventor/nodes/SoTextureCoordinateEnvironment.h>
#include <App/Application.h>
#include <Base/Parameter.h>
#include <Gui/BitmapFactory.h>
#include "AppearancePreview.h"
@@ -123,11 +131,24 @@ AppearancePreview::AppearancePreview(QWidget* parent)
// setBackground();
setEnabledNaviCube(false);
auto root = dynamic_cast<SoSeparator*>(getSceneGraph());
_group = dynamic_cast<SoSeparator*>(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()
{}

View File

@@ -26,7 +26,11 @@
#include <Gui/View3DInventorViewer.h>
#include <Gui/View3DSettings.h>
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<AppearanceSettings> viewSettings;
void applySettings();
void setCoinTexture();
void setCoinMaterial();
};
} // namespace MatGui

View File

@@ -369,7 +369,7 @@
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Shape Appearance:</string>
<string>Custom Appearance</string>
</property>
</widget>
</item>
@@ -401,7 +401,7 @@
<widget class="Gui::ColorButton" name="buttonLineColor"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="buttonUserDefinedMaterial">
<widget class="QPushButton" name="buttonCustomAppearance">
<property name="text">
<string notr="true">...</string>
</property>

View File

@@ -167,7 +167,6 @@ DlgDisplayPropertiesImp::DlgDisplayPropertiesImp(bool floating, QWidget* parent,
std::vector<Gui::ViewProvider*> views = getSelection();
setDisplayModes(views);
setMaterial(views);
setColorPlot(views);
setShapeAppearance(views);
setLineColor(views);
@@ -276,10 +275,10 @@ void DlgDisplayPropertiesImp::setupConnections()
qOverload<int>(&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<Gui::ViewProvider*> 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<App::PropertyMaterialList>()) {
//auto& value = static_cast<const App::PropertyMaterialList&>(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<const App::PropertyMaterialList&>(prop).getValues();
auto& material = values[0];
d->ui.widgetMaterial->setMaterial(QString::fromStdString(material.uuid));
}
}
else if (prop.isDerivedFrom<App::PropertyInteger>()) {
@@ -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<Gui::ViewProvider*> 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<Gui::ViewProvide
}
}
void DlgDisplayPropertiesImp::setMaterial(const std::vector<Gui::ViewProvider*>& views)
{
Q_UNUSED(views);
// bool material = false;
// App::Material mat = App::Material(App::Material::DEFAULT);
// for (auto view : views) {
// if (auto* prop =
// dynamic_cast<App::PropertyMaterial*>(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<Gui::ViewProvider*>& views)
{
bool material = false;
@@ -627,16 +601,13 @@ void DlgDisplayPropertiesImp::setShapeAppearance(const std::vector<Gui::ViewProv
for (auto view : views) {
if (auto* prop =
dynamic_cast<App::PropertyMaterialList*>(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<Gui::ViewProvider*>& views)
@@ -694,21 +665,7 @@ void DlgDisplayPropertiesImp::onMaterialSelected(
for (auto it : Provider) {
if (auto* prop = dynamic_cast<App::PropertyMaterialList*>(
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());
}
}
}

View File

@@ -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<Materials::Material>& material);
@@ -87,7 +87,6 @@ private:
void setupFilters();
void slotChangedObject(const Gui::ViewProvider&, const App::Property& Prop);
void setDisplayModes(const std::vector<Gui::ViewProvider*>&);
void setMaterial(const std::vector<Gui::ViewProvider*>&);
void setColorPlot(const std::vector<Gui::ViewProvider*>&);
void setShapeAppearance(const std::vector<Gui::ViewProvider*>&);
void setLineColor(const std::vector<Gui::ViewProvider*>&);

View File

@@ -31,7 +31,6 @@
#include <Base/Console.h>
#include <Gui/Application.h>
#include <Gui/DlgMaterialPropertiesImp.h>
#include <Gui/DockWindowManager.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>

View File

@@ -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<QStandardItemModel*>(m_materialTree->model());

View File

@@ -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<Materials::Material>&
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;

View File

@@ -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);

View File

@@ -61,10 +61,10 @@
#include <Gui/QtAll.h>
#endif
// // Inventor includes OpenGL
// #ifndef __InventorAll__
// # include <Gui/InventorAll.h>
// #endif
// Inventor includes OpenGL
#ifndef __InventorAll__
# include <Gui/InventorAll.h>
#endif
#endif //_PreComp_

View File

@@ -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: ''

View File

@@ -378,7 +378,7 @@ void Tessellation::setFaceColors(int method, App::Document* doc, App::DocumentOb
auto svp = Base::freecad_dynamic_cast<PartGui::ViewProviderPartExt>(
Gui::Application::Instance->getViewProvider(obj));
if (vpmesh && svp) {
std::vector<App::Color> diff_col = svp->DiffuseColor.getValues();
std::vector<App::Color> diff_col = svp->ShapeAppearance.getDiffuseColors();
if (ui->groupsFaceColors->isChecked()) {
diff_col = getUniqueColors(diff_col);
}

View File

@@ -1,25 +1,25 @@
/***************************************************************************
* Copyright (c) 2002 Juergen Riegel <juergen.riegel@web.de> *
* *
* 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 <juergen.riegel@web.de> *
* *
* 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<Module>
namespace PartGui
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("PartGui")
Module()
: Py::ExtensionModule<Module>("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<PartGui::DlgSettingsGeneral>(QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgSettings3DViewPart>(QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgSettingsObjectColor>(QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgImportExportIges>(QT_TRANSLATE_NOOP("QObject", "Import-Export"));
(void)new Gui::PrefPageProducer<PartGui::DlgImportExportStep>(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<PartGui::DlgSettingsGeneral>(
QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgSettings3DViewPart>(
QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgSettingsObjectColor>(
QT_TRANSLATE_NOOP("QObject", "Part/Part Design"));
(void)new Gui::PrefPageProducer<PartGui::DlgImportExportIges>(
QT_TRANSLATE_NOOP("QObject", "Import-Export"));
(void)new Gui::PrefPageProducer<PartGui::DlgImportExportStep>(
QT_TRANSLATE_NOOP("QObject", "Import-Export"));
Gui::ViewProviderBuilder::add(Part::PropertyPartShape::getClassTypeId(),
PartGui::ViewProviderPart::getClassTypeId());
// add resources and reloads the translators
loadPartResource();

View File

@@ -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

View File

@@ -2112,7 +2112,7 @@ void CmdColorPerFace::activated(int iMsg)
return;
PartGui::ViewProviderPartExt* vp = dynamic_cast<PartGui::ViewProviderPartExt*>(Gui::Application::Instance->getViewProvider(sel.front()));
if (vp)
vp->changeFaceColors();
vp->changeFaceAppearances();
}
bool CmdColorPerFace::isActive()

View File

@@ -720,34 +720,38 @@ void PartGui::DlgProjectionOnSurface::higlight_object(Part::Feature* iCurrentObj
auto vp = dynamic_cast<PartGui::ViewProviderPartExt*>(
Gui::Application::Instance->getViewProvider(iCurrentObject));
if (vp) {
std::vector<App::Color> colors;
App::Color defaultColor;
App::Color aColor;
aColor.setPackedValue(iColor);
if (currentShapeType == TopAbs_FACE) {
colors = vp->DiffuseColor.getValues();
defaultColor = vp->ShapeAppearance.getDiffuseColor();
std::vector<App::Material> colors = vp->ShapeAppearance.getValues();
App::Color defaultColor = vp->ShapeAppearance.getDiffuseColor();
if (static_cast<Standard_Integer>(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<App::Color> colors = vp->LineColorArray.getValues();
App::Color defaultColor = vp->LineColor.getValue();
if (static_cast<Standard_Integer>(colors.size()) != anIndices.Extent()) {
colors.resize(anIndices.Extent(), defaultColor);
}
if (static_cast<Standard_Integer>(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;
}
}
}
}

View File

@@ -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<App::Material>& 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<std::string>& elements,
std::vector<App::Color>& colors) const
{
@@ -226,3 +237,24 @@ void ReferenceHighlighter::getFaceColors(const std::vector<std::string>& element
std::fill(colors.begin(), colors.end(), objectColor);
}
}
void ReferenceHighlighter::getFaceMaterials(const std::vector<std::string>& elements,
std::vector<App::Material>& 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);
}
}

View File

@@ -79,6 +79,14 @@ public:
*/
void getFaceColors(const std::vector<std::string>& elements,
std::vector<App::Color>& 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<std::string>& elements,
std::vector<App::Material>& materials) const;
private:
void getVertexColor(const std::string& element, std::vector<App::Color>& colors) const;
@@ -89,6 +97,7 @@ private:
void getEdgeColorsOfWire(const std::string& element, std::vector<App::Color>& colors) const;
void getEdgeColorsOfFace(const std::string& element, std::vector<App::Color>& colors) const;
void getFaceColor(const std::string& element, std::vector<App::Color>& colors) const;
void getFaceColor(const std::string& element, std::vector<App::Material>& materials) const;
private:
App::Color defaultColor;

View File

@@ -46,6 +46,7 @@
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/Control.h>
#include <Gui/DlgMaterialPropertiesImp.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
@@ -54,8 +55,10 @@
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include "TaskFaceColors.h"
#include "ui_TaskFaceColors.h"
#include <Mod/Material/Gui/MaterialTreeWidget.h>
#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<Gui::View3DInventorViewer> view;
ViewProviderPartExt* vp;
App::DocumentObject* obj;
Gui::Document* doc;
std::vector<App::Color> perface;
std::vector<App::Material> perface;
QSet<int> 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<App::Color> current = vp->DiffuseColor.getValues();
if (current.empty())
current.push_back(vp->ShapeAppearance.getDiffuseColor());
std::vector<App::Material> 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<FaceColors*>(ud);
FaceAppearances* self = static_cast<FaceAppearances*>(ud);
self->d->view = nullptr;
if (self->d->obj && self->d->obj->isDerivedFrom<Part::Feature>()) {
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::View3DInventor*>(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<Materials::Material>& 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<Gui::ViewProvider*> 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"

View File

@@ -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<Materials::Material>& 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

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartGui::TaskFaceColors</class>
<widget class="QWidget" name="PartGui::TaskFaceColors">
<class>PartGui::TaskFaceAppearances</class>
<widget class="QWidget" name="PartGui::TaskFaceAppearances">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>247</width>
<height>143</height>
<height>219</height>
</rect>
</property>
<property name="windowTitle">
<string>Set color per face</string>
<string>Set appearance per face</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@@ -26,57 +26,57 @@
<property name="title">
<string notr="true">Group box</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="faceLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Faces:</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="faceLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Faces:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelElement">
<property name="text">
<string notr="true">[]</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLabel" name="labelElement">
<property name="text">
<string notr="true">[]</string>
</property>
</widget>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="MatGui::MaterialTreeWidget" name="widgetMaterial" native="true"/>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="Gui::ColorButton" name="colorButton">
<property name="minimumSize">
<size>
<width>146</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>160</width>
<height>16777215</height>
</size>
</property>
</widget>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QPushButton" name="buttonCustomAppearance">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelCustomAppearance">
<property name="text">
<string>Custom Appearance</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</layout>
</widget>
</item>
<item>
@@ -136,9 +136,10 @@ by dragging a selection rectangle in the 3D view</string>
</widget>
<customwidgets>
<customwidget>
<class>Gui::ColorButton</class>
<extends>QPushButton</extends>
<header>Gui/Widgets.h</header>
<class>MatGui::MaterialTreeWidget</class>
<extends>QWidget</extends>
<header>Mod/Material/Gui/MaterialTreeWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>

View File

@@ -71,6 +71,20 @@ void ViewProviderPart::applyColor(const Part::ShapeHistory& hist,
}
}
void ViewProviderPart::applyMaterial(const Part::ShapeHistory& hist,
const App::PropertyMaterialList& colBase,
std::vector<App::Material>& colBool)
{
std::map<int, std::vector<int>>::const_iterator jt;
// apply color from modified faces
for (jt = hist.shapeMap.begin(); jt != hist.shapeMap.end(); ++jt) {
std::vector<int>::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<App::Color>& colors)
{
@@ -85,6 +99,20 @@ void ViewProviderPart::applyTransparency(const float& transparency,
}
}
void ViewProviderPart::applyTransparency(const float& transparency, std::vector<App::Material>& colors)
{
if (transparency != 0.0) {
// transparency has been set object-wide
std::vector<App::Material>::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<SoNode*>& ) const

View File

@@ -57,8 +57,13 @@ protected:
void applyColor(const Part::ShapeHistory& hist,
const std::vector<App::Color>& colBase,
std::vector<App::Color>& colBool);
void applyMaterial(const Part::ShapeHistory& hist,
const App::PropertyMaterialList& colBase,
std::vector<App::Material>& colBool);
void applyTransparency(const float& transparency,
std::vector<App::Color>& colors);
void applyTransparency(const float& transparency,
std::vector<App::Material>& colors);
};
} // namespace PartGui

View File

@@ -100,27 +100,27 @@ void ViewProviderBoolean::updateData(const App::Property* prop)
auto vpTool = dynamic_cast<PartGui::ViewProviderPart*>(
Gui::Application::Instance->getViewProvider(objTool));
if (vpBase && vpTool) {
std::vector<App::Color> colBase = vpBase->DiffuseColor.getValues();
std::vector<App::Color> colTool = vpTool->DiffuseColor.getValues();
std::vector<App::Color> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor());
applyTransparency(vpBase->Transparency.getValue(),colBase);
applyTransparency(vpTool->Transparency.getValue(),colTool);
std::vector<App::Material> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]);
vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue());
vpTool->ShapeAppearance.setTransparency(vpTool->Transparency.getValue());
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
applyColor(hist[0], colBase, colBool);
if (static_cast<int>(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<int>(colTool.size()) == toolMap.Extent()) {
applyColor(hist[1], colTool, colBool);
if (static_cast<int>(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<App::Color> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor());
std::vector<App::Material> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]);
int index=0;
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
@@ -201,14 +201,14 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop)
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
if (vpBase) {
std::vector<App::Color> colBase = vpBase->DiffuseColor.getValues();
applyTransparency(vpBase->Transparency.getValue(),colBase);
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
applyColor(hist[index], colBase, colBool);
vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue());
if (static_cast<int>(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<App::PropertyLinkList>()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();
@@ -321,8 +321,8 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop)
TopTools_IndexedMapOfShape boolMap;
TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap);
std::vector<App::Color> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance.getDiffuseColor());
std::vector<App::Material> colBool;
colBool.resize(boolMap.Extent(), this->ShapeAppearance[0]);
int index=0;
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
@@ -336,14 +336,14 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop)
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
if (vpBase) {
std::vector<App::Color> colBase = vpBase->DiffuseColor.getValues();
applyTransparency(vpBase->Transparency.getValue(),colBase);
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
applyColor(hist[index], colBase, colBool);
vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue());
if (static_cast<int>(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<App::PropertyLinkList>()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();

View File

@@ -95,8 +95,8 @@ void ViewProviderCompound::updateData(const App::Property* prop)
TopTools_IndexedMapOfShape compMap;
TopExp::MapShapes(compShape, TopAbs_FACE, compMap);
std::vector<App::Color> compCol;
compCol.resize(compMap.Extent(), this->ShapeAppearance.getDiffuseColor());
std::vector<App::Material> compCol;
compCol.resize(compMap.Extent(), this->ShapeAppearance[0]);
int index=0;
for (std::vector<App::DocumentObject*>::iterator it = sources.begin(); it != sources.end(); ++it, ++index) {
@@ -111,14 +111,14 @@ void ViewProviderCompound::updateData(const App::Property* prop)
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
if (vpBase) {
std::vector<App::Color> baseCol = vpBase->DiffuseColor.getValues();
applyTransparency(vpBase->Transparency.getValue(),baseCol);
if (static_cast<int>(baseCol.size()) == baseMap.Extent()) {
applyColor(hist[index], baseCol, compCol);
vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue());
if (static_cast<int>(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<App::PropertyLinkList>()) {
const std::vector<App::DocumentObject *>& pBases = static_cast<const App::PropertyLinkList*>(prop)->getValues();

View File

@@ -66,6 +66,7 @@
# include <Inventor/nodes/SoPolygonOffset.h>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoTexture3.h>
# include <boost/algorithm/string/predicate.hpp>
#endif
@@ -86,10 +87,11 @@
#include <Mod/Part/App/Tools.h>
#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<float>(value) / 100.0F;
return std::roundf(value) / 100.0F;
}
long toPercent(float value)
{
return static_cast<long>(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<App::Property::Status,App::Property> 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<Base::Vector3d> ViewProviderPartExt::getSelectionShape(const char* /
return {};
}
void ViewProviderPartExt::setHighlightedFaces(const std::vector<App::Color>& colors)
void ViewProviderPartExt::setHighlightedFaces(const std::vector<App::Material>& materials)
{
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange))
getObject()->touch(true);
Gui::SoUpdateVBOAction action;
action.apply(this->faceset);
int size = static_cast<int>(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<App::Material>& colors)
{
int size = static_cast<int>(colors.size());
int size = static_cast<int>(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<int>(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<std::string,App::Color> 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<size;++i) {
if(DiffuseColor[i]!=color)
ret[std::string(element,4)+std::to_string(i+1)] = DiffuseColor[i];
singleColor = singleColor && DiffuseColor[0]==DiffuseColor[i];
if (ShapeAppearance.getDiffuseColor(i) != color) {
ret[std::string(element, 4) + std::to_string(i + 1)] =
ShapeAppearance.getDiffuseColor(i);
}
singleColor = singleColor
&& ShapeAppearance.getDiffuseColor(0) == ShapeAppearance.getDiffuseColor(i);
}
if(size && singleColor) {
color = DiffuseColor[0];
color = ShapeAppearance.getDiffuseColor(0);
color.a = Transparency.getValue()/100.0f;
ret.clear();
}
@@ -697,7 +746,7 @@ std::map<std::string,App::Color> 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<std::string,App::Color> 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);
}
}

View File

@@ -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<App::Color>& colors);
void setHighlightedFaces(const std::vector<App::Material>& colors);
void setHighlightedFaces(const std::vector<App::Material>& materials);
void setHighlightedFaces(const App::PropertyMaterialList& appearance);
void unsetHighlightedFaces();
void setHighlightedEdges(const std::vector<App::Color>& 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;
};
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="ViewProviderGeometryObjectPy"
Name="ViewProviderPartExtPy"
Twin="ViewProviderPartExt"
TwinPointer="ViewProviderPartExt"
Include="Mod/Part/Gui/ViewProviderExt.h"
Namespace="PartGui"
FatherInclude="Gui/ViewProviderGeometryObjectPy.h"
FatherNamespace="Gui">
<Documentation>
<Author Licence="LGPL" Name="David Carter" EMail="dcarter@davidcarter.ca" />
<UserDocu>This is the ViewProvider geometry class</UserDocu>
</Documentation>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,73 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2024 David Carter <dcarter@david.carter.ca> *
* *
* 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 *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <sstream>
#endif
#include <App/GeoFeature.h>
#include <App/PropertyStandard.h>
#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 << "<View provider geometry object at " << getViewProviderPartExtPtr() << ">";
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;
}

View File

@@ -263,17 +263,18 @@ void ViewProviderFillet::updateData(const App::Property* prop)
auto vpBase = dynamic_cast<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
if (vpBase) {
std::vector<App::Color> colBase = vpBase->DiffuseColor.getValues();
std::vector<App::Color> colFill;
colFill.resize(fillMap.Extent(), vpBase->ShapeAppearance.getDiffuseColor());
applyTransparency(vpBase->Transparency.getValue(),colBase);
// std::vector<App::Color> colBase = vpBase->DiffuseColor.getValues();
std::vector<App::Material> colFill;
colFill.resize(fillMap.Extent(), vpBase->ShapeAppearance[0]);
vpBase->ShapeAppearance.setTransparency(vpBase->Transparency.getValue());
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
applyColor(hist[0], colBase, colFill);
if (static_cast<int>(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<PartGui::ViewProviderPart*>(Gui::Application::Instance->getViewProvider(objBase));
if (vpBase) {
std::vector<App::Color> colBase = static_cast<PartGui::ViewProviderPart*>(vpBase)->DiffuseColor.getValues();
std::vector<App::Color> colCham;
colCham.resize(chamMap.Extent(), static_cast<PartGui::ViewProviderPart*>(vpBase)->ShapeAppearance.getDiffuseColor());
applyTransparency(static_cast<PartGui::ViewProviderPart*>(vpBase)->Transparency.getValue(),colBase);
// std::vector<App::Color> colBase = static_cast<PartGui::ViewProviderPart*>(vpBase)->DiffuseColor.getValues();
auto& colBase = static_cast<PartGui::ViewProviderPart*>(vpBase)->ShapeAppearance;
std::vector<App::Material> colCham;
colCham.resize(chamMap.Extent(), colBase[0]);
colBase.setTransparency(static_cast<PartGui::ViewProviderPart*>(vpBase)->Transparency.getValue());
if (static_cast<int>(colBase.size()) == baseMap.Extent()) {
applyColor(hist[0], colBase, colCham);
if (static_cast<int>(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);
}
}
}

View File

@@ -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<PartGui::ViewProviderPartExt*>(vptip)->DiffuseColor.getValues();
this->DiffuseColor.setValues(colors);
auto materials = static_cast<PartGui::ViewProviderPartExt*>(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;

View File

@@ -100,13 +100,13 @@ void ViewProviderDressUp::highlightReferences(const bool on)
std::vector<std::string> edges = pcDressUp->Base.getSubValuesStartsWith("Edge");
if (on) {
if (!faces.empty() && originalFaceColors.empty()) {
originalFaceColors = vp->DiffuseColor.getValues();
std::vector<App::Color> colors = originalFaceColors;
if (!faces.empty() && originalFaceMaterials.empty()) {
originalFaceMaterials = vp->ShapeAppearance.getValues();
std::vector<App::Material> 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);

View File

@@ -60,7 +60,7 @@ protected:
bool setEdit(int ModNum) override;
private:
std::vector<App::Color> originalFaceColors;
std::vector<App::Material> originalFaceMaterials;
std::vector<App::Color> originalLineColors;
};

View File

@@ -161,9 +161,9 @@ void ViewProviderShapeBinder::highlightReferences(bool on)
lcolors.resize(eMap.Extent(), svp->LineColor.getValue());
TopExp::MapShapes(static_cast<Part::Feature*>(obj)->Shape.getValue(), TopAbs_FACE, eMap);
originalFaceColors = svp->DiffuseColor.getValues();
std::vector<App::Color> fcolors = originalFaceColors;
fcolors.resize(eMap.Extent(), svp->ShapeAppearance.getDiffuseColor());
originalFaceAppearance = svp->ShapeAppearance.getValues();
std::vector<App::Material> 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<int>(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();
}
}
}

View File

@@ -48,7 +48,7 @@ protected:
private:
std::vector<App::Color> originalLineColors;
std::vector<App::Color> originalFaceColors;
std::vector<App::Material> originalFaceAppearance;
};

View File

@@ -161,22 +161,23 @@ void ViewProviderFilling::highlightReferences(ShapeType type, const References&
break;
case ViewProviderFilling::Face:
if (on) {
std::vector<App::Color> colors;
std::vector<App::Material> 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::size_t>(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();

View File

@@ -161,22 +161,23 @@ void ViewProviderSections::highlightReferences(ShapeType type, const References&
break;
case ViewProviderSections::Face:
if (on) {
std::vector<App::Color> colors;
std::vector<App::Material> 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::size_t>(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();