From 330e64fc89dc896cce008c56e55fad751f65e672 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 5 Jun 2024 00:42:29 +0200 Subject: [PATCH] Gui: Move texture handling to view provider extension It should be avoided to add all stuff to the base class when it's only needed in one sub-class --- src/Gui/Application.cpp | 5 + src/Gui/CMakeLists.txt | 2 + src/Gui/ViewProviderGeometryObject.cpp | 77 +--------- src/Gui/ViewProviderGeometryObject.h | 18 --- src/Gui/ViewProviderTextureExtension.cpp | 183 +++++++++++++++++++++++ src/Gui/ViewProviderTextureExtension.h | 100 +++++++++++++ src/Mod/Part/Gui/ViewProviderExt.cpp | 24 +-- src/Mod/Part/Gui/ViewProviderExt.h | 10 +- 8 files changed, 302 insertions(+), 117 deletions(-) create mode 100644 src/Gui/ViewProviderTextureExtension.cpp create mode 100644 src/Gui/ViewProviderTextureExtension.h diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index e8e14cb233..c355dcf4e1 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -122,6 +122,7 @@ #include "ViewProviderPart.h" #include "ViewProviderPythonFeature.h" #include "ViewProviderTextDocument.h" +#include "ViewProviderTextureExtension.h" #include "ViewProviderVRMLObject.h" #include "ViewProviderVarSet.h" #include "WaitCursor.h" @@ -1875,6 +1876,7 @@ void Application::initApplication() void Application::initTypes() { + // clang-format off // views Gui::BaseView ::init(); Gui::MDIView ::init(); @@ -1925,6 +1927,8 @@ void Application::initTypes() Gui::ViewProviderMaterialObject ::init(); Gui::ViewProviderMaterialObjectPython ::init(); Gui::ViewProviderTextDocument ::init(); + Gui::ViewProviderTextureExtension ::init(); + Gui::ViewProviderFaceTexture ::init(); Gui::ViewProviderLinkObserver ::init(); Gui::LinkView ::init(); Gui::ViewProviderLink ::init(); @@ -1945,6 +1949,7 @@ void Application::initTypes() // register transaction type new App::TransactionProducer (ViewProviderDocumentObject::getClassTypeId()); + // clang-format on } void Application::initOpenInventor() diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 21ec70d4fa..ae6ed25a5c 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -944,6 +944,7 @@ SET(Viewprovider_CPP_SRCS ViewProviderOrigin.cpp ViewProviderMaterialObject.cpp ViewProviderTextDocument.cpp + ViewProviderTextureExtension.cpp ViewProviderLink.cpp LinkViewPyImp.cpp ViewProviderLinkPyImp.cpp @@ -981,6 +982,7 @@ SET(Viewprovider_SRCS ViewProviderOrigin.h ViewProviderMaterialObject.h ViewProviderTextDocument.h + ViewProviderTextureExtension.h ViewProviderLink.h ViewProviderVarSet.h AxisOrigin.h diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index 3f8d7dd5c1..aa35d76b02 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -34,14 +34,12 @@ #include #include #include -#include #endif #include #include #include -#include #include "Application.h" #include "Document.h" @@ -96,29 +94,10 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() Selectable.setValue(isSelectionEnabled()); - pcSwitchAppearance = new SoSwitch; - pcSwitchAppearance->ref(); - pcSwitchTexture = new SoSwitch; - pcSwitchTexture->ref(); - pcShapeMaterial = new SoMaterial; 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(); @@ -130,11 +109,7 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() ViewProviderGeometryObject::~ViewProviderGeometryObject() { - pcSwitchAppearance->unref(); - pcSwitchTexture->unref(); pcShapeMaterial->unref(); - pcShapeTexture2D->unref(); - pcTextureGroup3D->unref(); pcBoundingBox->unref(); pcBoundColor->unref(); } @@ -273,31 +248,12 @@ unsigned long ViewProviderGeometryObject::getBoundColor() const 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); @@ -308,31 +264,6 @@ void ViewProviderGeometryObject::setCoinAppearance(const App::Material& source) pcShapeMaterial->transparency.setValue(source.transparency); } -void ViewProviderGeometryObject::activateMaterial() -{ - pcSwitchAppearance->whichChild.setValue(0); - pcSwitchTexture->whichChild.setValue(SO_SWITCH_NONE); -} - -void ViewProviderGeometryObject::activateTexture2D() -{ - pcSwitchAppearance->whichChild.setValue(1); - pcSwitchTexture->whichChild.setValue(0); -} - -void ViewProviderGeometryObject::activateTexture3D() -{ - pcSwitchAppearance->whichChild.setValue(1); - pcSwitchTexture->whichChild.setValue(1); -} - -void ViewProviderGeometryObject::activateMixed3D() -{ - pcSwitchAppearance->whichChild.setValue(SO_SWITCH_ALL); - pcSwitchTexture->whichChild.setValue(1); -} - - namespace { float getBoundBoxFontSize() diff --git a/src/Gui/ViewProviderGeometryObject.h b/src/Gui/ViewProviderGeometryObject.h index 5a8b4134e6..291d9d9c88 100644 --- a/src/Gui/ViewProviderGeometryObject.h +++ b/src/Gui/ViewProviderGeometryObject.h @@ -30,7 +30,6 @@ class SoPickedPointList; class SoSwitch; class SoSensor; -class SoTexture2; class SbVec2s; class SoBaseColor; @@ -110,28 +109,11 @@ protected: 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: bool isSelectionEnabled() const; protected: - SoSwitch* pcSwitchAppearance {nullptr}; - SoSwitch* pcSwitchTexture {nullptr}; SoMaterial* pcShapeMaterial {nullptr}; - SoTexture2* pcShapeTexture2D {nullptr}; - SoGroup* pcTextureGroup3D {nullptr}; SoFCBoundingBox* pcBoundingBox {nullptr}; SoSwitch* pcBoundSwitch {nullptr}; SoBaseColor* pcBoundColor {nullptr}; diff --git a/src/Gui/ViewProviderTextureExtension.cpp b/src/Gui/ViewProviderTextureExtension.cpp new file mode 100644 index 0000000000..b720fa2a08 --- /dev/null +++ b/src/Gui/ViewProviderTextureExtension.cpp @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#include +#include +#include +#include +#endif + +#include "ViewProviderTextureExtension.h" +#include +#include + + +using namespace Gui; + + +EXTENSION_PROPERTY_SOURCE(Gui::ViewProviderTextureExtension, Gui::ViewProviderExtension) + + +ViewProviderTextureExtension::ViewProviderTextureExtension() +{ + initExtensionType(ViewProviderTextureExtension::getExtensionClassTypeId()); + + pcSwitchAppearance = new SoSwitch; + pcSwitchAppearance->ref(); + pcSwitchTexture = new SoSwitch; + pcSwitchTexture->ref(); + + pcShapeTexture2D = new SoTexture2; + pcShapeTexture2D->ref(); + + pcTextureGroup3D = new SoGroup; + pcTextureGroup3D->ref(); +} + +void ViewProviderTextureExtension::setup(SoMaterial* pcShapeMaterial) +{ + // 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); +} + +ViewProviderTextureExtension::~ViewProviderTextureExtension() +{ + pcSwitchAppearance->unref(); + pcSwitchTexture->unref(); + pcShapeTexture2D->unref(); + pcTextureGroup3D->unref(); +} + +SoSwitch* ViewProviderTextureExtension::getAppearance() const +{ + return pcSwitchAppearance; +} + +SoGroup* ViewProviderTextureExtension::getTextureGroup3D() const +{ + return pcTextureGroup3D; +} + +void ViewProviderTextureExtension::setCoinAppearance(SoMaterial* pcShapeMaterial, 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); + pcShapeMaterial->diffuseColor.setValue(source.diffuseColor.r, + source.diffuseColor.g, + source.diffuseColor.b); + pcShapeMaterial->specularColor.setValue(source.specularColor.r, + source.specularColor.g, + source.specularColor.b); + pcShapeMaterial->emissiveColor.setValue(source.emissiveColor.r, + source.emissiveColor.g, + source.emissiveColor.b); + pcShapeMaterial->shininess.setValue(source.shininess); + pcShapeMaterial->transparency.setValue(source.transparency); +} + +void ViewProviderTextureExtension::activateMaterial() +{ + pcSwitchAppearance->whichChild.setValue(0); + pcSwitchTexture->whichChild.setValue(SO_SWITCH_NONE); +} + +void ViewProviderTextureExtension::activateTexture2D() +{ + pcSwitchAppearance->whichChild.setValue(1); + pcSwitchTexture->whichChild.setValue(0); +} + +void ViewProviderTextureExtension::activateTexture3D() +{ + pcSwitchAppearance->whichChild.setValue(1); + pcSwitchTexture->whichChild.setValue(1); +} + +void ViewProviderTextureExtension::activateMixed3D() +{ + pcSwitchAppearance->whichChild.setValue(SO_SWITCH_ALL); + pcSwitchTexture->whichChild.setValue(1); +} + +// ------------------------------------------------------------------------------------------------ + +EXTENSION_PROPERTY_SOURCE(Gui::ViewProviderFaceTexture, Gui::ViewProviderTextureExtension) + + +ViewProviderFaceTexture::ViewProviderFaceTexture() +{ + initExtensionType(ViewProviderFaceTexture::getExtensionClassTypeId()); + + // Support for textured faces + pcShapeTexture3D = new SoTexture3; + pcShapeTexture3D->ref(); + pcShapeCoordinates = new SoCoordinate3; + pcShapeCoordinates->ref(); + pcShapeFaceset = new SoIndexedFaceSet; + pcShapeFaceset->ref(); +} + +ViewProviderFaceTexture::~ViewProviderFaceTexture() +{ + pcShapeTexture3D->unref(); + pcShapeCoordinates->unref(); + pcShapeFaceset->unref(); +} + +void ViewProviderFaceTexture::setup(SoMaterial* mat) +{ + ViewProviderTextureExtension::setup(mat); + + getTextureGroup3D()->addChild(pcShapeTexture3D); + getTextureGroup3D()->addChild(pcShapeCoordinates); + getTextureGroup3D()->addChild(pcShapeFaceset); +} diff --git a/src/Gui/ViewProviderTextureExtension.h b/src/Gui/ViewProviderTextureExtension.h new file mode 100644 index 0000000000..dd3e0590cf --- /dev/null +++ b/src/Gui/ViewProviderTextureExtension.h @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + + +#ifndef GUI_VIEWPROVIDERTEXTUREEXT_H +#define GUI_VIEWPROVIDERTEXTUREEXT_H + +#include + +class SoCoordinate3; +class SoGroup; +class SoIndexedFaceSet; +class SoMaterial; +class SoSwitch; +class SoTexture2; +class SoTexture3; + +namespace App +{ +class Material; +} + +namespace Gui +{ + +class GuiExport ViewProviderTextureExtension: public Gui::ViewProviderExtension +{ + EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderTextureExtension); + +public: + /// Constructor + ViewProviderTextureExtension(); + ~ViewProviderTextureExtension() override; + void setup(SoMaterial*); + void setCoinAppearance(SoMaterial* pcShapeMaterial, const App::Material& source); + SoSwitch* getAppearance() const; + SoGroup* getTextureGroup3D() const; + + /** + * 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: + SoSwitch* pcSwitchAppearance {nullptr}; + SoSwitch* pcSwitchTexture {nullptr}; + SoTexture2* pcShapeTexture2D {nullptr}; + SoGroup* pcTextureGroup3D {nullptr}; +}; + +class GuiExport ViewProviderFaceTexture: public Gui::ViewProviderTextureExtension +{ + EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderFaceTexture); + +public: + /// Constructor + ViewProviderFaceTexture(); + ~ViewProviderFaceTexture() override; + void setup(SoMaterial*); + +private: + // Used to support per face textures + SoTexture3 * pcShapeTexture3D; + SoCoordinate3 * pcShapeCoordinates; + SoIndexedFaceSet * pcShapeFaceset; +}; + +} //namespace Gui + + +#endif // GUI_VIEWPROVIDERTEXTUREEXT_H + diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 38140df7de..b9c7df7885 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -125,6 +125,8 @@ const char* ViewProviderPartExt::DrawStyleEnums[]= {"Solid","Dashed","Dotted","D ViewProviderPartExt::ViewProviderPartExt() { + texture.initExtension(this); + VisualTouched = true; forceUpdateCount = 0; NormalsFromUV = true; @@ -221,14 +223,6 @@ 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(); @@ -280,10 +274,6 @@ ViewProviderPartExt::~ViewProviderPartExt() normb->unref(); lineset->unref(); nodeset->unref(); - - pcShapeTexture3D->unref(); - pcShapeCoordinates->unref(); - pcShapeFaceset->unref(); } PyObject* ViewProviderPartExt::getPyObject() @@ -467,10 +457,8 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat) // just faces with no edges or points pcFlatRoot->addChild(pShapeHints); pcFlatRoot->addChild(pcFaceBind); - pcFlatRoot->addChild(pcSwitchAppearance); - pcTextureGroup3D->addChild(pcShapeTexture3D); - pcTextureGroup3D->addChild(pcShapeCoordinates); - pcTextureGroup3D->addChild(pcShapeFaceset); + pcFlatRoot->addChild(texture.getAppearance()); + texture.setup(pcShapeMaterial); SoDrawStyle* pcFaceStyle = new SoDrawStyle(); pcFaceStyle->style = SoDrawStyle::FILLED; pcFlatRoot->addChild(pcFaceStyle); @@ -630,7 +618,7 @@ void ViewProviderPartExt::setHighlightedFaces(const std::vector& int size = static_cast(materials.size()); if (size > 1 && size == this->faceset->partIndex.getNum()) { pcFaceBind->value = SoMaterialBinding::PER_PART; - activateMaterial(); + texture.activateMaterial(); pcShapeMaterial->diffuseColor.setNum(size); pcShapeMaterial->ambientColor.setNum(size); @@ -669,7 +657,7 @@ void ViewProviderPartExt::setHighlightedFaces(const App::PropertyMaterialList& a int size = static_cast(appearance.getSize()); if (size > 1 && size == this->faceset->partIndex.getNum()) { pcFaceBind->value = SoMaterialBinding::PER_PART; - activateMaterial(); + texture.activateMaterial(); pcShapeMaterial->diffuseColor.setNum(size); pcShapeMaterial->ambientColor.setNum(size); diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index 249cae1d2f..af366249ae 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -52,7 +53,6 @@ class SoNormal; class SoNormalBinding; class SoMaterialBinding; class SoIndexedLineSet; -class SoTexture3; namespace PartGui { @@ -86,8 +86,6 @@ public: App::PropertyColor LineColor; App::PropertyMaterial LineMaterial; App::PropertyColorList LineColorArray; - // Faces (Gui::ViewProviderGeometryObject::ShapeAppearance and Gui::ViewProviderGeometryObject::ShapeMaterial apply) - // App::PropertyColorList DiffuseColor; void attach(App::DocumentObject *) override; void setDisplayMode(const char* ModeName) override; @@ -186,15 +184,11 @@ protected: SoBrepEdgeSet * lineset; SoBrepPointSet * nodeset; - // Used to support per face textures - SoTexture3 * pcShapeTexture3D; - SoCoordinate3 * pcShapeCoordinates; - SoIndexedFaceSet * pcShapeFaceset; - bool VisualTouched; bool NormalsFromUV; private: + Gui::ViewProviderFaceTexture texture; // settings stuff int forceUpdateCount; static App::PropertyFloatConstraint::Constraints sizeRange;