Material: Appearance Updates 2
Improves the use of the ShapeAppearance property for the Part workbench.
removes DiffuseColor property
adds Python compatibility using custom attributes
transitions DiffuseColor to ShapeAppearance on open
Improved UI elements for setting object appearance, and appearance per face
Lays the foundation for future texture support
This commit is contained in:
committed by
Chris Hennes
parent
c4d0f3ed97
commit
5feb963f9d
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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/>
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
17
src/Mod/Part/Gui/ViewProviderExtPy.xml
Normal file
17
src/Mod/Part/Gui/ViewProviderExtPy.xml
Normal 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>
|
||||
73
src/Mod/Part/Gui/ViewProviderExtPyImp.cpp
Normal file
73
src/Mod/Part/Gui/ViewProviderExtPyImp.cpp
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user