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

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