Material: Material appearance
Uses new material system for appearance Each feature object now has a property called ShapeMaterial that describes its physical properties. If it has a shape, it has a material. The ShapeColor attribute is replaced by a ShapeAppearance attribute. This is a material list that describes all appearance properties, not just diffuse color. As a list in can be used for all elements of a shape, such as edges and faces. A new widget is provided to allow the user to select materials in a consistent fashion. It can also launch the material editor with its more advanced capabilities.
This commit is contained in:
committed by
Chris Hennes
parent
37c38acd19
commit
ba20441935
@@ -36,6 +36,7 @@
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "ModelPy.h"
|
||||
#include "UUIDsPy.h"
|
||||
#include "PropertyMaterial.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
@@ -43,9 +44,9 @@ class Module: public Py::ExtensionModule<Module>
|
||||
{
|
||||
public:
|
||||
Module()
|
||||
: Py::ExtensionModule<Module>("Material")
|
||||
: Py::ExtensionModule<Module>("Materials")
|
||||
{
|
||||
initialize("This module is the Material module."); // register with Python
|
||||
initialize("This module is the Materials module."); // register with Python
|
||||
}
|
||||
|
||||
~Module() override = default;
|
||||
@@ -60,18 +61,18 @@ PyObject* initModule()
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
PyMOD_INIT_FUNC(Material)
|
||||
PyMOD_INIT_FUNC(Materials)
|
||||
{
|
||||
PyObject* module = Materials::initModule();
|
||||
|
||||
Base::Console().Log("Loading Material module... done\n");
|
||||
|
||||
Base::Interpreter().addType(&Materials::MaterialManagerPy ::Type, module, "MaterialManager");
|
||||
Base::Interpreter().addType(&Materials::MaterialPy ::Type, module, "Material");
|
||||
Base::Interpreter().addType(&Materials::ModelManagerPy ::Type, module, "ModelManager");
|
||||
Base::Interpreter().addType(&Materials::ModelPropertyPy ::Type, module, "ModelProperty");
|
||||
Base::Interpreter().addType(&Materials::ModelPy ::Type, module, "Model");
|
||||
Base::Interpreter().addType(&Materials::UUIDsPy ::Type, module, "UUIDs");
|
||||
Base::Interpreter().addType(&Materials::MaterialManagerPy::Type, module, "MaterialManager");
|
||||
Base::Interpreter().addType(&Materials::MaterialPy::Type, module, "Material");
|
||||
Base::Interpreter().addType(&Materials::ModelManagerPy::Type, module, "ModelManager");
|
||||
Base::Interpreter().addType(&Materials::ModelPropertyPy::Type, module, "ModelProperty");
|
||||
Base::Interpreter().addType(&Materials::ModelPy::Type, module, "Model");
|
||||
Base::Interpreter().addType(&Materials::UUIDsPy::Type, module, "UUIDs");
|
||||
|
||||
|
||||
// Initialize types
|
||||
@@ -95,5 +96,7 @@ PyMOD_INIT_FUNC(Material)
|
||||
Materials::Material2DArray ::init();
|
||||
Materials::Material3DArray ::init();
|
||||
|
||||
Materials::PropertyMaterial ::init();
|
||||
|
||||
PyMOD_Return(module);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ include_directories(
|
||||
)
|
||||
link_directories(${YAML_CPP_LIBRARY_DIR})
|
||||
|
||||
set(Material_LIBS
|
||||
set(Materials_LIBS
|
||||
${Boost_LIBRARIES}
|
||||
FreeCADApp
|
||||
)
|
||||
@@ -28,22 +28,23 @@ set(Material_LIBS
|
||||
include_directories(
|
||||
${QtConcurrent_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND Material_LIBS
|
||||
list(APPEND Materials_LIBS
|
||||
${QtConcurrent_LIBRARIES}
|
||||
)
|
||||
|
||||
if(yaml-cpp_VERSION VERSION_LESS 0.8.0)
|
||||
list(APPEND Material_LIBS
|
||||
list(APPEND Materials_LIBS
|
||||
${YAML_CPP_LIBRARIES}
|
||||
)
|
||||
else()
|
||||
list(APPEND Material_LIBS
|
||||
list(APPEND Materials_LIBS
|
||||
yaml-cpp::yaml-cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
generate_from_xml(Array2DPy)
|
||||
generate_from_xml(Array3DPy)
|
||||
generate_from_xml(MaterialFilterPy)
|
||||
generate_from_xml(MaterialManagerPy)
|
||||
generate_from_xml(MaterialPy)
|
||||
generate_from_xml(ModelManagerPy)
|
||||
@@ -61,6 +62,8 @@ SET(Python_SRCS
|
||||
MaterialManagerPyImpl.cpp
|
||||
MaterialPy.xml
|
||||
MaterialPyImpl.cpp
|
||||
MaterialFilterPy.xml
|
||||
MaterialFilterPyImpl.cpp
|
||||
ModelManagerPy.xml
|
||||
ModelManagerPyImpl.cpp
|
||||
ModelPropertyPy.xml
|
||||
@@ -72,7 +75,7 @@ SET(Python_SRCS
|
||||
)
|
||||
SOURCE_GROUP("Python" FILES ${Python_SRCS})
|
||||
|
||||
SET(Material_SRCS
|
||||
SET(Materials_SRCS
|
||||
${Python_SRCS}
|
||||
AppMaterial.cpp
|
||||
FolderTree.h
|
||||
@@ -102,19 +105,21 @@ SET(Material_SRCS
|
||||
ModelUuids.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
PropertyMaterial.cpp
|
||||
PropertyMaterial.h
|
||||
trim.h
|
||||
)
|
||||
|
||||
if(FREECAD_USE_PCH)
|
||||
add_definitions(-D_PreComp_)
|
||||
GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" PCH_SRCS ${Material_SRCS})
|
||||
ADD_MSVC_PRECOMPILED_HEADER(Material PreCompiled.h PreCompiled.cpp PCH_SRCS)
|
||||
GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" PCH_SRCS ${Materials_SRCS})
|
||||
ADD_MSVC_PRECOMPILED_HEADER(Materials PreCompiled.h PreCompiled.cpp PCH_SRCS)
|
||||
endif(FREECAD_USE_PCH)
|
||||
|
||||
add_library(Material SHARED ${Material_SRCS})
|
||||
target_link_libraries(Material ${Material_LIBS})
|
||||
add_library(Materials SHARED ${Materials_SRCS})
|
||||
target_link_libraries(Materials ${Materials_LIBS})
|
||||
|
||||
SET_BIN_DIR(Material Material /Mod/Material)
|
||||
SET_PYTHON_PREFIX_SUFFIX(Material)
|
||||
SET_BIN_DIR(Materials Materials /Mod/Material)
|
||||
SET_PYTHON_PREFIX_SUFFIX(Materials)
|
||||
|
||||
INSTALL(TARGETS Material DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
INSTALL(TARGETS Materials DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* Copyright (c) 2023-2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialFilter.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "Materials.h"
|
||||
|
||||
|
||||
@@ -56,6 +58,18 @@ bool MaterialFilter::modelIncluded(const std::shared_ptr<Material>& material) co
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaterialFilter::modelIncluded(const QString& uuid) const
|
||||
{
|
||||
MaterialManager manager;
|
||||
try {
|
||||
auto material = manager.getMaterial(uuid);
|
||||
return modelIncluded(material);
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialFilter::addRequired(const QString& uuid)
|
||||
{
|
||||
// Ignore any uuids already present
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* Copyright (c) 2023-2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
@@ -56,9 +56,9 @@ public:
|
||||
{
|
||||
return _includeFolders;
|
||||
}
|
||||
void setIncludeEmptyFolders(bool include)
|
||||
void setIncludeEmptyFolders(bool value)
|
||||
{
|
||||
_includeFolders = include;
|
||||
_includeFolders = value;
|
||||
}
|
||||
|
||||
/* Indicates if we should include materials in the older format
|
||||
@@ -80,10 +80,26 @@ public:
|
||||
* Models only need to be included in one set.
|
||||
*/
|
||||
bool modelIncluded(const std::shared_ptr<Material>& material) const;
|
||||
bool modelIncluded(const QString& uuid) const;
|
||||
|
||||
/* Add model UUIDs for required models, or models that are both required
|
||||
* and complete.
|
||||
*/
|
||||
void addRequired(const QString& uuid);
|
||||
void addRequiredComplete(const QString& uuid);
|
||||
|
||||
/* These functions shouldn't normally be called directly. They are
|
||||
* for use by conversion methods, such as MaterialFilterPy
|
||||
*/
|
||||
const QSet<QString>* getRequired() const
|
||||
{
|
||||
return &_required;
|
||||
}
|
||||
const QSet<QString>* getRequiredComplete() const
|
||||
{
|
||||
return &_requiredComplete;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _includeFolders;
|
||||
bool _includeLegacy;
|
||||
|
||||
43
src/Mod/Material/App/MaterialFilterPy.xml
Normal file
43
src/Mod/Material/App/MaterialFilterPy.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="MaterialFilterPy"
|
||||
Twin="MaterialFilter"
|
||||
TwinPointer="MaterialFilter"
|
||||
Include="Mod/Material/App/MaterialFilter.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material filters.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="IncludeEmptyFolders" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include empty folders in the material list.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeEmptyFolders" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="IncludeLegacy" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include legacy materials in the material list.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeLegacy" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="RequiredModels" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Materials must include the specified models.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="RequiredModels" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="RequiredCompleteModels" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Materials must have complete versions of the specified models.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="RequiredCompleteModels" Type="List"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
132
src/Mod/Material/App/MaterialFilterPyImpl.cpp
Normal file
132
src/Mod/Material/App/MaterialFilterPyImpl.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023-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"
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "MaterialFilter.h"
|
||||
|
||||
#include "MaterialFilterPy.h"
|
||||
|
||||
#include "MaterialFilterPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// Forward declaration
|
||||
// static PyObject* _pyObjectFromVariant(const QVariant& value);
|
||||
// static Py::List getList(const QVariant& value);
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialFilterPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<MaterialFilter object at " << getMaterialFilterPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialFilterPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialFilterPy(new MaterialFilter());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialFilterPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterPy::getIncludeEmptyFolders() const
|
||||
{
|
||||
return {getMaterialFilterPtr()->includeEmptyFolders()};
|
||||
}
|
||||
|
||||
void MaterialFilterPy::setIncludeEmptyFolders(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterPtr()->setIncludeEmptyFolders(value.isTrue());
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterPy::getIncludeLegacy() const
|
||||
{
|
||||
return {getMaterialFilterPtr()->includeLegacy()};
|
||||
}
|
||||
|
||||
void MaterialFilterPy::setIncludeLegacy(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterPtr()->setIncludeLegacy(value.isTrue());
|
||||
}
|
||||
|
||||
Py::List MaterialFilterPy::getRequiredModels() const
|
||||
{
|
||||
auto listValue = getMaterialFilterPtr()->getRequired();
|
||||
Py::List list;
|
||||
|
||||
for (auto& it : *listValue) {
|
||||
list.append(Py::String(it.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void MaterialFilterPy::setRequiredModels(Py::List value)
|
||||
{
|
||||
for (const auto& it : value) {
|
||||
Py::String uuid(it);
|
||||
getMaterialFilterPtr()->addRequired(QString::fromStdString(uuid));
|
||||
}
|
||||
}
|
||||
|
||||
Py::List MaterialFilterPy::getRequiredCompleteModels() const
|
||||
{
|
||||
auto listValue = getMaterialFilterPtr()->getRequiredComplete();
|
||||
Py::List list;
|
||||
|
||||
for (auto& it : *listValue) {
|
||||
list.append(Py::String(it.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void MaterialFilterPy::setRequiredCompleteModels(Py::List value)
|
||||
{
|
||||
for (const auto& it : value) {
|
||||
Py::String uuid(it);
|
||||
getMaterialFilterPtr()->addRequiredComplete(QString::fromStdString(uuid));
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* MaterialFilterPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialFilterPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QVector>
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ QString MaterialLibrary::getUUIDFromPath(const QString& path) const
|
||||
}
|
||||
|
||||
bool MaterialLibrary::materialInTree(const std::shared_ptr<Material>& material,
|
||||
const MaterialFilter* filter) const
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const
|
||||
{
|
||||
if (!filter) {
|
||||
// If there's no filter we always include
|
||||
@@ -283,7 +283,7 @@ bool MaterialLibrary::materialInTree(const std::shared_ptr<Material>& material,
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialLibrary::getMaterialTree(const MaterialFilter* filter) const
|
||||
MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter) const
|
||||
{
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> materialTree =
|
||||
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
std::shared_ptr<Material> addMaterial(const std::shared_ptr<Material>& material,
|
||||
const QString& path);
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const MaterialFilter* filter = nullptr) const;
|
||||
getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter) const;
|
||||
|
||||
bool isReadOnly() const
|
||||
{
|
||||
@@ -99,7 +99,7 @@ protected:
|
||||
void updatePaths(const QString& oldPath, const QString& newPath);
|
||||
QString getUUIDFromPath(const QString& path) const;
|
||||
bool materialInTree(const std::shared_ptr<Material>& material,
|
||||
const MaterialFilter* filter) const;
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const;
|
||||
|
||||
bool _readOnly;
|
||||
std::unique_ptr<std::map<QString, std::shared_ptr<Material>>> _materialPathMap;
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Material.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialConfigLoader.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "ModelManager.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
@@ -108,6 +110,47 @@ bool MaterialManager::isMaterial(const QFileInfo& file) const
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::defaultMaterial()
|
||||
{
|
||||
MaterialManager manager;
|
||||
|
||||
ParameterGrp::handle hGrp =
|
||||
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
bool randomColor = hGrp->GetBool("RandomColor", false);
|
||||
float r, g, b;
|
||||
|
||||
if (randomColor) {
|
||||
auto fMax = (float)RAND_MAX;
|
||||
r = (float)rand() / fMax;
|
||||
g = (float)rand() / fMax;
|
||||
b = (float)rand() / fMax;
|
||||
}
|
||||
else {
|
||||
unsigned long shcol = hGrp->GetUnsigned("DefaultShapeColor", 3435980543UL);
|
||||
r = ((shcol >> 24) & 0xff) / 255.0;
|
||||
g = ((shcol >> 16) & 0xff) / 255.0;
|
||||
b = ((shcol >> 8) & 0xff) / 255.0;
|
||||
}
|
||||
|
||||
int initialTransparency = hGrp->GetInt("DefaultShapeTransparency", 0);
|
||||
|
||||
auto material = manager.getMaterial(defaultMaterialUUID());
|
||||
if (material->hasAppearanceModel(ModelUUIDs::ModelUUID_Rendering_Basic)) {
|
||||
material->getAppearanceProperty(QString::fromLatin1("DiffuseColor"))
|
||||
->setColor(App::Color(r, g, b));
|
||||
material->getAppearanceProperty(QString::fromLatin1("Transparency"))
|
||||
->setFloat((float)initialTransparency / 100.0f);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
QString MaterialManager::defaultMaterialUUID()
|
||||
{
|
||||
// Make this a preference
|
||||
return QString::fromLatin1("7f9fd73b-50c9-41d8-b7b2-575a030c1eeb");
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterial(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
@@ -118,6 +161,13 @@ std::shared_ptr<Material> MaterialManager::getMaterial(const QString& uuid) cons
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterial(const App::Material& material)
|
||||
{
|
||||
MaterialManager manager;
|
||||
|
||||
return manager.getMaterial(QString::fromStdString(material.uuid));
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterialByPath(const QString& path) const
|
||||
{
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
@@ -126,7 +176,9 @@ std::shared_ptr<Material> MaterialManager::getMaterialByPath(const QString& path
|
||||
if (cleanPath.startsWith(library->getDirectory())) {
|
||||
try {
|
||||
return library->getMaterialByPath(cleanPath);
|
||||
} catch (const MaterialNotFound&) {}
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
// See if it's a new file saved by the old editor
|
||||
{
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Material;
|
||||
}
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
@@ -50,11 +55,15 @@ public:
|
||||
MaterialManager();
|
||||
~MaterialManager() override = default;
|
||||
|
||||
static std::shared_ptr<Material> defaultMaterial();
|
||||
static QString defaultMaterialUUID();
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> getMaterials() const
|
||||
{
|
||||
return _materialMap;
|
||||
}
|
||||
std::shared_ptr<Material> getMaterial(const QString& uuid) const;
|
||||
static std::shared_ptr<Material> getMaterial(const App::Material& material);
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path) const;
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path, const QString& library) const;
|
||||
std::shared_ptr<Material> getParent(const std::shared_ptr<Material>& material) const;
|
||||
@@ -66,10 +75,16 @@ public:
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries() const;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const MaterialFilter* filter = nullptr) const
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const
|
||||
{
|
||||
return library->getMaterialTree(filter);
|
||||
}
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library) const
|
||||
{
|
||||
std::shared_ptr<Materials::MaterialFilter> filter;
|
||||
return library->getMaterialTree(filter);
|
||||
}
|
||||
std::shared_ptr<std::list<QString>>
|
||||
getMaterialFolders(const std::shared_ptr<MaterialLibrary>& library) const;
|
||||
void createFolder(const std::shared_ptr<MaterialLibrary>& library, const QString& path) const
|
||||
|
||||
@@ -103,69 +103,69 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
Py::String MaterialPy::getLibraryName() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return Py::String(library ? library->getName().toStdString() : "");
|
||||
return {library ? library->getName().toStdString() : ""};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryRoot() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return Py::String(library ? library->getDirectoryPath().toStdString() : "");
|
||||
return {library ? library->getDirectoryPath().toStdString() : ""};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryIcon() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return Py::String(library ? library->getIconPath().toStdString() : "");
|
||||
return {library ? library->getIconPath().toStdString() : ""};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getName() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getName().toStdString());
|
||||
return {getMaterialPtr()->getName().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getDirectory() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getDirectory().toStdString());
|
||||
return {getMaterialPtr()->getDirectory().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getUUID() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getUUID().toStdString());
|
||||
return {getMaterialPtr()->getUUID().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getDescription() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getDescription().toStdString());
|
||||
return {getMaterialPtr()->getDescription().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getURL() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getURL().toStdString());
|
||||
return {getMaterialPtr()->getURL().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getReference() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getReference().toStdString());
|
||||
return {getMaterialPtr()->getReference().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getParent() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getParentUUID().toStdString());
|
||||
return {getMaterialPtr()->getParentUUID().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getAuthorAndLicense() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString());
|
||||
return {getMaterialPtr()->getAuthorAndLicense().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getAuthor() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getAuthor().toStdString());
|
||||
return {getMaterialPtr()->getAuthor().toStdString()};
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLicense() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getLicense().toStdString());
|
||||
return {getMaterialPtr()->getLicense().toStdString()};
|
||||
}
|
||||
|
||||
Py::List MaterialPy::getPhysicalModels() const
|
||||
@@ -173,8 +173,8 @@ Py::List MaterialPy::getPhysicalModels() const
|
||||
auto models = getMaterialPtr()->getPhysicalModels();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
list.append(Py::String(it->toStdString()));
|
||||
for (auto it : *models) {
|
||||
list.append(Py::String(it.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -185,8 +185,8 @@ Py::List MaterialPy::getAppearanceModels() const
|
||||
auto models = getMaterialPtr()->getAppearanceModels();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
list.append(Py::String(it->toStdString()));
|
||||
for (auto it : *models) {
|
||||
list.append(Py::String(it.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -197,8 +197,8 @@ Py::List MaterialPy::getTags() const
|
||||
auto& tags = getMaterialPtr()->getTags();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = tags.begin(); it != tags.end(); it++) {
|
||||
list.append(Py::String(it->toStdString()));
|
||||
for (auto it : tags) {
|
||||
list.append(Py::String(it.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -298,9 +298,9 @@ Py::Dict MaterialPy::getProperties() const
|
||||
dict.setItem(Py::String("SourceURL"), Py::String(getMaterialPtr()->getURL().toStdString()));
|
||||
|
||||
auto properties = getMaterialPtr()->getPhysicalProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
auto materialProperty = it->second;
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
|
||||
if (!materialProperty->isNull()) {
|
||||
auto value = materialProperty->getDictionaryString();
|
||||
@@ -309,9 +309,9 @@ Py::Dict MaterialPy::getProperties() const
|
||||
}
|
||||
|
||||
properties = getMaterialPtr()->getAppearanceProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
auto materialProperty = it->second;
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
|
||||
if (!materialProperty->isNull()) {
|
||||
auto value = materialProperty->getDictionaryString();
|
||||
@@ -327,9 +327,9 @@ Py::Dict MaterialPy::getPhysicalProperties() const
|
||||
Py::Dict dict;
|
||||
|
||||
auto properties = getMaterialPtr()->getPhysicalProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
auto materialProperty = it->second;
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
|
||||
if (!materialProperty->isNull()) {
|
||||
auto value = materialProperty->getDictionaryString();
|
||||
@@ -345,9 +345,9 @@ Py::Dict MaterialPy::getAppearanceProperties() const
|
||||
Py::Dict dict;
|
||||
|
||||
auto properties = getMaterialPtr()->getAppearanceProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
auto materialProperty = it->second;
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
|
||||
if (!materialProperty->isNull()) {
|
||||
auto value = materialProperty->getDictionaryString();
|
||||
@@ -425,7 +425,7 @@ PyObject* MaterialPy::getPhysicalValue(PyObject* args)
|
||||
std::static_pointer_cast<Materials::Material2DArray>(property->getMaterialValue());
|
||||
return new Array2DPy(new Material2DArray(*value));
|
||||
}
|
||||
else if (property->getType() == MaterialValue::Array3D) {
|
||||
if (property->getType() == MaterialValue::Array3D) {
|
||||
auto value =
|
||||
std::static_pointer_cast<Materials::Material3DArray>(property->getMaterialValue());
|
||||
return new Array3DPy(new Material3DArray(*value));
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "MaterialLibrary.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "ModelManager.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
@@ -142,6 +143,32 @@ QString MaterialProperty::getYAMLString() const
|
||||
return _valuePtr->getYAMLString();
|
||||
}
|
||||
|
||||
App::Color MaterialProperty::getColor() const
|
||||
{
|
||||
auto colorString = getValue().toString();
|
||||
std::stringstream stream(colorString.toStdString());
|
||||
|
||||
char c;
|
||||
stream >> c; // read "("
|
||||
float red;
|
||||
stream >> red;
|
||||
stream >> c; // ","
|
||||
float green;
|
||||
stream >> green;
|
||||
stream >> c; // ","
|
||||
float blue;
|
||||
stream >> blue;
|
||||
stream >> c; // ","
|
||||
float alpha = 1.0;
|
||||
if (c == ',') {
|
||||
stream >> alpha;
|
||||
}
|
||||
|
||||
App::Color color(red, green, blue, alpha);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
QString MaterialProperty::getDictionaryString() const
|
||||
{
|
||||
// This method produces a non-localized string. For a localized string use
|
||||
@@ -377,6 +404,13 @@ void MaterialProperty::setURL(const QString& value)
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setColor(const App::Color& value)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(" << value.r << ", " << value.g << ", " << value.b << ", " << value.a << ")";
|
||||
_valuePtr->setValue(QVariant(QString::fromStdString(ss.str())));
|
||||
}
|
||||
|
||||
MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
@@ -1434,6 +1468,23 @@ Material& Material::operator=(const Material& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Material& Material::operator=(const App::Material& other)
|
||||
{
|
||||
if (!hasAppearanceModel(ModelUUIDs::ModelUUID_Rendering_Basic)) {
|
||||
addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
}
|
||||
|
||||
getAppearanceProperty(QString::fromLatin1("AmbientColor"))->setColor(other.ambientColor);
|
||||
getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->setColor(other.diffuseColor);
|
||||
getAppearanceProperty(QString::fromLatin1("SpecularColor"))->setColor(other.specularColor);
|
||||
getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->setColor(other.emissiveColor);
|
||||
getAppearanceProperty(QString::fromLatin1("Shininess"))->setFloat(other.shininess);
|
||||
getAppearanceProperty(QString::fromLatin1("Transparency"))->setFloat(other.transparency);
|
||||
// std::string uuid;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize models by removing any inherited models
|
||||
*/
|
||||
@@ -1509,3 +1560,50 @@ QStringList Material::inheritedAddedModels(const Material& parent) const
|
||||
*/
|
||||
void Material::inheritedPropertyDiff([[maybe_unused]] const QString& parent)
|
||||
{}
|
||||
|
||||
/*
|
||||
* Return an App::Material object describing the materials appearance, or DEFAULT if
|
||||
* undefined.
|
||||
*/
|
||||
App::Material Material::getMaterialAppearance() const
|
||||
{
|
||||
App::Material material(App::Material::DEFAULT);
|
||||
|
||||
bool custom = false;
|
||||
if (hasAppearanceProperty(QString::fromLatin1("AmbientColor"))) {
|
||||
material.ambientColor =
|
||||
getAppearanceProperty(QString::fromLatin1("AmbientColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QString::fromLatin1("DiffuseColor"))) {
|
||||
material.diffuseColor =
|
||||
getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QString::fromLatin1("SpecularColor"))) {
|
||||
material.specularColor =
|
||||
getAppearanceProperty(QString::fromLatin1("SpecularColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QString::fromLatin1("EmissiveColor"))) {
|
||||
material.emissiveColor =
|
||||
getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QString::fromLatin1("Shininess"))) {
|
||||
material.shininess = getAppearanceProperty(QString::fromLatin1("Shininess"))->getFloat();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QString::fromLatin1("Transparency"))) {
|
||||
material.transparency =
|
||||
getAppearanceProperty(QString::fromLatin1("Transparency"))->getFloat();
|
||||
custom = true;
|
||||
}
|
||||
|
||||
if (custom) {
|
||||
material.setType(App::Material::USER_DEFINED);
|
||||
material.uuid = getUUID().toStdString();
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <QTextStream>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Color.h>
|
||||
#include <App/Material.h>
|
||||
#include <Base/BaseClass.h>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
@@ -79,11 +81,24 @@ public:
|
||||
QString getString() const;
|
||||
QString getYAMLString() const;
|
||||
QString getDictionaryString() const; // Non-localized string
|
||||
bool getBoolean() const;
|
||||
int getInt() const;
|
||||
double getFloat() const;
|
||||
bool getBoolean() const
|
||||
{
|
||||
return getValue().toBool();
|
||||
}
|
||||
int getInt() const
|
||||
{
|
||||
return getValue().toInt();
|
||||
}
|
||||
double getFloat() const
|
||||
{
|
||||
return getValue().toFloat();
|
||||
}
|
||||
const Base::Quantity& getQuantity() const;
|
||||
const QString getURL() const;
|
||||
QString getURL() const
|
||||
{
|
||||
return getValue().toString();
|
||||
}
|
||||
App::Color getColor() const;
|
||||
|
||||
MaterialProperty& getColumn(int column);
|
||||
const MaterialProperty& getColumn(int column) const;
|
||||
@@ -109,6 +124,7 @@ public:
|
||||
void setQuantity(const QString& value);
|
||||
void setList(const QList<QVariant>& value);
|
||||
void setURL(const QString& value);
|
||||
void setColor(const App::Color& value);
|
||||
|
||||
MaterialProperty& operator=(const MaterialProperty& other);
|
||||
friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property);
|
||||
@@ -218,6 +234,8 @@ public:
|
||||
return &_appearanceUuids;
|
||||
}
|
||||
|
||||
App::Material getMaterialAppearance() const;
|
||||
|
||||
void setLibrary(const std::shared_ptr<MaterialLibrary>& library)
|
||||
{
|
||||
_library = library;
|
||||
@@ -365,8 +383,24 @@ public:
|
||||
|
||||
void save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool saveInherited);
|
||||
|
||||
/*
|
||||
* Assignment operator
|
||||
*/
|
||||
Material& operator=(const Material& other);
|
||||
|
||||
/*
|
||||
* Set the appearance properties
|
||||
*/
|
||||
Material& operator=(const App::Material& other);
|
||||
|
||||
bool operator==(const Material& other) const
|
||||
{
|
||||
if (&other == this) {
|
||||
return true;
|
||||
}
|
||||
return getTypeId() == other.getTypeId() && _uuid == other._uuid;
|
||||
}
|
||||
|
||||
protected:
|
||||
void addModel(const QString& uuid);
|
||||
static void removeUUID(QSet<QString>& uuidList, const QString& uuid);
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material property descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<!-- <Methode Name="mirror">
|
||||
<Documentation>
|
||||
<UserDocu>Performs the symmetrical transformation of this geometric object</UserDocu>
|
||||
</Documentation>
|
||||
</Methode> -->
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property name.</UserDocu>
|
||||
|
||||
119
src/Mod/Material/App/PropertyMaterial.cpp
Normal file
119
src/Mod/Material/App/PropertyMaterial.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 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 <QMetaType>
|
||||
#include <QUuid>
|
||||
#endif
|
||||
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "MaterialPy.h"
|
||||
#include "PropertyMaterial.h"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::PropertyMaterial */
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::PropertyMaterial, App::Property)
|
||||
|
||||
PropertyMaterial::PropertyMaterial() = default;
|
||||
|
||||
PropertyMaterial::~PropertyMaterial() = default;
|
||||
|
||||
void PropertyMaterial::setValue(const Material& mat)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_material = mat;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyMaterial::setValue(const App::Material& mat)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_material = mat;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const Material& PropertyMaterial::getValue() const
|
||||
{
|
||||
return _material;
|
||||
}
|
||||
|
||||
PyObject* PropertyMaterial::getPyObject()
|
||||
{
|
||||
return new MaterialPy(new Material(_material));
|
||||
}
|
||||
|
||||
void PropertyMaterial::setPyObject(PyObject* value)
|
||||
{
|
||||
if (PyObject_TypeCheck(value, &(MaterialPy::Type))) {
|
||||
setValue(*static_cast<MaterialPy*>(value)->getMaterialPtr());
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'Material' not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyMaterial::Save(Base::Writer& writer) const
|
||||
{
|
||||
writer.Stream() << writer.ind() << "<PropertyMaterial uuid=\""
|
||||
<< _material.getUUID().toStdString() << "\"/>" << std::endl;
|
||||
}
|
||||
|
||||
void PropertyMaterial::Restore(Base::XMLReader& reader)
|
||||
{
|
||||
// read my Element
|
||||
reader.readElement("PropertyMaterial");
|
||||
// get the value of my Attribute
|
||||
aboutToSetValue();
|
||||
auto uuid = reader.getAttribute("uuid");
|
||||
_material.setUUID(QString::fromLatin1(uuid));
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const char* PropertyMaterial::getEditorName() const
|
||||
{
|
||||
if (testStatus(MaterialEdit)) {
|
||||
return ""; //"Gui::PropertyEditor::PropertyMaterialItem";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
App::Property* PropertyMaterial::Copy() const
|
||||
{
|
||||
PropertyMaterial* p = new PropertyMaterial();
|
||||
p->_material = _material;
|
||||
return p;
|
||||
}
|
||||
|
||||
void PropertyMaterial::Paste(const App::Property& from)
|
||||
{
|
||||
aboutToSetValue();
|
||||
_material = dynamic_cast<const PropertyMaterial&>(from)._material;
|
||||
hasSetValue();
|
||||
}
|
||||
101
src/Mod/Material/App/PropertyMaterial.h
Normal file
101
src/Mod/Material/App/PropertyMaterial.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023-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/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_PROPERTYMATERIAL_H
|
||||
#define MATERIAL_PROPERTYMATERIAL_H
|
||||
|
||||
#include <App/Property.h>
|
||||
#include <Base/Reader.h>
|
||||
|
||||
#include "Materials.h"
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Material;
|
||||
}
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
/** Material properties
|
||||
* This is the father of all properties handling colors.
|
||||
*/
|
||||
class MaterialsExport PropertyMaterial: public App::Property
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
/**
|
||||
* A constructor.
|
||||
* A more elaborate description of the constructor.
|
||||
*/
|
||||
PropertyMaterial();
|
||||
|
||||
/**
|
||||
* A destructor.
|
||||
* A more elaborate description of the destructor.
|
||||
*/
|
||||
~PropertyMaterial() override;
|
||||
|
||||
/** Sets the property
|
||||
*/
|
||||
void setValue(const Material& mat);
|
||||
|
||||
/** Sets the appearance properties
|
||||
*/
|
||||
void setValue(const App::Material& mat);
|
||||
|
||||
/** This method returns a string representation of the property
|
||||
*/
|
||||
const Material& getValue() const;
|
||||
|
||||
PyObject* getPyObject() override;
|
||||
void setPyObject(PyObject*) override;
|
||||
|
||||
void Save(Base::Writer& writer) const override;
|
||||
void Restore(Base::XMLReader& reader) override;
|
||||
|
||||
const char* getEditorName() const override;
|
||||
|
||||
Property* Copy() const override;
|
||||
void Paste(const Property& from) override;
|
||||
|
||||
unsigned int getMemSize() const override
|
||||
{
|
||||
return sizeof(_material);
|
||||
}
|
||||
|
||||
bool isSame(const Property& other) const override
|
||||
{
|
||||
if (&other == this) {
|
||||
return true;
|
||||
}
|
||||
return getTypeId() == other.getTypeId()
|
||||
&& getValue() == static_cast<decltype(this)>(&other)->getValue();
|
||||
}
|
||||
|
||||
private:
|
||||
Material _material;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_PROPERTYMATERIAL_H
|
||||
@@ -34,6 +34,7 @@ SET(Material_Icon_Files
|
||||
|
||||
# collect all the material cards:
|
||||
SET(MaterialLib_Files
|
||||
Resources/Materials/Standard/Default.FCMat
|
||||
Resources/Materials/Standard/Aggregate/Concrete-EN-C35_45.FCMat
|
||||
Resources/Materials/Standard/Aggregate/Concrete-Generic.FCMat
|
||||
Resources/Materials/Standard/Aggregate/Reinforcement-FIB-B500.FCMat
|
||||
|
||||
@@ -19,8 +19,9 @@ include_directories(
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
set(MatGui_LIBS
|
||||
Material
|
||||
Materials
|
||||
FreeCADGui
|
||||
Part
|
||||
)
|
||||
|
||||
include_directories(
|
||||
@@ -39,6 +40,8 @@ qt_add_resources(MatGui_QRC_SRCS Resources/Material.qrc ${Material_TR_QRC})
|
||||
set(MatGui_UIC_SRCS
|
||||
Array2D.ui
|
||||
Array3D.ui
|
||||
DlgDisplayProperties.ui
|
||||
DlgMaterial.ui
|
||||
DlgSettingsMaterial.ui
|
||||
ImageEdit.ui
|
||||
ListEdit.ui
|
||||
@@ -67,6 +70,15 @@ SET(MatGui_SRCS
|
||||
BaseDelegate.cpp
|
||||
BaseDelegate.h
|
||||
Command.cpp
|
||||
DlgDisplayPropertiesImp.cpp
|
||||
DlgDisplayPropertiesImp.h
|
||||
DlgDisplayProperties.ui
|
||||
DlgMaterialImp.cpp
|
||||
DlgMaterialImp.h
|
||||
DlgDisplayProperties.ui
|
||||
DlgMaterialImp.cpp
|
||||
DlgMaterialImp.h
|
||||
DlgMaterial.ui
|
||||
DlgSettingsMaterial.cpp
|
||||
DlgSettingsMaterial.h
|
||||
DlgSettingsMaterial.ui
|
||||
@@ -88,6 +100,8 @@ SET(MatGui_SRCS
|
||||
MaterialsEditor.cpp
|
||||
MaterialsEditor.h
|
||||
MaterialsEditor.ui
|
||||
MaterialTreeWidget.cpp
|
||||
MaterialTreeWidget.h
|
||||
ModelSelect.cpp
|
||||
ModelSelect.h
|
||||
ModelSelect.ui
|
||||
|
||||
@@ -25,8 +25,12 @@
|
||||
#endif
|
||||
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/Selection.h>
|
||||
|
||||
#include "DlgDisplayPropertiesImp.h"
|
||||
#include "DlgMaterialImp.h"
|
||||
#include "MaterialSave.h"
|
||||
#include "MaterialsEditor.h"
|
||||
#include "ModelSelect.h"
|
||||
@@ -71,6 +75,64 @@ bool CmdMaterialsEdit::isActive()
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Std_SetAppearance
|
||||
//===========================================================================
|
||||
DEF_STD_CMD_A(StdCmdSetAppearance)
|
||||
|
||||
StdCmdSetAppearance::StdCmdSetAppearance()
|
||||
: Command("Std_SetAppearance")
|
||||
{
|
||||
sGroup = "Standard-View";
|
||||
sMenuText = QT_TR_NOOP("Appearance...");
|
||||
sToolTipText = QT_TR_NOOP("Sets the display properties of the selected object");
|
||||
sWhatsThis = "Std_SetAppearance";
|
||||
sStatusTip = QT_TR_NOOP("Sets the display properties of the selected object");
|
||||
sPixmap = "Std_SetAppearance";
|
||||
sAccel = "Ctrl+D";
|
||||
eType = Alter3DView;
|
||||
}
|
||||
|
||||
void StdCmdSetAppearance::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
Gui::Control().showDialog(new MatGui::TaskDisplayProperties());
|
||||
}
|
||||
|
||||
bool StdCmdSetAppearance::isActive()
|
||||
{
|
||||
return (Gui::Control().activeDialog() == nullptr) && (Gui::Selection().size() != 0);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Std_SetMaterial
|
||||
//===========================================================================
|
||||
DEF_STD_CMD_A(StdCmdSetMaterial)
|
||||
|
||||
StdCmdSetMaterial::StdCmdSetMaterial()
|
||||
: Command("Std_SetMaterial")
|
||||
{
|
||||
sGroup = "Standard-View";
|
||||
sMenuText = QT_TR_NOOP("Material...");
|
||||
sToolTipText = QT_TR_NOOP("Sets the material of the selected object");
|
||||
sWhatsThis = "Std_SetMaterial";
|
||||
sStatusTip = QT_TR_NOOP("Sets the material of the selected object");
|
||||
sPixmap = "Materials_Edit";
|
||||
// sAccel = "Ctrl+D";
|
||||
// eType = Alter3DView;
|
||||
}
|
||||
|
||||
void StdCmdSetMaterial::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
Gui::Control().showDialog(new MatGui::TaskMaterial());
|
||||
}
|
||||
|
||||
bool StdCmdSetMaterial::isActive()
|
||||
{
|
||||
return (Gui::Control().activeDialog() == nullptr) && (Gui::Selection().size() != 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void CreateMaterialCommands()
|
||||
@@ -78,4 +140,6 @@ void CreateMaterialCommands()
|
||||
Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
|
||||
rcCmdMgr.addCommand(new CmdMaterialsEdit());
|
||||
rcCmdMgr.addCommand(new StdCmdSetAppearance());
|
||||
rcCmdMgr.addCommand(new StdCmdSetMaterial());
|
||||
}
|
||||
|
||||
524
src/Mod/Material/Gui/DlgDisplayProperties.ui
Normal file
524
src/Mod/Material/Gui/DlgDisplayProperties.ui
Normal file
@@ -0,0 +1,524 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::DlgDisplayProperties</class>
|
||||
<widget class="QDialog" name="MatGui::DlgDisplayProperties">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>503</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Display properties</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox1">
|
||||
<property name="title">
|
||||
<string>Viewing mode</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel1">
|
||||
<property name="text">
|
||||
<string>Document window:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="changeMode"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel1_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="changePlot">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox2">
|
||||
<property name="title">
|
||||
<string>Display</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel2">
|
||||
<property name="text">
|
||||
<string>Point size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>71</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinPointSize">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="textLabel3">
|
||||
<property name="text">
|
||||
<string>Line width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>71</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinLineWidth">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="textLabel1_2">
|
||||
<property name="text">
|
||||
<string>Transparency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinTransparency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Line transparency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderLineTransparency">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinLineTransparency">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox3">
|
||||
<property name="title">
|
||||
<string>Material</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Color plot:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Shape Appearance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::ColorButton" name="buttonPointColor"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Point color:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Line color:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="buttonColorPlot">
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::ColorButton" name="buttonLineColor"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="buttonUserDefinedMaterial">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>32767</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="MatGui::MaterialTreeWidget" name="widgetMaterial" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Gui/Widgets.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MatGui::MaterialTreeWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Mod/Material/Gui/MaterialTreeWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>changeMode</tabstop>
|
||||
<tabstop>changePlot</tabstop>
|
||||
<tabstop>buttonLineColor</tabstop>
|
||||
<tabstop>spinPointSize</tabstop>
|
||||
<tabstop>spinLineWidth</tabstop>
|
||||
<tabstop>horizontalSlider</tabstop>
|
||||
<tabstop>spinTransparency</tabstop>
|
||||
<tabstop>sliderLineTransparency</tabstop>
|
||||
<tabstop>spinLineTransparency</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>spinTransparency</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>horizontalSlider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>240</x>
|
||||
<y>339</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>113</x>
|
||||
<y>339</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>horizontalSlider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>spinTransparency</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>113</x>
|
||||
<y>339</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>240</x>
|
||||
<y>339</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>sliderLineTransparency</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>spinLineTransparency</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>147</x>
|
||||
<y>408</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>246</x>
|
||||
<y>393</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spinLineTransparency</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>sliderLineTransparency</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>254</x>
|
||||
<y>402</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>98</x>
|
||||
<y>404</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
700
src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp
Normal file
700
src/Mod/Material/Gui/DlgDisplayPropertiesImp.cpp
Normal file
@@ -0,0 +1,700 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QDockWidget>
|
||||
#include <QSignalBlocker>
|
||||
#include <algorithm>
|
||||
#include <boost_signals2.hpp>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/DlgMaterialPropertiesImp.h>
|
||||
#include <Gui/DockWindowManager.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/ModelUuids.h>
|
||||
|
||||
#include "DlgDisplayPropertiesImp.h"
|
||||
#include "ui_DlgDisplayProperties.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
using namespace std;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DlgDisplayPropertiesImp */
|
||||
|
||||
#if 0 // needed for Qt's lupdate utility
|
||||
qApp->translate("QDockWidget", "Display properties");
|
||||
#endif
|
||||
|
||||
class DlgDisplayPropertiesImp::Private
|
||||
{
|
||||
using DlgDisplayPropertiesImp_Connection = boost::signals2::connection;
|
||||
|
||||
public:
|
||||
Ui::DlgDisplayProperties ui;
|
||||
bool floating;
|
||||
DlgDisplayPropertiesImp_Connection connectChangedObject;
|
||||
|
||||
static void setElementColor(const std::vector<Gui::ViewProvider*>& views,
|
||||
const char* property,
|
||||
Gui::ColorButton* buttonColor)
|
||||
{
|
||||
bool hasElementColor = false;
|
||||
for (const auto& view : views) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyColor*>(view->getPropertyByName(property))) {
|
||||
App::Color color = prop->getValue();
|
||||
QSignalBlocker block(buttonColor);
|
||||
buttonColor->setColor(color.asValue<QColor>());
|
||||
hasElementColor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buttonColor->setEnabled(hasElementColor);
|
||||
}
|
||||
|
||||
static void setElementAppearance(const std::vector<Gui::ViewProvider*>& views,
|
||||
const char* property,
|
||||
Gui::ColorButton* buttonColor)
|
||||
{
|
||||
bool hasElementColor = false;
|
||||
for (const auto& view : views) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyMaterial*>(view->getPropertyByName(property))) {
|
||||
App::Color color = prop->getDiffuseColor();
|
||||
QSignalBlocker block(buttonColor);
|
||||
buttonColor->setColor(color.asValue<QColor>());
|
||||
hasElementColor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buttonColor->setEnabled(hasElementColor);
|
||||
}
|
||||
|
||||
static void setDrawStyle(const std::vector<Gui::ViewProvider*>& views,
|
||||
const char* property,
|
||||
QSpinBox* spinbox)
|
||||
{
|
||||
bool hasDrawStyle = false;
|
||||
for (const auto& view : views) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyFloat*>(view->getPropertyByName(property))) {
|
||||
QSignalBlocker block(spinbox);
|
||||
spinbox->setValue(int(prop->getValue()));
|
||||
hasDrawStyle = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spinbox->setEnabled(hasDrawStyle);
|
||||
}
|
||||
|
||||
static void setTransparency(const std::vector<Gui::ViewProvider*>& views,
|
||||
const char* property,
|
||||
QSpinBox* spinbox,
|
||||
QSlider* slider)
|
||||
{
|
||||
bool hasTransparency = false;
|
||||
for (const auto& view : views) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyInteger*>(view->getPropertyByName(property))) {
|
||||
QSignalBlocker blockSpinBox(spinbox);
|
||||
spinbox->setValue(prop->getValue());
|
||||
|
||||
QSignalBlocker blockSlider(slider);
|
||||
slider->setValue(prop->getValue());
|
||||
hasTransparency = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spinbox->setEnabled(hasTransparency);
|
||||
slider->setEnabled(hasTransparency);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a DlgDisplayPropertiesImp which is a child of 'parent', with the
|
||||
* name 'name' and widget flags set to 'f'
|
||||
*
|
||||
* The dialog will by default be modeless, unless you set 'modal' to
|
||||
* true to construct a modal dialog.
|
||||
*/
|
||||
DlgDisplayPropertiesImp::DlgDisplayPropertiesImp(bool floating, QWidget* parent, Qt::WindowFlags fl)
|
||||
: QDialog(parent, fl)
|
||||
, d(new Private)
|
||||
{
|
||||
d->ui.setupUi(this);
|
||||
setupConnections();
|
||||
|
||||
d->ui.textLabel1_3->hide();
|
||||
d->ui.changePlot->hide();
|
||||
d->ui.buttonLineColor->setModal(false);
|
||||
d->ui.buttonPointColor->setModal(false);
|
||||
d->floating = floating;
|
||||
|
||||
// Create a filter to only include current format materials
|
||||
// that contain the basic render model.
|
||||
auto filter = std::make_shared<Materials::MaterialFilter>();
|
||||
filter->setIncludeEmptyFolders(false);
|
||||
filter->setIncludeLegacy(false);
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
d->ui.widgetMaterial->setFilter(filter);
|
||||
|
||||
std::vector<Gui::ViewProvider*> views = getSelection();
|
||||
setDisplayModes(views);
|
||||
setMaterial(views);
|
||||
setColorPlot(views);
|
||||
setShapeAppearance(views);
|
||||
setLineColor(views);
|
||||
setPointColor(views);
|
||||
setPointSize(views);
|
||||
setLineWidth(views);
|
||||
setTransparency(views);
|
||||
setLineTransparency(views);
|
||||
|
||||
// embed this dialog into a dockable widget container
|
||||
if (floating) {
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
QDockWidget* dw =
|
||||
pDockMgr->addDockWindow("Display properties", this, Qt::AllDockWidgetAreas);
|
||||
dw->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
|
||||
dw->setFloating(true);
|
||||
dw->show();
|
||||
}
|
||||
|
||||
Gui::Selection().Attach(this);
|
||||
|
||||
// NOLINTBEGIN
|
||||
d->connectChangedObject = Gui::Application::Instance->signalChangedObject.connect(
|
||||
std::bind(&DlgDisplayPropertiesImp::slotChangedObject, this, sp::_1, sp::_2));
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
DlgDisplayPropertiesImp::~DlgDisplayPropertiesImp()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
d->connectChangedObject.disconnect();
|
||||
Gui::Selection().Detach(this);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setupConnections()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
connect(d->ui.changeMode,
|
||||
qOverload<const QString&>(&QComboBox::activated),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onChangeModeActivated);
|
||||
connect(d->ui.changePlot,
|
||||
qOverload<const QString&>(&QComboBox::activated),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onChangePlotActivated);
|
||||
#else
|
||||
connect(d->ui.changeMode,
|
||||
&QComboBox::textActivated,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onChangeModeActivated);
|
||||
connect(d->ui.changePlot,
|
||||
&QComboBox::textActivated,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onChangePlotActivated);
|
||||
#endif
|
||||
connect(d->ui.spinTransparency,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onSpinTransparencyValueChanged);
|
||||
connect(d->ui.spinPointSize,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onSpinPointSizeValueChanged);
|
||||
connect(d->ui.buttonLineColor,
|
||||
&Gui::ColorButton::changed,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onButtonLineColorChanged);
|
||||
connect(d->ui.buttonPointColor,
|
||||
&Gui::ColorButton::changed,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onButtonPointColorChanged);
|
||||
connect(d->ui.spinLineWidth,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onSpinLineWidthValueChanged);
|
||||
connect(d->ui.spinLineTransparency,
|
||||
qOverload<int>(&QSpinBox::valueChanged),
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onSpinLineTransparencyValueChanged);
|
||||
connect(d->ui.buttonUserDefinedMaterial,
|
||||
&Gui::ColorButton::clicked,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onButtonUserDefinedMaterialClicked);
|
||||
connect(d->ui.buttonColorPlot,
|
||||
&Gui::ColorButton::clicked,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onButtonColorPlotClicked);
|
||||
connect(d->ui.widgetMaterial,
|
||||
&MaterialTreeWidget::materialSelected,
|
||||
this,
|
||||
&DlgDisplayPropertiesImp::onMaterialSelected);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::changeEvent(QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
d->ui.retranslateUi(this);
|
||||
}
|
||||
QDialog::changeEvent(e);
|
||||
}
|
||||
|
||||
/// @cond DOXERR
|
||||
void DlgDisplayPropertiesImp::OnChange(Gui::SelectionSingleton::SubjectType& rCaller,
|
||||
Gui::SelectionSingleton::MessageType Reason)
|
||||
{
|
||||
Q_UNUSED(rCaller);
|
||||
if (Reason.Type == Gui::SelectionChanges::AddSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::RmvSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::SetSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::ClrSelection) {
|
||||
std::vector<Gui::ViewProvider*> views = getSelection();
|
||||
setDisplayModes(views);
|
||||
setMaterial(views);
|
||||
setColorPlot(views);
|
||||
setShapeAppearance(views);
|
||||
setLineColor(views);
|
||||
setPointColor(views);
|
||||
setPointSize(views);
|
||||
setLineWidth(views);
|
||||
setTransparency(views);
|
||||
setLineTransparency(views);
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
void DlgDisplayPropertiesImp::slotChangedObject(const Gui::ViewProvider& obj,
|
||||
const App::Property& prop)
|
||||
{
|
||||
// This method gets called if a property of any view provider is changed.
|
||||
// We pick out all the properties for which we need to update this dialog.
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
auto vp = std::find_if(Provider.begin(), Provider.end(), [&obj](Gui::ViewProvider* v) {
|
||||
return v == &obj;
|
||||
});
|
||||
|
||||
if (vp != Provider.end()) {
|
||||
const char* name = obj.getPropertyName(&prop);
|
||||
// this is not a property of the view provider but of the document object
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
std::string prop_name = name;
|
||||
if (prop.is<App::PropertyColor>()) {
|
||||
App::Color value = static_cast<const App::PropertyColor&>(prop).getValue();
|
||||
if (prop_name == "LineColor") {
|
||||
bool blocked = d->ui.buttonLineColor->blockSignals(true);
|
||||
d->ui.buttonLineColor->setColor(QColor((int)(255.0f * value.r),
|
||||
(int)(255.0f * value.g),
|
||||
(int)(255.0f * value.b)));
|
||||
d->ui.buttonLineColor->blockSignals(blocked);
|
||||
}
|
||||
else if (prop_name == "PointColor") {
|
||||
bool blocked = d->ui.buttonPointColor->blockSignals(true);
|
||||
d->ui.buttonPointColor->setColor(QColor((int)(255.0f * value.r),
|
||||
(int)(255.0f * value.g),
|
||||
(int)(255.0f * value.b)));
|
||||
d->ui.buttonPointColor->blockSignals(blocked);
|
||||
}
|
||||
}
|
||||
else if (prop.isDerivedFrom<App::PropertyMaterialList>()) {
|
||||
auto& value = static_cast<const App::PropertyMaterialList&>(prop).getValue();
|
||||
if (prop_name == "ShapeAppearance") {
|
||||
// bool blocked = d->ui.buttonColor->blockSignals(true);
|
||||
// auto color = value.diffuseColor;
|
||||
// d->ui.buttonColor->setColor(QColor((int)(255.0f * color.r),
|
||||
// (int)(255.0f * color.g),
|
||||
// (int)(255.0f * color.b)));
|
||||
// d->ui.buttonColor->blockSignals(blocked);
|
||||
}
|
||||
}
|
||||
else if (prop.isDerivedFrom<App::PropertyInteger>()) {
|
||||
long value = static_cast<const App::PropertyInteger&>(prop).getValue();
|
||||
if (prop_name == "Transparency") {
|
||||
bool blocked = d->ui.spinTransparency->blockSignals(true);
|
||||
d->ui.spinTransparency->setValue(value);
|
||||
d->ui.spinTransparency->blockSignals(blocked);
|
||||
blocked = d->ui.horizontalSlider->blockSignals(true);
|
||||
d->ui.horizontalSlider->setValue(value);
|
||||
d->ui.horizontalSlider->blockSignals(blocked);
|
||||
}
|
||||
else if (prop_name == "LineTransparency") {
|
||||
bool blocked = d->ui.spinLineTransparency->blockSignals(true);
|
||||
d->ui.spinLineTransparency->setValue(value);
|
||||
d->ui.spinLineTransparency->blockSignals(blocked);
|
||||
blocked = d->ui.sliderLineTransparency->blockSignals(true);
|
||||
d->ui.sliderLineTransparency->setValue(value);
|
||||
d->ui.sliderLineTransparency->blockSignals(blocked);
|
||||
}
|
||||
}
|
||||
else if (prop.isDerivedFrom<App::PropertyFloat>()) {
|
||||
double value = static_cast<const App::PropertyFloat&>(prop).getValue();
|
||||
if (prop_name == "PointSize") {
|
||||
bool blocked = d->ui.spinPointSize->blockSignals(true);
|
||||
d->ui.spinPointSize->setValue((int)value);
|
||||
d->ui.spinPointSize->blockSignals(blocked);
|
||||
}
|
||||
else if (prop_name == "LineWidth") {
|
||||
bool blocked = d->ui.spinLineWidth->blockSignals(true);
|
||||
d->ui.spinLineWidth->setValue((int)value);
|
||||
d->ui.spinLineWidth->blockSignals(blocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the dock window this object is embedded into without destroying itself.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::reject()
|
||||
{
|
||||
if (d->floating) {
|
||||
// closes the dock window
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
pDockMgr->removeDockWindow(this);
|
||||
}
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog that allows to modify the 'ShapeMaterial' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onButtonUserDefinedMaterialClicked()
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
Gui::Dialog::DlgMaterialPropertiesImp dlg("ShapeMaterial", this);
|
||||
dlg.setViewProviders(Provider);
|
||||
dlg.exec();
|
||||
|
||||
// d->ui.buttonColor->setColor(dlg.diffuseColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog that allows to modify the 'ShapeMaterial' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onButtonColorPlotClicked()
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
static QPointer<Gui::Dialog::DlgMaterialPropertiesImp> dlg = nullptr;
|
||||
if (!dlg) {
|
||||
dlg = new Gui::Dialog::DlgMaterialPropertiesImp("TextureMaterial", this);
|
||||
}
|
||||
dlg->setModal(false);
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dlg->setViewProviders(Provider);
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'Display' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onChangeModeActivated(const QString& s)
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyEnumeration*>(it->getPropertyByName("DisplayMode"))) {
|
||||
prop->setValue(static_cast<const char*>(s.toLatin1()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::onChangePlotActivated(const QString& s)
|
||||
{
|
||||
Base::Console().Log("Plot = %s\n", (const char*)s.toLatin1());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'Transparency' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onSpinTransparencyValueChanged(int transparency)
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyInteger*>(it->getPropertyByName("Transparency"))) {
|
||||
prop->setValue(transparency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'PointSize' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onSpinPointSizeValueChanged(int pointsize)
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyFloat*>(it->getPropertyByName("PointSize"))) {
|
||||
prop->setValue(static_cast<double>(pointsize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'LineWidth' property of all selected view providers.
|
||||
*/
|
||||
void DlgDisplayPropertiesImp::onSpinLineWidthValueChanged(int linewidth)
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyFloat*>(it->getPropertyByName("LineWidth"))) {
|
||||
prop->setValue(static_cast<double>(linewidth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::onButtonLineColorChanged()
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
QColor s = d->ui.buttonLineColor->color();
|
||||
App::Color c(s.red() / 255.0, s.green() / 255.0, s.blue() / 255.0);
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyColor*>(it->getPropertyByName("LineColor"))) {
|
||||
prop->setValue(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::onButtonPointColorChanged()
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
QColor s = d->ui.buttonPointColor->color();
|
||||
App::Color c(s.red() / 255.0, s.green() / 255.0, s.blue() / 255.0);
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyColor*>(it->getPropertyByName("PointColor"))) {
|
||||
prop->setValue(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::onSpinLineTransparencyValueChanged(int transparency)
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyInteger*>(it->getPropertyByName("LineTransparency"))) {
|
||||
prop->setValue(transparency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setDisplayModes(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
QStringList commonModes, modes;
|
||||
for (auto it = views.begin(); it != views.end(); ++it) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyEnumeration*>((*it)->getPropertyByName("DisplayMode"))) {
|
||||
if (!prop->hasEnums()) {
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> value = prop->getEnumVector();
|
||||
if (it == views.begin()) {
|
||||
for (const auto& jt : value) {
|
||||
commonModes << QLatin1String(jt.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const auto& jt : value) {
|
||||
if (commonModes.contains(QLatin1String(jt.c_str()))) {
|
||||
modes << QLatin1String(jt.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
commonModes = modes;
|
||||
modes.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->ui.changeMode->clear();
|
||||
d->ui.changeMode->addItems(commonModes);
|
||||
d->ui.changeMode->setDisabled(commonModes.isEmpty());
|
||||
|
||||
// find the display mode to activate
|
||||
for (const auto& view : views) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyEnumeration*>(view->getPropertyByName("DisplayMode"))) {
|
||||
QString activeMode = QString::fromLatin1(prop->getValueAsString());
|
||||
int index = d->ui.changeMode->findText(activeMode);
|
||||
if (index != -1) {
|
||||
d->ui.changeMode->setCurrentIndex(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setMaterial(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
bool material = false;
|
||||
App::Material::MaterialType matType = App::Material::DEFAULT;
|
||||
for (auto view : views) {
|
||||
if (auto* prop =
|
||||
dynamic_cast<App::PropertyMaterial*>(view->getPropertyByName("ShapeMaterial"))) {
|
||||
material = true;
|
||||
matType = prop->getValue().getType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
d->ui.buttonUserDefinedMaterial->setEnabled(material);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setColorPlot(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
bool material = false;
|
||||
for (auto view : views) {
|
||||
auto* prop =
|
||||
dynamic_cast<App::PropertyMaterial*>(view->getPropertyByName("TextureMaterial"));
|
||||
if (prop) {
|
||||
material = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
d->ui.buttonColorPlot->setEnabled(material);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setShapeAppearance(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Q_UNUSED(views)
|
||||
|
||||
// Private::setElementAppearance(views, "ShapeColor", d->ui.buttonColor);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setLineColor(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setElementColor(views, "LineColor", d->ui.buttonLineColor);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setPointColor(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setElementColor(views, "PointColor", d->ui.buttonPointColor);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setPointSize(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setDrawStyle(views, "PointSize", d->ui.spinPointSize);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setLineWidth(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setDrawStyle(views, "LineWidth", d->ui.spinLineWidth);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setTransparency(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setTransparency(views, "Transparency", d->ui.spinTransparency, d->ui.horizontalSlider);
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::setLineTransparency(const std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
Private::setTransparency(views,
|
||||
"LineTransparency",
|
||||
d->ui.spinLineTransparency,
|
||||
d->ui.sliderLineTransparency);
|
||||
}
|
||||
|
||||
std::vector<Gui::ViewProvider*> DlgDisplayPropertiesImp::getSelection() const
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> views;
|
||||
|
||||
// get the complete selection
|
||||
std::vector<Gui::SelectionSingleton::SelObj> sel = Gui::Selection().getCompleteSelection();
|
||||
for (const auto& it : sel) {
|
||||
Gui::ViewProvider* view =
|
||||
Gui::Application::Instance->getDocument(it.pDoc)->getViewProvider(it.pObject);
|
||||
views.push_back(view);
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
void DlgDisplayPropertiesImp::onMaterialSelected(
|
||||
const std::shared_ptr<Materials::Material>& material)
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
for (auto it : Provider) {
|
||||
if (auto* prop = dynamic_cast<App::PropertyMaterialList*>(
|
||||
it->getPropertyByName("ShapeAppearance"))) {
|
||||
App::Material mat;
|
||||
mat.ambientColor =
|
||||
material->getAppearanceProperty(QString::fromLatin1("AmbientColor"))->getColor();
|
||||
mat.diffuseColor =
|
||||
material->getAppearanceProperty(QString::fromLatin1("DiffuseColor"))->getColor();
|
||||
mat.emissiveColor =
|
||||
material->getAppearanceProperty(QString::fromLatin1("EmissiveColor"))->getColor();
|
||||
mat.specularColor =
|
||||
material->getAppearanceProperty(QString::fromLatin1("SpecularColor"))->getColor();
|
||||
mat.shininess =
|
||||
material->getAppearanceProperty(QString::fromLatin1("Shininess"))->getFloat();
|
||||
mat.transparency =
|
||||
material->getAppearanceProperty(QString::fromLatin1("Transparency"))->getFloat();
|
||||
prop->setValue(mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::TaskDisplayProperties */
|
||||
|
||||
TaskDisplayProperties::TaskDisplayProperties()
|
||||
{
|
||||
this->setButtonPosition(TaskDisplayProperties::North);
|
||||
widget = new DlgDisplayPropertiesImp(false);
|
||||
addTaskBox(widget);
|
||||
}
|
||||
|
||||
TaskDisplayProperties::~TaskDisplayProperties() = default;
|
||||
|
||||
QDialogButtonBox::StandardButtons TaskDisplayProperties::getStandardButtons() const
|
||||
{
|
||||
return QDialogButtonBox::Close;
|
||||
}
|
||||
|
||||
bool TaskDisplayProperties::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return (widget->result() == QDialog::Rejected);
|
||||
}
|
||||
|
||||
#include "moc_DlgDisplayPropertiesImp.cpp"
|
||||
136
src/Mod/Material/Gui/DlgDisplayPropertiesImp.h
Normal file
136
src/Mod/Material/Gui/DlgDisplayPropertiesImp.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef MATGUI_DIALOG_DLGDISPLAYPROPERTIES_IMP_H
|
||||
#define MATGUI_DIALOG_DLGDISPLAYPROPERTIES_IMP_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <App/Material.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Property;
|
||||
}
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class ViewProvider;
|
||||
class Command;
|
||||
|
||||
/**
|
||||
* The DlgDisplayPropertiesImp class implements a dialog containing all available document
|
||||
* templates to create a new document.
|
||||
* \author Jürgen Riegel
|
||||
*/
|
||||
class DlgDisplayPropertiesImp: public QDialog, public Gui::SelectionSingleton::ObserverType
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgDisplayPropertiesImp(bool floating,
|
||||
QWidget* parent = nullptr,
|
||||
Qt::WindowFlags fl = Qt::WindowFlags());
|
||||
~DlgDisplayPropertiesImp() override;
|
||||
/// Observer message from the Selection
|
||||
void OnChange(Gui::SelectionSingleton::SubjectType& rCaller,
|
||||
Gui::SelectionSingleton::MessageType Reason) override;
|
||||
void showDefaultButtons(bool);
|
||||
void reject() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onChangeModeActivated(const QString&);
|
||||
void onChangePlotActivated(const QString&);
|
||||
void onSpinTransparencyValueChanged(int);
|
||||
void onSpinPointSizeValueChanged(int);
|
||||
void onButtonLineColorChanged();
|
||||
void onButtonPointColorChanged();
|
||||
void onSpinLineWidthValueChanged(int);
|
||||
void onSpinLineTransparencyValueChanged(int);
|
||||
void onButtonUserDefinedMaterialClicked();
|
||||
void onButtonColorPlotClicked();
|
||||
void onMaterialSelected(const std::shared_ptr<Materials::Material>& material);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent* e) override;
|
||||
|
||||
private:
|
||||
void setupConnections();
|
||||
void slotChangedObject(const Gui::ViewProvider&, const App::Property& Prop);
|
||||
void setDisplayModes(const std::vector<Gui::ViewProvider*>&);
|
||||
void setMaterial(const std::vector<Gui::ViewProvider*>&);
|
||||
void setColorPlot(const std::vector<Gui::ViewProvider*>&);
|
||||
void setShapeAppearance(const std::vector<Gui::ViewProvider*>&);
|
||||
void setLineColor(const std::vector<Gui::ViewProvider*>&);
|
||||
void setPointColor(const std::vector<Gui::ViewProvider*>&);
|
||||
void setPointSize(const std::vector<Gui::ViewProvider*>&);
|
||||
void setLineWidth(const std::vector<Gui::ViewProvider*>&);
|
||||
void setTransparency(const std::vector<Gui::ViewProvider*>&);
|
||||
void setLineTransparency(const std::vector<Gui::ViewProvider*>&);
|
||||
std::vector<Gui::ViewProvider*> getSelection() const;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
class TaskDisplayProperties: public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskDisplayProperties();
|
||||
~TaskDisplayProperties() override;
|
||||
|
||||
public:
|
||||
bool reject() override;
|
||||
|
||||
bool isAllowedAlterDocument() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool isAllowedAlterView() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool isAllowedAlterSelection() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const override;
|
||||
|
||||
private:
|
||||
DlgDisplayPropertiesImp* widget;
|
||||
};
|
||||
|
||||
} // namespace MatGui
|
||||
|
||||
#endif // MATGUI_DIALOG_DLGDISPLAYPROPERTIES_IMP_H
|
||||
52
src/Mod/Material/Gui/DlgMaterial.ui
Normal file
52
src/Mod/Material/Gui/DlgMaterial.ui
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::DlgMaterial</class>
|
||||
<widget class="QDialog" name="MatGui::DlgMaterial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>503</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Material</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="MatGui::MaterialTreeWidget" name="widgetMaterial" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MatGui::MaterialTreeWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Mod/Material/Gui/MaterialTreeWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
282
src/Mod/Material/Gui/DlgMaterialImp.cpp
Normal file
282
src/Mod/Material/Gui/DlgMaterialImp.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QDockWidget>
|
||||
#include <QSignalBlocker>
|
||||
#include <QString>
|
||||
#include <algorithm>
|
||||
#include <boost_signals2.hpp>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/DlgMaterialPropertiesImp.h>
|
||||
#include <Gui/DockWindowManager.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/ModelUuids.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
#include "DlgMaterialImp.h"
|
||||
#include "ui_DlgMaterial.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
using namespace std;
|
||||
namespace sp = std::placeholders;
|
||||
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::DlgMaterialImp */
|
||||
|
||||
#if 0 // needed for Qt's lupdate utility
|
||||
qApp->translate("QDockWidget", "Material");
|
||||
#endif
|
||||
|
||||
class DlgMaterialImp::Private
|
||||
{
|
||||
using DlgMaterialImp_Connection = boost::signals2::connection;
|
||||
|
||||
public:
|
||||
Ui::DlgMaterial ui;
|
||||
bool floating;
|
||||
DlgMaterialImp_Connection connectChangedObject;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a DlgMaterialImp which is a child of 'parent', with the
|
||||
* name 'name' and widget flags set to 'f'
|
||||
*
|
||||
* The dialog will by default be modeless, unless you set 'modal' to
|
||||
* true to construct a modal dialog.
|
||||
*/
|
||||
DlgMaterialImp::DlgMaterialImp(bool floating, QWidget* parent, Qt::WindowFlags fl)
|
||||
: QDialog(parent, fl)
|
||||
, d(new Private)
|
||||
{
|
||||
d->ui.setupUi(this);
|
||||
setupConnections();
|
||||
|
||||
d->floating = floating;
|
||||
|
||||
// // Create a filter to only include current format materials
|
||||
// // that contain the basic render model.
|
||||
// auto filter = std::make_shared<Materials::MaterialFilter>();
|
||||
// filter->setIncludeEmptyFolders(false);
|
||||
// filter->setIncludeLegacy(false);
|
||||
// filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
// d->ui.widgetMaterial->setFilter(filter);
|
||||
|
||||
std::vector<App::DocumentObject*> objects = getSelectionObjects();
|
||||
setMaterial(objects);
|
||||
|
||||
// embed this dialog into a dockable widget container
|
||||
if (floating) {
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
QDockWidget* dw =
|
||||
pDockMgr->addDockWindow("Display properties", this, Qt::AllDockWidgetAreas);
|
||||
dw->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
|
||||
dw->setFloating(true);
|
||||
dw->show();
|
||||
}
|
||||
|
||||
Gui::Selection().Attach(this);
|
||||
|
||||
// NOLINTBEGIN
|
||||
d->connectChangedObject = Gui::Application::Instance->signalChangedObject.connect(
|
||||
std::bind(&DlgMaterialImp::slotChangedObject, this, sp::_1, sp::_2));
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
DlgMaterialImp::~DlgMaterialImp()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
d->connectChangedObject.disconnect();
|
||||
Gui::Selection().Detach(this);
|
||||
}
|
||||
|
||||
void DlgMaterialImp::setupConnections()
|
||||
{
|
||||
connect(d->ui.widgetMaterial,
|
||||
&MaterialTreeWidget::materialSelected,
|
||||
this,
|
||||
&DlgMaterialImp::onMaterialSelected);
|
||||
}
|
||||
|
||||
void DlgMaterialImp::changeEvent(QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
d->ui.retranslateUi(this);
|
||||
}
|
||||
QDialog::changeEvent(e);
|
||||
}
|
||||
|
||||
/// @cond DOXERR
|
||||
void DlgMaterialImp::OnChange(Gui::SelectionSingleton::SubjectType& rCaller,
|
||||
Gui::SelectionSingleton::MessageType Reason)
|
||||
{
|
||||
Q_UNUSED(rCaller);
|
||||
if (Reason.Type == Gui::SelectionChanges::AddSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::RmvSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::SetSelection
|
||||
|| Reason.Type == Gui::SelectionChanges::ClrSelection) {
|
||||
std::vector<App::DocumentObject*> objects = getSelectionObjects();
|
||||
setMaterial(objects);
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
void DlgMaterialImp::slotChangedObject(const Gui::ViewProvider& obj, const App::Property& prop)
|
||||
{
|
||||
// This method gets called if a property of any view provider is changed.
|
||||
// We pick out all the properties for which we need to update this dialog.
|
||||
std::vector<Gui::ViewProvider*> Provider = getSelection();
|
||||
auto vp = std::find_if(Provider.begin(), Provider.end(), [&obj](Gui::ViewProvider* v) {
|
||||
return v == &obj;
|
||||
});
|
||||
|
||||
if (vp != Provider.end()) {
|
||||
const char* name = obj.getPropertyName(&prop);
|
||||
// this is not a property of the view provider but of the document object
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
std::string prop_name = name;
|
||||
if (prop.isDerivedFrom<App::PropertyMaterial>()) {
|
||||
auto& value = static_cast<const App::PropertyMaterial&>(prop).getValue();
|
||||
if (prop_name == "ShapeMaterial") {
|
||||
// bool blocked = d->ui.buttonColor->blockSignals(true);
|
||||
// auto color = value.diffuseColor;
|
||||
// d->ui.buttonColor->setColor(QColor((int)(255.0f * color.r),
|
||||
// (int)(255.0f * color.g),
|
||||
// (int)(255.0f * color.b)));
|
||||
// d->ui.buttonColor->blockSignals(blocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the dock window this object is embedded into without destroying itself.
|
||||
*/
|
||||
void DlgMaterialImp::reject()
|
||||
{
|
||||
if (d->floating) {
|
||||
// closes the dock window
|
||||
Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance();
|
||||
pDockMgr->removeDockWindow(this);
|
||||
}
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void DlgMaterialImp::setMaterial(const std::vector<App::DocumentObject*>& objects)
|
||||
{
|
||||
for (auto it : objects) {
|
||||
if (auto* obj = dynamic_cast<Part::Feature*>(it)) {
|
||||
auto material = obj->ShapeMaterial.getValue();
|
||||
try {
|
||||
std::string mat = material.getUUID().toStdString();
|
||||
d->ui.widgetMaterial->setMaterial(material.getUUID());
|
||||
return;
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
d->ui.widgetMaterial->setMaterial(Materials::MaterialManager::defaultMaterialUUID());
|
||||
}
|
||||
|
||||
std::vector<Gui::ViewProvider*> DlgMaterialImp::getSelection() const
|
||||
{
|
||||
std::vector<Gui::ViewProvider*> views;
|
||||
|
||||
// get the complete selection
|
||||
std::vector<Gui::SelectionSingleton::SelObj> sel = Gui::Selection().getCompleteSelection();
|
||||
for (const auto& it : sel) {
|
||||
Gui::ViewProvider* view =
|
||||
Gui::Application::Instance->getDocument(it.pDoc)->getViewProvider(it.pObject);
|
||||
views.push_back(view);
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> DlgMaterialImp::getSelectionObjects() const
|
||||
{
|
||||
std::vector<App::DocumentObject*> objects;
|
||||
|
||||
// get the complete selection
|
||||
std::vector<Gui::SelectionSingleton::SelObj> sel = Gui::Selection().getCompleteSelection();
|
||||
for (const auto& it : sel) {
|
||||
objects.push_back(it.pObject);
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
void DlgMaterialImp::onMaterialSelected(const std::shared_ptr<Materials::Material>& material)
|
||||
{
|
||||
std::string mat = material->getUUID().toStdString();
|
||||
std::vector<App::DocumentObject*> objects = getSelectionObjects();
|
||||
for (auto it : objects) {
|
||||
if (auto* obj = dynamic_cast<Part::Feature*>(it)) {
|
||||
obj->ShapeMaterial.setValue(*material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::TaskMaterial */
|
||||
|
||||
TaskMaterial::TaskMaterial()
|
||||
{
|
||||
this->setButtonPosition(TaskMaterial::North);
|
||||
widget = new DlgMaterialImp(false);
|
||||
taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskMaterial::~TaskMaterial() = default;
|
||||
|
||||
QDialogButtonBox::StandardButtons TaskMaterial::getStandardButtons() const
|
||||
{
|
||||
return QDialogButtonBox::Close;
|
||||
}
|
||||
|
||||
bool TaskMaterial::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return (widget->result() == QDialog::Rejected);
|
||||
}
|
||||
|
||||
#include "moc_DlgMaterialImp.cpp"
|
||||
119
src/Mod/Material/Gui/DlgMaterialImp.h
Normal file
119
src/Mod/Material/Gui/DlgMaterialImp.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef MATGUI_DIALOGMATERIALIMP_H
|
||||
#define MATGUI_DIALOGMATERIALIMP_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <App/Material.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Property;
|
||||
}
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class ViewProvider;
|
||||
class Command;
|
||||
|
||||
/**
|
||||
* The DlgMaterialImp class implements a dialog containing all available document
|
||||
* templates to create a new document.
|
||||
* \author Jürgen Riegel
|
||||
*/
|
||||
class DlgMaterialImp: public QDialog, public Gui::SelectionSingleton::ObserverType
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgMaterialImp(bool floating,
|
||||
QWidget* parent = nullptr,
|
||||
Qt::WindowFlags fl = Qt::WindowFlags());
|
||||
~DlgMaterialImp() override;
|
||||
/// Observer message from the Selection
|
||||
void OnChange(Gui::SelectionSingleton::SubjectType& rCaller,
|
||||
Gui::SelectionSingleton::MessageType Reason) override;
|
||||
void showDefaultButtons(bool);
|
||||
void reject() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onMaterialSelected(const std::shared_ptr<Materials::Material>& material);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent* e) override;
|
||||
|
||||
private:
|
||||
void setupConnections();
|
||||
void slotChangedObject(const Gui::ViewProvider&, const App::Property& Prop);
|
||||
void setMaterial(const std::vector<App::DocumentObject*>&);
|
||||
std::vector<Gui::ViewProvider*> getSelection() const;
|
||||
std::vector<App::DocumentObject*> getSelectionObjects() const;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
class TaskMaterial: public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskMaterial();
|
||||
~TaskMaterial() override;
|
||||
|
||||
public:
|
||||
bool reject() override;
|
||||
|
||||
bool isAllowedAlterDocument() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool isAllowedAlterView() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool isAllowedAlterSelection() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const override;
|
||||
|
||||
private:
|
||||
DlgMaterialImp* widget;
|
||||
Gui::TaskView::TaskBox* taskbox;
|
||||
};
|
||||
|
||||
} // namespace MatGui
|
||||
|
||||
#endif // MATGUI_DIALOGMATERIALIMP_H
|
||||
461
src/Mod/Material/Gui/MaterialTreeWidget.cpp
Normal file
461
src/Mod/Material/Gui/MaterialTreeWidget.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 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 <QContextMenuEvent>
|
||||
#include <QMenu>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QSpacerItem>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <App/Color.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Gui/Command.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/MaterialFilter.h>
|
||||
#include <Mod/Material/App/ModelUuids.h>
|
||||
|
||||
#include "MaterialTreeWidget.h"
|
||||
#include "MaterialsEditor.h"
|
||||
#include "ui_MaterialsEditor.h"
|
||||
|
||||
|
||||
using Base::Console;
|
||||
using namespace MatGui;
|
||||
|
||||
/** Constructs a Material tree widget.
|
||||
*/
|
||||
|
||||
MaterialTreeWidget::MaterialTreeWidget(std::shared_ptr<Materials::MaterialFilter> filter,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_expanded(false)
|
||||
, _filter(filter)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
MaterialTreeWidget::MaterialTreeWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_expanded(false)
|
||||
, _filter(nullptr)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::setup()
|
||||
{
|
||||
getFavorites();
|
||||
getRecents();
|
||||
|
||||
createLayout();
|
||||
createMaterialTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the widget and detaches it from its parameter group.
|
||||
*/
|
||||
MaterialTreeWidget::~MaterialTreeWidget() = default;
|
||||
|
||||
void MaterialTreeWidget::createLayout()
|
||||
{
|
||||
m_material = new QLineEdit(this);
|
||||
m_expand = new QPushButton(this);
|
||||
m_expand->setIcon(style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
|
||||
m_materialTree = new QTreeView(this);
|
||||
m_editor = new QPushButton(tr("Launch editor"), this);
|
||||
|
||||
// m_materialTree->setSelectionModel(QAbstractItemView::SingleSelection);
|
||||
m_materialTree->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_materialTree->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
|
||||
auto materialLayout = new QHBoxLayout();
|
||||
materialLayout->addWidget(m_material);
|
||||
materialLayout->addWidget(m_expand);
|
||||
|
||||
auto treeLayout = new QHBoxLayout();
|
||||
treeLayout->addWidget(m_materialTree);
|
||||
|
||||
auto buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Preferred));
|
||||
buttonLayout->addWidget(m_editor);
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 9, 0, 9);
|
||||
layout->addItem(materialLayout);
|
||||
layout->addItem(treeLayout);
|
||||
layout->addItem(buttonLayout);
|
||||
setLayout(layout);
|
||||
|
||||
// Start in an unexpanded state. Store the state?
|
||||
openWidgetState(false);
|
||||
|
||||
connect(m_expand, &QPushButton::clicked, this, &MaterialTreeWidget::expandClicked);
|
||||
connect(m_editor, &QPushButton::clicked, this, &MaterialTreeWidget::editorClicked);
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::openWidgetState(bool open)
|
||||
{
|
||||
m_materialTree->setVisible(open);
|
||||
m_editor->setVisible(open);
|
||||
|
||||
m_expanded = open;
|
||||
|
||||
if (open) {
|
||||
m_expand->setIcon(style()->standardIcon(QStyle::SP_TitleBarShadeButton));
|
||||
}
|
||||
else {
|
||||
m_expand->setIcon(style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::expandClicked(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
// Toggle the open state
|
||||
openWidgetState(!m_expanded);
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::editorClicked(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
MaterialsEditor dialog(_filter, this);
|
||||
dialog.setModal(true);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
// updateMaterialGeneral();
|
||||
// _material->resetEditState();
|
||||
// refreshMaterialTree();
|
||||
// _materialSelected = true;
|
||||
auto material = dialog.getMaterial();
|
||||
updateMaterialTree();
|
||||
setMaterial(material->getUUID());
|
||||
}
|
||||
|
||||
// Gui::Application::Instance->commandManager().runCommandByName("Materials_Edit");
|
||||
// Toggle the open state
|
||||
// openWidgetState(!m_expanded);
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::updateMaterial(const QString& uuid)
|
||||
{
|
||||
if (uuid.isEmpty() || uuid == m_uuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_uuid = uuid;
|
||||
|
||||
// Fetch the material from the manager
|
||||
auto material = std::make_shared<Materials::Material>();
|
||||
try {
|
||||
material = std::make_shared<Materials::Material>(*getMaterialManager().getMaterial(uuid));
|
||||
}
|
||||
catch (Materials::ModelNotFound const&) {
|
||||
Base::Console().Log("*** Unable to load material '%s'\n", uuid.toStdString().c_str());
|
||||
}
|
||||
|
||||
m_materialDisplay = material->getName();
|
||||
m_material->setText(m_materialDisplay);
|
||||
}
|
||||
|
||||
bool MaterialTreeWidget::findInTree(const QStandardItem& node,
|
||||
QModelIndex* index,
|
||||
const QString& uuid)
|
||||
{
|
||||
auto vv = node.data(Qt::UserRole);
|
||||
if (vv.isValid() && vv == uuid) {
|
||||
*index = node.index();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.hasChildren()) {
|
||||
int rows = node.rowCount();
|
||||
for (int i = 0; i < node.rowCount(); i++) {
|
||||
auto child = node.child(i);
|
||||
if (findInTree(*child, index, uuid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex MaterialTreeWidget::findInTree(const QString& uuid)
|
||||
{
|
||||
auto model = dynamic_cast<QStandardItemModel*>(m_materialTree->model());
|
||||
auto root = model->invisibleRootItem();
|
||||
|
||||
QModelIndex index;
|
||||
if (findInTree(*root, &index, uuid)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::setMaterial(const QString& uuid)
|
||||
{
|
||||
if (uuid.isEmpty() || uuid == m_uuid) {
|
||||
return;
|
||||
}
|
||||
updateMaterial(uuid);
|
||||
|
||||
// Now select the material in the tree
|
||||
auto index = findInTree(uuid);
|
||||
if (index.isValid()) {
|
||||
QItemSelectionModel* selectionModel = m_materialTree->selectionModel();
|
||||
selectionModel->select(index, QItemSelectionModel::SelectCurrent);
|
||||
}
|
||||
}
|
||||
|
||||
QString MaterialTreeWidget::getMaterialUUID() const
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::setFilter(std::shared_ptr<Materials::MaterialFilter> filter)
|
||||
{
|
||||
_filter.reset();
|
||||
_filter = filter;
|
||||
|
||||
updateMaterialTree();
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::updateMaterialTree()
|
||||
{
|
||||
_favorites.clear();
|
||||
_recents.clear();
|
||||
|
||||
auto model = dynamic_cast<QStandardItemModel*>(m_materialTree->model());
|
||||
model->clear();
|
||||
|
||||
getFavorites();
|
||||
getRecents();
|
||||
fillMaterialTree();
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::getFavorites()
|
||||
{
|
||||
_favorites.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Favorites");
|
||||
auto count = param->GetInt("Favorites", 0);
|
||||
for (int i = 0; static_cast<long>(i) < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
if (!_filter || _filter->modelIncluded(uuid)) {
|
||||
_favorites.push_back(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::getRecents()
|
||||
{
|
||||
_recents.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Recent");
|
||||
_recentMax = static_cast<int>(param->GetInt("RecentMax", 5));
|
||||
auto count = param->GetInt("Recent", 0);
|
||||
for (int i = 0; static_cast<long>(i) < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
if (!_filter || _filter->modelIncluded(uuid)) {
|
||||
_recents.push_back(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::createMaterialTree()
|
||||
{
|
||||
auto model = new QStandardItemModel(this);
|
||||
m_materialTree->setModel(model);
|
||||
m_materialTree->setHeaderHidden(true);
|
||||
|
||||
// This needs to be done after the model is set
|
||||
QItemSelectionModel* selectionModel = m_materialTree->selectionModel();
|
||||
connect(selectionModel,
|
||||
&QItemSelectionModel::selectionChanged,
|
||||
this,
|
||||
&MaterialTreeWidget::onSelectMaterial);
|
||||
connect(m_materialTree, &QTreeView::doubleClicked, this, &MaterialTreeWidget::onDoubleClick);
|
||||
|
||||
fillMaterialTree();
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::fillMaterialTree()
|
||||
{
|
||||
auto model = dynamic_cast<QStandardItemModel*>(m_materialTree->model());
|
||||
|
||||
auto lib = new QStandardItem(tr("Favorites"));
|
||||
lib->setFlags(Qt::ItemIsEnabled);
|
||||
addExpanded(model, lib);
|
||||
addFavorites(lib);
|
||||
|
||||
lib = new QStandardItem(tr("Recent"));
|
||||
lib->setFlags(Qt::ItemIsEnabled);
|
||||
addExpanded(model, lib);
|
||||
addRecents(lib);
|
||||
|
||||
// // Create a filter to only include current format materials
|
||||
// // that contain the basic render model.
|
||||
// Materials::MaterialFilter filter;
|
||||
// filter.setIncludeEmptyFolders(false);
|
||||
// filter.setIncludeLegacy(false);
|
||||
// filter.addRequired(Materials::ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
|
||||
auto libraries = _materialManager.getMaterialLibraries();
|
||||
for (const auto& library : *libraries) {
|
||||
lib = new QStandardItem(library->getName());
|
||||
lib->setFlags(Qt::ItemIsEnabled);
|
||||
addExpanded(model, lib);
|
||||
|
||||
QIcon icon(library->getIconPath());
|
||||
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
|
||||
|
||||
auto modelTree = _materialManager.getMaterialTree(library, _filter);
|
||||
addMaterials(*lib, modelTree, folderIcon, icon);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::addExpanded(QStandardItem* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
m_materialTree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::addExpanded(QStandardItemModel* model, QStandardItem* child)
|
||||
{
|
||||
model->appendRow(child);
|
||||
m_materialTree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::addRecents(QStandardItem* parent)
|
||||
{
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(parent, card);
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::addFavorites(QStandardItem* parent)
|
||||
{
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(parent, card);
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void MaterialTreeWidget::addMaterials(
|
||||
QStandardItem& parent,
|
||||
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>&
|
||||
modelTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon)
|
||||
{
|
||||
for (auto& mat : *modelTree) {
|
||||
auto nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
auto material = nodePtr->getData();
|
||||
QString uuid = material->getUUID();
|
||||
// Base::Console().Log("Material path '%s'\n",
|
||||
// material->getDirectory().toStdString().c_str());
|
||||
|
||||
// auto card = new QStandardItem(icon, material->getName());
|
||||
auto card = new QStandardItem(icon, mat.first);
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(&parent, card);
|
||||
}
|
||||
else {
|
||||
auto node = new QStandardItem(folderIcon, mat.first);
|
||||
addExpanded(&parent, node);
|
||||
node->setFlags(Qt::ItemIsEnabled);
|
||||
auto treeMap = nodePtr->getFolder();
|
||||
addMaterials(*node, treeMap, folderIcon, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::onSelectMaterial(const QItemSelection& selected,
|
||||
const QItemSelection& deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
// Get the UUID before changing the underlying data model
|
||||
QString uuid;
|
||||
auto model = dynamic_cast<QStandardItemModel*>(m_materialTree->model());
|
||||
QModelIndexList indexes = selected.indexes();
|
||||
for (auto it = indexes.begin(); it != indexes.end(); it++) {
|
||||
QStandardItem* item = model->itemFromIndex(*it);
|
||||
|
||||
if (item) {
|
||||
uuid = item->data(Qt::UserRole).toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateMaterial(uuid);
|
||||
std::string _uuid = uuid.toStdString();
|
||||
|
||||
Q_EMIT materialSelected(getMaterialManager().getMaterial(uuid));
|
||||
}
|
||||
|
||||
void MaterialTreeWidget::onDoubleClick(const QModelIndex& index)
|
||||
{
|
||||
auto model = dynamic_cast<QStandardItemModel*>(m_materialTree->model());
|
||||
auto item = model->itemFromIndex(index);
|
||||
|
||||
if (item) {
|
||||
auto uuid = item->data(Qt::UserRole).toString();
|
||||
updateMaterial(uuid);
|
||||
}
|
||||
}
|
||||
177
src/Mod/Material/Gui/MaterialTreeWidget.h
Normal file
177
src/Mod/Material/Gui/MaterialTreeWidget.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 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/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATGUI_MATERIALTREEWIDGET_H
|
||||
#define MATGUI_MATERIALTREEWIDGET_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QFontComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QStandardItem>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <FCGlobal.h>
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
#include <Gui/WidgetFactory.h>
|
||||
|
||||
|
||||
#include <Mod/Material/App/MaterialFilter.h>
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
class CommandManager;
|
||||
class WidgetFactoryInst;
|
||||
|
||||
/** The Material Tree widget class
|
||||
* This widget is intended for use wherever materials are used. It is a light weight
|
||||
* alternative to the full Materials editor.
|
||||
*
|
||||
* The widget itself is the combination of a number of smaller widgets. A simple text
|
||||
* field shows any currently selected material. An arrow will expand a tree to show
|
||||
* the widget library, allowing the user to select the material they require.
|
||||
*
|
||||
* When expanded, the user will be presented the option to launch the full material
|
||||
* editor. This will allow them to create/copy/modify as required.
|
||||
*
|
||||
* Additionally, they will be given the option to create a material card based on the
|
||||
* current settings.
|
||||
*
|
||||
* \author David Carter
|
||||
*/
|
||||
class MatGuiExport MaterialTreeWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MaterialTreeWidget(std::shared_ptr<Materials::MaterialFilter> filter,
|
||||
QWidget* parent = nullptr);
|
||||
explicit MaterialTreeWidget(QWidget* parent = nullptr);
|
||||
~MaterialTreeWidget() override;
|
||||
|
||||
// void setEntryName( const QByteArray& name );
|
||||
// QByteArray entryName() const;
|
||||
// /** Does the same as setEntryName().
|
||||
// * This function is added for convenience because the ui compiler
|
||||
// * will use this function if the attribute stdset isn't set to 0 in a .ui file.
|
||||
// */
|
||||
// void setPrefEntry(const QByteArray& name);
|
||||
|
||||
// void setParamGrpPath( const QByteArray& path );
|
||||
// QByteArray paramGrpPath() const;
|
||||
// /** Does the same as setParamGrpPath().
|
||||
// * This function is added for convenience because the ui compiler
|
||||
// * will use this function if the attribute stdset isn't set to 0 in a .ui file.
|
||||
// */
|
||||
// void setPrefPath(const QByteArray& name);
|
||||
|
||||
// void OnChange(Base::Subject<const char*> &rCaller, const char * sReason) override;
|
||||
// void onSave();
|
||||
// void onRestore();
|
||||
|
||||
/** Set the material by specifying its UUID
|
||||
*/
|
||||
void setMaterial(const QString& uuid);
|
||||
/** get the material UUID
|
||||
*/
|
||||
QString getMaterialUUID() const;
|
||||
/** Set the material filter
|
||||
*/
|
||||
void setFilter(std::shared_ptr<Materials::MaterialFilter> filter);
|
||||
|
||||
Q_SIGNALS:
|
||||
/** Emits this signal when a material has been selected */
|
||||
void materialSelected(const std::shared_ptr<Materials::Material>& material);
|
||||
|
||||
private Q_SLOTS:
|
||||
void expandClicked(bool checked);
|
||||
void editorClicked(bool checked);
|
||||
void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
void onDoubleClick(const QModelIndex& index);
|
||||
|
||||
private:
|
||||
void setup();
|
||||
|
||||
QLineEdit* m_material;
|
||||
QPushButton* m_expand;
|
||||
QTreeView* m_materialTree;
|
||||
QPushButton* m_editor;
|
||||
bool m_expanded;
|
||||
|
||||
QString m_materialDisplay;
|
||||
QString m_uuid;
|
||||
|
||||
std::list<QString> _favorites;
|
||||
std::list<QString> _recents;
|
||||
std::shared_ptr<Materials::MaterialFilter> _filter;
|
||||
int _recentMax;
|
||||
|
||||
Materials::MaterialManager _materialManager;
|
||||
|
||||
// friends
|
||||
friend class Gui::WidgetFactoryInst;
|
||||
|
||||
protected:
|
||||
// bool m_Restored = false;
|
||||
|
||||
Materials::MaterialManager& getMaterialManager()
|
||||
{
|
||||
return _materialManager;
|
||||
}
|
||||
|
||||
void getFavorites();
|
||||
void getRecents();
|
||||
|
||||
/** Create the widgets UI objects
|
||||
*/
|
||||
void createLayout();
|
||||
|
||||
bool findInTree(const QStandardItem& node, QModelIndex* index, const QString& uuid);
|
||||
QModelIndex findInTree(const QString& uuid);
|
||||
void updateMaterial(const QString& uuid);
|
||||
void createMaterialTree();
|
||||
void fillMaterialTree();
|
||||
void updateMaterialTree();
|
||||
void addExpanded(QStandardItem* parent, QStandardItem* child);
|
||||
void addExpanded(QStandardItemModel* model, QStandardItem* child);
|
||||
void addRecents(QStandardItem* parent);
|
||||
void addFavorites(QStandardItem* parent);
|
||||
void addMaterials(
|
||||
QStandardItem& parent,
|
||||
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>&
|
||||
modelTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon);
|
||||
|
||||
void openWidgetState(bool open);
|
||||
};
|
||||
|
||||
} // namespace MatGui
|
||||
|
||||
#endif // MATGUI_MATERIALTREEWIDGET_H
|
||||
@@ -59,14 +59,33 @@ using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::MaterialsEditor */
|
||||
|
||||
MaterialsEditor::MaterialsEditor(std::shared_ptr<Materials::MaterialFilter> filter, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_MaterialsEditor)
|
||||
, _material(std::make_shared<Materials::Material>())
|
||||
, _materialSelected(false)
|
||||
, _rendered(nullptr)
|
||||
, _recentMax(0)
|
||||
, _filter(filter)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
MaterialsEditor::MaterialsEditor(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_MaterialsEditor)
|
||||
, _material(std::make_shared<Materials::Material>())
|
||||
, _materialSelected(false)
|
||||
, _rendered(nullptr)
|
||||
, _edited(false)
|
||||
, _recentMax(0)
|
||||
, _filter(nullptr)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
void MaterialsEditor::setup()
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
ui->setupUi(this);
|
||||
|
||||
_warningIcon = QIcon(QString::fromStdString(":/icons/Warning.svg"));
|
||||
@@ -158,7 +177,9 @@ void MaterialsEditor::getFavorites()
|
||||
for (int i = 0; static_cast<long>(i) < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_favorites.push_back(uuid);
|
||||
if (!_filter || _filter->modelIncluded(uuid)) {
|
||||
_favorites.push_back(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +255,9 @@ void MaterialsEditor::getRecents()
|
||||
for (int i = 0; static_cast<long>(i) < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_recents.push_back(uuid);
|
||||
if (!_filter || _filter->modelIncluded(uuid)) {
|
||||
_recents.push_back(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +365,6 @@ void MaterialsEditor::propertyChange(const QString& property, const QString valu
|
||||
updatePreview();
|
||||
}
|
||||
update();
|
||||
_edited = true;
|
||||
}
|
||||
|
||||
void MaterialsEditor::onURL(bool checked)
|
||||
@@ -486,6 +508,7 @@ void MaterialsEditor::onNewMaterial(bool checked)
|
||||
// Create a new material
|
||||
_material = std::make_shared<Materials::Material>();
|
||||
setMaterialDefaults();
|
||||
_materialSelected = false;
|
||||
}
|
||||
|
||||
void MaterialsEditor::onInheritNewMaterial(bool checked)
|
||||
@@ -548,6 +571,7 @@ void MaterialsEditor::saveMaterial()
|
||||
updateMaterialGeneral();
|
||||
_material->resetEditState();
|
||||
refreshMaterialTree();
|
||||
_materialSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,6 +1171,7 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected,
|
||||
|
||||
updateMaterial();
|
||||
_material->resetEditState();
|
||||
_materialSelected = true;
|
||||
}
|
||||
|
||||
void MaterialsEditor::onDoubleClick(const QModelIndex& index)
|
||||
@@ -1162,6 +1187,7 @@ void MaterialsEditor::onDoubleClick(const QModelIndex& index)
|
||||
}
|
||||
}
|
||||
|
||||
_materialSelected = true;
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <Base/Handle.h>
|
||||
#include <Base/Parameter.h>
|
||||
|
||||
#include <Mod/Material/App/MaterialFilter.h>
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
@@ -52,6 +53,8 @@ class MaterialsEditor: public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MaterialsEditor(std::shared_ptr<Materials::MaterialFilter> filter,
|
||||
QWidget* parent = nullptr);
|
||||
explicit MaterialsEditor(QWidget* parent = nullptr);
|
||||
~MaterialsEditor() override = default;
|
||||
|
||||
@@ -96,6 +99,15 @@ public:
|
||||
void onDoubleClick(const QModelIndex& index);
|
||||
void onContextMenu(const QPoint& pos);
|
||||
|
||||
bool isMaterialSelected() const
|
||||
{
|
||||
return _materialSelected;
|
||||
}
|
||||
std::shared_ptr<Materials::Material> getMaterial()
|
||||
{
|
||||
return _material;
|
||||
}
|
||||
|
||||
protected:
|
||||
int confirmSave(QWidget* parent);
|
||||
void saveMaterial();
|
||||
@@ -106,11 +118,14 @@ private:
|
||||
Materials::ModelManager _modelManager;
|
||||
std::shared_ptr<Materials::Material> _material;
|
||||
AppearancePreview* _rendered;
|
||||
bool _edited;
|
||||
bool _materialSelected;
|
||||
std::list<QString> _favorites;
|
||||
std::list<QString> _recents;
|
||||
int _recentMax;
|
||||
QIcon _warningIcon;
|
||||
std::shared_ptr<Materials::MaterialFilter> _filter;
|
||||
|
||||
void setup();
|
||||
|
||||
void saveWindow();
|
||||
void saveMaterialTreeChildren(const Base::Reference<ParameterGrp>& param,
|
||||
|
||||
@@ -685,9 +685,9 @@ class MaterialEditor:
|
||||
|
||||
from importFCMat import write
|
||||
write(filename, d)
|
||||
import Material
|
||||
import Materials
|
||||
# Load the material
|
||||
manager = Material.MaterialManager()
|
||||
manager = Materials.MaterialManager()
|
||||
manager.getMaterialByPath(filename)
|
||||
self.edited = False
|
||||
self.updateCardsInCombo()
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
// Material
|
||||
#ifndef MaterialsExport
|
||||
#ifdef Material_EXPORTS
|
||||
#ifdef Materials_EXPORTS
|
||||
#define MaterialsExport FREECAD_DECL_EXPORT
|
||||
#else
|
||||
#define MaterialsExport FREECAD_DECL_IMPORT
|
||||
|
||||
15
src/Mod/Material/Resources/Materials/Standard/Default.FCMat
Normal file
15
src/Mod/Material/Resources/Materials/Standard/Default.FCMat
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "7f9fd73b-50c9-41d8-b7b2-575a030c1eeb"
|
||||
Author: "David Carter"
|
||||
License: "GPL-2.0-or-later"
|
||||
Name: "Default"
|
||||
Description: "Generic material with density of 1"
|
||||
Inherits:
|
||||
Default:
|
||||
UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973"
|
||||
Models:
|
||||
Density:
|
||||
UUID: '454661e5-265b-4320-8e6f-fcf6223ac3af'
|
||||
Density: "1 kg/m^3"
|
||||
@@ -35,7 +35,12 @@ AppearanceModel:
|
||||
Type: 'File'
|
||||
Units: ''
|
||||
URL: ''
|
||||
Description: " "
|
||||
Description: "Path to file containing a texture image. Only used if TextureImage is unpopulated"
|
||||
TextureImage:
|
||||
Type: 'Image'
|
||||
Units: ''
|
||||
URL: ''
|
||||
Description: "Embedded texture image"
|
||||
TextureScaling:
|
||||
DisplayName: "Texture Scaling"
|
||||
Type: 'Float'
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
from os import walk
|
||||
import unittest
|
||||
import FreeCAD
|
||||
import Material
|
||||
import Materials
|
||||
|
||||
from materialtests.TestModels import ModelTestCases
|
||||
from materialtests.TestMaterials import MaterialTestCases
|
||||
|
||||
@@ -30,7 +30,7 @@ import os
|
||||
import FreeCAD
|
||||
|
||||
from materialtools.cardutils import get_material_template
|
||||
import Material
|
||||
import Materials
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
from PySide import QtGui
|
||||
@@ -99,7 +99,7 @@ def decode(name):
|
||||
# https://github.com/berndhahnebach/FreeCAD_bhb/commits/materialdev
|
||||
|
||||
def read(filename):
|
||||
materialManager = Material.MaterialManager()
|
||||
materialManager = Materials.MaterialManager()
|
||||
material = materialManager.getMaterialByPath(filename)
|
||||
return material.Properties
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Test module for FreeCAD material cards and APIs
|
||||
|
||||
import unittest
|
||||
import FreeCAD
|
||||
import Material
|
||||
import Materials
|
||||
|
||||
parseQuantity = FreeCAD.Units.parseQuantity
|
||||
|
||||
@@ -37,9 +37,9 @@ class MaterialTestCases(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
""" Setup function to initialize test data """
|
||||
self.ModelManager = Material.ModelManager()
|
||||
self.MaterialManager = Material.MaterialManager()
|
||||
self.uuids = Material.UUIDs()
|
||||
self.ModelManager = Materials.ModelManager()
|
||||
self.MaterialManager = Materials.MaterialManager()
|
||||
self.uuids = Materials.UUIDs()
|
||||
|
||||
def testMaterialManager(self):
|
||||
""" Ensure the MaterialManager has been initialized correctly """
|
||||
|
||||
@@ -26,7 +26,7 @@ Test module for FreeCAD material models
|
||||
|
||||
import unittest
|
||||
import FreeCAD
|
||||
import Material
|
||||
import Materials
|
||||
|
||||
parseQuantity = FreeCAD.Units.parseQuantity
|
||||
|
||||
@@ -36,8 +36,8 @@ class ModelTestCases(unittest.TestCase):
|
||||
"""
|
||||
def setUp(self):
|
||||
""" Setup function to initialize test data """
|
||||
self.ModelManager = Material.ModelManager()
|
||||
self.uuids = Material.UUIDs()
|
||||
self.ModelManager = Materials.ModelManager()
|
||||
self.uuids = Materials.UUIDs()
|
||||
|
||||
def testModelManager(self):
|
||||
""" Ensure we can access ModelManager member functions """
|
||||
|
||||
@@ -28,7 +28,7 @@ from os.path import join
|
||||
from pathlib import Path
|
||||
|
||||
import FreeCAD
|
||||
import Material
|
||||
import Materials
|
||||
|
||||
|
||||
unicode = str
|
||||
@@ -260,7 +260,7 @@ def output_resources(resources):
|
||||
# used in material editor and FEM material task panels
|
||||
|
||||
def import_materials(category='Solid', template=False):
|
||||
materialManager = Material.MaterialManager()
|
||||
materialManager = Materials.MaterialManager()
|
||||
mats = materialManager.Materials
|
||||
materials = {}
|
||||
cards = {}
|
||||
|
||||
Reference in New Issue
Block a user