Material: Material editor enhancements

Continues the work of the material subsystem improvements.

This merge covers the continued development of the material editor. The
primary improvements are in the handling of 2D and 3D array properties.
These properties are now fully editable, and can be saved and restored.

The cards now separate the author and license. These were previously
saved as a single item. Future support will be provided for standard
open source licenses.

Saving operations validate the cards to ensure UUIDs of materials are
considered. Warnings are given when a save could potentially impact the
models, such as saving over a material instead of creating a new
instance.

The editor is still not complete. There are a number of functional
elements, such as drag/drop operations, folder creation, and deletion
operations that need to be added to the main tree. State needs to be
saved and restored to improve the user experience. The appearance
preview also needs significant work. This will be handled in a future
PR.
This commit is contained in:
David Carter
2023-10-23 15:19:20 -04:00
parent e3ad4d35dc
commit b3ab6c1ac1
229 changed files with 6530 additions and 1650 deletions

View File

@@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui)
// clang-format on
PyMOD_Return(mod);
}
}

View File

@@ -9,6 +9,12 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(-Wno-pedantic) # needed for vtk headers
endif()
if(MSVC)
add_definitions(-DFCGuiFem -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH)
else(MSVC)
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
endif(MSVC)
if(BUILD_FEM_NETGEN)
add_definitions(-DFCWithNetgen)
endif(BUILD_FEM_NETGEN)

View File

@@ -33,6 +33,7 @@
#include "ModelManagerPy.h"
#include "ModelPropertyPy.h"
#include "ModelPy.h"
#include "UUIDsPy.h"
namespace Materials
{
@@ -68,6 +69,7 @@ PyMOD_INIT_FUNC(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");
PyMOD_Return(module);
}

View File

@@ -0,0 +1,36 @@
<?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="Array2DPy"
Twin="Material2DArray"
TwinPointer="Material2DArray"
Include="Mod/Material/App/MaterialValue.h"
Namespace="Materials"
FatherInclude="Base/BaseClassPy.h"
FatherNamespace="Base"
Constructor="true"
Delete="true">
<Documentation>
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
<UserDocu>2D Array of material properties.</UserDocu>
</Documentation>
<Attribute Name="Rows" ReadOnly="true">
<Documentation>
<UserDocu>The number of rows in the array.</UserDocu>
</Documentation>
<Parameter Name="Rows" Type="Int"/>
</Attribute>
<Attribute Name="Columns" ReadOnly="true">
<Documentation>
<UserDocu>The number of columns in the array.</UserDocu>
</Documentation>
<Parameter Name="Columns" Type="Int"/>
</Attribute>
<Methode Name="getDefaultValue" ReadOnly="true">
<Documentation>
<UserDocu>Get the default value for the first column of the array</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,85 @@
/***************************************************************************
* 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"
#include "Array2DPy.h"
#include "Model.h"
#include "ModelLibrary.h"
#include "ModelPropertyPy.h"
#include "ModelUuids.h"
#include "Array2DPy.cpp"
using namespace Materials;
// returns a string which represents the object e.g. when printed in python
std::string Array2DPy::representation() const
{
std::stringstream str;
str << "<Array2D object at " << getMaterial2DArrayPtr() << ">";
return str.str();
}
PyObject* Array2DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
{
// never create such objects with the constructor
return new Array2DPy(new Material2DArray());
}
// constructor method
int Array2DPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
return 0;
}
Py::Int Array2DPy::getRows() const
{
return Py::Int(getMaterial2DArrayPtr()->rows());
}
Py::Int Array2DPy::getColumns() const
{
return Py::Int(getMaterial2DArrayPtr()->columns());
}
PyObject* Array2DPy::getDefaultValue(PyObject* args)
{
char* name;
if (!PyArg_ParseTuple(args, "s", &name)) {
return nullptr;
}
// QVariant value = getMaterial2DArrayPtr()->getPhysicalValue(QString::fromStdString(name));
// return _pyObjectFromVariant(value);
return nullptr;
}
PyObject* Array2DPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int Array2DPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -33,14 +33,18 @@ list(APPEND Material_LIBS
${YAML_CPP_LIBRARIES}
)
generate_from_xml(Array2DPy)
generate_from_xml(MaterialManagerPy)
generate_from_xml(MaterialPy)
generate_from_xml(ModelManagerPy)
generate_from_xml(ModelPropertyPy)
generate_from_xml(ModelPy)
generate_from_xml(UUIDsPy)
SET(Python_SRCS
Exceptions.h
Array2DPy.xml
Array2DPyImpl.cpp
MaterialManagerPy.xml
MaterialManagerPyImpl.cpp
MaterialPy.xml
@@ -51,6 +55,8 @@ SET(Python_SRCS
ModelPropertyPyImpl.cpp
ModelPy.xml
ModelPyImpl.cpp
UUIDsPy.xml
UUIDsPyImpl.cpp
)
SOURCE_GROUP("Python" FILES ${Python_SRCS})
@@ -78,6 +84,7 @@ SET(Material_SRCS
ModelLoader.h
ModelManager.cpp
ModelManager.h
ModelUuids.cpp
ModelUuids.h
PreCompiled.cpp
PreCompiled.h

View File

@@ -22,6 +22,8 @@
#ifndef MATERIAL_EXCEPTIONS_H
#define MATERIAL_EXCEPTIONS_H
#include <QString>
#include <Base/BaseClass.h>
#include <Base/Exception.h>
@@ -37,6 +39,10 @@ public:
{
this->setMessage(msg);
}
explicit Uninitialized(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~Uninitialized() noexcept override = default;
};
@@ -49,9 +55,29 @@ public:
{
this->setMessage(msg);
}
explicit ModelNotFound(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~ModelNotFound() noexcept override = default;
};
class InvalidMaterialType: public Base::Exception
{
public:
InvalidMaterialType()
{}
explicit InvalidMaterialType(const char* msg)
{
this->setMessage(msg);
}
explicit InvalidMaterialType(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidMaterialType() noexcept override = default;
};
class MaterialNotFound: public Base::Exception
{
public:
@@ -61,9 +87,29 @@ public:
{
this->setMessage(msg);
}
explicit MaterialNotFound(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~MaterialNotFound() noexcept override = default;
};
class MaterialExists: public Base::Exception
{
public:
MaterialExists()
{}
explicit MaterialExists(const char* msg)
{
this->setMessage(msg);
}
explicit MaterialExists(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~MaterialExists() noexcept override = default;
};
class PropertyNotFound: public Base::Exception
{
public:
@@ -73,6 +119,10 @@ public:
{
this->setMessage(msg);
}
explicit PropertyNotFound(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~PropertyNotFound() noexcept override = default;
};
@@ -85,6 +135,10 @@ public:
{
this->setMessage(msg);
}
explicit LibraryNotFound(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~LibraryNotFound() noexcept override = default;
};
@@ -97,6 +151,10 @@ public:
{
this->setMessage(msg);
}
explicit InvalidModel(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidModel() noexcept override = default;
};
@@ -109,6 +167,10 @@ public:
{
this->setMessage(msg);
}
explicit InvalidRow(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidRow() noexcept override = default;
};
@@ -121,9 +183,29 @@ public:
{
this->setMessage(msg);
}
explicit InvalidColumn(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidColumn() noexcept override = default;
};
class InvalidDepth: public Base::Exception
{
public:
InvalidDepth()
{}
explicit InvalidDepth(char* msg)
{
this->setMessage(msg);
}
explicit InvalidDepth(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidDepth() noexcept override = default;
};
class InvalidIndex: public Base::Exception
{
public:
@@ -133,6 +215,10 @@ public:
{
this->setMessage(msg);
}
explicit InvalidIndex(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~InvalidIndex() noexcept override = default;
};
@@ -145,9 +231,29 @@ public:
{
this->setMessage(msg);
}
explicit UnknownValueType(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~UnknownValueType() noexcept override = default;
};
class DeleteError: public Base::Exception
{
public:
DeleteError()
{}
explicit DeleteError(char* msg)
{
this->setMessage(msg);
}
explicit DeleteError(const QString& msg)
{
this->setMessage(msg.toStdString().c_str());
}
~DeleteError() noexcept override = default;
};
} // namespace Materials
#endif // MATERIAL_EXCEPTIONS_H

View File

@@ -22,10 +22,10 @@
#ifndef MATERIAL_FOLDERTREE_H
#define MATERIAL_FOLDERTREE_H
#include <QString>
#include <map>
#include <memory>
#include <QString>
namespace Materials
{
@@ -53,25 +53,25 @@ public:
_type = type;
}
const std::shared_ptr<std::map<QString, FolderTreeNode<T>*>> getFolder() const
const std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> getFolder() const
{
return _folder;
}
std::shared_ptr<std::map<QString, FolderTreeNode<T>*>> getFolder()
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> getFolder()
{
return _folder;
}
const T* getData() const
std::shared_ptr<T> getData() const
{
return _data;
}
void setFolder(std::shared_ptr<std::map<QString, FolderTreeNode<T>*>> folder)
void setFolder(std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> folder)
{
setType(FolderNode);
_folder = folder;
}
void setData(const T* data)
void setData(std::shared_ptr<T> data)
{
setType(DataNode);
_data = data;
@@ -79,8 +79,8 @@ public:
private:
NodeType _type;
std::shared_ptr<std::map<QString, FolderTreeNode<T>*>> _folder;
const T* _data;
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> _folder;
std::shared_ptr<T> _data;
};
} // namespace Materials

View File

@@ -85,7 +85,8 @@ QString MaterialConfigLoader::getAuthorAndLicense(const QString& path)
return noAuthor;
}
void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat,
std::shared_ptr<Material> finalModel)
{
QString sectionFillPattern = value(fcmat, "VectorRendering/SectionFillPattern", "");
QString sectionLinewidth = value(fcmat, "VectorRendering/SectionLinewidth", "");
@@ -97,7 +98,7 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material*
if (sectionFillPattern.length() + sectionLinewidth.length() + sectionColor.length()
+ viewColor.length() + viewFillPattern.length() + viewLinewidth.length()
> 0) {
finalModel->addAppearance(ModelUUID_Rendering_Vector);
finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Vector);
}
// Now add the data
@@ -109,7 +110,8 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material*
setAppearanceValue(finalModel, "ViewLinewidth", viewLinewidth);
}
void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addRendering(const QSettings& fcmat,
std::shared_ptr<Material> finalModel)
{
QString ambientColor = value(fcmat, "Rendering/AmbientColor", "");
QString diffuseColor = value(fcmat, "Rendering/DiffuseColor", "");
@@ -139,13 +141,13 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM
}
if (useAdvanced) {
finalModel->addAppearance(ModelUUID_Rendering_Advanced);
finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Advanced);
}
else if (useTexture) {
finalModel->addAppearance(ModelUUID_Rendering_Texture);
finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture);
}
else if (useBasic) {
finalModel->addAppearance(ModelUUID_Rendering_Basic);
finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic);
}
// Now add the data
@@ -161,14 +163,14 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM
setAppearanceValue(finalModel, "VertexShader", vertexShader);
}
void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addCosts(const QSettings& fcmat, std::shared_ptr<Material> finalModel)
{
QString productURL = value(fcmat, "Cost/ProductURL", "");
QString specificPrice = value(fcmat, "Cost/SpecificPrice", "");
QString vendor = value(fcmat, "Cost/Vendor", "");
if (productURL.length() + specificPrice.length() + vendor.length() > 0) {
finalModel->addPhysical(ModelUUID_Costs_Default);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Costs_Default);
}
// Now add the data
@@ -177,7 +179,8 @@ void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel
setPhysicalValue(finalModel, "Vendor", vendor);
}
void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addArchitectural(const QSettings& fcmat,
std::shared_ptr<Material> finalModel)
{
QString color = value(fcmat, "Architectural/Color", "");
QString environmentalEfficiencyClass =
@@ -193,7 +196,7 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi
+ finish.length() + fireResistanceClass.length() + model.length()
+ soundTransmissionClass.length() + unitsPerQuantity.length()
> 0) {
finalModel->addPhysical(ModelUUID_Architectural_Default);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Architectural_Default);
}
// Now add the data
@@ -207,7 +210,8 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi
setPhysicalValue(finalModel, "UnitsPerQuantity", unitsPerQuantity);
}
void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat,
std::shared_ptr<Material> finalModel)
{
QString relativePermittivity = value(fcmat, "Electromagnetic/RelativePermittivity", "");
QString electricalConductivity = value(fcmat, "Electromagnetic/ElectricalConductivity", "");
@@ -216,7 +220,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material*
if (relativePermittivity.length() + electricalConductivity.length()
+ relativePermeability.length()
> 0) {
finalModel->addPhysical(ModelUUID_Electromagnetic_Default);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Electromagnetic_Default);
}
// Now add the data
@@ -225,7 +229,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material*
setPhysicalValue(finalModel, "RelativePermeability", relativePermeability);
}
void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addThermal(const QSettings& fcmat, std::shared_ptr<Material> finalModel)
{
QString specificHeat = value(fcmat, "Thermal/SpecificHeat", "");
QString thermalConductivity = value(fcmat, "Thermal/ThermalConductivity", "");
@@ -233,7 +237,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod
if (specificHeat.length() + thermalConductivity.length() + thermalExpansionCoefficient.length()
> 0) {
finalModel->addPhysical(ModelUUID_Thermal_Default);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Thermal_Default);
}
// Now add the data
@@ -242,7 +246,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod
setPhysicalValue(finalModel, "ThermalExpansionCoefficient", thermalExpansionCoefficient);
}
void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addFluid(const QSettings& fcmat, std::shared_ptr<Material> finalModel)
{
QString density = value(fcmat, "Fluidic/Density", "");
QString dynamicViscosity = value(fcmat, "Fluidic/DynamicViscosity", "");
@@ -260,10 +264,10 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel
}
if (useFluid) {
finalModel->addPhysical(ModelUUID_Fluid_Default);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Fluid_Default);
}
else if (useDensity) {
finalModel->addPhysical(ModelUUID_Mechanical_Density);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density);
}
// Now add the data
@@ -273,7 +277,8 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel
setPhysicalValue(finalModel, "PrandtlNumber", prandtlNumber);
}
void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* finalModel)
void MaterialConfigLoader::addMechanical(const QSettings& fcmat,
std::shared_ptr<Material> finalModel)
{
QString density = value(fcmat, "Mechanical/Density", "");
QString bulkModulus = value(fcmat, "Mechanical/BulkModulus", "");
@@ -308,14 +313,14 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final
}
if (useLinearElastic) {
finalModel->addPhysical(ModelUUID_Mechanical_LinearElastic);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_LinearElastic);
}
else {
if (useIso) {
finalModel->addPhysical(ModelUUID_Mechanical_IsotropicLinearElastic);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic);
}
if (useDensity) {
finalModel->addPhysical(ModelUUID_Mechanical_Density);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density);
}
}
@@ -334,10 +339,11 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final
setPhysicalValue(finalModel, "Stiffness", stiffness);
}
Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& library,
const QString& path)
std::shared_ptr<Material>
MaterialConfigLoader::getMaterialFromPath(std::shared_ptr<MaterialLibrary> library,
const QString& path)
{
QString authorAndLicense = getAuthorAndLicense(path);
QString author = getAuthorAndLicense(path); // Place them both in the author field
QSettings fcmat(path, QSettings::IniFormat);
@@ -352,15 +358,15 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra
QString sourceReference = value(fcmat, "ReferenceSource", "");
QString sourceURL = value(fcmat, "SourceURL", "");
Material* finalModel = new Material(library, path, uuid, name);
finalModel->setAuthorAndLicense(authorAndLicense);
std::shared_ptr<Material> finalModel = std::make_shared<Material>(library, path, uuid, name);
finalModel->setAuthor(author);
finalModel->setDescription(description);
finalModel->setReference(sourceReference);
finalModel->setURL(sourceURL);
QString father = value(fcmat, "Father", "");
if (father.length() > 0) {
finalModel->addPhysical(ModelUUID_Legacy_Father);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_Father);
// Now add the data
setPhysicalValue(finalModel, "Father", father);
@@ -372,7 +378,7 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra
QString standardCode = value(fcmat, "StandardCode", "");
if (kindOfMaterial.length() + materialNumber.length() + norm.length() + standardCode.length()
> 0) {
finalModel->addPhysical(ModelUUID_Legacy_MaterialStandard);
finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_MaterialStandard);
// Now add the data
setPhysicalValue(finalModel, "KindOfMaterial", kindOfMaterial);

View File

@@ -22,6 +22,8 @@
#ifndef MATERIAL_MATERIALCONFIGLOADER_H
#define MATERIAL_MATERIALCONFIGLOADER_H
#include <memory>
#include <QDir>
#include <QSettings>
#include <QString>
@@ -39,7 +41,8 @@ public:
static bool isConfigStyle(const QString& path);
static Material* getMaterialFromPath(const MaterialLibrary& library, const QString& path);
static std::shared_ptr<Material> getMaterialFromPath(std::shared_ptr<MaterialLibrary> library,
const QString& path);
private:
static QString
@@ -49,15 +52,17 @@ private:
.toString();
}
static void
setPhysicalValue(Material* finalModel, const std::string& name, const QString& value)
static void setPhysicalValue(std::shared_ptr<Material> finalModel,
const std::string& name,
const QString& value)
{
if (value.length() > 0) {
finalModel->setPhysicalValue(QString::fromStdString(name), value);
}
}
static void
setAppearanceValue(Material* finalModel, const std::string& name, const QString& value)
static void setAppearanceValue(std::shared_ptr<Material> finalModel,
const std::string& name,
const QString& value)
{
if (value.length() > 0) {
finalModel->setAppearanceValue(QString::fromStdString(name), value);
@@ -65,14 +70,14 @@ private:
}
static QString getAuthorAndLicense(const QString& path);
static void addMechanical(const QSettings& fcmat, Material* finalModel);
static void addFluid(const QSettings& fcmat, Material* finalModel);
static void addThermal(const QSettings& fcmat, Material* finalModel);
static void addElectromagnetic(const QSettings& fcmat, Material* finalModel);
static void addArchitectural(const QSettings& fcmat, Material* finalModel);
static void addCosts(const QSettings& fcmat, Material* finalModel);
static void addRendering(const QSettings& fcmat, Material* finalModel);
static void addVectorRendering(const QSettings& fcmat, Material* finalModel);
static void addMechanical(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addFluid(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addThermal(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addElectromagnetic(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addArchitectural(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addCosts(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addRendering(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
static void addVectorRendering(const QSettings& fcmat, std::shared_ptr<Material> finalModel);
};
} // namespace Materials

View File

@@ -21,11 +21,17 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QVector>
#endif
#include <QDirIterator>
#include <QFileInfo>
#include <App/Application.h>
#include "MaterialLibrary.h"
#include "MaterialLoader.h"
#include "MaterialManager.h"
#include "Materials.h"
#include "ModelManager.h"
@@ -34,9 +40,6 @@ using namespace Materials;
/* TRANSLATOR Material::Materials */
std::unique_ptr<std::map<QString, Material*>> MaterialLibrary::_materialPathMap =
std::make_unique<std::map<QString, Material*>>();
TYPESYSTEM_SOURCE(Materials::MaterialLibrary, LibraryBase)
MaterialLibrary::MaterialLibrary()
@@ -48,24 +51,165 @@ MaterialLibrary::MaterialLibrary(const QString& libraryName,
bool readOnly)
: LibraryBase(libraryName, dir, icon)
, _readOnly(readOnly)
, _materialPathMap(std::make_unique<std::map<QString, std::shared_ptr<Material>>>())
{}
void MaterialLibrary::createPath(const QString& path)
{
Q_UNUSED(path)
}
Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, bool saveAsCopy)
void MaterialLibrary::createFolder(const QString& path)
{
QString filePath = getLocalPath(path);
Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str());
// Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str());
QDir fileDir(filePath);
if (!fileDir.exists()) {
if (!fileDir.mkpath(filePath)) {
Base::Console().Error("Unable to create directory path '%s'\n",
filePath.toStdString().c_str());
}
}
}
// This accepts the filesystem path as returned from getLocalPath
void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path)
{
// Base::Console().Log("Removing directory '%s'\n", path.toStdString().c_str());
// Remove the children first
QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
// Add paths to a list so there are no iterator errors
QVector<QString> dirList;
QVector<QString> fileList;
while (it.hasNext()) {
auto pathname = it.next();
QFileInfo file(pathname);
if (file.isFile()) {
fileList.push_back(pathname);
}
else if (file.isDir()) {
dirList.push_back(pathname);
}
}
// Remove the subdirs first
while (!dirList.isEmpty()) {
QString dirPath = dirList.takeFirst();
deleteDir(manager, dirPath);
}
// Remove the files
while (!fileList.isEmpty()) {
QString filePath = fileList.takeFirst();
deleteFile(manager, filePath);
}
// Finally, remove ourself
QDir dir;
if (!dir.rmdir(path)) {
throw DeleteError(path);
}
}
// This accepts the filesystem path as returned from getLocalPath
void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path)
{
// Base::Console().Log("Removing file '%s'\n", path.toStdString().c_str());
if (QFile::remove(path)) {
// Remove from the map
QString rPath = getRelativePath(path);
// Base::Console().Log("\trpath '%s'\n", rPath.toStdString().c_str());
try {
auto material = getMaterialByPath(rPath);
manager.remove(material->getUUID());
}
catch (const MaterialNotFound&) {
Base::Console().Log("Unable to remove file from materials list\n");
}
_materialPathMap->erase(rPath);
}
else {
QString error = QString::fromStdString("DeleteError: Unable to delete ") + path;
throw DeleteError(error);
}
}
void MaterialLibrary::deleteRecursive(const QString& path)
{
std::string pstring = path.toStdString();
Base::Console().Log("\tdeleteRecursive '%s'\n", pstring.c_str());
if (isRoot(path)) {
return;
}
QString filePath = getLocalPath(path);
// Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str());
MaterialManager manager;
QFileInfo info(filePath);
if (info.isDir()) {
deleteDir(manager, filePath);
}
else {
deleteFile(manager, filePath);
}
}
void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath)
{
// Update the path map
QString op = getRelativePath(oldPath);
QString np = getRelativePath(newPath);
std::unique_ptr<std::map<QString, std::shared_ptr<Material>>> pathMap =
std::make_unique<std::map<QString, std::shared_ptr<Material>>>();
for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) {
QString path = itp->first;
if (path.startsWith(op)) {
path = np + path.remove(0, op.size());
}
Base::Console().Error("Path '%s' -> '%s'\n",
itp->first.toStdString().c_str(),
path.toStdString().c_str());
itp->second->setDirectory(path);
(*pathMap)[path] = itp->second;
}
_materialPathMap = std::move(pathMap);
}
void MaterialLibrary::renameFolder(const QString& oldPath, const QString& newPath)
{
QString filePath = getLocalPath(oldPath);
// Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str());
QString newFilePath = getLocalPath(newPath);
// Base::Console().Log("\tnew filePath = '%s'\n", newFilePath.toStdString().c_str());
QDir fileDir(filePath);
if (fileDir.exists()) {
if (!fileDir.rename(filePath, newFilePath)) {
Base::Console().Error("Unable to rename directory path '%s'\n",
filePath.toStdString().c_str());
}
}
updatePaths(oldPath, newPath);
}
std::shared_ptr<Material> MaterialLibrary::saveMaterial(std::shared_ptr<Material> material,
const QString& path,
bool overwrite,
bool saveAsCopy,
bool saveInherited)
{
QString filePath = getLocalPath(path);
// Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str());
QFile file(filePath);
// Update UUID if required
// if name changed true
if (material.getName() != file.fileName()) {
material.newUuid();
}
// if (material->getName() != file.fileName()) {
// material->newUuid();
// }
// if overwrite false having warned the user
// if old format true, but already set
@@ -79,43 +223,49 @@ Material* MaterialLibrary::saveMaterial(Material& material, const QString& path,
}
}
if (info.exists()) {
if (!overwrite) {
Base::Console().Error("File already exists '%s'\n", info.path().toStdString().c_str());
throw MaterialExists();
}
}
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream stream(&file);
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
stream.setCodec("UTF-8");
#endif
stream.setGenerateByteOrderMark(true);
// Write the contents
material.setLibrary(*this);
material.setDirectory(getRelativePath(path));
material.save(stream, saveAsCopy);
material->setLibrary(getptr());
material->setDirectory(getRelativePath(path));
material->save(stream, saveAsCopy, saveInherited);
}
return addMaterial(material, path);
}
Material* MaterialLibrary::addMaterial(const Material& material, const QString& path)
bool MaterialLibrary::fileExists(const QString& path) const
{
QString filePath = getLocalPath(path);
QFileInfo info(filePath);
return info.exists();
}
std::shared_ptr<Material> MaterialLibrary::addMaterial(std::shared_ptr<Material> material,
const QString& path)
{
QString filePath = getRelativePath(path);
Material* newMaterial = new Material(material);
newMaterial->setLibrary(*this);
std::shared_ptr<Material> newMaterial = std::make_shared<Material>(*material);
newMaterial->setLibrary(getptr());
newMaterial->setDirectory(filePath);
try {
// If there's already a material at that path we'll replace it
Material* old = _materialPathMap->at(filePath);
delete old;
}
catch (const std::out_of_range&) {
}
(*_materialPathMap)[filePath] = newMaterial;
return newMaterial;
}
const Material& MaterialLibrary::getMaterialByPath(const QString& path) const
std::shared_ptr<Material> MaterialLibrary::getMaterialByPath(const QString& path) const
{
// Base::Console().Log("MaterialLibrary::getMaterialByPath(%s)\n", path.toStdString().c_str());
// for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) {
@@ -124,10 +274,10 @@ const Material& MaterialLibrary::getMaterialByPath(const QString& path) const
QString filePath = getRelativePath(path);
try {
Material* material = _materialPathMap->at(filePath);
return *material;
auto material = _materialPathMap->at(filePath);
return material;
}
catch (std::out_of_range&) {
catch (std::out_of_range& e) {
throw MaterialNotFound();
}
}
@@ -136,14 +286,80 @@ const QString MaterialLibrary::getUUIDFromPath(const QString& path) const
{
QString filePath = getRelativePath(path);
try {
Material* material = _materialPathMap->at(filePath);
auto material = _materialPathMap->at(filePath);
return material->getUUID();
}
catch (std::out_of_range&) {
catch (std::out_of_range& e) {
throw MaterialNotFound();
}
}
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
MaterialLibrary::getMaterialTree() const
{
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> materialTree =
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
for (auto it = _materialPathMap->begin(); it != _materialPathMap->end(); it++) {
auto filename = it->first;
auto material = it->second;
// Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str());
QStringList list = filename.split(QString::fromStdString("/"));
// Start at the root
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> node = materialTree;
for (auto itp = list.begin(); itp != list.end(); itp++) {
// Base::Console().Log("\t%s", itp->toStdString().c_str());
if (itp->endsWith(QString::fromStdString(".FCMat"))) {
std::shared_ptr<MaterialTreeNode> child = std::make_shared<MaterialTreeNode>();
child->setData(material);
(*node)[*itp] = child;
}
else {
// Add the folder only if it's not already there
if (node->count(*itp) == 0) {
auto mapPtr =
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
std::shared_ptr<MaterialTreeNode> child = std::make_shared<MaterialTreeNode>();
child->setFolder(mapPtr);
(*node)[*itp] = child;
node = mapPtr;
}
else {
node = (*node)[*itp]->getFolder();
}
}
}
}
// Empty folders aren't included in _materialPathMap, so we add them by looking at the file
// system
auto folderList = MaterialLoader::getMaterialFolders(*this);
for (auto folder : *folderList) {
QStringList list = folder.split(QString::fromStdString("/"));
// Start at the root
auto node = materialTree;
for (auto itp = list.begin(); itp != list.end(); itp++) {
// Add the folder only if it's not already there
if (node->count(*itp) == 0) {
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> mapPtr =
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
std::shared_ptr<MaterialTreeNode> child = std::make_shared<MaterialTreeNode>();
child->setFolder(mapPtr);
(*node)[*itp] = child;
node = mapPtr;
}
else {
node = (*node)[*itp]->getFolder();
}
}
}
return materialTree;
}
TYPESYSTEM_SOURCE(Materials::MaterialExternalLibrary, MaterialLibrary::MaterialLibrary)
MaterialExternalLibrary::MaterialExternalLibrary()

View File

@@ -22,14 +22,17 @@
#ifndef MATERIAL_MATERIALLIBRARY_H
#define MATERIAL_MATERIALLIBRARY_H
#include <Mod/Material/MaterialGlobal.h>
#include <Base/BaseClass.h>
#include <memory>
#include <QDir>
#include <QString>
#include <QVariant>
#include <Base/BaseClass.h>
#include <Mod/Material/MaterialGlobal.h>
#include "Materials.h"
#include "Model.h"
#include "ModelLibrary.h"
@@ -37,17 +40,19 @@ namespace Materials
{
class Material;
class MaterialManager;
class MaterialsExport MaterialLibrary: public LibraryBase
class MaterialsExport MaterialLibrary: public LibraryBase,
public std::enable_shared_from_this<MaterialLibrary>
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
MaterialLibrary();
explicit MaterialLibrary(const QString& libraryName,
const QString& dir,
const QString& icon,
bool readOnly = true);
MaterialLibrary(const QString& libraryName,
const QString& dir,
const QString& icon,
bool readOnly = true);
~MaterialLibrary() override = default;
bool operator==(const MaterialLibrary& library) const
@@ -58,40 +63,60 @@ public:
{
return !operator==(library);
}
const Material& getMaterialByPath(const QString& path) const;
std::shared_ptr<Material> getMaterialByPath(const QString& path) const;
void createPath(const QString& path);
Material* saveMaterial(Material& material, const QString& path, bool saveAsCopy);
Material* addMaterial(const Material& material, const QString& path);
void createFolder(const QString& path);
void renameFolder(const QString& oldPath, const QString& newPath);
void deleteRecursive(const QString& path);
std::shared_ptr<Material> saveMaterial(std::shared_ptr<Material> material,
const QString& path,
bool overwrite,
bool saveAsCopy,
bool saveInherited);
bool fileExists(const QString& path) const;
std::shared_ptr<Material> addMaterial(std::shared_ptr<Material> material, const QString& path);
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> getMaterialTree() const;
bool isReadOnly() const
{
return _readOnly;
}
// Use this to get a shared_ptr for *this
std::shared_ptr<MaterialLibrary> getptr()
{
return shared_from_this();
}
protected:
MaterialLibrary(const MaterialLibrary&) = default;
void deleteDir(MaterialManager& manager, const QString& path);
void deleteFile(MaterialManager& manager, const QString& path);
void updatePaths(const QString& oldPath, const QString& newPath);
const QString getUUIDFromPath(const QString& path) const;
bool _readOnly;
static std::unique_ptr<std::map<QString, Material*>> _materialPathMap;
std::unique_ptr<std::map<QString, std::shared_ptr<Material>>> _materialPathMap;
};
class MaterialsExport MaterialExternalLibrary: public MaterialLibrary
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
MaterialExternalLibrary();
explicit MaterialExternalLibrary(const QString& libraryName,
const QString& dir,
const QString& icon,
bool readOnly = true);
MaterialExternalLibrary(const QString& libraryName,
const QString& dir,
const QString& icon,
bool readOnly = true);
~MaterialExternalLibrary() override;
};
} // namespace Materials
Q_DECLARE_METATYPE(Materials::MaterialLibrary)
Q_DECLARE_METATYPE(Materials::MaterialExternalLibrary)
Q_DECLARE_METATYPE(std::shared_ptr<Materials::MaterialLibrary>)
#endif // MATERIAL_MATERIALLIBRARY_H

View File

@@ -24,13 +24,18 @@
#include <QString>
#endif
#include <App/Application.h>
#include <Base/Interpreter.h>
#include <QDirIterator>
#include <QFileInfo>
#include <QMetaType>
#include <App/Application.h>
#include <Base/Interpreter.h>
#include <Gui/MetaTypes.h>
#include "Materials.h"
#include "MaterialConfigLoader.h"
#include "MaterialLibrary.h"
#include "MaterialLoader.h"
#include "Model.h"
#include "ModelManager.h"
@@ -41,7 +46,7 @@ using namespace Materials;
MaterialEntry::MaterialEntry()
{}
MaterialEntry::MaterialEntry(const MaterialLibrary& library,
MaterialEntry::MaterialEntry(std::shared_ptr<MaterialLibrary> library,
const QString& modelName,
const QString& dir,
const QString& modelUuid)
@@ -51,7 +56,7 @@ MaterialEntry::MaterialEntry(const MaterialLibrary& library,
, _uuid(modelUuid)
{}
MaterialYamlEntry::MaterialYamlEntry(const MaterialLibrary& library,
MaterialYamlEntry::MaterialYamlEntry(std::shared_ptr<MaterialLibrary> library,
const QString& modelName,
const QString& dir,
const QString& modelUuid,
@@ -73,7 +78,82 @@ QString MaterialYamlEntry::yamlValue(const YAML::Node& node,
return QString::fromStdString(defaultValue);
}
void MaterialYamlEntry::addToTree(std::shared_ptr<std::map<QString, Material*>> materialMap)
std::shared_ptr<Material2DArray> MaterialYamlEntry::read2DArray(const YAML::Node& node)
{
// Base::Console().Log("Read 2D Array\n");
auto array2d = std::make_shared<Material2DArray>();
if (node.size() == 2) {
// Get the default
Base::Quantity defaultValue =
Base::Quantity::parse(QString::fromStdString(node[0].as<std::string>()));
array2d->setDefault(QVariant::fromValue(defaultValue));
auto yamlArray = node[1];
for (std::size_t i = 0; i < yamlArray.size(); i++) {
auto yamlRow = yamlArray[i];
auto row = std::make_shared<std::vector<QVariant>>();
for (std::size_t j = 0; j < yamlRow.size(); j++) {
Base::Quantity q =
Base::Quantity::parse(QString::fromStdString(yamlRow[j].as<std::string>()));
row->push_back(QVariant::fromValue(q));
}
array2d->addRow(row);
}
}
return array2d;
}
std::shared_ptr<Material3DArray> MaterialYamlEntry::read3DArray(const YAML::Node& node)
{
Base::Console().Log("Read 3D Array\n");
auto array3d = std::make_shared<Material3DArray>();
if (node.size() == 2) {
// Get the default
Base::Quantity defaultValue =
Base::Quantity::parse(QString::fromStdString(node[0].as<std::string>()));
array3d->setDefault(QVariant::fromValue(defaultValue));
auto yamlArray = node[1];
for (std::size_t depth = 0; depth < yamlArray.size(); depth++) {
auto yamlDepth = yamlArray[depth];
MaterialLoader::showYaml(yamlDepth);
for (auto it = yamlDepth.begin(); it != yamlDepth.end(); it++) {
MaterialLoader::showYaml(it->first);
MaterialLoader::showYaml(it->second);
Base::Console().Log("Depth %d '%s'\n", depth, it->first.as<std::string>().c_str());
auto depthValue =
Base::Quantity::parse(QString::fromStdString(it->first.as<std::string>()));
array3d->addDepth(depth, depthValue);
auto yamlTable = it->second;
for (std::size_t i = 0; i < yamlTable.size(); i++) {
auto yamlRow = yamlTable[i];
auto row = std::make_shared<std::vector<Base::Quantity>>();
for (std::size_t j = 0; j < yamlRow.size(); j++) {
row->push_back(Base::Quantity::parse(
QString::fromStdString(yamlRow[j].as<std::string>())));
}
array3d->addRow(depth, row);
}
}
}
}
return array3d;
}
void MaterialYamlEntry::addToTree(
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap)
{
std::set<QString> exclude;
exclude.insert(QString::fromStdString("General"));
@@ -85,11 +165,14 @@ void MaterialYamlEntry::addToTree(std::shared_ptr<std::map<QString, Material*>>
auto directory = getDirectory();
QString uuid = getUUID();
QString authorAndLicense = yamlValue(yamlModel["General"], "AuthorAndLicense", "");
QString author = yamlValue(yamlModel["General"], "Author", "");
QString license = yamlValue(yamlModel["General"], "License", "");
QString description = yamlValue(yamlModel["General"], "Description", "");
Material* finalModel = new Material(library, directory, uuid, name);
finalModel->setAuthorAndLicense(authorAndLicense);
std::shared_ptr<Material> finalModel =
std::make_shared<Material>(library, directory, uuid, name);
finalModel->setAuthor(author);
finalModel->setLicense(license);
finalModel->setDescription(description);
// Add inheritance list
@@ -118,11 +201,34 @@ void MaterialYamlEntry::addToTree(std::shared_ptr<std::map<QString, Material*>>
auto properties = yamlModel["Models"][modelName];
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
std::string propertyName = (itp->first).as<std::string>();
std::string propertyValue = (itp->second).as<std::string>();
if (finalModel->hasPhysicalProperty(QString::fromStdString(propertyName))) {
finalModel->setPhysicalValue(QString::fromStdString(propertyName),
QString::fromStdString(propertyValue));
auto prop =
finalModel->getPhysicalProperty(QString::fromStdString(propertyName));
auto type = prop->getType();
try {
if (type == MaterialValue::Array2D) {
auto array2d = read2DArray(itp->second);
finalModel->setPhysicalValue(QString::fromStdString(propertyName),
array2d);
}
else if (type == MaterialValue::Array3D) {
auto array3d = read3DArray(itp->second);
finalModel->setPhysicalValue(QString::fromStdString(propertyName),
array3d);
}
else {
std::string propertyValue = (itp->second).as<std::string>();
finalModel->setPhysicalValue(QString::fromStdString(propertyName),
QString::fromStdString(propertyValue));
}
}
catch (const YAML::BadConversion& e) {
Base::Console().Log("Exception %s <%s:%s> - ignored\n",
e.what(),
name.toStdString().c_str(),
propertyName.c_str());
}
}
else if (propertyName != "UUID") {
Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n",
@@ -147,11 +253,32 @@ void MaterialYamlEntry::addToTree(std::shared_ptr<std::map<QString, Material*>>
auto properties = yamlModel["AppearanceModels"][modelName];
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
std::string propertyName = (itp->first).as<std::string>();
std::string propertyValue = (itp->second).as<std::string>();
if (finalModel->hasAppearanceProperty(QString::fromStdString(propertyName))) {
finalModel->setAppearanceValue(QString::fromStdString(propertyName),
QString::fromStdString(propertyValue));
auto prop =
finalModel->getAppearanceProperty(QString::fromStdString(propertyName));
auto type = prop->getType();
try {
if (type == MaterialValue::Array2D) {
auto array2d = read2DArray(itp->second);
finalModel->setAppearanceValue(QString::fromStdString(propertyName),
array2d);
}
else if (type == MaterialValue::Array3D) {
Base::Console().Log("Read 3D Array\n");
}
else {
std::string propertyValue = (itp->second).as<std::string>();
finalModel->setAppearanceValue(QString::fromStdString(propertyName),
QString::fromStdString(propertyValue));
}
}
catch (const YAML::BadConversion& e) {
Base::Console().Log("Exception %s <%s:%s> - ignored\n",
e.what(),
name.toStdString().c_str(),
propertyName.c_str());
}
}
else if (propertyName != "UUID") {
Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n",
@@ -163,13 +290,15 @@ void MaterialYamlEntry::addToTree(std::shared_ptr<std::map<QString, Material*>>
QString path = QDir(directory).absolutePath();
// Base::Console().Log("\tPath '%s'\n", path.toStdString().c_str());
(*materialMap)[uuid] = library.addMaterial(*finalModel, path);
(*materialMap)[uuid] = library->addMaterial(finalModel, path);
}
std::unique_ptr<std::map<QString, MaterialEntry*>> MaterialLoader::_materialEntryMap = nullptr;
std::unique_ptr<std::map<QString, std::shared_ptr<MaterialEntry>>>
MaterialLoader::_materialEntryMap = nullptr;
MaterialLoader::MaterialLoader(std::shared_ptr<std::map<QString, Material*>> materialMap,
std::shared_ptr<std::list<MaterialLibrary*>> libraryList)
MaterialLoader::MaterialLoader(
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap,
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> libraryList)
: _materialMap(materialMap)
, _libraryList(libraryList)
{
@@ -182,25 +311,58 @@ MaterialLoader::MaterialLoader(std::shared_ptr<std::map<QString, Material*>> mat
MaterialLoader::~MaterialLoader()
{}
void MaterialLoader::addLibrary(MaterialLibrary* model)
void MaterialLoader::addLibrary(std::shared_ptr<MaterialLibrary> model)
{
_libraryList->push_back(model);
}
MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library,
const QString& path) const
std::shared_ptr<MaterialEntry>
MaterialLoader::getMaterialFromYAML(std::shared_ptr<MaterialLibrary> library,
YAML::Node& yamlroot,
const QString& path) const
{
MaterialEntry* model = nullptr;
std::shared_ptr<MaterialEntry> model = nullptr;
try {
const std::string uuid = yamlroot["General"]["UUID"].as<std::string>();
// Always get the name from the filename
// QString name = QString::fromStdString(yamlroot["General"]["Name"].as<std::string>());
QFileInfo filepath(path);
QString name =
filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive);
model = std::make_shared<MaterialYamlEntry>(library,
name,
path,
QString::fromStdString(uuid),
yamlroot);
// showYaml(yamlroot);
}
catch (YAML::Exception const& e) {
Base::Console().Error("YAML parsing error: '%s'\n", path.toStdString().c_str());
Base::Console().Error("\t'%s'\n", e.what());
showYaml(yamlroot);
}
return model;
}
std::shared_ptr<MaterialEntry>
MaterialLoader::getMaterialFromPath(std::shared_ptr<MaterialLibrary> library,
const QString& path) const
{
std::shared_ptr<MaterialEntry> model = nullptr;
// Used for debugging
std::string uuid;
std::string pathName = path.toStdString();
if (MaterialConfigLoader::isConfigStyle(path)) {
Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str());
Material* material = MaterialConfigLoader::getMaterialFromPath(library, path);
// Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str());
auto material = MaterialConfigLoader::getMaterialFromPath(library, path);
if (material) {
(*_materialMap)[material->getUUID()] = library.addMaterial(*material, path);
(*_materialMap)[material->getUUID()] = library->addMaterial(material, path);
}
// Return the nullptr as there are no intermediate steps to take, such
@@ -212,15 +374,7 @@ MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library,
try {
yamlroot = YAML::LoadFile(pathName);
const std::string uuid = yamlroot["General"]["UUID"].as<std::string>();
// Always get the name from the filename
// QString name = QString::fromStdString(yamlroot["General"]["Name"].as<std::string>());
QFileInfo filepath(path);
QString name =
filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive);
model = new MaterialYamlEntry(library, name, path, QString::fromStdString(uuid), yamlroot);
// showYaml(yamlroot);
model = getMaterialFromYAML(library, yamlroot, path);
}
catch (YAML::Exception const& e) {
Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str());
@@ -242,7 +396,9 @@ void MaterialLoader::showYaml(const YAML::Node& yaml)
}
void MaterialLoader::dereference(Material* material)
void MaterialLoader::dereference(
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap,
std::shared_ptr<Material> material)
{
// Avoid recursion
if (material->getDereferenced()) {
@@ -254,19 +410,20 @@ void MaterialLoader::dereference(Material* material)
auto parentUUID = material->getParentUUID();
if (parentUUID.size() > 0) {
Material* parent;
std::shared_ptr<Material> parent;
try {
parent = (*_materialMap)[parentUUID];
parent = materialMap->at(parentUUID);
}
catch (std::out_of_range&) {
catch (std::out_of_range& e) {
Base::Console().Log(
"Unable to apply inheritance for material '%s', parent '%s' not found.\n",
material->getName().toStdString().c_str(),
parentUUID.toStdString().c_str());
return;
}
// Ensure the parent has been dereferenced
dereference(parent);
dereference(materialMap, parent);
// Add physical models
auto modelVector = parent->getPhysicalModels();
@@ -288,20 +445,20 @@ void MaterialLoader::dereference(Material* material)
auto properties = parent->getPhysicalProperties();
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
auto name = itp->first;
auto property = static_cast<const MaterialProperty>(itp->second);
auto property = itp->second;
if (material->getPhysicalProperty(name).isNull()) {
material->getPhysicalProperty(name).setValue(property.getValue());
if (material->getPhysicalProperty(name)->isNull()) {
material->getPhysicalProperty(name)->setValue(property->getValue());
}
}
properties = parent->getAppearanceProperties();
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
auto name = itp->first;
auto property = static_cast<const MaterialProperty>(itp->second);
auto property = itp->second;
if (material->getAppearanceProperty(name).isNull()) {
material->getAppearanceProperty(name).setValue(property.getValue());
if (material->getAppearanceProperty(name)->isNull()) {
material->getAppearanceProperty(name)->setValue(property->getValue());
}
}
}
@@ -309,13 +466,18 @@ void MaterialLoader::dereference(Material* material)
material->markDereferenced();
}
void MaterialLoader::loadLibrary(MaterialLibrary& library)
void MaterialLoader::dereference(std::shared_ptr<Material> material)
{
dereference(_materialMap, material);
}
void MaterialLoader::loadLibrary(std::shared_ptr<MaterialLibrary> library)
{
if (_materialEntryMap == nullptr) {
_materialEntryMap = std::make_unique<std::map<QString, MaterialEntry*>>();
_materialEntryMap = std::make_unique<std::map<QString, std::shared_ptr<MaterialEntry>>>();
}
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories);
while (it.hasNext()) {
auto pathname = it.next();
QFileInfo file(pathname);
@@ -341,7 +503,7 @@ void MaterialLoader::loadLibraries()
auto _libraryList = getMaterialLibraries();
if (_libraryList) {
for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) {
loadLibrary(**it);
loadLibrary(*it);
}
}
@@ -350,7 +512,7 @@ void MaterialLoader::loadLibraries()
}
}
std::shared_ptr<std::list<MaterialLibrary*>> MaterialLoader::getMaterialLibraries()
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialLoader::getMaterialLibraries()
{
auto param = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Material/Resources");
@@ -362,10 +524,11 @@ std::shared_ptr<std::list<MaterialLibrary*>> MaterialLoader::getMaterialLibrarie
if (useBuiltInMaterials) {
QString resourceDir = QString::fromStdString(App::Application::getResourceDir()
+ "/Mod/Material/Resources/Materials");
auto libData = new MaterialLibrary(QString::fromStdString("System"),
resourceDir,
QString::fromStdString(":/icons/freecad.svg"),
true);
auto libData =
std::make_shared<MaterialLibrary>(QString::fromStdString("System"),
resourceDir,
QString::fromStdString(":/icons/freecad.svg"),
true);
_libraryList->push_back(libData);
}
@@ -382,10 +545,10 @@ std::shared_ptr<std::list<MaterialLibrary*>> MaterialLoader::getMaterialLibrarie
if (materialDir.length() > 0) {
QDir dir(materialDir);
if (dir.exists()) {
auto libData = new MaterialLibrary(moduleName,
materialDir,
materialIcon,
materialReadOnly);
auto libData = std::make_shared<MaterialLibrary>(moduleName,
materialDir,
materialIcon,
materialReadOnly);
_libraryList->push_back(libData);
}
}
@@ -397,12 +560,19 @@ std::shared_ptr<std::list<MaterialLibrary*>> MaterialLoader::getMaterialLibrarie
QString::fromStdString(App::Application::getUserAppDataDir() + "/Material");
if (!resourceDir.isEmpty()) {
QDir materialDir(resourceDir);
if (!materialDir.exists()) {
// Try creating the user dir if it doesn't exist
if (!materialDir.mkpath(resourceDir)) {
Base::Console().Log("Unable to create user library '%s'\n",
resourceDir.toStdString().c_str());
}
}
if (materialDir.exists()) {
auto libData =
new MaterialLibrary(QString::fromStdString("User"),
resourceDir,
QString::fromStdString(":/icons/preferences-general.svg"),
false);
auto libData = std::make_shared<MaterialLibrary>(
QString::fromStdString("User"),
resourceDir,
QString::fromStdString(":/icons/preferences-general.svg"),
false);
_libraryList->push_back(libData);
}
}
@@ -413,10 +583,11 @@ std::shared_ptr<std::list<MaterialLibrary*>> MaterialLoader::getMaterialLibrarie
if (!resourceDir.isEmpty()) {
QDir materialDir(resourceDir);
if (materialDir.exists()) {
auto libData = new MaterialLibrary(QString::fromStdString("Custom"),
resourceDir,
QString::fromStdString(":/icons/user.svg"),
false);
auto libData =
std::make_shared<MaterialLibrary>(QString::fromStdString("Custom"),
resourceDir,
QString::fromStdString(":/icons/user.svg"),
false);
_libraryList->push_back(libData);
}
}

View File

@@ -22,6 +22,8 @@
#ifndef MATERIAL_MATERIALLOADER_H
#define MATERIAL_MATERIALLOADER_H
#include <memory>
#include <QDir>
#include <QString>
#include <yaml-cpp/yaml.h>
@@ -36,15 +38,16 @@ class MaterialEntry
{
public:
MaterialEntry();
explicit MaterialEntry(const MaterialLibrary& library,
const QString& modelName,
const QString& dir,
const QString& modelUuid);
MaterialEntry(std::shared_ptr<MaterialLibrary> library,
const QString& modelName,
const QString& dir,
const QString& modelUuid);
virtual ~MaterialEntry() = default;
virtual void addToTree(std::shared_ptr<std::map<QString, Material*>> materialMap) = 0;
virtual void
addToTree(std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap) = 0;
const MaterialLibrary& getLibrary() const
std::shared_ptr<MaterialLibrary> getLibrary() const
{
return _library;
}
@@ -62,7 +65,7 @@ public:
}
protected:
MaterialLibrary _library;
std::shared_ptr<MaterialLibrary> _library;
QString _name;
QString _directory;
QString _uuid;
@@ -71,14 +74,15 @@ protected:
class MaterialYamlEntry: public MaterialEntry
{
public:
explicit MaterialYamlEntry(const MaterialLibrary& library,
const QString& modelName,
const QString& dir,
const QString& modelUuid,
const YAML::Node& modelData);
MaterialYamlEntry(std::shared_ptr<MaterialLibrary> library,
const QString& modelName,
const QString& dir,
const QString& modelUuid,
const YAML::Node& modelData);
~MaterialYamlEntry() override = default;
void addToTree(std::shared_ptr<std::map<QString, Material*>> materialMap) override;
void
addToTree(std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap) override;
const YAML::Node& getModel() const
{
@@ -94,6 +98,8 @@ private:
QString
yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue);
std::shared_ptr<Material2DArray> read2DArray(const YAML::Node& node);
std::shared_ptr<Material3DArray> read3DArray(const YAML::Node& node);
YAML::Node _model;
};
@@ -101,26 +107,34 @@ private:
class MaterialLoader
{
public:
explicit MaterialLoader(std::shared_ptr<std::map<QString, Material*>> materialMap,
std::shared_ptr<std::list<MaterialLibrary*>> libraryList);
MaterialLoader(std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap,
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> libraryList);
virtual ~MaterialLoader();
std::shared_ptr<std::list<MaterialLibrary*>> getMaterialLibraries();
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries();
static std::shared_ptr<std::list<QString>> getMaterialFolders(const MaterialLibrary& library);
static void showYaml(const YAML::Node& yaml);
static void
dereference(std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap,
std::shared_ptr<Material> material);
std::shared_ptr<MaterialEntry> getMaterialFromYAML(std::shared_ptr<MaterialLibrary> library,
YAML::Node& yamlroot,
const QString& path) const;
private:
MaterialLoader();
void addToTree(MaterialEntry* model);
void dereference(Material* material);
MaterialEntry* getMaterialFromPath(MaterialLibrary& library, const QString& path) const;
void addLibrary(MaterialLibrary* model);
void loadLibrary(MaterialLibrary& library);
void addToTree(std::shared_ptr<MaterialEntry> model);
void dereference(std::shared_ptr<Material> material);
std::shared_ptr<MaterialEntry> getMaterialFromPath(std::shared_ptr<MaterialLibrary> library,
const QString& path) const;
void addLibrary(std::shared_ptr<MaterialLibrary> model);
void loadLibrary(std::shared_ptr<MaterialLibrary> library);
void loadLibraries();
static std::unique_ptr<std::map<QString, MaterialEntry*>> _materialEntryMap;
std::shared_ptr<std::map<QString, Material*>> _materialMap;
std::shared_ptr<std::list<MaterialLibrary*>> _libraryList;
static std::unique_ptr<std::map<QString, std::shared_ptr<MaterialEntry>>> _materialEntryMap;
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> _materialMap;
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> _libraryList;
};
} // namespace Materials

View File

@@ -23,6 +23,7 @@
#ifndef _PreComp_
#endif
#include <QDirIterator>
#include <QMutexLocker>
#include <App/Application.h>
@@ -37,8 +38,10 @@ using namespace Materials;
/* TRANSLATOR Material::Materials */
std::shared_ptr<std::list<MaterialLibrary*>> MaterialManager::_libraryList = nullptr;
std::shared_ptr<std::map<QString, Material*>> MaterialManager::_materialMap = nullptr;
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialManager::_libraryList =
nullptr;
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> MaterialManager::_materialMap =
nullptr;
QMutex MaterialManager::_mutex;
TYPESYSTEM_SOURCE(Materials::MaterialManager, Base::BaseClass)
@@ -60,10 +63,10 @@ void MaterialManager::initLibraries()
delete manager;
_materialMap = std::make_shared<std::map<QString, Material*>>();
_materialMap = std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
if (_libraryList == nullptr) {
_libraryList = std::make_shared<std::list<MaterialLibrary*>>();
_libraryList = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
}
// Load the libraries
@@ -71,23 +74,15 @@ void MaterialManager::initLibraries()
}
}
void MaterialManager::saveMaterial(MaterialLibrary* library,
Material& material,
void MaterialManager::saveMaterial(std::shared_ptr<MaterialLibrary> library,
std::shared_ptr<Material> material,
const QString& path,
bool saveAsCopy)
bool overwrite,
bool saveAsCopy,
bool saveInherited)
{
Material* newMaterial = library->saveMaterial(material, path, saveAsCopy);
try {
Material* old = _materialMap->at(newMaterial->getUUID());
if (old) {
delete old;
}
}
catch (const std::out_of_range&) {
}
(*_materialMap)[material.getUUID()] = newMaterial;
auto newMaterial = library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited);
(*_materialMap)[newMaterial->getUUID()] = newMaterial;
}
bool MaterialManager::isMaterial(const fs::path& p)
@@ -102,31 +97,43 @@ bool MaterialManager::isMaterial(const fs::path& p)
return false;
}
const Material& MaterialManager::getMaterial(const QString& uuid) const
bool MaterialManager::isMaterial(const QFileInfo& file)
{
if (!file.isFile()) {
return false;
}
// check file extension
if (file.suffix() == QString::fromStdString("FCMat")) {
return true;
}
return false;
}
std::shared_ptr<Material> MaterialManager::getMaterial(const QString& uuid) const
{
try {
return *(_materialMap->at(uuid));
return _materialMap->at(uuid);
}
catch (std::out_of_range&) {
catch (std::out_of_range& e) {
throw MaterialNotFound();
}
}
const Material& MaterialManager::getMaterialByPath(const QString& path) const
std::shared_ptr<Material> MaterialManager::getMaterialByPath(const QString& path) const
{
QString cleanPath = QDir::cleanPath(path);
for (auto library : *_libraryList) {
Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n",
library->getName().toStdString().c_str(),
library->getDirectory().toStdString().c_str());
// Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n",
// library->getName().toStdString().c_str(),
// library->getDirectory().toStdString().c_str());
if (cleanPath.startsWith(library->getDirectory())) {
Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n",
library->getDirectory().toStdString().c_str());
Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n",
cleanPath.toStdString().c_str());
// Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n",
// library->getDirectory().toStdString().c_str());
// Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n",
// cleanPath.toStdString().c_str());
return library->getMaterialByPath(cleanPath);
}
}
@@ -136,13 +143,51 @@ const Material& MaterialManager::getMaterialByPath(const QString& path) const
throw MaterialNotFound();
}
const Material& MaterialManager::getMaterialByPath(const QString& path, const QString& lib) const
std::shared_ptr<Material> MaterialManager::getMaterialByPath(const QString& path,
const QString& lib) const
{
auto library = getLibrary(lib); // May throw LibraryNotFound
return library->getMaterialByPath(path); // May throw MaterialNotFound
}
MaterialLibrary* MaterialManager::getLibrary(const QString& name) const
bool MaterialManager::exists(const QString& uuid) const
{
try {
auto material = getMaterial(uuid);
if (material.get() != nullptr) {
return true;
}
}
catch (const MaterialNotFound&) {
}
return false;
}
std::shared_ptr<Material> MaterialManager::getParent(std::shared_ptr<Material> material)
{
if (material->getParentUUID().isEmpty()) {
throw MaterialNotFound();
}
return getMaterial(material->getParentUUID());
}
bool MaterialManager::exists(std::shared_ptr<MaterialLibrary> library, const QString& uuid) const
{
try {
auto material = getMaterial(uuid);
if (material.get() != nullptr) {
return (*material->getLibrary() == *library);
}
}
catch (const MaterialNotFound&) {
}
return false;
}
std::shared_ptr<MaterialLibrary> MaterialManager::getLibrary(const QString& name) const
{
for (auto library : *_libraryList) {
if (library->getName() == name) {
@@ -153,13 +198,13 @@ MaterialLibrary* MaterialManager::getLibrary(const QString& name) const
throw LibraryNotFound();
}
std::shared_ptr<std::list<MaterialLibrary*>> MaterialManager::getMaterialLibraries()
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialManager::getMaterialLibraries()
{
if (_libraryList == nullptr) {
if (_materialMap == nullptr) {
_materialMap = std::make_shared<std::map<QString, Material*>>();
_materialMap = std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
}
_libraryList = std::make_shared<std::list<MaterialLibrary*>>();
_libraryList = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
// Load the libraries
MaterialLoader loader(_materialMap, _libraryList);
@@ -167,87 +212,21 @@ std::shared_ptr<std::list<MaterialLibrary*>> MaterialManager::getMaterialLibrari
return _libraryList;
}
std::shared_ptr<std::map<QString, MaterialTreeNode*>>
MaterialManager::getMaterialTree(const MaterialLibrary& library) const
{
std::shared_ptr<std::map<QString, MaterialTreeNode*>> materialTree =
std::make_shared<std::map<QString, MaterialTreeNode*>>();
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
auto filename = it->first;
auto material = it->second;
if (material->getLibrary() == library) {
fs::path path = material->getDirectory().toStdString();
// Start at the root
auto node = materialTree;
for (auto itp = path.begin(); itp != path.end(); itp++) {
if (QString::fromStdString(itp->string())
.endsWith(QString::fromStdString(".FCMat"))) {
MaterialTreeNode* child = new MaterialTreeNode();
child->setData(material);
(*node)[QString::fromStdString(itp->string())] = child;
}
else {
// Add the folder only if it's not already there
QString folderName = QString::fromStdString(itp->string());
std::shared_ptr<std::map<QString, MaterialTreeNode*>> mapPtr;
if (node->count(folderName) == 0) {
mapPtr = std::make_shared<std::map<QString, MaterialTreeNode*>>();
MaterialTreeNode* child = new MaterialTreeNode();
child->setFolder(mapPtr);
(*node)[folderName] = child;
node = mapPtr;
}
else {
node = (*node)[folderName]->getFolder();
}
}
}
}
}
auto folderList = getMaterialFolders(library);
for (auto folder : *folderList) {
fs::path path = folder.toStdString();
// Start at the root
auto node = materialTree;
for (auto itp = path.begin(); itp != path.end(); itp++) {
// Add the folder only if it's not already there
QString folderName = QString::fromStdString(itp->string());
if (node->count(folderName) == 0) {
std::shared_ptr<std::map<QString, MaterialTreeNode*>> mapPtr =
std::make_shared<std::map<QString, MaterialTreeNode*>>();
MaterialTreeNode* child = new MaterialTreeNode();
child->setFolder(mapPtr);
(*node)[folderName] = child;
node = mapPtr;
}
else {
node = (*node)[folderName]->getFolder();
}
}
}
return materialTree;
}
std::shared_ptr<std::list<QString>>
MaterialManager::getMaterialFolders(const MaterialLibrary& library) const
MaterialManager::getMaterialFolders(std::shared_ptr<MaterialLibrary> library) const
{
return MaterialLoader::getMaterialFolders(library);
return MaterialLoader::getMaterialFolders(*library);
}
std::shared_ptr<std::map<QString, Material*>> MaterialManager::materialsWithModel(QString uuid)
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
MaterialManager::materialsWithModel(QString uuid)
{
std::shared_ptr<std::map<QString, Material*>> dict =
std::make_shared<std::map<QString, Material*>>();
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> dict =
std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
QString key = it->first;
Material* material = it->second;
auto material = it->second;
if (material->hasModel(uuid)) {
(*dict)[key] = material;
@@ -257,15 +236,15 @@ std::shared_ptr<std::map<QString, Material*>> MaterialManager::materialsWithMode
return dict;
}
std::shared_ptr<std::map<QString, Material*>>
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
MaterialManager::materialsWithModelComplete(QString uuid)
{
std::shared_ptr<std::map<QString, Material*>> dict =
std::make_shared<std::map<QString, Material*>>();
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> dict =
std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
QString key = it->first;
Material* material = it->second;
auto material = it->second;
if (material->isModelComplete(uuid)) {
(*dict)[key] = material;
@@ -274,3 +253,8 @@ MaterialManager::materialsWithModelComplete(QString uuid)
return dict;
}
void MaterialManager::dereference(std::shared_ptr<Material> material)
{
MaterialLoader::dereference(_materialMap, material);
}

View File

@@ -22,61 +22,90 @@
#ifndef MATERIAL_MATERIALMANAGER_H
#define MATERIAL_MATERIALMANAGER_H
#include <Mod/Material/MaterialGlobal.h>
#include <memory>
#include <QMutex>
#include <boost/filesystem.hpp>
#include <Mod/Material/MaterialGlobal.h>
#include "FolderTree.h"
#include "Materials.h"
#include "MaterialLibrary.h"
namespace fs = boost::filesystem;
namespace Materials
{
typedef FolderTreeNode<Material> MaterialTreeNode;
class MaterialsExport MaterialManager: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
MaterialManager();
~MaterialManager() override = default;
std::shared_ptr<std::map<QString, Material*>> getMaterials()
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> getMaterials()
{
return _materialMap;
}
const Material& getMaterial(const QString& uuid) const;
const Material& getMaterialByPath(const QString& path) const;
const Material& getMaterialByPath(const QString& path, const QString& library) const;
MaterialLibrary* getLibrary(const QString& name) const;
std::shared_ptr<Material> getMaterial(const QString& uuid) const;
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(std::shared_ptr<Material> material);
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
bool exists(const QString& uuid) const;
bool exists(std::shared_ptr<MaterialLibrary> library, const QString& uuid) const;
// Library management
static std::shared_ptr<std::list<MaterialLibrary*>> getMaterialLibraries();
std::shared_ptr<std::map<QString, MaterialTreeNode*>>
getMaterialTree(const MaterialLibrary& library) const;
std::shared_ptr<std::list<QString>> getMaterialFolders(const MaterialLibrary& library) const;
void createPath(MaterialLibrary* library, const QString& path)
static std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries();
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
getMaterialTree(std::shared_ptr<MaterialLibrary> library) const
{
library->createPath(path);
return library->getMaterialTree();
}
void saveMaterial(MaterialLibrary* library,
Material& material,
std::shared_ptr<std::list<QString>>
getMaterialFolders(std::shared_ptr<MaterialLibrary> library) const;
void createFolder(std::shared_ptr<MaterialLibrary> library, const QString& path)
{
library->createFolder(path);
}
void renameFolder(std::shared_ptr<MaterialLibrary> library,
const QString& oldPath,
const QString& newPath)
{
library->renameFolder(oldPath, newPath);
}
void deleteRecursive(std::shared_ptr<MaterialLibrary> library, const QString& path)
{
library->deleteRecursive(path);
}
void remove(const QString& uuid)
{
_materialMap->erase(uuid);
}
void saveMaterial(std::shared_ptr<MaterialLibrary> library,
std::shared_ptr<Material> material,
const QString& path,
bool saveAsCopy = true);
bool overwrite,
bool saveAsCopy,
bool saveInherited);
static bool isMaterial(const fs::path& p);
static bool isMaterial(const QFileInfo& file);
std::shared_ptr<std::map<QString, Material*>> materialsWithModel(QString uuid);
std::shared_ptr<std::map<QString, Material*>> materialsWithModelComplete(QString uuid);
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialsWithModel(QString uuid);
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
materialsWithModelComplete(QString uuid);
void dereference(std::shared_ptr<Material> material);
private:
static std::shared_ptr<std::list<MaterialLibrary*>> _libraryList;
static std::shared_ptr<std::map<QString, Material*>> _materialMap;
static std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> _libraryList;
static std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> _materialMap;
static QMutex _mutex;
static void initLibraries();

View File

@@ -21,10 +21,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_io.hpp>
#endif
#include "Exceptions.h"
#include "MaterialManager.h"
#include "MaterialManagerPy.h"
@@ -64,9 +60,8 @@ PyObject* MaterialManagerPy::getMaterial(PyObject* args)
}
try {
const Material& material =
getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid));
return new MaterialPy(new Material(material));
auto material = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid));
return new MaterialPy(new Material(*material));
}
catch (const MaterialNotFound&) {
PyErr_SetString(PyExc_LookupError, "Material not found");
@@ -85,9 +80,9 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
QString libPath(QString::fromStdString(lib));
if (!libPath.isEmpty()) {
try {
const Material& material =
auto material =
getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path), libPath);
return new MaterialPy(new Material(material));
return new MaterialPy(new Material(*material));
}
catch (const MaterialNotFound&) {
PyErr_SetString(PyExc_LookupError, "Material not found");
@@ -100,9 +95,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
}
try {
const Material& material =
getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path));
return new MaterialPy(new Material(material));
auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path));
return new MaterialPy(new Material(*material));
}
catch (const MaterialNotFound&) {
PyErr_SetString(PyExc_LookupError, "Material not found");
@@ -116,7 +110,7 @@ Py::List MaterialManagerPy::getMaterialLibraries() const
Py::List list;
for (auto it = libraries->begin(); it != libraries->end(); it++) {
MaterialLibrary* lib = *it;
auto lib = *it;
Py::Tuple libTuple(3);
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
@@ -136,7 +130,7 @@ Py::Dict MaterialManagerPy::getMaterials() const
for (auto it = materials->begin(); it != materials->end(); it++) {
QString key = it->first;
Material* material = it->second;
auto material = it->second;
PyObject* materialPy = new MaterialPy(new Material(*material));
dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true));
@@ -168,7 +162,7 @@ PyObject* MaterialManagerPy::materialsWithModel(PyObject* args)
for (auto it = materials->begin(); it != materials->end(); it++) {
QString key = it->first;
Material* material = it->second;
auto material = it->second;
PyObject* materialPy = new MaterialPy(new Material(*material));
PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy);
@@ -190,7 +184,7 @@ PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args)
for (auto it = materials->begin(); it != materials->end(); it++) {
QString key = it->first;
Material* material = it->second;
auto material = it->second;
PyObject* materialPy = new MaterialPy(new Material(*material));
PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy);

View File

@@ -77,10 +77,22 @@
</Attribute>
<Attribute Name="AuthorAndLicense" ReadOnly="true">
<Documentation>
<UserDocu>Author and license information.</UserDocu>
<UserDocu>deprecated -- Author and license information.</UserDocu>
</Documentation>
<Parameter Name="AuthorAndLicense" Type="String"/>
</Attribute>
<Attribute Name="Author" ReadOnly="true">
<Documentation>
<UserDocu>Author information.</UserDocu>
</Documentation>
<Parameter Name="Author" Type="String"/>
</Attribute>
<Attribute Name="License" ReadOnly="true">
<Documentation>
<UserDocu>License information.</UserDocu>
</Documentation>
<Parameter Name="License" Type="String"/>
</Attribute>
<Attribute Name="PhysicalModels" ReadOnly="true">
<Documentation>
<UserDocu>List of implemented models.</UserDocu>

View File

@@ -21,20 +21,18 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_io.hpp>
#endif
#include <QMetaType>
#include <Base/Quantity.h>
#include <Base/QuantityPy.h>
#include <Gui/MetaTypes.h>
#include "Exceptions.h"
#include "MaterialPy.h"
#include "Materials.h"
#include "Exceptions.h"
#include "MaterialLibrary.h"
#include "MaterialPy.h"
#include "MaterialPy.cpp"
using namespace Materials;
@@ -49,11 +47,11 @@ std::string MaterialPy::representation() const
str << "), UUID=(";
str << ptr->getUUID().toStdString();
str << "), Library Name=(";
str << ptr->getLibrary().getName().toStdString();
str << ptr->getLibrary()->getName().toStdString();
str << "), Library Root=(";
str << ptr->getLibrary().getDirectoryPath().toStdString();
str << ptr->getLibrary()->getDirectoryPath().toStdString();
str << "), Library Icon=(";
str << ptr->getLibrary().getIconPath().toStdString();
str << ptr->getLibrary()->getIconPath().toStdString();
str << "), Directory=(";
str << ptr->getDirectory().toStdString();
// str << "), URL=(";
@@ -93,17 +91,17 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
Py::String MaterialPy::getLibraryName() const
{
return Py::String(getMaterialPtr()->getLibrary().getName().toStdString());
return Py::String(getMaterialPtr()->getLibrary()->getName().toStdString());
}
Py::String MaterialPy::getLibraryRoot() const
{
return Py::String(getMaterialPtr()->getLibrary().getDirectoryPath().toStdString());
return Py::String(getMaterialPtr()->getLibrary()->getDirectoryPath().toStdString());
}
Py::String MaterialPy::getLibraryIcon() const
{
return Py::String(getMaterialPtr()->getLibrary().getIconPath().toStdString());
return Py::String(getMaterialPtr()->getLibrary()->getIconPath().toStdString());
}
Py::String MaterialPy::getName() const
@@ -146,15 +144,23 @@ Py::String MaterialPy::getAuthorAndLicense() const
return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString());
}
Py::String MaterialPy::getAuthor() const
{
return Py::String(getMaterialPtr()->getAuthor().toStdString());
}
Py::String MaterialPy::getLicense() const
{
return Py::String(getMaterialPtr()->getLicense().toStdString());
}
Py::List MaterialPy::getPhysicalModels() const
{
const std::vector<QString>* models = getMaterialPtr()->getPhysicalModels();
auto models = getMaterialPtr()->getPhysicalModels();
Py::List list;
for (auto it = models->begin(); it != models->end(); it++) {
QString uuid = *it;
list.append(Py::String(uuid.toStdString()));
list.append(Py::String(it->toStdString()));
}
return list;
@@ -162,13 +168,11 @@ Py::List MaterialPy::getPhysicalModels() const
Py::List MaterialPy::getAppearanceModels() const
{
const std::vector<QString>* models = getMaterialPtr()->getAppearanceModels();
auto models = getMaterialPtr()->getAppearanceModels();
Py::List list;
for (auto it = models->begin(); it != models->end(); it++) {
QString uuid = *it;
list.append(Py::String(uuid.toStdString()));
list.append(Py::String(it->toStdString()));
}
return list;
@@ -176,13 +180,11 @@ Py::List MaterialPy::getAppearanceModels() const
Py::List MaterialPy::getTags() const
{
const std::list<QString>& tags = getMaterialPtr()->getTags();
auto& tags = getMaterialPtr()->getTags();
Py::List list;
for (auto it = tags.begin(); it != tags.end(); it++) {
QString uuid = *it;
list.append(Py::String(uuid.toStdString()));
list.append(Py::String(it->toStdString()));
}
return list;
@@ -272,6 +274,8 @@ Py::Dict MaterialPy::getProperties() const
dict.setItem(Py::String("CardName"), Py::String(getMaterialPtr()->getName().toStdString()));
dict.setItem(Py::String("AuthorAndLicense"),
Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString()));
dict.setItem(Py::String("Author"), Py::String(getMaterialPtr()->getAuthor().toStdString()));
dict.setItem(Py::String("License"), Py::String(getMaterialPtr()->getLicense().toStdString()));
dict.setItem(Py::String("Name"), Py::String(getMaterialPtr()->getName().toStdString()));
dict.setItem(Py::String("Description"),
Py::String(getMaterialPtr()->getDescription().toStdString()));
@@ -282,10 +286,10 @@ Py::Dict MaterialPy::getProperties() const
auto properties = getMaterialPtr()->getPhysicalProperties();
for (auto it = properties.begin(); it != properties.end(); it++) {
QString key = it->first;
MaterialProperty& materialProperty = it->second;
auto materialProperty = it->second;
if (!materialProperty.isNull()) {
auto value = materialProperty.getString();
if (!materialProperty->isNull()) {
auto value = materialProperty->getString();
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
}
}
@@ -293,10 +297,10 @@ Py::Dict MaterialPy::getProperties() const
properties = getMaterialPtr()->getAppearanceProperties();
for (auto it = properties.begin(); it != properties.end(); it++) {
QString key = it->first;
MaterialProperty& materialProperty = it->second;
auto materialProperty = it->second;
if (!materialProperty.isNull()) {
auto value = materialProperty.getString();
if (!materialProperty->isNull()) {
auto value = materialProperty->getString();
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
}
}
@@ -311,10 +315,10 @@ Py::Dict MaterialPy::getPhysicalProperties() const
auto properties = getMaterialPtr()->getPhysicalProperties();
for (auto it = properties.begin(); it != properties.end(); it++) {
QString key = it->first;
MaterialProperty& materialProperty = it->second;
auto materialProperty = it->second;
if (!materialProperty.isNull()) {
auto value = materialProperty.getString();
if (!materialProperty->isNull()) {
auto value = materialProperty->getString();
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
}
}
@@ -329,10 +333,10 @@ Py::Dict MaterialPy::getAppearanceProperties() const
auto properties = getMaterialPtr()->getAppearanceProperties();
for (auto it = properties.begin(); it != properties.end(); it++) {
QString key = it->first;
MaterialProperty& materialProperty = it->second;
auto materialProperty = it->second;
if (!materialProperty.isNull()) {
auto value = materialProperty.getString();
if (!materialProperty->isNull()) {
auto value = materialProperty->getString();
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
}
}
@@ -346,7 +350,7 @@ static PyObject* _pyObjectFromVariant(const QVariant& value)
return new PyObject();
}
if (value.userType() == qMetaTypeId<Base::Quantity>()) {
if (value.userType() == QMetaType::type("Base::Quantity")) {
return new Base::QuantityPy(new Base::Quantity(value.value<Base::Quantity>()));
}
else if (value.userType() == QMetaType::Double) {

View File

@@ -23,7 +23,11 @@
#ifndef _PreComp_
#endif
#include <QMetaType>
#include <App/Application.h>
#include <Base/Quantity.h>
#include <Gui/MetaTypes.h>
#include "Exceptions.h"
#include "MaterialValue.h"
@@ -33,29 +37,203 @@ using namespace Materials;
/* TRANSLATOR Material::MaterialValue */
TYPESYSTEM_SOURCE(Materials::MaterialValue, Base::BaseClass)
MaterialValue::MaterialValue()
: _valueType(None)
{
this->setInitialValue(None);
}
MaterialValue::MaterialValue(const MaterialValue& other)
: _valueType(other._valueType)
, _value(other._value)
{}
MaterialValue::MaterialValue(ValueType type)
: _valueType(type)
{}
{
this->setInitialValue(None);
}
MaterialValue::MaterialValue(ValueType type, ValueType inherited)
: _valueType(type)
{
this->setInitialValue(inherited);
}
MaterialValue& MaterialValue::operator=(const MaterialValue& other)
{
if (this == &other) {
return *this;
}
_valueType = other._valueType;
_value = other._value;
return *this;
}
bool MaterialValue::operator==(const MaterialValue& other) const
{
if (this == &other) {
return true;
}
return (_valueType == other._valueType) && (_value == other._value);
}
void MaterialValue::setInitialValue(ValueType inherited)
{
if (_valueType == String) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == Boolean) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::Bool));
}
else if (_valueType == Integer) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::Int));
}
else if (_valueType == Float) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::Float));
}
else if (_valueType == URL) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == Quantity) {
Base::Quantity q;
q.setInvalid();
_value = QVariant::fromValue(q);
}
else if (_valueType == Color) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == File) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == Image) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == List) {
_value = QVariant(static_cast<QVariant::Type>(QMetaType::QString));
}
else if (_valueType == Array2D) {
if (_valueType != inherited) {
throw InvalidMaterialType("Initializing a regular material value as a 2D Array");
}
_value = QVariant(); // Uninitialized default value
}
else if (_valueType == Array3D) {
if (_valueType != inherited) {
throw InvalidMaterialType("Initializing a regular material value as a 3D Array");
}
_value = QVariant(); // Uninitialized default value
}
else {
// Default is to set the type to None and leave the variant uninitialized
_valueType = None;
_value = QVariant();
}
}
bool MaterialValue::isNull() const
{
if (_value.isNull()) {
return true;
}
if (_valueType == Quantity) {
return !_value.value<Base::Quantity>().isValid();
}
return false;
}
const QString MaterialValue::getYAMLString() const
{
QString yaml = QString::fromStdString("\"");
if (!isNull()) {
if (getType() == MaterialValue::Quantity) {
Base::Quantity quantity = getValue().value<Base::Quantity>();
yaml += quantity.getUserString();
}
else if (getType() == MaterialValue::Float) {
auto value = getValue();
if (!value.isNull()) {
yaml += QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6);
}
}
else {
yaml += getValue().toString();
}
}
yaml += QString::fromStdString("\"");
return yaml;
}
//===
TYPESYSTEM_SOURCE(Materials::Material2DArray, Materials::MaterialValue)
Material2DArray::Material2DArray()
: MaterialValue(Array2D)
: MaterialValue(Array2D, Array2D)
, _defaultSet(false)
{}
MaterialValue Material2DArray::getDefault() const
{
MaterialValue ret(_valueType);
ret.setValue(_value);
return ret;
// Initialize separatelt to prevent recursion
// setType(Array2D);
}
const std::vector<QVariant>* Material2DArray::getRow(int row) const
Material2DArray::Material2DArray(const Material2DArray& other)
: MaterialValue(other)
, _defaultSet(other._defaultSet)
{
deepCopy(other);
}
Material2DArray& Material2DArray::operator=(const Material2DArray& other)
{
if (this == &other) {
return *this;
}
MaterialValue::operator=(other);
_defaultSet = other._defaultSet;
deepCopy(other);
return *this;
}
void Material2DArray::deepCopy(const Material2DArray& other)
{
// Deep copy
for (auto row : other._rows) {
std::vector<QVariant> v;
for (auto col : *row) {
QVariant newVariant(col);
v.push_back(newVariant);
}
addRow(std::make_shared<std::vector<QVariant>>(v));
}
}
bool Material2DArray::isNull() const
{
return rows() <= 0;
}
const QVariant Material2DArray::getDefault() const
{
if (_defaultSet) {
return _value;
}
return QVariant();
}
std::shared_ptr<std::vector<QVariant>> Material2DArray::getRow(int row) const
{
try {
return _rows.at(row);
@@ -65,7 +243,7 @@ const std::vector<QVariant>* Material2DArray::getRow(int row) const
}
}
std::vector<QVariant>* Material2DArray::getRow(int row)
std::shared_ptr<std::vector<QVariant>> Material2DArray::getRow(int row)
{
try {
return _rows.at(row);
@@ -75,12 +253,12 @@ std::vector<QVariant>* Material2DArray::getRow(int row)
}
}
void Material2DArray::addRow(std::vector<QVariant>* row)
void Material2DArray::addRow(std::shared_ptr<std::vector<QVariant>> row)
{
_rows.push_back(row);
}
void Material2DArray::insertRow(int index, std::vector<QVariant>* row)
void Material2DArray::insertRow(int index, std::shared_ptr<std::vector<QVariant>> row)
{
_rows.insert(_rows.begin() + index, row);
}
@@ -99,7 +277,7 @@ void Material2DArray::setValue(int row, int column, const QVariant& value)
throw InvalidIndex();
}
std::vector<QVariant>* val = getRow(row);
auto val = getRow(row);
try {
val->at(column) = value;
}
@@ -124,10 +302,10 @@ const QVariant Material2DArray::getValue(int row, int column) const
}
}
void Material2DArray::dumpRow(const std::vector<QVariant>& row) const
void Material2DArray::dumpRow(std::shared_ptr<std::vector<QVariant>> row) const
{
Base::Console().Log("row: ");
for (auto column : row) {
for (auto column : *row) {
Base::Console().Log("'%s' ", column.toString().toStdString().c_str());
}
Base::Console().Log("\n");
@@ -136,107 +314,389 @@ void Material2DArray::dumpRow(const std::vector<QVariant>& row) const
void Material2DArray::dump() const
{
for (auto row : _rows) {
dumpRow(*row);
dumpRow(row);
}
}
const QString Material2DArray::getYAMLString() const
{
if (isNull()) {
return QString();
}
// Set the correct indentation. 9 chars in this case
QString pad;
pad.fill(QChar::fromLatin1(' '), 9);
// Save the default value
QString yaml = QString::fromStdString("\n - \"");
Base::Quantity quantity = getDefault().value<Base::Quantity>();
yaml += quantity.getUserString();
yaml += QString::fromStdString("\"\n");
// Next the array contents
yaml += QString::fromStdString(" - [");
bool firstRow = true;
for (auto row : _rows) {
if (!firstRow) {
// Each row is on its own line, padded for correct indentation
yaml += QString::fromStdString(",\n") + pad;
}
else {
firstRow = false;
}
yaml += QString::fromStdString("[");
bool first = true;
for (auto column : *row) {
if (!first) {
// TODO: Fix for arrays with too many columns to fit on a single line
yaml += QString::fromStdString(", ");
}
else {
first = false;
}
yaml += QString::fromStdString("\"");
Base::Quantity quantity = column.value<Base::Quantity>();
yaml += quantity.getUserString();
yaml += QString::fromStdString("\"");
}
yaml += QString::fromStdString("]");
}
yaml += QString::fromStdString("]");
return yaml;
}
//===
TYPESYSTEM_SOURCE(Materials::Material3DArray, Materials::MaterialValue)
Material3DArray::Material3DArray()
: MaterialValue(Array3D)
: MaterialValue(Array3D, Array3D)
, _defaultSet(false)
{}
MaterialValue Material3DArray::getDefault() const
, _currentDepth(0)
{
MaterialValue ret(_valueType);
ret.setValue(_value);
return ret;
// Initialize separatelt to prevent recursion
// setType(Array3D);
}
const std::vector<std::vector<QVariant>*>& Material3DArray::getTable(const QVariant& depth) const
bool Material3DArray::isNull() const
{
return depth() <= 0;
}
const QVariant Material3DArray::getDefault() const
{
return _value;
}
const std::shared_ptr<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>&
Material3DArray::getTable(const Base::Quantity& depth) const
{
for (auto it = _rowMap.begin(); it != _rowMap.end(); it++) {
if (std::get<0>(*it) == depth) {
return std::get<1>(*it);
}
}
throw InvalidDepth();
}
const std::shared_ptr<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>&
Material3DArray::getTable(int depthIndex) const
{
try {
return _rowMap.at(depth);
return std::get<1>(_rowMap.at(depthIndex));
}
catch (std::out_of_range const&) {
throw InvalidDepth();
}
}
const std::shared_ptr<std::vector<Base::Quantity>> Material3DArray::getRow(int depth, int row) const
{
try {
return getTable(depth)->at(row);
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
const std::vector<QVariant>& Material3DArray::getRow(const QVariant& depth, int row) const
std::shared_ptr<std::vector<Base::Quantity>> Material3DArray::getRow(int row) const
{
// Check if we can convert otherwise throw error
return getRow(_currentDepth, row);
}
std::shared_ptr<std::vector<Base::Quantity>> Material3DArray::getRow(int depth, int row)
{
try {
return *(_rowMap.at(depth).at(row));
return getTable(depth)->at(row);
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
const std::vector<QVariant>& Material3DArray::getRow(int row) const
std::shared_ptr<std::vector<Base::Quantity>> Material3DArray::getRow(int row)
{
return getRow(getDefault().getValue().toString(), row);
return getRow(_currentDepth, row);
}
std::vector<QVariant>& Material3DArray::getRow(const QVariant& depth, int row)
void Material3DArray::addRow(int depth, std::shared_ptr<std::vector<Base::Quantity>> row)
{
try {
return *(_rowMap.at(depth).at(row));
getTable(depth)->push_back(row);
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
std::vector<QVariant>& Material3DArray::getRow(int row)
void Material3DArray::addRow(std::shared_ptr<std::vector<Base::Quantity>> row)
{
return getRow(getDefault().getValue().toString(), row);
addRow(_currentDepth, row);
}
void Material3DArray::addRow(const QVariant& depth, std::vector<QVariant>* row)
int Material3DArray::addDepth(int depth, Base::Quantity value)
{
_rowMap[depth].push_back(row);
if (depth == this->depth()) {
// Append to the end
return addDepth(value);
}
else if (depth > this->depth()) {
throw InvalidDepth();
}
auto rowVector = std::make_shared<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>();
auto entry = std::make_pair(value, rowVector);
_rowMap.insert(_rowMap.begin() + depth, entry);
return depth;
}
void Material3DArray::deleteRow(const QVariant& depth, int row)
int Material3DArray::addDepth(Base::Quantity value)
{
Q_UNUSED(depth)
Q_UNUSED(row)
auto rowVector = std::make_shared<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>();
auto entry = std::make_pair(value, rowVector);
_rowMap.push_back(entry);
return depth() - 1;
}
void Material3DArray::deleteDepth(int depth)
{
deleteRows(depth); // This may throw an InvalidDepth
_rowMap.erase(_rowMap.begin() + depth);
}
void Material3DArray::insertRow(int depth,
int row,
std::shared_ptr<std::vector<Base::Quantity>> rowData)
{
try {
auto table = getTable(depth);
// auto it = table->begin();
// std::advance(it, row);
table->insert(table->begin() + row, rowData);
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
void Material3DArray::insertRow(int row, std::shared_ptr<std::vector<Base::Quantity>> rowData)
{
insertRow(_currentDepth, row, rowData);
}
void Material3DArray::deleteRow(int depth, int row)
{
auto table = getTable(depth);
if (static_cast<std::size_t>(row) >= table->size() || row < 0) {
throw InvalidRow();
}
table->erase(table->begin() + row);
}
void Material3DArray::deleteRow(int row)
{
deleteRow(_currentDepth, row);
}
void Material3DArray::deleteRows(int depth)
{
Q_UNUSED(depth)
auto table = getTable(depth);
table->clear();
}
void Material3DArray::setValue(const QVariant& depth, int row, int column, const QVariant& value)
void Material3DArray::deleteRows()
{
Q_UNUSED(depth)
Q_UNUSED(row)
Q_UNUSED(column)
Q_UNUSED(value)
deleteRows(_currentDepth);
}
void Material3DArray::setValue(int row, int column, const QVariant& value)
int Material3DArray::rows(int depth) const
{
Q_UNUSED(row)
Q_UNUSED(column)
Q_UNUSED(value)
if (depth < 0 || (depth == 0 && this->depth() == 0)) {
return 0;
}
return getTable(depth)->size();
}
const QVariant Material3DArray::getValue(const QVariant& depth, int row, int column)
int Material3DArray::columns(int depth) const
{
if (depth < 0 || (depth == 0 && this->depth() == 0)) {
return 0;
}
if (rows() == 0) {
return 0;
}
return getTable(depth)->at(0)->size();
}
void Material3DArray::setValue(int depth, int row, int column, const Base::Quantity& value)
{
auto val = getRow(depth, row);
try {
return val.at(column);
val->at(column) = value;
}
catch (std::out_of_range const&) {
throw InvalidColumn();
}
}
const QVariant Material3DArray::getValue(int row, int column)
void Material3DArray::setValue(int row, int column, const Base::Quantity& value)
{
return getValue(getDefault().getValue().toString(), row, column);
setValue(_currentDepth, row, column, value);
}
void Material3DArray::setDepthValue(int depth, const Base::Quantity& value)
{
try {
auto oldRows = getTable(depth);
_rowMap.at(depth) = std::pair(value, oldRows);
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
void Material3DArray::setDepthValue(const Base::Quantity& value)
{
setDepthValue(_currentDepth, value);
}
const Base::Quantity Material3DArray::getValue(int depth, int row, int column) const
{
auto val = getRow(depth, row);
try {
return val->at(column);
}
catch (std::out_of_range const&) {
throw InvalidColumn();
}
}
const Base::Quantity Material3DArray::getValue(int row, int column) const
{
return getValue(_currentDepth, row, column);
}
const Base::Quantity Material3DArray::getDepthValue(int depth) const
{
try {
return std::get<0>(_rowMap.at(depth));
}
catch (std::out_of_range const&) {
throw InvalidRow();
}
}
int Material3DArray::currentDepth() const
{
return _currentDepth;
}
void Material3DArray::setCurrentDepth(int depth)
{
if (depth < 0 || _rowMap.size() == 0) {
_currentDepth = 0;
}
else if (static_cast<std::size_t>(depth) >= _rowMap.size()) {
_currentDepth = _rowMap.size() - 1;
}
else {
_currentDepth = depth;
}
}
const QString Material3DArray::getYAMLString() const
{
if (isNull()) {
return QString();
}
// Set the correct indentation. 7 chars + name length
QString pad;
pad.fill(QChar::fromLatin1(' '), 9);
// Save the default value
QString yaml = QString::fromStdString("\n - \"");
Base::Quantity quantity = getDefault().value<Base::Quantity>();
yaml += quantity.getUserString();
yaml += QString::fromStdString("\"\n");
// Next the array contents
yaml += QString::fromStdString(" - [");
for (int depth = 0; depth < this->depth(); depth++) {
if (depth > 0) {
// Each row is on its own line, padded for correct indentation
yaml += QString::fromStdString(",\n") + pad;
}
yaml += QString::fromStdString("\"");
auto value = getDepthValue(depth).getUserString();
yaml += value;
yaml += QString::fromStdString("\": [");
QString pad2;
pad2.fill(QChar::fromLatin1(' '), 14 + value.length());
bool firstRow = true;
auto rows = getTable(depth);
for (auto row : *rows) {
if (!firstRow) {
// Each row is on its own line, padded for correct indentation
yaml += QString::fromStdString(",\n") + pad2;
}
else {
firstRow = false;
}
yaml += QString::fromStdString("[");
bool first = true;
for (auto column : *row) {
if (!first) {
// TODO: Fix for arrays with too many columns to fit on a single line
yaml += QString::fromStdString(", ");
}
else {
first = false;
}
yaml += QString::fromStdString("\"");
// Base::Quantity quantity = column.value<Base::Quantity>();
yaml += column.getUserString();
yaml += QString::fromStdString("\"");
}
yaml += QString::fromStdString("]");
}
yaml += QString::fromStdString("]");
}
yaml += QString::fromStdString("]");
return yaml;
}

View File

@@ -22,15 +22,22 @@
#ifndef MATERIAL_MATERIALVALUE_H
#define MATERIAL_MATERIALVALUE_H
#include <Mod/Material/MaterialGlobal.h>
#include <memory>
#include <QMetaType>
#include <QVariant>
#include <Gui/MetaTypes.h>
#include <Mod/Material/MaterialGlobal.h>
namespace Materials
{
class MaterialsExport MaterialValue
class MaterialsExport MaterialValue: public Base::BaseClass
{
TYPESYSTEM_HEADER();
public:
enum ValueType
{
@@ -50,9 +57,17 @@ public:
URL = 13
};
MaterialValue();
explicit MaterialValue(ValueType type);
MaterialValue(const MaterialValue& other);
MaterialValue(ValueType type);
virtual ~MaterialValue() = default;
MaterialValue& operator=(const MaterialValue& other);
virtual bool operator==(const MaterialValue& other) const;
bool operator!=(const MaterialValue& other) const
{
return !operator==(other);
}
ValueType getType() const
{
return _valueType;
@@ -62,10 +77,8 @@ public:
{
return _value;
}
bool isNull() const
{
return _value.isNull();
}
virtual bool isNull() const;
virtual const QVariant getValueAt(const QVariant& value) const
{
Q_UNUSED(value);
@@ -76,126 +89,182 @@ public:
_value = value;
}
virtual const QString getYAMLString() const;
protected:
ValueType _valueType;
QVariant _value;
MaterialValue(ValueType type, ValueType inherited);
void setType(ValueType type)
{
_valueType = type;
}
void setInitialValue(ValueType inherited);
ValueType _valueType;
QVariant _value;
};
class MaterialsExport Material2DArray: public MaterialValue
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
Material2DArray();
Material2DArray(const Material2DArray& other);
~Material2DArray() override = default;
void setDefault(MaterialValue value)
Material2DArray& operator=(const Material2DArray& other);
bool isNull() const override;
void setDefault(MaterialValue value, bool markSet = true)
{
_value = value.getValue();
_defaultSet = true;
_defaultSet = markSet;
}
void setDefault(const QVariant& value)
void setDefault(const QVariant& value, bool markSet = true)
{
_value = value;
_defaultSet = true;
_defaultSet = markSet;
}
MaterialValue getDefault() const;
void setDefault(const Base::Quantity& value, bool markSet = true)
{
_value = QVariant::fromValue(value);
_defaultSet = markSet;
}
const QVariant getDefault() const;
bool defaultSet() const
{
return _defaultSet;
}
const std::vector<QVariant>* getRow(int row) const;
std::vector<QVariant>* getRow(int row);
std::shared_ptr<std::vector<QVariant>> getRow(int row) const;
std::shared_ptr<std::vector<QVariant>> getRow(int row);
int rows() const
{
return _rows.size();
}
void addRow(std::vector<QVariant>* row);
void insertRow(int index, std::vector<QVariant>* row);
int columns() const
{
if (rows() == 0) {
return 0;
}
return _rows.at(0)->size();
}
void addRow(std::shared_ptr<std::vector<QVariant>> row);
void insertRow(int index, std::shared_ptr<std::vector<QVariant>> row);
void deleteRow(int row);
void setValue(int row, int column, const QVariant& value);
const QVariant getValue(int row, int column) const;
const QString getYAMLString() const override;
protected:
std::vector<std::vector<QVariant>*> _rows;
void deepCopy(const Material2DArray& other);
std::vector<std::shared_ptr<std::vector<QVariant>>> _rows;
bool _defaultSet;
private:
void dumpRow(const std::vector<QVariant>& row) const;
void dumpRow(std::shared_ptr<std::vector<QVariant>> row) const;
void dump() const;
};
class MaterialsExport Material3DArray: public MaterialValue
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
Material3DArray();
~Material3DArray() override = default;
void setDefault(MaterialValue value)
bool isNull() const override;
void setDefault(MaterialValue value, bool markSet = true)
{
_value = value.getValue();
_defaultSet = true;
_defaultSet = markSet;
}
void setDefault(const QVariant& value)
void setDefault(const QVariant& value, bool markSet = true)
{
_value = value;
_defaultSet = true;
_defaultSet = markSet;
}
MaterialValue getDefault() const;
void setDefault(const Base::Quantity& value, bool markSet = true)
{
_value = QVariant::fromValue(value);
_defaultSet = markSet;
}
const QVariant getDefault() const;
bool defaultSet() const
{
return _defaultSet;
}
const std::vector<std::vector<QVariant>*>& getTable(const QVariant& depth) const;
const std::vector<QVariant>& getRow(const QVariant& depth, int row) const;
const std::vector<QVariant>& getRow(int row) const;
std::vector<QVariant>& getRow(const QVariant& depth, int row);
std::vector<QVariant>& getRow(int row);
void addRow(const QVariant& depth, std::vector<QVariant>* row);
void deleteRow(const QVariant& depth, int row);
const std::shared_ptr<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>&
getTable(const Base::Quantity& depth) const;
const std::shared_ptr<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>&
getTable(int depthIndex) const;
const std::shared_ptr<std::vector<Base::Quantity>> getRow(int depth, int row) const;
std::shared_ptr<std::vector<Base::Quantity>> getRow(int row) const;
std::shared_ptr<std::vector<Base::Quantity>> getRow(int depth, int row);
std::shared_ptr<std::vector<Base::Quantity>> getRow(int row);
void addRow(int depth, std::shared_ptr<std::vector<Base::Quantity>> row);
void addRow(std::shared_ptr<std::vector<Base::Quantity>> row);
int addDepth(int depth, Base::Quantity value);
int addDepth(Base::Quantity value);
void deleteDepth(int depth);
void insertRow(int depth, int row, std::shared_ptr<std::vector<Base::Quantity>> rowData);
void insertRow(int row, std::shared_ptr<std::vector<Base::Quantity>> rowData);
void deleteRow(int depth, int row);
void deleteRow(int row);
void deleteRows(int depth);
void deleteRows();
int depth() const
{
return _rowMap.size();
}
int rows(const QVariant& depth) const
int rows(int depth) const;
int rows() const
{
return getTable(depth).size();
return rows(_currentDepth);
}
int columns(int depth) const;
int columns() const
{
return columns(_currentDepth);
}
void setValue(const QVariant& depth, int row, int column, const QVariant& value);
void setValue(int row, int column, const QVariant& value);
const QVariant getValue(const QVariant& depth, int row, int column);
const QVariant getValue(int row, int column);
void setValue(int depth, int row, int column, const Base::Quantity& value);
void setValue(int row, int column, const Base::Quantity& value);
void setDepthValue(int depth, const Base::Quantity& value);
void setDepthValue(const Base::Quantity& value);
const Base::Quantity getValue(int depth, int row, int column) const;
const Base::Quantity getValue(int row, int column) const;
const Base::Quantity getDepthValue(int depth) const;
int currentDepth() const;
void setCurrentDepth(int depth);
const QString getYAMLString() const override;
protected:
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
std::map<QVariant, std::vector<std::vector<QVariant>*>> _rowMap;
#else
struct variant_comp
{
bool operator()(const QVariant& var1,
const QVariant& var2) const
{
return QVariant::compare(var1, var2) == QPartialOrdering::Less;
}
};
std::map<QVariant, std::vector<std::vector<QVariant>*>, variant_comp> _rowMap;
#endif
std::vector<
std::pair<Base::Quantity,
std::shared_ptr<std::vector<std::shared_ptr<std::vector<Base::Quantity>>>>>>
_rowMap;
bool _defaultSet;
int _currentDepth;
};
} // namespace Materials
Q_DECLARE_METATYPE(Materials::MaterialValue)
Q_DECLARE_METATYPE(Materials::Material2DArray)
Q_DECLARE_METATYPE(Materials::Material3DArray)
// Q_DECLARE_METATYPE(Materials::Material2DArray)
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material2DArray>)
// Q_DECLARE_METATYPE(Materials::Material3DArray)
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material3DArray>)
#endif // MATERIAL_MATERIALVALUE_H

File diff suppressed because it is too large Load Diff

View File

@@ -22,31 +22,34 @@
#ifndef MATERIAL_MATERIALS_H
#define MATERIAL_MATERIALS_H
#include <Mod/Material/MaterialGlobal.h>
#include <memory>
#include <Base/BaseClass.h>
#include <QDir>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <App/Application.h>
#include <Base/BaseClass.h>
#include <Mod/Material/MaterialGlobal.h>
#include "MaterialLibrary.h"
#include "Model.h"
namespace fs = boost::filesystem;
namespace Materials
{
class MaterialLibrary;
class MaterialsExport MaterialProperty: public ModelProperty
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
MaterialProperty();
explicit MaterialProperty(const ModelProperty& property);
explicit MaterialProperty(const MaterialProperty& property);
MaterialProperty(const ModelProperty& property);
MaterialProperty(const MaterialProperty& property);
MaterialProperty(std::shared_ptr<MaterialProperty> property);
~MaterialProperty() override = default;
MaterialValue::ValueType getType() const
@@ -63,6 +66,7 @@ public:
std::shared_ptr<MaterialValue> getMaterialValue();
const std::shared_ptr<MaterialValue> getMaterialValue() const;
const QString getString() const;
const QString getYAMLString() const;
bool getBoolean() const;
int getInt() const;
double getFloat() const;
@@ -79,6 +83,7 @@ public:
void setPropertyType(const QString& type) override;
void setValue(const QVariant& value);
void setValue(const QString& value);
void setValue(std::shared_ptr<MaterialValue> value);
void setString(const QString& value);
void setBoolean(bool value);
void setBoolean(int value);
@@ -93,10 +98,23 @@ public:
void setURL(const QString& value);
MaterialProperty& operator=(const MaterialProperty& other);
friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property)
{
output << property.getName() << ": " << property.getYAMLString();
return output;
}
bool operator==(const MaterialProperty& other) const;
bool operator!=(const MaterialProperty& other) const
{
return !operator==(other);
}
// void save(QTextStream& stream);
protected:
void setType(const QString& type);
// void setType(MaterialValue::ValueType type) { _valueType = type; }
void copyValuePtr(std::shared_ptr<MaterialValue> value);
void addColumn(MaterialProperty& column)
{
@@ -122,14 +140,14 @@ public:
};
Material();
explicit Material(const MaterialLibrary& library,
const QString& directory,
const QString& uuid,
const QString& name);
explicit Material(const Material& other);
virtual ~Material();
Material(std::shared_ptr<MaterialLibrary> library,
const QString& directory,
const QString& uuid,
const QString& name);
Material(const Material& other);
~Material() override = default;
const MaterialLibrary& getLibrary() const
std::shared_ptr<MaterialLibrary> getLibrary() const
{
return _library;
}
@@ -145,9 +163,14 @@ public:
{
return _name;
}
const QString getAuthorAndLicense() const
const QString getAuthorAndLicense() const;
const QString getAuthor() const
{
return _authorAndLicense;
return _author;
}
const QString getLicense() const
{
return _license;
}
const QString getParentUUID() const
{
@@ -169,56 +192,39 @@ public:
{
return _editState;
}
const std::list<QString>& getTags() const
const QStringList& getTags() const
{
return _tags;
}
const std::vector<QString>* getPhysicalModels() const
const QStringList* getPhysicalModels() const
{
return &_physicalUuids;
}
const std::vector<QString>* getAppearanceModels() const
const QStringList* getAppearanceModels() const
{
return &_appearanceUuids;
}
void setLibrary(const MaterialLibrary& library)
void setLibrary(std::shared_ptr<MaterialLibrary> library)
{
_library = library;
}
void setDirectory(const QString& directory)
{
Base::Console().Log("Materials::setDirectory(%s)\n", directory.toStdString().c_str());
_directory = directory;
}
void setUUID(const QString& uuid)
{
_uuid = uuid;
}
void setName(const QString& name)
{
_name = name;
}
void setAuthorAndLicense(const QString& authorAndLicense)
{
_authorAndLicense = authorAndLicense;
}
void setParentUUID(const QString& uuid)
{
_parentUuid = uuid;
}
void setDescription(const QString& description)
{
_description = description;
}
void setURL(const QString& url)
{
_url = url;
}
void setReference(const QString& reference)
{
_reference = reference;
}
void setName(const QString& name);
void setAuthor(const QString& author);
void setLicense(const QString& license);
void setParentUUID(const QString& uuid);
void setDescription(const QString& description);
void setURL(const QString& url);
void setReference(const QString& reference);
void setEditState(ModelEdit newState);
void setEditStateAlter()
{
@@ -228,6 +234,7 @@ public:
{
setEditState(ModelEdit_Extend);
}
void setPropertyEditState(const QString& name);
void setPhysicalEditState(const QString& name);
void setAppearanceEditState(const QString& name);
void resetEditState()
@@ -243,23 +250,30 @@ public:
Q_UNUSED(tag);
}
void addPhysical(const QString& uuid);
void removePhysical(const QString& uuid);
void addAppearance(const QString& uuid);
void removeAppearance(const QString& uuid);
void clearModels();
void newUuid();
void setPhysicalValue(const QString& name, const QString& value);
void setPhysicalValue(const QString& name, int value);
void setPhysicalValue(const QString& name, double value);
void setPhysicalValue(const QString& name, const Base::Quantity value);
void setPhysicalValue(const QString& name, std::shared_ptr<MaterialValue> value);
void setAppearanceValue(const QString& name, const QString& value);
void setAppearanceValue(const QString& name, std::shared_ptr<MaterialValue> value);
MaterialProperty& getPhysicalProperty(const QString& name);
const MaterialProperty& getPhysicalProperty(const QString& name) const;
MaterialProperty& getAppearanceProperty(const QString& name);
const MaterialProperty& getAppearanceProperty(const QString& name) const;
std::shared_ptr<MaterialProperty> getPhysicalProperty(const QString& name);
const std::shared_ptr<MaterialProperty> getPhysicalProperty(const QString& name) const;
std::shared_ptr<MaterialProperty> getAppearanceProperty(const QString& name);
const std::shared_ptr<MaterialProperty> getAppearanceProperty(const QString& name) const;
const QVariant getPhysicalValue(const QString& name) const;
const Base::Quantity getPhysicalQuantity(const QString& name) const;
const QString getPhysicalValueString(const QString& name) const;
const QVariant getAppearanceValue(const QString& name) const;
const Base::Quantity getAppearanceQuantity(const QString& name) const;
const QString getAppearanceValueString(const QString& name) const;
bool hasPhysicalProperty(const QString& name) const;
bool hasAppearanceProperty(const QString& name) const;
@@ -275,15 +289,17 @@ public:
bool isPhysicalModelComplete(const QString& uuid) const;
bool isAppearanceModelComplete(const QString& uuid) const;
const std::map<QString, MaterialProperty>& getPhysicalProperties() const
std::map<QString, std::shared_ptr<MaterialProperty>>& getPhysicalProperties()
{
return _physical;
}
const std::map<QString, MaterialProperty>& getAppearanceProperties() const
std::map<QString, std::shared_ptr<MaterialProperty>>& getAppearanceProperties()
{
return _appearance;
}
QString getModelByName(const QString& name) const;
bool getDereferenced() const
{
return _dereferenced;
@@ -293,45 +309,80 @@ public:
_dereferenced = true;
}
void save(QTextStream& stream, bool saveAsCopy);
/*
* Normalize models by removing any inherited models
*/
QStringList normalizeModels(const QStringList& models);
/*
* Set or change the base material for the current material, updating the properties as
* required.
*/
void updateInheritance(const QString& parent);
/*
* Return a list of models that are defined in the parent material but not in this one
*/
QStringList inheritedMissingModels(const Material& parent);
/*
* Return a list of models that are defined in this model but not the parent
*/
QStringList inheritedAddedModels(const Material& parent);
/*
* Return a list of properties that have different values from the parent material
*/
void inheritedPropertyDiff(const QString& parent);
void save(QTextStream& stream, bool saveAsCopy, bool saveInherited);
Material& operator=(const Material& other);
protected:
void addModel(const QString& uuid);
void removeModel(const QString& uuid);
void removeUUID(QStringList& uuidList, const QString& uuid);
const QVariant getValue(const std::map<QString, MaterialProperty>& propertyList,
const QString& name) const;
const QString getValueString(const std::map<QString, MaterialProperty>& propertyList,
const QString& name) const;
const QVariant
getValue(const std::map<QString, std::shared_ptr<MaterialProperty>>& propertyList,
const QString& name) const;
const QString
getValueString(const std::map<QString, std::shared_ptr<MaterialProperty>>& propertyList,
const QString& name) const;
bool modelChanged(const std::shared_ptr<Material> parent,
const std::shared_ptr<Model> model) const;
bool modelAppearanceChanged(const std::shared_ptr<Material> parent,
const std::shared_ptr<Model> model) const;
void saveGeneral(QTextStream& stream) const;
void saveInherits(QTextStream& stream) const;
void saveModels(QTextStream& stream) const;
void saveAppearanceModels(QTextStream& stream) const;
void saveModels(QTextStream& stream, bool saveInherited) const;
void saveAppearanceModels(QTextStream& stream, bool saveInherited) const;
private:
MaterialLibrary _library;
std::shared_ptr<MaterialLibrary> _library;
QString _directory;
QString _uuid;
QString _name;
QString _authorAndLicense;
QString _author;
QString _license;
QString _parentUuid;
QString _description;
QString _url;
QString _reference;
std::list<QString> _tags;
std::vector<QString> _physicalUuids;
std::vector<QString> _appearanceUuids;
std::vector<QString> _allUuids; // Includes inherited models
std::map<QString, MaterialProperty> _physical;
std::map<QString, MaterialProperty> _appearance;
QStringList _tags;
QStringList _physicalUuids;
QStringList _appearanceUuids;
QStringList _allUuids; // Includes inherited models
std::map<QString, std::shared_ptr<MaterialProperty>> _physical;
std::map<QString, std::shared_ptr<MaterialProperty>> _appearance;
bool _dereferenced;
ModelEdit _editState;
};
typedef FolderTreeNode<Material> MaterialTreeNode;
} // namespace Materials
Q_DECLARE_METATYPE(Materials::Material*)
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material>)
#endif // MATERIAL_MATERIALS_H

View File

@@ -23,10 +23,13 @@
#ifndef _PreComp_
#endif
#include <string>
#include <App/Application.h>
#include "Exceptions.h"
#include "Model.h"
#include "ModelLibrary.h"
#include <string>
using namespace Materials;
@@ -81,12 +84,27 @@ ModelProperty& ModelProperty::operator=(const ModelProperty& other)
return *this;
}
bool ModelProperty::operator==(const ModelProperty& other) const
{
if (this == &other) {
return true;
}
if (&other == nullptr) {
return false;
}
return (_name == other._name) && (_propertyType == other._propertyType)
&& (_units == other._units) && (_url == other._url) && (_description == other._description)
&& (_inheritance == other._inheritance);
}
TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass)
Model::Model()
{}
Model::Model(const ModelLibrary& library,
Model::Model(std::shared_ptr<ModelLibrary> library,
ModelType type,
const QString& name,
const QString& directory,

View File

@@ -22,31 +22,45 @@
#ifndef MATERIAL_MODEL_H
#define MATERIAL_MODEL_H
#include <Mod/Material/MaterialGlobal.h>
#include <memory>
#include <QDir>
#include <QString>
#include <QStringList>
#include <Base/BaseClass.h>
#include <Base/Quantity.h>
#include <QDir>
#include <QString>
#include <Mod/Material/MaterialGlobal.h>
#include "FolderTree.h"
#include "MaterialValue.h"
#include "ModelLibrary.h"
// #include "ModelLibrary.h"
namespace Materials
{
class ModelLibrary;
enum ModelFilter
{
ModelFilter_None,
ModelFilter_Physical,
ModelFilter_Appearance
};
class MaterialsExport ModelProperty: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
ModelProperty();
explicit ModelProperty(const QString& name,
const QString& type,
const QString& units,
const QString& url,
const QString& description);
explicit ModelProperty(const ModelProperty& other);
ModelProperty(const QString& name,
const QString& type,
const QString& units,
const QString& url,
const QString& description);
ModelProperty(const ModelProperty& other);
~ModelProperty() override = default;
const QString getName() const
@@ -117,6 +131,11 @@ public:
}
ModelProperty& operator=(const ModelProperty& other);
bool operator==(const ModelProperty& other) const;
bool operator!=(const ModelProperty& other) const
{
return !operator==(other);
}
private:
QString _name;
@@ -140,17 +159,17 @@ public:
};
Model();
explicit Model(const ModelLibrary& library,
ModelType type,
const QString& name,
const QString& directory,
const QString& uuid,
const QString& description,
const QString& url,
const QString& doi);
Model(std::shared_ptr<ModelLibrary> library,
ModelType type,
const QString& name,
const QString& directory,
const QString& uuid,
const QString& description,
const QString& url,
const QString& doi);
~Model() override = default;
const ModelLibrary& getLibrary() const
std::shared_ptr<ModelLibrary> getLibrary() const
{
return _library;
}
@@ -175,10 +194,10 @@ public:
{
return QDir(_directory).absolutePath();
}
const QString getRelativePath() const
{
return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath());
}
// const QString getRelativePath() const
// {
// return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath());
// }
const QString getUUID() const
{
return _uuid;
@@ -196,7 +215,7 @@ public:
return _doi;
}
void setLibrary(const ModelLibrary& library)
void setLibrary(std::shared_ptr<ModelLibrary> library)
{
_library = library;
}
@@ -231,12 +250,16 @@ public:
void addInheritance(const QString& uuid)
{
_inheritedUuids.push_back(uuid);
_inheritedUuids << uuid;
}
const std::vector<QString>& getInheritance() const
const QStringList& getInheritance() const
{
return _inheritedUuids;
}
bool inherits(const QString& uuid) const
{
return _inheritedUuids.contains(uuid);
}
bool operator==(const Model& m) const
{
@@ -281,7 +304,7 @@ public:
}
private:
ModelLibrary _library;
std::shared_ptr<ModelLibrary> _library;
ModelType _type;
QString _name;
QString _directory;
@@ -289,10 +312,12 @@ private:
QString _description;
QString _url;
QString _doi;
std::vector<QString> _inheritedUuids;
QStringList _inheritedUuids;
std::map<QString, ModelProperty> _properties;
};
typedef FolderTreeNode<Model> ModelTreeNode;
} // namespace Materials
#endif // MATERIAL_MODEL_H

View File

@@ -30,6 +30,7 @@
#include "Exceptions.h"
#include "Model.h"
#include "ModelLibrary.h"
#include "ModelManager.h"
using namespace Materials;
@@ -66,6 +67,15 @@ QString LibraryBase::getLocalPath(const QString& path) const
return filePath;
}
bool LibraryBase::isRoot(const QString& path) const
{
QString localPath = getLocalPath(path);
QString cleanPath = getLocalPath(QString::fromStdString(""));
std::string pLocal = localPath.toStdString();
std::string pclean = cleanPath.toStdString();
return (cleanPath == localPath);
}
QString LibraryBase::getRelativePath(const QString& path) const
{
QString filePath;
@@ -97,17 +107,80 @@ TYPESYSTEM_SOURCE(Materials::ModelLibrary, LibraryBase)
ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon)
: LibraryBase(libraryName, dir, icon)
{}
{
_modelPathMap = std::make_unique<std::map<QString, std::shared_ptr<Model>>>();
}
ModelLibrary::ModelLibrary()
{}
{
_modelPathMap = std::make_unique<std::map<QString, std::shared_ptr<Model>>>();
}
Model* ModelLibrary::addModel(const Model& model, const QString& path)
std::shared_ptr<Model> ModelLibrary::getModelByPath(const QString& path) const
{
QString filePath = getRelativePath(path);
Model* newModel = new Model(model);
newModel->setLibrary(*this);
try {
std::shared_ptr<Model> model = _modelPathMap->at(filePath);
return model;
}
catch (std::out_of_range& e) {
throw ModelNotFound();
}
}
std::shared_ptr<Model> ModelLibrary::addModel(const Model& model, const QString& path)
{
QString filePath = getRelativePath(path);
std::shared_ptr<Model> newModel = std::make_shared<Model>(model);
newModel->setLibrary(getptr());
newModel->setDirectory(filePath);
(*_modelPathMap)[filePath] = newModel;
return newModel;
}
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
ModelLibrary::getModelTree(ModelFilter filter) const
{
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>> modelTree =
std::make_shared<std::map<QString, std::shared_ptr<ModelTreeNode>>>();
for (auto it = _modelPathMap->begin(); it != _modelPathMap->end(); it++) {
auto filename = it->first;
auto model = it->second;
if (ModelManager::passFilter(filter, model->getType())) {
// Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str());
QStringList list = filename.split(QString::fromStdString("/"));
// Start at the root
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>> node = modelTree;
for (auto itp = list.begin(); itp != list.end(); itp++) {
// Base::Console().Log("\t%s", itp->toStdString().c_str());
if (ModelManager::isModel(*itp)) {
std::shared_ptr<ModelTreeNode> child = std::make_shared<ModelTreeNode>();
child->setData(model);
(*node)[*itp] = child;
}
else {
// Add the folder only if it's not already there
if (node->count(*itp) == 0) {
auto mapPtr =
std::make_shared<std::map<QString, std::shared_ptr<ModelTreeNode>>>();
std::shared_ptr<ModelTreeNode> child = std::make_shared<ModelTreeNode>();
child->setFolder(mapPtr);
(*node)[*itp] = child;
node = mapPtr;
}
else {
node = (*node)[*itp]->getFolder();
}
}
}
// Base::Console().Log("\n");
}
}
return modelTree;
}

View File

@@ -22,27 +22,30 @@
#ifndef MATERIAL_MODELLIBRARY_H
#define MATERIAL_MODELLIBRARY_H
#include <Mod/Material/MaterialGlobal.h>
#include <memory>
#include <Base/BaseClass.h>
#include <Base/Quantity.h>
#include <QDir>
#include <QString>
#include "MaterialValue.h"
#include <Base/BaseClass.h>
#include <Base/Quantity.h>
#include <Mod/Material/MaterialGlobal.h>
#include "MaterialValue.h"
#include "Model.h"
namespace Materials
{
class Model;
// class Model;
class MaterialsExport LibraryBase: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
LibraryBase();
explicit LibraryBase(const QString& libraryName, const QString& dir, const QString& icon);
LibraryBase(const QString& libraryName, const QString& dir, const QString& icon);
~LibraryBase() override = default;
const QString getName() const
@@ -68,20 +71,24 @@ public:
}
QString getLocalPath(const QString& path) const;
QString getRelativePath(const QString& path) const;
bool isRoot(const QString& path) const;
private:
LibraryBase(const LibraryBase&);
QString _name;
QString _directory;
QString _iconPath;
};
class MaterialsExport ModelLibrary: public LibraryBase
class MaterialsExport ModelLibrary: public LibraryBase,
public std::enable_shared_from_this<ModelLibrary>
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
ModelLibrary();
explicit ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon);
ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon);
~ModelLibrary() override = default;
bool operator==(const ModelLibrary& library) const
@@ -92,8 +99,22 @@ public:
{
return !operator==(library);
}
std::shared_ptr<Model> getModelByPath(const QString& path) const;
Model* addModel(const Model& model, const QString& path);
std::shared_ptr<Model> addModel(const Model& model, const QString& path);
// Use this to get a shared_ptr for *this
std::shared_ptr<ModelLibrary> getptr()
{
return shared_from_this();
}
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
getModelTree(ModelFilter filter) const;
private:
ModelLibrary(const ModelLibrary&);
std::unique_ptr<std::map<QString, std::shared_ptr<Model>>> _modelPathMap;
};
} // namespace Materials

View File

@@ -37,7 +37,7 @@
using namespace Materials;
ModelEntry::ModelEntry(const ModelLibrary& library,
ModelEntry::ModelEntry(std::shared_ptr<ModelLibrary> library,
const QString& baseName,
const QString& modelName,
const QString& dir,
@@ -52,17 +52,18 @@ ModelEntry::ModelEntry(const ModelLibrary& library,
, _dereferenced(false)
{}
std::unique_ptr<std::map<QString, ModelEntry*>> ModelLoader::_modelEntryMap = nullptr;
std::unique_ptr<std::map<QString, std::shared_ptr<ModelEntry>>> ModelLoader::_modelEntryMap =
nullptr;
ModelLoader::ModelLoader(std::shared_ptr<std::map<QString, Model*>> modelMap,
std::shared_ptr<std::list<ModelLibrary*>> libraryList)
ModelLoader::ModelLoader(std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> modelMap,
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> libraryList)
: _modelMap(modelMap)
, _libraryList(libraryList)
{
loadLibraries();
}
void ModelLoader::addLibrary(ModelLibrary* model)
void ModelLoader::addLibrary(std::shared_ptr<ModelLibrary> model)
{
_libraryList->push_back(model);
}
@@ -84,12 +85,13 @@ const QString ModelLoader::getUUIDFromPath(const QString& path)
const QString uuid = QString::fromStdString(yamlroot[base]["UUID"].as<std::string>());
return uuid;
}
catch (YAML::Exception&) {
catch (YAML::Exception& ex) {
throw ModelNotFound();
}
}
ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QString& path) const
std::shared_ptr<ModelEntry> ModelLoader::getModelFromPath(std::shared_ptr<ModelLibrary> library,
const QString& path) const
{
QFile file(path);
if (!file.exists()) {
@@ -113,12 +115,12 @@ ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QSt
throw InvalidModel();
}
ModelEntry* model = new ModelEntry(library,
QString::fromStdString(base),
QString::fromStdString(name),
path,
QString::fromStdString(uuid),
yamlroot);
std::shared_ptr<ModelEntry> model = std::make_shared<ModelEntry>(library,
QString::fromStdString(base),
QString::fromStdString(name),
path,
QString::fromStdString(uuid),
yamlroot);
return model;
}
@@ -133,8 +135,8 @@ void ModelLoader::showYaml(const YAML::Node& yaml) const
}
void ModelLoader::dereference(const QString& uuid,
ModelEntry* parent,
const ModelEntry* child,
std::shared_ptr<ModelEntry> parent,
std::shared_ptr<ModelEntry> child,
std::map<std::pair<QString, QString>, QString>* inheritances)
{
auto parentPtr = parent->getModelPtr();
@@ -168,7 +170,7 @@ void ModelLoader::dereference(const QString& uuid,
}
void ModelLoader::dereference(ModelEntry* model,
void ModelLoader::dereference(std::shared_ptr<ModelEntry> model,
std::map<std::pair<QString, QString>, QString>* inheritances)
{
// Avoid recursion
@@ -185,10 +187,10 @@ void ModelLoader::dereference(ModelEntry* model,
// This requires that all models have already been loaded undereferenced
try {
const ModelEntry* child = (*_modelEntryMap)[nodeName];
std::shared_ptr<ModelEntry> child = (*_modelEntryMap)[nodeName];
dereference(model->getUUID(), model, child, inheritances);
}
catch (const std::out_of_range&) {
catch (const std::out_of_range& oor) {
Base::Console().Log("Unable to find '%s' in model map\n",
nodeName.toStdString().c_str());
}
@@ -208,7 +210,7 @@ QString ModelLoader::yamlValue(const YAML::Node& node,
return QString::fromStdString(defaultValue);
}
void ModelLoader::addToTree(ModelEntry* model,
void ModelLoader::addToTree(std::shared_ptr<ModelEntry> model,
std::map<std::pair<QString, QString>, QString>* inheritances)
{
std::set<QString> exclude;
@@ -268,12 +270,12 @@ void ModelLoader::addToTree(ModelEntry* model,
if (propType == QString::fromStdString("2DArray")
|| propType == QString::fromStdString("3DArray")) {
Base::Console().Log("Reading columns\n");
// Base::Console().Log("Reading columns\n");
// Read the columns
auto cols = yamlProp["Columns"];
for (auto col : cols) {
std::string colName = col.first.as<std::string>();
Base::Console().Log("\tColumns '%s'\n", colName.c_str());
// Base::Console().Log("\tColumns '%s'\n", colName.c_str());
auto colProp = cols[colName];
auto colPropType = yamlValue(colProp, "Type", "");
@@ -299,16 +301,16 @@ void ModelLoader::addToTree(ModelEntry* model,
}
}
(*_modelMap)[uuid] = library.addModel(*finalModel, directory);
(*_modelMap)[uuid] = library->addModel(*finalModel, directory);
}
void ModelLoader::loadLibrary(const ModelLibrary& library)
void ModelLoader::loadLibrary(std::shared_ptr<ModelLibrary> library)
{
if (_modelEntryMap == nullptr) {
_modelEntryMap = std::make_unique<std::map<QString, ModelEntry*>>();
_modelEntryMap = std::make_unique<std::map<QString, std::shared_ptr<ModelEntry>>>();
}
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories);
while (it.hasNext()) {
auto pathname = it.next();
QFileInfo file(pathname);
@@ -345,7 +347,7 @@ void ModelLoader::loadLibraries()
getModelLibraries();
if (_libraryList) {
for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) {
loadLibrary(**it);
loadLibrary(*it);
}
}
}
@@ -362,9 +364,10 @@ void ModelLoader::getModelLibraries()
if (useBuiltInMaterials) {
QString resourceDir = QString::fromStdString(App::Application::getResourceDir()
+ "/Mod/Material/Resources/Models");
auto libData = new ModelLibrary(QString::fromStdString("System"),
resourceDir,
QString::fromStdString(":/icons/freecad.svg"));
auto libData =
std::make_shared<ModelLibrary>(QString::fromStdString("System"),
resourceDir,
QString::fromStdString(":/icons/freecad.svg"));
_libraryList->push_back(libData);
}
@@ -380,7 +383,7 @@ void ModelLoader::getModelLibraries()
if (modelDir.length() > 0) {
QDir dir(modelDir);
if (dir.exists()) {
auto libData = new ModelLibrary(moduleName, modelDir, modelIcon);
auto libData = std::make_shared<ModelLibrary>(moduleName, modelDir, modelIcon);
_libraryList->push_back(libData);
}
}
@@ -393,10 +396,10 @@ void ModelLoader::getModelLibraries()
if (!resourceDir.isEmpty()) {
QDir materialDir(resourceDir);
if (materialDir.exists()) {
auto libData =
new ModelLibrary(QString::fromStdString("User"),
resourceDir,
QString::fromStdString(":/icons/preferences-general.svg"));
auto libData = std::make_shared<ModelLibrary>(
QString::fromStdString("User"),
resourceDir,
QString::fromStdString(":/icons/preferences-general.svg"));
_libraryList->push_back(libData);
}
}
@@ -407,9 +410,10 @@ void ModelLoader::getModelLibraries()
if (!resourceDir.isEmpty()) {
QDir materialDir(resourceDir);
if (materialDir.exists()) {
auto libData = new ModelLibrary(QString::fromStdString("Custom"),
resourceDir,
QString::fromStdString(":/icons/user.svg"));
auto libData =
std::make_shared<ModelLibrary>(QString::fromStdString("Custom"),
resourceDir,
QString::fromStdString(":/icons/user.svg"));
_libraryList->push_back(libData);
}
}

View File

@@ -22,6 +22,8 @@
#ifndef MATERIAL_MODELLOADER_H
#define MATERIAL_MODELLOADER_H
#include <memory>
#include <QDir>
#include <QString>
#include <yaml-cpp/yaml.h>
@@ -34,15 +36,15 @@ namespace Materials
class ModelEntry
{
public:
explicit ModelEntry(const ModelLibrary& library,
const QString& baseName,
const QString& modelName,
const QString& dir,
const QString& modelUuid,
const YAML::Node& modelData);
ModelEntry(std::shared_ptr<ModelLibrary> library,
const QString& baseName,
const QString& modelName,
const QString& dir,
const QString& modelUuid,
const YAML::Node& modelData);
virtual ~ModelEntry() = default;
const ModelLibrary& getLibrary() const
std::shared_ptr<ModelLibrary> getLibrary() const
{
return _library;
}
@@ -83,7 +85,7 @@ public:
private:
ModelEntry();
ModelLibrary _library;
std::shared_ptr<ModelLibrary> _library;
QString _base;
QString _name;
QString _directory;
@@ -95,8 +97,8 @@ private:
class ModelLoader
{
public:
explicit ModelLoader(std::shared_ptr<std::map<QString, Model*>> modelMap,
std::shared_ptr<std::list<ModelLibrary*>> libraryList);
ModelLoader(std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> modelMap,
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> libraryList);
virtual ~ModelLoader() = default;
static const QString getUUIDFromPath(const QString& path);
@@ -107,21 +109,24 @@ private:
void getModelLibraries();
QString
yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue);
void addToTree(ModelEntry* model, std::map<std::pair<QString, QString>, QString>* inheritances);
void addToTree(std::shared_ptr<ModelEntry> model,
std::map<std::pair<QString, QString>, QString>* inheritances);
void showYaml(const YAML::Node& yaml) const;
void dereference(const QString& uuid,
ModelEntry* parent,
const ModelEntry* child,
std::shared_ptr<ModelEntry> parent,
std::shared_ptr<ModelEntry> child,
std::map<std::pair<QString, QString>, QString>* inheritances);
void dereference(ModelEntry* model,
void dereference(std::shared_ptr<ModelEntry> model,
std::map<std::pair<QString, QString>, QString>* inheritances);
ModelEntry* getModelFromPath(const ModelLibrary& library, const QString& path) const;
void addLibrary(ModelLibrary* model);
void loadLibrary(const ModelLibrary& library);
std::shared_ptr<ModelEntry> getModelFromPath(std::shared_ptr<ModelLibrary> library,
const QString& path) const;
void addLibrary(std::shared_ptr<ModelLibrary> model);
void loadLibrary(std::shared_ptr<ModelLibrary> library);
void loadLibraries();
static std::unique_ptr<std::map<QString, ModelEntry*>> _modelEntryMap;
std::shared_ptr<std::map<QString, Model*>> _modelMap;
std::shared_ptr<std::list<ModelLibrary*>> _libraryList;
static std::unique_ptr<std::map<QString, std::shared_ptr<ModelEntry>>> _modelEntryMap;
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> _modelMap;
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> _libraryList;
};
} // namespace Materials

View File

@@ -23,6 +23,7 @@
#ifndef _PreComp_
#endif
#include <QDirIterator>
#include <QMutexLocker>
#include <Base/Console.h>
@@ -34,8 +35,8 @@
using namespace Materials;
std::shared_ptr<std::list<ModelLibrary*>> ModelManager::_libraryList = nullptr;
std::shared_ptr<std::map<QString, Model*>> ModelManager::_modelMap = nullptr;
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManager::_libraryList = nullptr;
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> ModelManager::_modelMap = nullptr;
QMutex ModelManager::_mutex;
TYPESYSTEM_SOURCE(Materials::ModelManager, Base::BaseClass)
@@ -50,9 +51,9 @@ void ModelManager::initLibraries()
QMutexLocker locker(&_mutex);
if (_modelMap == nullptr) {
_modelMap = std::make_shared<std::map<QString, Model*>>();
_modelMap = std::make_shared<std::map<QString, std::shared_ptr<Model>>>();
if (_libraryList == nullptr) {
_libraryList = std::make_shared<std::list<ModelLibrary*>>();
_libraryList = std::make_shared<std::list<std::shared_ptr<ModelLibrary>>>();
}
// Load the libraries
@@ -60,12 +61,12 @@ void ModelManager::initLibraries()
}
}
bool ModelManager::isModel(const fs::path& p)
bool ModelManager::isModel(const QString& file)
{
// if (!fs::is_regular_file(p))
// return false;
// check file extension
if (p.extension() == ".yml") {
if (file.endsWith(QString::fromStdString(".yml"))) {
return true;
}
return false;
@@ -80,36 +81,62 @@ void ModelManager::refresh()
ModelLoader loader(_modelMap, _libraryList);
}
const Model& ModelManager::getModel(const QString& uuid) const
std::shared_ptr<Model> ModelManager::getModel(const QString& uuid) const
{
try {
if (_modelMap == nullptr) {
throw Uninitialized();
}
return *(_modelMap->at(uuid));
return _modelMap->at(uuid);
}
catch (std::out_of_range const&) {
throw ModelNotFound();
}
}
const Model& ModelManager::getModelByPath(const QString& path) const
std::shared_ptr<Model> ModelManager::getModelByPath(const QString& path) const
{
const QString& uuid = ModelLoader::getUUIDFromPath(path);
const Model& model = getModel(uuid);
QString cleanPath = QDir::cleanPath(path);
return model;
for (auto library : *_libraryList) {
// Base::Console().Log("ModelManager::getModelByPath() Checking library '%s'->'%s'\n",
// library->getName().toStdString().c_str(),
// library->getDirectory().toStdString().c_str());
if (cleanPath.startsWith(library->getDirectory())) {
// Base::Console().Log("ModelManager::getModelByPath() Library '%s'\n",
// library->getDirectory().toStdString().c_str());
// Base::Console().Log("ModelManager::getModelByPath() Path '%s'\n",
// cleanPath.toStdString().c_str());
return library->getModelByPath(cleanPath);
}
}
Base::Console().Log("ModelManager::getModelByPath() Library not found for path '%s'\n",
cleanPath.toStdString().c_str());
throw MaterialNotFound();
}
const Model& ModelManager::getModelByPath(const QString& path, const QString& libraryPath) const
std::shared_ptr<Model> ModelManager::getModelByPath(const QString& path, const QString& lib) const
{
QDir modelDir(QDir::cleanPath(libraryPath + QString::fromStdString("/") + path));
QString absPath = modelDir.absolutePath();
return getModelByPath(absPath);
auto library = getLibrary(lib); // May throw LibraryNotFound
return library->getModelByPath(path); // May throw ModelNotFound
}
bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) const
std::shared_ptr<ModelLibrary> ModelManager::getLibrary(const QString& name) const
{
for (auto library : *_libraryList) {
if (library->getName() == name) {
return library;
}
}
throw LibraryNotFound();
}
bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType)
{
switch (filter) {
case ModelFilter_None:
@@ -124,49 +151,3 @@ bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) co
return false;
}
std::shared_ptr<std::map<QString, ModelTreeNode*>>
ModelManager::getModelTree(const ModelLibrary& library, ModelFilter filter) const
{
std::shared_ptr<std::map<QString, ModelTreeNode*>> modelTree =
std::make_shared<std::map<QString, ModelTreeNode*>>();
for (auto it = _modelMap->begin(); it != _modelMap->end(); it++) {
auto filename = it->first;
auto model = it->second;
if (model->getLibrary() == library && passFilter(filter, model->getType())) {
fs::path path = model->getDirectory().toStdString();
Base::Console().Log("Relative path '%s'\n\t", path.string().c_str());
// Start at the root
std::shared_ptr<std::map<QString, ModelTreeNode*>> node = modelTree;
for (auto itp = path.begin(); itp != path.end(); itp++) {
if (isModel(itp->string())) {
ModelTreeNode* child = new ModelTreeNode();
child->setData(model);
(*node)[QString::fromStdString(itp->string())] = child;
}
else {
// Add the folder only if it's not already there
QString folderName = QString::fromStdString(itp->string());
std::shared_ptr<std::map<QString, ModelTreeNode*>> mapPtr;
if (node->count(QString::fromStdString(itp->string())) == 0) {
mapPtr = std::make_shared<std::map<QString, ModelTreeNode*>>();
ModelTreeNode* child = new ModelTreeNode();
child->setFolder(mapPtr);
(*node)[QString::fromStdString(itp->string())] = child;
node = mapPtr;
}
else {
node = (*node)[QString::fromStdString(itp->string())]->getFolder();
}
}
Base::Console().Log("'%s' ", itp->string().c_str());
}
Base::Console().Log("\n");
}
}
return modelTree;
}

View File

@@ -22,62 +22,57 @@
#ifndef MATERIAL_MODELMANAGER_H
#define MATERIAL_MODELMANAGER_H
#include <memory>
#include <Mod/Material/MaterialGlobal.h>
#include <QMutex>
#include <boost/filesystem.hpp>
#include "Exceptions.h"
#include "FolderTree.h"
#include "Model.h"
#include "ModelLibrary.h"
namespace fs = boost::filesystem;
namespace Materials
{
typedef FolderTreeNode<Model> ModelTreeNode;
class MaterialsExport ModelManager: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER();
public:
enum ModelFilter
{
ModelFilter_None,
ModelFilter_Physical,
ModelFilter_Appearance
};
ModelManager();
~ModelManager() override = default;
void refresh();
std::shared_ptr<std::list<ModelLibrary*>> getModelLibraries()
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getModelLibraries()
{
return _libraryList;
}
std::shared_ptr<std::map<QString, Model*>> getModels()
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getModels()
{
return _modelMap;
}
std::shared_ptr<std::map<QString, ModelTreeNode*>>
getModelTree(const ModelLibrary& library, ModelFilter filter = ModelFilter_None) const;
const Model& getModel(const QString& uuid) const;
const Model& getModelByPath(const QString& path) const;
const Model& getModelByPath(const QString& path, const QString& libraryPath) const;
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
getModelTree(std::shared_ptr<ModelLibrary> library, ModelFilter filter = ModelFilter_None) const
{
return library->getModelTree(filter);
}
std::shared_ptr<Model> getModel(const QString& uuid) const;
std::shared_ptr<Model> getModelByPath(const QString& path) const;
std::shared_ptr<Model> getModelByPath(const QString& path, const QString& lib) const;
std::shared_ptr<ModelLibrary> getLibrary(const QString& name) const;
static bool isModel(const fs::path& p);
bool passFilter(ModelFilter filter, Model::ModelType modelType) const;
static bool isModel(const QString& file);
static bool passFilter(ModelFilter filter, Model::ModelType modelType);
private:
static void initLibraries();
static std::shared_ptr<std::list<ModelLibrary*>> _libraryList;
static std::shared_ptr<std::map<QString, Model*>> _modelMap;
static std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> _libraryList;
static std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> _modelMap;
static QMutex _mutex;
};

View File

@@ -21,10 +21,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_io.hpp>
#endif
#include "Model.h"
#include "ModelLibrary.h"
#include "ModelManager.h"
#include "ModelManagerPy.h"
#include "ModelPy.h"
@@ -62,8 +60,8 @@ PyObject* ModelManagerPy::getModel(PyObject* args)
}
try {
const Model model = getModelManagerPtr()->getModel(QString::fromStdString(uuid));
return new ModelPy(new Model(model));
auto model = getModelManagerPtr()->getModel(QString::fromStdString(uuid));
return new ModelPy(new Model(*model));
}
catch (ModelNotFound const&) {
QString error = QString::fromStdString("Model not found:\n");
@@ -96,10 +94,9 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args)
std::string libPath(lib);
if (libPath.length() > 0) {
try {
const Model& model =
getModelManagerPtr()->getModelByPath(QString::fromStdString(path),
QString::fromStdString(libPath));
return new ModelPy(new Model(model));
auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path),
QString::fromStdString(libPath));
return new ModelPy(new Model(*model));
}
catch (ModelNotFound const&) {
PyErr_SetString(PyExc_LookupError, "Model not found");
@@ -108,8 +105,8 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args)
}
try {
const Model& model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path));
return new ModelPy(new Model(model));
auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path));
return new ModelPy(new Model(*model));
}
catch (ModelNotFound const&) {
PyErr_SetString(PyExc_LookupError, "Model not found");
@@ -119,11 +116,11 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args)
Py::List ModelManagerPy::getModelLibraries() const
{
std::shared_ptr<std::list<ModelLibrary*>> libraries = getModelManagerPtr()->getModelLibraries();
auto libraries = getModelManagerPtr()->getModelLibraries();
Py::List list;
for (auto it = libraries->begin(); it != libraries->end(); it++) {
ModelLibrary* lib = *it;
auto lib = *it;
Py::Tuple libTuple(3);
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
@@ -142,7 +139,7 @@ Py::Dict ModelManagerPy::getModels() const
for (auto it = models->begin(); it != models->end(); it++) {
QString key = it->first;
Model* model = it->second;
auto model = it->second;
PyObject* modelPy = new ModelPy(new Model(*model));
dict.setItem(Py::String(key.toStdString()), Py::Object(modelPy, true));

View File

@@ -21,10 +21,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_io.hpp>
#endif
#include "Model.h"
#include "ModelPropertyPy.h"

View File

@@ -21,13 +21,11 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/uuid/uuid_io.hpp>
#endif
#include "Model.h"
#include "ModelLibrary.h"
#include "ModelPropertyPy.h"
#include "ModelPy.h"
#include "ModelUuids.h"
#include "ModelPy.cpp"
@@ -43,11 +41,11 @@ std::string ModelPy::representation() const
str << "), UUID=(";
str << ptr->getUUID().toStdString();
str << "), Library Name=(";
str << ptr->getLibrary().getName().toStdString();
str << ptr->getLibrary()->getName().toStdString();
str << "), Library Root=(";
str << ptr->getLibrary().getDirectoryPath().toStdString();
str << ptr->getLibrary()->getDirectoryPath().toStdString();
str << "), Library Icon=(";
str << ptr->getLibrary().getIconPath().toStdString();
str << ptr->getLibrary()->getIconPath().toStdString();
str << "), Directory=(";
str << ptr->getDirectory().toStdString();
str << "), URL=(";
@@ -57,7 +55,7 @@ std::string ModelPy::representation() const
str << "), Description=(";
str << ptr->getDescription().toStdString();
str << "), Inherits=[";
const std::vector<QString>& inherited = getModelPtr()->getInheritance();
auto& inherited = getModelPtr()->getInheritance();
for (auto it = inherited.begin(); it != inherited.end(); it++) {
QString uuid = *it;
if (it != inherited.begin()) {
@@ -87,17 +85,17 @@ int ModelPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
Py::String ModelPy::getLibraryName() const
{
return Py::String(getModelPtr()->getLibrary().getName().toStdString());
return Py::String(getModelPtr()->getLibrary()->getName().toStdString());
}
Py::String ModelPy::getLibraryRoot() const
{
return Py::String(getModelPtr()->getLibrary().getDirectoryPath().toStdString());
return Py::String(getModelPtr()->getLibrary()->getDirectoryPath().toStdString());
}
Py::String ModelPy::getLibraryIcon() const
{
return Py::String(getModelPtr()->getLibrary().getIconPath().toStdString());
return Py::String(getModelPtr()->getLibrary()->getIconPath().toStdString());
}
Py::String ModelPy::getName() const
@@ -132,13 +130,11 @@ Py::String ModelPy::getDOI() const
Py::List ModelPy::getInherited() const
{
const std::vector<QString>& inherited = getModelPtr()->getInheritance();
auto& inherited = getModelPtr()->getInheritance();
Py::List list;
for (auto it = inherited.begin(); it != inherited.end(); it++) {
QString uuid = *it;
list.append(Py::String(uuid.toStdString()));
list.append(Py::String(it->toStdString()));
}
return list;

View File

@@ -0,0 +1,70 @@
/***************************************************************************
* 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_
#endif
#include "ModelUuids.h"
using namespace Materials;
TYPESYSTEM_SOURCE(Materials::ModelUUIDs, Base::BaseClass)
const QString ModelUUIDs::ModelUUID_Legacy_Father =
QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67");
const QString ModelUUIDs::ModelUUID_Legacy_MaterialStandard =
QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700");
const QString ModelUUIDs::ModelUUID_Mechanical_Density =
QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af");
const QString ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic =
QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50");
const QString ModelUUIDs::ModelUUID_Mechanical_LinearElastic =
QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536");
const QString ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18 =
QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f");
const QString ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic =
QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146");
const QString ModelUUIDs::ModelUUID_Fluid_Default =
QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202");
const QString ModelUUIDs::ModelUUID_Thermal_Default =
QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7");
const QString ModelUUIDs::ModelUUID_Electromagnetic_Default =
QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3");
const QString ModelUUIDs::ModelUUID_Architectural_Default =
QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8");
const QString ModelUUIDs::ModelUUID_Costs_Default =
QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466");
const QString ModelUUIDs::ModelUUID_Rendering_Basic =
QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e");
const QString ModelUUIDs::ModelUUID_Rendering_Texture =
QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160");
const QString ModelUUIDs::ModelUUID_Rendering_Advanced =
QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf");
const QString ModelUUIDs::ModelUUID_Rendering_Vector =
QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e");

View File

@@ -24,50 +24,48 @@
#include <QString>
#include <Base/BaseClass.h>
#include <Mod/Material/MaterialGlobal.h>
namespace Materials
{
// UUIDs for predefined material models
class MaterialsExport ModelUUIDs: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
static const QString ModelUUID_Legacy_Father =
QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67");
static const QString ModelUUID_Legacy_MaterialStandard =
QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700");
public:
ModelUUIDs()
{}
~ModelUUIDs() override = default;
static const QString ModelUUID_Mechanical_Density =
QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af");
static const QString ModelUUID_Mechanical_IsotropicLinearElastic =
QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50");
static const QString ModelUUID_Mechanical_LinearElastic =
QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536");
static const QString ModelUUID_Mechanical_OgdenYld2004p18 =
QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f");
static const QString ModelUUID_Mechanical_OrthotropicLinearElastic =
QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146");
// UUIDs for predefined material models
static const QString ModelUUID_Fluid_Default =
QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202");
static const QString ModelUUID_Legacy_Father;
static const QString ModelUUID_Legacy_MaterialStandard;
static const QString ModelUUID_Thermal_Default =
QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7");
static const QString ModelUUID_Mechanical_Density;
static const QString ModelUUID_Mechanical_IsotropicLinearElastic;
static const QString ModelUUID_Mechanical_LinearElastic;
static const QString ModelUUID_Mechanical_OgdenYld2004p18;
static const QString ModelUUID_Mechanical_OrthotropicLinearElastic;
static const QString ModelUUID_Electromagnetic_Default =
QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3");
static const QString ModelUUID_Fluid_Default;
static const QString ModelUUID_Architectural_Default =
QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8");
static const QString ModelUUID_Thermal_Default;
static const QString ModelUUID_Costs_Default =
QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466");
static const QString ModelUUID_Electromagnetic_Default;
static const QString ModelUUID_Rendering_Basic =
QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e");
static const QString ModelUUID_Rendering_Texture =
QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160");
static const QString ModelUUID_Rendering_Advanced =
QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf");
static const QString ModelUUID_Rendering_Vector =
QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e");
static const QString ModelUUID_Architectural_Default;
static const QString ModelUUID_Costs_Default;
static const QString ModelUUID_Rendering_Basic;
static const QString ModelUUID_Rendering_Texture;
static const QString ModelUUID_Rendering_Advanced;
static const QString ModelUUID_Rendering_Vector;
};
} // namespace Materials

View File

@@ -55,10 +55,6 @@
// Qt
#include <QtGlobal>
// Boost
#include <boost/algorithm/string/predicate.hpp>
#include <boost/regex.hpp>
#endif //_PreComp_
#endif // MATERIAL_PRECOMPILED_H

View File

@@ -0,0 +1,116 @@
<?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="UUIDsPy"
PythonName="Material.UUIDs"
Twin="ModelUUIDs"
TwinPointer="ModelUUIDs"
Include="Mod/Material/App/ModelUuids.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 model UUID identifiers.</UserDocu>
</Documentation>
<Attribute Name="Father" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Legacy/Father</UserDocu>
</Documentation>
<Parameter Name="Father" Type="String"/>
</Attribute>
<Attribute Name="MaterialStandard" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Legacy/MaterialStandard</UserDocu>
</Documentation>
<Parameter Name="MaterialStandard" Type="String"/>
</Attribute>
<Attribute Name="Density" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Mechanical/Density</UserDocu>
</Documentation>
<Parameter Name="Density" Type="String"/>
</Attribute>
<Attribute Name="IsotropicLinearElastic" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Mechanical/IsotropicLinearElastic</UserDocu>
</Documentation>
<Parameter Name="IsotropicLinearElastic" Type="String"/>
</Attribute>
<Attribute Name="LinearElastic" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Mechanical/LinearElastic</UserDocu>
</Documentation>
<Parameter Name="LinearElastic" Type="String"/>
</Attribute>
<Attribute Name="OgdenYld2004p18" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Mechanical/OgdenYld2004p18</UserDocu>
</Documentation>
<Parameter Name="OgdenYld2004p18" Type="String"/>
</Attribute>
<Attribute Name="OrthotropicLinearElastic" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Mechanical/OrthotropicLinearElastic</UserDocu>
</Documentation>
<Parameter Name="OrthotropicLinearElastic" Type="String"/>
</Attribute>
<Attribute Name="Fluid" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Fluid/Fluid</UserDocu>
</Documentation>
<Parameter Name="Fluid" Type="String"/>
</Attribute>
<Attribute Name="Thermal" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Thermal/Thermal</UserDocu>
</Documentation>
<Parameter Name="Thermal" Type="String"/>
</Attribute>
<Attribute Name="Electromagnetic" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Electromagnetic/Electromagnetic</UserDocu>
</Documentation>
<Parameter Name="Electromagnetic" Type="String"/>
</Attribute>
<Attribute Name="Architectural" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Architectural/Architectural</UserDocu>
</Documentation>
<Parameter Name="Architectural" Type="String"/>
</Attribute>
<Attribute Name="Costs" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Costs/Costs</UserDocu>
</Documentation>
<Parameter Name="Costs" Type="String"/>
</Attribute>
<Attribute Name="BasicRendering" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Rendering/BasicRendering</UserDocu>
</Documentation>
<Parameter Name="BasicRendering" Type="String"/>
</Attribute>
<Attribute Name="TextureRendering" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Rendering/TextureRendering</UserDocu>
</Documentation>
<Parameter Name="TextureRendering" Type="String"/>
</Attribute>
<Attribute Name="AdvancedRendering" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Rendering/AdvancedRendering</UserDocu>
</Documentation>
<Parameter Name="AdvancedRendering" Type="String"/>
</Attribute>
<Attribute Name="VectorRendering" ReadOnly="true">
<Documentation>
<UserDocu>UUID for model System:Rendering/VectorRendering</UserDocu>
</Documentation>
<Parameter Name="VectorRendering" Type="String"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,139 @@
/***************************************************************************
* 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"
#include "ModelUuids.h"
#include "UUIDsPy.h"
#include "UUIDsPy.cpp"
using namespace Materials;
// returns a string which represents the object e.g. when printed in python
std::string UUIDsPy::representation() const
{
return {"<ModelUUIDs object>"};
}
PyObject* UUIDsPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
{
// create a new instance of UUIDsPy and the Twin object
return new UUIDsPy(new ModelUUIDs);
}
// constructor method
int UUIDsPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
return 0;
}
Py::String UUIDsPy::getFather() const
{
return Py::String(ModelUUIDs::ModelUUID_Legacy_Father.toStdString());
}
Py::String UUIDsPy::getMaterialStandard() const
{
return Py::String(ModelUUIDs::ModelUUID_Legacy_MaterialStandard.toStdString());
}
Py::String UUIDsPy::getDensity() const
{
return Py::String(ModelUUIDs::ModelUUID_Mechanical_Density.toStdString());
}
Py::String UUIDsPy::getIsotropicLinearElastic() const
{
return Py::String(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic.toStdString());
}
Py::String UUIDsPy::getLinearElastic() const
{
return Py::String(ModelUUIDs::ModelUUID_Mechanical_LinearElastic.toStdString());
}
Py::String UUIDsPy::getOgdenYld2004p18() const
{
return Py::String(ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18.toStdString());
}
Py::String UUIDsPy::getOrthotropicLinearElastic() const
{
return Py::String(ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic.toStdString());
}
Py::String UUIDsPy::getFluid() const
{
return Py::String(ModelUUIDs::ModelUUID_Fluid_Default.toStdString());
}
Py::String UUIDsPy::getThermal() const
{
return Py::String(ModelUUIDs::ModelUUID_Thermal_Default.toStdString());
}
Py::String UUIDsPy::getElectromagnetic() const
{
return Py::String(ModelUUIDs::ModelUUID_Electromagnetic_Default.toStdString());
}
Py::String UUIDsPy::getArchitectural() const
{
return Py::String(ModelUUIDs::ModelUUID_Architectural_Default.toStdString());
}
Py::String UUIDsPy::getCosts() const
{
return Py::String(ModelUUIDs::ModelUUID_Costs_Default.toStdString());
}
Py::String UUIDsPy::getBasicRendering() const
{
return Py::String(ModelUUIDs::ModelUUID_Rendering_Basic.toStdString());
}
Py::String UUIDsPy::getTextureRendering() const
{
return Py::String(ModelUUIDs::ModelUUID_Rendering_Texture.toStdString());
}
Py::String UUIDsPy::getAdvancedRendering() const
{
Base::Console().Log(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString().c_str());
return Py::String(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString());
}
Py::String UUIDsPy::getVectorRendering() const
{
return Py::String(ModelUUIDs::ModelUUID_Rendering_Vector.toStdString());
}
PyObject* UUIDsPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int UUIDsPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -22,7 +22,6 @@
#ifndef MATERIAL_TRIM_H
#define MATERIAL_TRIM_H
#include <algorithm>
#include <string>
namespace Materials

View File

@@ -194,7 +194,6 @@ SET(MaterialModel_Files
Resources/Models/Legacy/Father.yml
Resources/Models/Legacy/MaterialStandard.yml
Resources/Models/Mechanical/Density.yml
Resources/Models/Mechanical/HypotheticalExample.yml
Resources/Models/Mechanical/IsotropicLinearElastic.yml
Resources/Models/Mechanical/LinearElastic.yml
Resources/Models/Mechanical/OgdenYld2004p18.yml
@@ -206,6 +205,21 @@ SET(MaterialModel_Files
Resources/Models/Thermal/Thermal.yml
)
set(MaterialTest_Files
materialtests/__init__.py
materialtests/TestModels.py
materialtests/TestMaterials.py
)
ADD_CUSTOM_TARGET(MateriaTestLib ALL
SOURCES ${MaterialTest_Files}
)
fc_target_copy_resource(MateriaTestLib
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_BINARY_DIR}/Mod/Material
${MaterialTest_Files})
ADD_CUSTOM_TARGET(MaterialScripts ALL
SOURCES ${MaterialScripts_Files} ${Material_QRC_SRCS}
)
@@ -275,8 +289,13 @@ INSTALL(
DESTINATION Mod/Material
)
INSTALL(
FILES ${MaterialTest_Files}
DESTINATION Mod/Material/materialtests
)
foreach(file ${MaterialLib_Files} ${FluidMaterial_Files} ${AppearanceLib_Files} ${MaterialModel_Files})
get_filename_component(filepath ${file} DIRECTORY)
cmake_path(REMOVE_FILENAME file OUTPUT_VARIABLE filepath)
INSTALL(
FILES ${file}
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Material/${filepath}

View File

@@ -96,6 +96,9 @@ PyMOD_INIT_FUNC(MatGui)
// register preferences pages on Material, the order here will be the order of the tabs in pref
// widget
Gui::Dialog::DlgPreferencesImp::setGroupData("Material",
"Material",
QObject::tr("Material workbench"));
new Gui::PrefPageProducer<MatGui::DlgSettingsMaterial>(
QT_TRANSLATE_NOOP("QObject", "Material"));

View File

@@ -24,6 +24,8 @@
#include <QMessageBox>
#endif
#include <QMenu>
#include <Gui/MainWindow.h>
#include <Mod/Material/App/Exceptions.h>
@@ -39,32 +41,52 @@ using namespace MatGui;
/* TRANSLATOR MatGui::Array2D */
Array2D::Array2D(const QString& propertyName, Materials::Material* material, QWidget* parent)
Array2D::Array2D(const QString& propertyName,
std::shared_ptr<Materials::Material> material,
QWidget* parent)
: QDialog(parent)
, ui(new Ui_Array2D)
, _material(material)
{
ui->setupUi(this);
if (material->hasPhysicalProperty(propertyName)) {
_property = &(material->getPhysicalProperty(propertyName));
_property = material->getPhysicalProperty(propertyName);
}
else if (material->hasAppearanceProperty(propertyName)) {
_property = &(material->getAppearanceProperty(propertyName));
_property = material->getAppearanceProperty(propertyName);
}
else {
Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str());
_property = nullptr;
}
if (_property) {
Base::Console().Log("Value type %d\n",
static_cast<int>(_property->getMaterialValue()->getType()));
_value =
std::static_pointer_cast<Materials::Material2DArray>(_property->getMaterialValue());
}
else {
Base::Console().Log("No value loaded\n");
_value = nullptr;
}
if (_value) {
Base::Console().Log("Value type %d\n", static_cast<int>(_value->getType()));
// auto value = _property->getMaterialValue()->getValue();
// Base::Console().Log("\tQVariant type %d\n", value.userType());
}
setupDefault();
setupArray();
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->tableView, &QWidget::customContextMenuRequested, this, &Array2D::onContextMenu);
_deleteAction.setText(tr("Delete row"));
_deleteAction.setShortcut(Qt::Key_Delete);
connect(&_deleteAction, &QAction::triggered, this, &Array2D::onDelete);
ui->tableView->addAction(&_deleteAction);
connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &Array2D::accept);
connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &Array2D::reject);
}
@@ -77,13 +99,16 @@ void Array2D::setupDefault()
try {
const Materials::MaterialProperty& column1 = _property->getColumn(0);
QString label = QString::fromStdString("Default ") + column1.getName();
QString label = tr("Default ") + column1.getName();
ui->labelDefault->setText(label);
if (column1.getPropertyType() == QString::fromStdString("Quantity")) {
ui->editDefault->setMinimum(std::numeric_limits<double>::min());
ui->editDefault->setMaximum(std::numeric_limits<double>::max());
ui->editDefault->setUnitText(_property->getColumnUnits(0));
ui->editDefault->setValue(_value->getDefault().getValue().value<Base::Quantity>());
if (!_value->defaultSet()) {
_value->setDefault(_property->getColumnNull(0).value<Base::Quantity>());
}
ui->editDefault->setValue(_value->getDefault().value<Base::Quantity>());
connect(ui->editDefault,
qOverload<const Base::Quantity&>(&Gui::QuantitySpinBox::valueChanged),
@@ -134,15 +159,99 @@ void Array2D::setupArray()
auto table = ui->tableView;
auto model = new Array2DModel(_property, _value, this);
table->setModel(model);
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
// table->setEditTriggers(QAbstractItemView::AllEditTriggers);
table->setSelectionMode(QAbstractItemView::SingleSelection);
setColumnWidths(table);
setColumnDelegates(table);
connect(model, &QAbstractItemModel::dataChanged, this, &Array2D::onDataChanged);
}
void Array2D::onDataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight,
const QVector<int>& roles)
{
Q_UNUSED(topLeft)
Q_UNUSED(bottomRight)
Q_UNUSED(roles)
_material->setEditStateAlter();
}
void Array2D::defaultValueChanged(const Base::Quantity& value)
{
_value->setDefault(QVariant::fromValue(value));
_material->setEditStateAlter();
}
void Array2D::onContextMenu(const QPoint& pos)
{
Base::Console().Log("Array2D::onContextMenu(%d,%d)\n", pos.x(), pos.y());
QModelIndex index = ui->tableView->indexAt(pos);
Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column());
QMenu contextMenu(tr("Context menu"), this);
contextMenu.addAction(&_deleteAction);
contextMenu.exec(ui->tableView->mapToGlobal(pos));
}
bool Array2D::newRow(const QModelIndex& index)
{
Array2DModel* model = static_cast<Array2DModel*>(ui->tableView->model());
return model->newRow(index);
}
void Array2D::onDelete(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("Array2D::onDelete()\n");
QItemSelectionModel* selectionModel = ui->tableView->selectionModel();
if (!selectionModel->hasSelection() || newRow(selectionModel->currentIndex())) {
Base::Console().Log("\tNothing selected\n");
return;
}
int res = confirmDelete();
if (res == QMessageBox::Cancel) {
return;
}
}
int Array2D::confirmDelete()
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(QObject::tr("Confirm Delete"));
QString prompt = QObject::tr("Are you sure you want to delete the row?");
box.setText(prompt);
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
deleteSelected();
res = QMessageBox::Ok;
break;
}
return res;
}
void Array2D::deleteSelected()
{
Array2DModel* model = static_cast<Array2DModel*>(ui->tableView->model());
QItemSelectionModel* selectionModel = ui->tableView->selectionModel();
auto index = selectionModel->currentIndex();
model->deleteRow(index);
}
void Array2D::accept()

View File

@@ -22,14 +22,20 @@
#ifndef MATGUI_ARRAY2D_H
#define MATGUI_ARRAY2D_H
#include <memory>
#include <QAbstractTableModel>
#include <QAction>
#include <QDialog>
#include <QPoint>
#include <QStandardItem>
#include <QStandardItemModel>
#include <QTableView>
#include "ArrayModel.h"
#include <Mod/Material/App/Model.h>
#include "ArrayModel.h"
namespace MatGui
{
@@ -40,26 +46,38 @@ class Array2D: public QDialog
Q_OBJECT
public:
explicit Array2D(const QString& propertyName,
Materials::Material* material,
QWidget* parent = nullptr);
Array2D(const QString& propertyName,
std::shared_ptr<Materials::Material> material,
QWidget* parent = nullptr);
~Array2D() override = default;
void onDataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight,
const QVector<int>& roles = QVector<int>());
void defaultValueChanged(const Base::Quantity& value);
void onDelete(bool checked);
void onContextMenu(const QPoint& pos);
void accept() override;
void reject() override;
private:
std::unique_ptr<Ui_Array2D> ui;
const Materials::MaterialProperty* _property;
std::shared_ptr<Materials::Material> _material;
std::shared_ptr<Materials::MaterialProperty> _property;
std::shared_ptr<Materials::Material2DArray> _value;
QAction _deleteAction;
void setupDefault();
void setHeaders(QStandardItemModel* model);
void setColumnWidths(QTableView* table);
void setColumnDelegates(QTableView* table);
void setupArray();
bool newRow(const QModelIndex& index);
int confirmDelete();
void deleteSelected();
};
} // namespace MatGui

View File

@@ -25,9 +25,12 @@
#include <QPushButton>
#endif
#include <QMenu>
#include <Gui/MainWindow.h>
#include <Mod/Material/App/Exceptions.h>
#include <Mod/Material/App/Materials.h>
#include "Array3D.h"
#include "ArrayDelegate.h"
@@ -37,19 +40,23 @@
using namespace MatGui;
Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWidget* parent)
Array3D::Array3D(const QString& propertyName,
std::shared_ptr<Materials::Material> material,
QWidget* parent)
: QDialog(parent)
, ui(new Ui_Array3D)
, _material(material)
{
ui->setupUi(this);
if (material->hasPhysicalProperty(propertyName)) {
_property = &(material->getPhysicalProperty(propertyName));
_property = material->getPhysicalProperty(propertyName);
}
else if (material->hasAppearanceProperty(propertyName)) {
_property = &(material->getAppearanceProperty(propertyName));
_property = material->getAppearanceProperty(propertyName);
}
else {
Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str());
_property = nullptr;
}
if (_property) {
@@ -57,6 +64,7 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi
std::static_pointer_cast<Materials::Material3DArray>(_property->getMaterialValue());
}
else {
Base::Console().Log("No value loaded\n");
_value = nullptr;
}
@@ -64,6 +72,22 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi
setupDepthArray();
setupArray();
ui->table3D->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->table3D, &QWidget::customContextMenuRequested, this, &Array3D::onDepthContextMenu);
ui->table2D->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->table2D, &QWidget::customContextMenuRequested, this, &Array3D::on2DContextMenu);
_deleteDepthAction.setText(tr("Delete row"));
// _deleteDepthAction.setShortcut(Qt::Key_Delete);
connect(&_deleteDepthAction, &QAction::triggered, this, &Array3D::onDepthDelete);
ui->table3D->addAction(&_deleteDepthAction);
_delete2DAction.setText(tr("Delete row"));
// _delete2DAction.setShortcut(Qt::Key_Delete);
connect(&_delete2DAction, &QAction::triggered, this, &Array3D::on2DDelete);
ui->table2D->addAction(&_delete2DAction);
Base::Console().Log("Material '%s'\n", material->getName().toStdString().c_str());
Base::Console().Log("\tproperty '%s'\n", propertyName.toStdString().c_str());
@@ -78,6 +102,10 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi
&QPushButton::clicked,
this,
&Array3D::onCancel);
QItemSelectionModel* selectionModel = ui->table3D->selectionModel();
connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &Array3D::onSelectDepth);
}
bool Array3D::onSplitter(QEvent* e)
@@ -95,13 +123,16 @@ void Array3D::setupDefault()
try {
auto& column1 = _property->getColumn(0);
QString label = QString::fromStdString("Default ") + column1.getName();
QString label = tr("Default ") + column1.getName();
ui->labelDefault->setText(label);
if (column1.getPropertyType() == QString::fromStdString("Quantity")) {
ui->editDefault->setMinimum(std::numeric_limits<double>::min());
ui->editDefault->setMaximum(std::numeric_limits<double>::max());
ui->editDefault->setUnitText(_property->getColumnUnits(0));
ui->editDefault->setValue(_value->getDefault().getValue().value<Base::Quantity>());
if (!_value->defaultSet()) {
_value->setDefault(_property->getColumnNull(0).value<Base::Quantity>());
}
ui->editDefault->setValue(_value->getDefault().value<Base::Quantity>());
connect(ui->editDefault,
qOverload<const Base::Quantity&>(&Gui::QuantitySpinBox::valueChanged),
@@ -117,6 +148,7 @@ void Array3D::setupDefault()
void Array3D::defaultValueChanged(const Base::Quantity& value)
{
_value->setDefault(QVariant::fromValue(value));
_material->setEditStateAlter();
}
void Array3D::setDepthColumnDelegate(QTableView* table)
@@ -140,10 +172,43 @@ void Array3D::setupDepthArray()
auto table = ui->table3D;
auto model = new Array3DDepthModel(_property, _value, this);
table->setModel(model);
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
// table->setEditTriggers(QAbstractItemView::AllEditTriggers);
table->setSelectionMode(QAbstractItemView::SingleSelection);
setDepthColumnWidth(table);
setDepthColumnDelegate(table);
connect(model, &QAbstractItemModel::rowsInserted, this, &Array3D::onRowsInserted);
connect(model, &QAbstractItemModel::rowsRemoved, this, &Array3D::onRowsRemoved);
connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged);
}
void Array3D::onRowsInserted(const QModelIndex& parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
update2DArray();
}
void Array3D::onRowsRemoved(const QModelIndex& parent, int first, int last)
{
Q_UNUSED(parent)
Q_UNUSED(first)
Q_UNUSED(last)
update2DArray();
}
void Array3D::onDataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight,
const QVector<int>& roles)
{
Q_UNUSED(topLeft)
Q_UNUSED(bottomRight)
Q_UNUSED(roles)
_material->setEditStateAlter();
}
void Array3D::setColumnWidths(QTableView* table)
@@ -174,10 +239,190 @@ void Array3D::setupArray()
auto table = ui->table2D;
auto model = new Array3DModel(_property, _value, this);
table->setModel(model);
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
// table->setEditTriggers(QAbstractItemView::AllEditTriggers);
table->setSelectionMode(QAbstractItemView::SingleSelection);
setColumnWidths(table);
setColumnDelegates(table);
if (_value->depth() == 0) {
table->setEnabled(false);
}
connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged);
}
void Array3D::onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected)
{
Q_UNUSED(deselected);
QModelIndexList indexes = selected.indexes();
// This should be a list of length 1
for (auto it = indexes.begin(); it != indexes.end(); it++) {
_value->setCurrentDepth(it->row());
break;
}
update2DArray();
}
void Array3D::update2DArray()
{
auto table = ui->table2D;
auto model = static_cast<Array3DModel*>(table->model());
model->updateData();
table->setEnabled(_value->depth() > 0);
}
void Array3D::onDepthContextMenu(const QPoint& pos)
{
Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y());
QModelIndex index = ui->table3D->indexAt(pos);
Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column());
QMenu contextMenu(tr("Context menu"), this);
contextMenu.addAction(&_deleteDepthAction);
contextMenu.exec(ui->table3D->mapToGlobal(pos));
}
bool Array3D::newDepthRow(const QModelIndex& index)
{
Array3DDepthModel* model = static_cast<Array3DDepthModel*>(ui->table3D->model());
return model->newRow(index);
}
void Array3D::onDepthDelete(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("Array3D::onDepthDelete()\n");
QItemSelectionModel* selectionModel = ui->table3D->selectionModel();
if (!selectionModel->hasSelection() || newDepthRow(selectionModel->currentIndex())) {
Base::Console().Log("\tNothing selected\n");
return;
}
int res = confirmDepthDelete();
if (res == QMessageBox::Cancel) {
return;
}
}
int Array3D::confirmDepthDelete()
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(tr("Confirm Delete"));
QString prompt = tr("Are you sure you want to delete the row?");
box.setText(prompt);
box.setInformativeText(tr("Removing this will also remove all 2D contents."));
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
deleteDepthSelected();
res = QMessageBox::Ok;
break;
}
return res;
}
void Array3D::deleteDepthSelected()
{
Array3DDepthModel* model = static_cast<Array3DDepthModel*>(ui->table3D->model());
QItemSelectionModel* selectionModel = ui->table3D->selectionModel();
auto index = selectionModel->currentIndex();
model->deleteRow(index);
auto depth = _value->currentDepth();
if (depth >= _value->depth()) {
depth = depth - 1;
}
_value->setCurrentDepth(depth);
update2DArray();
}
void Array3D::on2DContextMenu(const QPoint& pos)
{
Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y());
QModelIndex index = ui->table2D->indexAt(pos);
Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column());
QMenu contextMenu(tr("Context menu"), this);
contextMenu.addAction(&_delete2DAction);
// contextMenu.exec(mapToGlobal(pos));
contextMenu.exec(ui->table2D->mapToGlobal(pos));
}
bool Array3D::new2DRow(const QModelIndex& index)
{
Array3DModel* model = static_cast<Array3DModel*>(ui->table2D->model());
return model->newRow(index);
}
void Array3D::on2DDelete(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("Array3D::on2DDelete()\n");
QItemSelectionModel* selectionModel = ui->table2D->selectionModel();
if (!selectionModel->hasSelection() || new2DRow(selectionModel->currentIndex())) {
Base::Console().Log("\tNothing selected\n");
return;
}
int res = confirm2dDelete();
if (res == QMessageBox::Cancel) {
return;
}
}
int Array3D::confirm2dDelete()
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(tr("Confirm Delete"));
QString prompt = tr("Are you sure you want to delete the row?");
box.setText(prompt);
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
delete2DSelected();
res = QMessageBox::Ok;
break;
}
return res;
}
void Array3D::delete2DSelected()
{
Array3DModel* model = static_cast<Array3DModel*>(ui->table2D->model());
QItemSelectionModel* selectionModel = ui->table2D->selectionModel();
auto index = selectionModel->currentIndex();
model->deleteRow(index);
update2DArray();
}
void Array3D::onOk(bool checked)

View File

@@ -22,11 +22,10 @@
#ifndef MATGUI_ARRAY3D_H
#define MATGUI_ARRAY3D_H
#include <QAction>
#include <QDialog>
#include <QStandardItem>
#include <QTableView>
#include <Mod/Material/App/Materials.h>
namespace MatGui
{
@@ -37,22 +36,42 @@ class Array3D: public QDialog
Q_OBJECT
public:
explicit Array3D(const QString& propertyName,
Materials::Material* material,
QWidget* parent = nullptr);
Array3D(const QString& propertyName,
std::shared_ptr<Materials::Material> material,
QWidget* parent = nullptr);
~Array3D() override = default;
void defaultValueChanged(const Base::Quantity& value);
void onRowsInserted(const QModelIndex& parent, int first, int last);
void onRowsRemoved(const QModelIndex& parent, int first, int last);
void onDataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight,
const QVector<int>& roles = QVector<int>());
void onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected);
bool onSplitter(QEvent* e);
void onDepthDelete(bool checked);
int confirmDepthDelete();
void deleteDepthSelected();
void on2DDelete(bool checked);
int confirm2dDelete();
void delete2DSelected();
void onDepthContextMenu(const QPoint& pos);
void on2DContextMenu(const QPoint& pos);
void onOk(bool checked);
void onCancel(bool checked);
private:
std::unique_ptr<Ui_Array3D> ui;
const Materials::MaterialProperty* _property;
std::shared_ptr<Materials::Material> _material;
std::shared_ptr<Materials::MaterialProperty> _property;
std::shared_ptr<Materials::Material3DArray> _value;
QAction _deleteDepthAction;
QAction _delete2DAction;
bool newDepthRow(const QModelIndex& index);
bool new2DRow(const QModelIndex& index);
void setupDefault();
void setDepthColumnWidth(QTableView* table);
void setDepthColumnDelegate(QTableView* table);
@@ -60,6 +79,7 @@ private:
void setColumnWidths(QTableView* table);
void setColumnDelegates(QTableView* table);
void setupArray();
void update2DArray();
};
} // namespace MatGui

View File

@@ -156,8 +156,8 @@ QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) cons
else if (_type == Materials::MaterialValue::Boolean) {
Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent);
combo->insertItem(0, QString::fromStdString(""));
combo->insertItem(1, QString::fromStdString("False"));
combo->insertItem(2, QString::fromStdString("True"));
combo->insertItem(1, tr("False"));
combo->insertItem(2, tr("True"));
combo->setCurrentText(item.toString());
widget = combo;
}

View File

@@ -22,8 +22,6 @@
#ifndef MATGUI_ArrayDelegate_H
#define MATGUI_ArrayDelegate_H
#include <boost/filesystem.hpp>
#include <QDialog>
#include <QDir>
#include <QStandardItem>
@@ -35,8 +33,6 @@
#include <Mod/Material/App/Materials.h>
#include <Mod/Material/App/ModelManager.h>
namespace fs = boost::filesystem;
namespace MatGui
{
@@ -44,10 +40,9 @@ class ArrayDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ArrayDelegate(
Materials::MaterialValue::ValueType type = Materials::MaterialValue::None,
QString units = QString(),
QObject* parent = nullptr);
ArrayDelegate(Materials::MaterialValue::ValueType type = Materials::MaterialValue::None,
QString units = QString(),
QObject* parent = nullptr);
virtual ~ArrayDelegate() = default;
void paint(QPainter* painter,

View File

@@ -26,6 +26,7 @@
#include <QMetaType>
#include <Base/Console.h>
#include <Gui/MainWindow.h>
#include <Gui/MetaTypes.h>
@@ -46,7 +47,7 @@ AbstractArrayModel::AbstractArrayModel(QObject* parent)
//===
Array2DModel::Array2DModel(const Materials::MaterialProperty* property,
Array2DModel::Array2DModel(std::shared_ptr<Materials::MaterialProperty> property,
std::shared_ptr<Materials::Material2DArray> value,
QObject* parent)
: AbstractArrayModel(parent)
@@ -68,6 +69,12 @@ bool Array2DModel::newRow(const QModelIndex& index) const
return (index.row() == _value->rows());
}
void Array2DModel::deleteRow(const QModelIndex& index)
{
removeRows(index.row(), 1);
Q_EMIT dataChanged(index, index);
}
int Array2DModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
@@ -145,7 +152,7 @@ bool Array2DModel::insertRows(int row, int count, const QModelIndex& parent)
int columns = columnCount();
for (int i = 0; i < count; i++) {
std::vector<QVariant>* rowPtr = new std::vector<QVariant>();
auto rowPtr = std::make_shared<std::vector<QVariant>>();
for (int j = 0; j < columns; j++) {
rowPtr->push_back(_property->getColumnNull(j));
}
@@ -162,6 +169,10 @@ bool Array2DModel::removeRows(int row, int count, const QModelIndex& parent)
{
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) {
_value->deleteRow(row);
}
endRemoveRows();
return false;
@@ -187,7 +198,7 @@ bool Array2DModel::removeColumns(int column, int count, const QModelIndex& paren
//===
Array3DDepthModel::Array3DDepthModel(const Materials::MaterialProperty* property,
Array3DDepthModel::Array3DDepthModel(std::shared_ptr<Materials::MaterialProperty> property,
std::shared_ptr<Materials::Material3DArray> value,
QObject* parent)
: AbstractArrayModel(parent)
@@ -209,26 +220,34 @@ bool Array3DDepthModel::newRow(const QModelIndex& index) const
return (index.row() == _value->depth());
}
void Array3DDepthModel::deleteRow(const QModelIndex& index)
{
removeRows(index.row(), 1);
Q_EMIT dataChanged(index, index);
}
QVariant Array3DDepthModel::data(const QModelIndex& index, int role) const
{
if (role == Qt::DisplayRole) {
try {
return _value->getValue(index.row(), index.column());
Base::Quantity q = _value->getDepthValue(index.row());
return QVariant::fromValue(q);
}
catch (const Materials::InvalidDepth&) {
}
catch (const Materials::InvalidRow&) {
}
catch (const Materials::InvalidColumn&) {
}
catch (const Materials::InvalidIndex&) {
}
try {
auto column = _property->getColumnType(index.column());
if (column == Materials::MaterialValue::Quantity) {
Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column()));
return QVariant::fromValue(q);
}
Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(0));
return QVariant::fromValue(q);
}
catch (const Materials::InvalidColumn&) {
}
return QString();
}
return QVariant();
@@ -259,8 +278,9 @@ bool Array3DDepthModel::setData(const QModelIndex& index, const QVariant& value,
if (index.row() == _value->depth()) {
insertRows(index.row(), 1);
_value->setCurrentDepth(index.row());
}
_value->setValue(index.row(), index.column(), value);
_value->setDepthValue(index.row(), value.value<Base::Quantity>());
Q_EMIT dataChanged(index, index);
return true;
@@ -277,14 +297,8 @@ bool Array3DDepthModel::insertRows(int row, int count, const QModelIndex& parent
{
beginInsertRows(parent, row, row + count - 1);
int columns = columnCount();
for (int i = 0; i < count; i++) {
std::vector<QVariant>* rowPtr = new std::vector<QVariant>();
for (int j = 0; j < columns; j++) {
rowPtr->push_back(_property->getColumnNull(j));
}
// _value->insertRow(row, rowPtr);
_value->addDepth(row, Base::Quantity(0, _property->getColumnUnits(0)));
}
endInsertRows();
@@ -296,6 +310,10 @@ bool Array3DDepthModel::removeRows(int row, int count, const QModelIndex& parent
{
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) {
_value->deleteDepth(row);
}
endRemoveRows();
return false;
@@ -321,7 +339,7 @@ bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex&
//===
Array3DModel::Array3DModel(const Materials::MaterialProperty* property,
Array3DModel::Array3DModel(std::shared_ptr<Materials::MaterialProperty> property,
std::shared_ptr<Materials::Material3DArray> value,
QObject* parent)
: AbstractArrayModel(parent)
@@ -335,7 +353,15 @@ int Array3DModel::rowCount(const QModelIndex& parent) const
return 0; // No children
}
return _value->depth() + 1; // Will always have 1 empty row
try {
return _value->rows() + 1; // Will always have 1 empty row
}
catch (const Materials::InvalidDepth&) {
return 1;
}
catch (const Materials::InvalidRow&) {
return 1;
}
}
int Array3DModel::columnCount(const QModelIndex& parent) const
@@ -347,15 +373,36 @@ int Array3DModel::columnCount(const QModelIndex& parent) const
bool Array3DModel::newRow(const QModelIndex& index) const
{
return (index.row() == _value->depth());
try {
return (index.row() == _value->rows());
}
catch (const Materials::InvalidDepth&) {
return true;
}
catch (const Materials::InvalidRow&) {
return true;
}
}
void Array3DModel::deleteRow(const QModelIndex& index)
{
removeRows(index.row(), 1);
Q_EMIT dataChanged(index, index);
}
QVariant Array3DModel::data(const QModelIndex& index, int role) const
{
if (role == Qt::DisplayRole) {
Base::Console().Error("Row %d, column %d\n", index.row(), index.column());
// Base::Console().Log("Row %d, column %d\n", index.row(), index.column());
try {
return _value->getValue(index.row(), index.column() + 1);
Base::Quantity q = _value->getValue(index.row(), index.column());
return QVariant::fromValue(q);
}
catch (const Materials::InvalidDepth&) {
}
catch (const Materials::InvalidRow&) {
}
catch (const Materials::InvalidColumn&) {
}
catch (const Materials::InvalidIndex&) {
}
@@ -364,16 +411,11 @@ QVariant Array3DModel::data(const QModelIndex& index, int role) const
}
try {
auto column = _property->getColumnType(index.column() + 1);
if (column == Materials::MaterialValue::Quantity) {
Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() - 1));
return QVariant::fromValue(q);
}
Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() + 1));
return QVariant::fromValue(q);
}
catch (const Materials::InvalidColumn&) {
}
return QString();
}
return QVariant();
@@ -402,10 +444,32 @@ bool Array3DModel::setData(const QModelIndex& index, const QVariant& value, int
{
Q_UNUSED(role);
if (index.row() == _value->depth()) {
Base::Console().Log("Array3DModel::setData at (%d, %d, %d)\n",
_value->currentDepth(),
index.row(),
index.column());
if (_value->depth() == 0) {
// Create the first row
// _value->addDepth(Base::Quantity(0, _property->getColumnUnits(0)));
return false;
}
if (index.row() == _value->rows()) {
insertRows(index.row(), 1);
}
_value->setValue(index.row(), index.column(), value);
try {
_value->setValue(index.row(), index.column(), value.value<Base::Quantity>());
}
catch (const Materials::InvalidDepth&) {
Base::Console().Error("Array3DModel::setData - InvalidDepth");
}
catch (const Materials::InvalidRow&) {
Base::Console().Error("Array3DModel::setData - invalidRow");
}
catch (const Materials::InvalidColumn&) {
Base::Console().Error("Array3DModel::setData - InvalidColumn");
}
Q_EMIT dataChanged(index, index);
return true;
@@ -424,12 +488,12 @@ bool Array3DModel::insertRows(int row, int count, const QModelIndex& parent)
int columns = columnCount();
for (int i = 0; i < count; i++) {
std::vector<QVariant>* rowPtr = new std::vector<QVariant>();
auto rowPtr = std::make_shared<std::vector<Base::Quantity>>();
for (int j = 0; j < columns; j++) {
rowPtr->push_back(_property->getColumnNull(j));
rowPtr->push_back(_property->getColumnNull(j).value<Base::Quantity>());
}
// _value->insertRow(row, rowPtr);
_value->insertRow(row, rowPtr);
}
endInsertRows();
@@ -441,6 +505,10 @@ bool Array3DModel::removeRows(int row, int count, const QModelIndex& parent)
{
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) {
_value->deleteRow(row);
}
endRemoveRows();
return false;
@@ -463,3 +531,13 @@ bool Array3DModel::removeColumns(int column, int count, const QModelIndex& paren
return false;
}
void Array3DModel::updateData()
{
beginResetModel();
// The table has changed at this point, typically by setting the current depth.
// The existing structure needs to be cleared and the table redrawn.
endResetModel();
}

View File

@@ -22,6 +22,8 @@
#ifndef MATGUI_ARRAYMODEL_H
#define MATGUI_ARRAYMODEL_H
#include <memory>
#include <QAbstractTableModel>
#include <QDialog>
#include <QStandardItem>
@@ -36,7 +38,7 @@ namespace MatGui
class AbstractArrayModel: public QAbstractTableModel
{
public:
explicit AbstractArrayModel(QObject* parent = nullptr);
AbstractArrayModel(QObject* parent = nullptr);
~AbstractArrayModel() override = default;
virtual bool newRow(const QModelIndex& index) const = 0;
@@ -45,14 +47,15 @@ public:
class Array2DModel: public AbstractArrayModel
{
public:
explicit Array2DModel(const Materials::MaterialProperty* property = nullptr,
std::shared_ptr<Materials::Material2DArray> value = nullptr,
QObject* parent = nullptr);
Array2DModel(std::shared_ptr<Materials::MaterialProperty> property = nullptr,
std::shared_ptr<Materials::Material2DArray> value = nullptr,
QObject* parent = nullptr);
~Array2DModel() override = default;
// Overridden virtual functions
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
bool newRow(const QModelIndex& index) const override;
void deleteRow(const QModelIndex& index);
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QVariant
@@ -67,21 +70,22 @@ public:
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
private:
const Materials::MaterialProperty* _property;
std::shared_ptr<Materials::MaterialProperty> _property;
std::shared_ptr<Materials::Material2DArray> _value;
};
class Array3DDepthModel: public AbstractArrayModel
{
public:
explicit Array3DDepthModel(const Materials::MaterialProperty* property = nullptr,
std::shared_ptr<Materials::Material3DArray> value = nullptr,
QObject* parent = nullptr);
Array3DDepthModel(std::shared_ptr<Materials::MaterialProperty> property = nullptr,
std::shared_ptr<Materials::Material3DArray> value = nullptr,
QObject* parent = nullptr);
~Array3DDepthModel() override = default;
// Overridden virtual functions
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
bool newRow(const QModelIndex& index) const override;
void deleteRow(const QModelIndex& index);
int columnCount(const QModelIndex& parent = QModelIndex()) const override
{
Q_UNUSED(parent)
@@ -100,21 +104,22 @@ public:
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
private:
const Materials::MaterialProperty* _property;
std::shared_ptr<Materials::MaterialProperty> _property;
std::shared_ptr<Materials::Material3DArray> _value;
};
class Array3DModel: public AbstractArrayModel
{
public:
explicit Array3DModel(const Materials::MaterialProperty* property = nullptr,
std::shared_ptr<Materials::Material3DArray> value = nullptr,
QObject* parent = nullptr);
Array3DModel(std::shared_ptr<Materials::MaterialProperty> property = nullptr,
std::shared_ptr<Materials::Material3DArray> value = nullptr,
QObject* parent = nullptr);
~Array3DModel() override = default;
// Overridden virtual functions
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
bool newRow(const QModelIndex& index) const override;
void deleteRow(const QModelIndex& index);
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QVariant
@@ -128,8 +133,10 @@ public:
bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
void updateData();
private:
const Materials::MaterialProperty* _property;
std::shared_ptr<Materials::MaterialProperty> _property;
std::shared_ptr<Materials::Material3DArray> _value;
};

View File

@@ -35,7 +35,7 @@ class DlgSettingsMaterial: public Gui::Dialog::PreferencePage
Q_OBJECT
public:
explicit DlgSettingsMaterial(QWidget* parent = nullptr);
DlgSettingsMaterial(QWidget* parent = nullptr);
~DlgSettingsMaterial() override = default;
protected:

View File

@@ -88,7 +88,7 @@ bool MaterialDelegate::editorEvent(QEvent* event,
std::string type = propertyType.toStdString();
if (type == "Color") {
Base::Console().Log("Edit color\n");
showColorModal(item);
showColorModal(item, propertyName);
// Mark as handled
return true;
}
@@ -109,7 +109,7 @@ bool MaterialDelegate::editorEvent(QEvent* event,
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
void MaterialDelegate::showColorModal(QStandardItem* item)
void MaterialDelegate::showColorModal(QStandardItem* item, QString propertyName)
{
QColor currentColor; // = d->col;
currentColor.setRgba(parseColor(item->text()));
@@ -126,14 +126,18 @@ void MaterialDelegate::showColorModal(QStandardItem* item)
connect(dlg, &QColorDialog::finished, this, [&](int result) {
if (result == QDialog::Accepted) {
Base::Console().Log("Accepted\n");
QColor color = dlg->selectedColor();
if (color.isValid()) {
Base::Console().Log("isValid\n");
QString colorText = QString(QString::fromStdString("(%1,%2,%3,%4)"))
.arg(color.red() / 255.0)
.arg(color.green() / 255.0)
.arg(color.blue() / 255.0)
.arg(color.alpha() / 255.0);
item->setText(colorText);
Q_EMIT const_cast<MaterialDelegate*>(this)->propertyChange(propertyName,
item->text());
}
}
});
@@ -143,7 +147,7 @@ void MaterialDelegate::showColorModal(QStandardItem* item)
void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item)
{
Materials::Material* material = item->data().value<Materials::Material*>();
auto material = item->data().value<std::shared_ptr<Materials::Material>>();
Array2D* dlg = new Array2D(propertyName, material);
dlg->setAttribute(Qt::WA_DeleteOnClose);
@@ -161,7 +165,7 @@ void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardIt
void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item)
{
Materials::Material* material = item->data().value<Materials::Material*>();
auto material = item->data().value<std::shared_ptr<Materials::Material>>();
Array3D* dlg = new Array3D(propertyName, material);
dlg->setAttribute(Qt::WA_DeleteOnClose);
@@ -411,8 +415,8 @@ QWidget* MaterialDelegate::createWidget(QWidget* parent,
else if (type == "Boolean") {
Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent);
combo->insertItem(0, QString::fromStdString(""));
combo->insertItem(1, QString::fromStdString("False"));
combo->insertItem(2, QString::fromStdString("True"));
combo->insertItem(1, tr("False"));
combo->insertItem(2, tr("True"));
combo->setCurrentText(propertyValue);
widget = combo;
}

View File

@@ -22,8 +22,6 @@
#ifndef MATGUI_MATERIALDELEGATE_H
#define MATGUI_MATERIALDELEGATE_H
#include <boost/filesystem.hpp>
#include <QDialog>
#include <QDir>
#include <QStandardItem>
@@ -35,8 +33,6 @@
#include <Mod/Material/App/Materials.h>
#include <Mod/Material/App/ModelManager.h>
namespace fs = boost::filesystem;
namespace MatGui
{
@@ -44,7 +40,7 @@ class MaterialDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MaterialDelegate(QObject* parent = nullptr);
MaterialDelegate(QObject* parent = nullptr);
~MaterialDelegate() override = default;
QWidget* createEditor(QWidget* parent,
@@ -76,7 +72,7 @@ private:
const QString& propertyValue,
const QString& propertyUnits) const;
QRgb parseColor(const QString& color) const;
void showColorModal(QStandardItem* item);
void showColorModal(QStandardItem* item, QString propertyName);
void showArray2DModal(const QString& propertyName, QStandardItem* item);
void showArray3DModal(const QString& propertyName, QStandardItem* item);
};

View File

@@ -21,6 +21,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QMenu>
#include <QMessageBox>
#include <QTreeView>
#endif
@@ -36,12 +37,15 @@ using namespace MatGui;
/* TRANSLATOR MatGui::MaterialsEditor */
MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent)
MaterialSave::MaterialSave(std::shared_ptr<Materials::Material> material, QWidget* parent)
: QDialog(parent)
, ui(new Ui_MaterialSave)
, _material(material)
, _saveInherited(true)
, _selectedPath(QString::fromStdString("/"))
, _selectedFull(QString::fromStdString("/"))
, _selectedUUID(QString())
, _deleteAction(this)
{
ui->setupUi(this);
@@ -57,6 +61,9 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent)
}
_filename = QString(ui->editFilename->text()); // No filename by default
ui->checkDerived->setChecked(_saveInherited);
connect(ui->checkDerived, &QCheckBox::stateChanged, this, &MaterialSave::onInherited);
connect(ui->standardButtons->button(QDialogButtonBox::Ok),
&QPushButton::clicked,
this,
@@ -73,11 +80,25 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent)
connect(ui->buttonNewFolder, &QPushButton::clicked, this, &MaterialSave::onNewFolder);
connect(ui->editFilename, &QLineEdit::textEdited, this, &MaterialSave::onFilename);
ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeMaterials,
&QWidget::customContextMenuRequested,
this,
&MaterialSave::onContextMenu);
_deleteAction.setText(tr("Delete"));
_deleteAction.setShortcut(Qt::Key_Delete);
connect(&_deleteAction, &QAction::triggered, this, &MaterialSave::onDelete);
ui->treeMaterials->addAction(&_deleteAction);
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
connect(selectionModel,
&QItemSelectionModel::selectionChanged,
this,
&MaterialSave::onSelectModel);
auto model = static_cast<QStandardItemModel*>(ui->treeMaterials->model());
connect(model, &QStandardItemModel::itemChanged, this, &MaterialSave::onItemChanged);
}
/*
@@ -88,6 +109,13 @@ MaterialSave::~MaterialSave()
// no need to delete child widgets, Qt does it all for us
}
void MaterialSave::onInherited(int state)
{
Q_UNUSED(state)
_saveInherited = ui->checkDerived->isChecked();
}
void MaterialSave::onOk(bool checked)
{
Q_UNUSED(checked)
@@ -100,18 +128,145 @@ void MaterialSave::onOk(bool checked)
}
auto variant = ui->comboLibrary->currentData();
auto library = variant.value<Materials::MaterialLibrary>();
auto library = variant.value<std::shared_ptr<Materials::MaterialLibrary>>();
QFileInfo filepath(_selectedPath + QString::fromStdString("/") + name
+ QString::fromStdString(".FCMat"));
Base::Console().Log("saveMaterial(library(%s), material(%s), path(%s))\n",
library.getName().toStdString().c_str(),
library->getName().toStdString().c_str(),
_material->getName().toStdString().c_str(),
filepath.filePath().toStdString().c_str());
_manager.saveMaterial(&library, *_material, filepath.filePath());
if (library->fileExists(filepath.filePath())) {
// confirm overwrite
auto res = confirmOverwrite(_filename);
if (res == QMessageBox::Cancel) {
return;
}
_manager.saveMaterial(library, _material, filepath.filePath(), true, false, _saveInherited);
accept();
return;
}
bool saveAsCopy = false;
if (_manager.exists(_material->getUUID())) {
// Does it already exist in this library?
if (_manager.exists(library, _material->getUUID())) {
// Confirm saving a new material
auto res = confirmNewMaterial();
if (res == QMessageBox::Cancel) {
return;
}
// saveAsCopy = false = already done
}
else {
// Copy or new
auto res = confirmCopy();
if (res == QMessageBox::Cancel) {
return;
}
else if (res == QMessageBox::Save) {
// QMessageBox::Save saves as normal, a duplicate
saveAsCopy = true;
}
// QMessageBox::Ok saves a new material
}
}
_manager
.saveMaterial(library, _material, filepath.filePath(), false, saveAsCopy, _saveInherited);
accept();
}
int MaterialSave::confirmOverwrite(const QString& filename)
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(QObject::tr("Confirm Overwrite"));
QFileInfo info(_selectedFull);
QString prompt = tr("Are you sure you want to save over '%1'?").arg(filename);
box.setText(prompt);
box.setInformativeText(tr("Saving over the original file may cause other documents to break. "
"This is not recommended."));
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
res = QMessageBox::Ok;
break;
}
return res;
}
int MaterialSave::confirmNewMaterial()
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(tr("Confirm Save As New Material"));
QString prompt = tr("Save as new material");
box.setText(prompt);
box.setInformativeText(tr(
"This material already exists in this library. Would you like to save as a new material?"));
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
res = QMessageBox::Ok;
break;
}
return res;
}
int MaterialSave::confirmCopy()
{
QMessageBox box(this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(tr("Confirm Save As Copy"));
QString prompt = tr("Save as Copy");
box.setText(prompt);
box.setInformativeText(tr("Saving a copy is not recommended as it can break other documents. "
"We recommend you save as a new material."));
QPushButton* duplicateButton = box.addButton(tr("Save Copy"), QMessageBox::AcceptRole);
QPushButton* newButton = box.addButton(tr("Save As New"), QMessageBox::ActionRole);
QPushButton* cancelButton = box.addButton(QMessageBox::Cancel);
box.setDefaultButton(cancelButton);
box.setEscapeButton(cancelButton);
box.adjustSize(); // Silence warnings from Qt on Windows
box.exec();
int res = QMessageBox::Cancel;
if (box.clickedButton() == duplicateButton) {
res = QMessageBox::Save;
}
else if (box.clickedButton() == newButton) {
res = QMessageBox::Ok;
}
return res;
}
void MaterialSave::onCancel(bool checked)
{
Q_UNUSED(checked)
@@ -135,7 +290,7 @@ void MaterialSave::setLibraries()
for (auto library : *libraries) {
if (!library->isReadOnly()) {
QVariant libraryVariant;
libraryVariant.setValue(*library);
libraryVariant.setValue(library);
ui->comboLibrary->addItem(library->getName(), libraryVariant);
}
}
@@ -163,31 +318,34 @@ void MaterialSave::addExpanded(QTreeView* tree, QStandardItemModel* parent, QSta
void MaterialSave::addMaterials(
QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::MaterialTreeNode*>> modelTree,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>
modelTree,
const QIcon& folderIcon,
const QIcon& icon)
{
auto tree = ui->treeMaterials;
for (auto& mat : *modelTree) {
Materials::MaterialTreeNode* nodePtr = mat.second;
std::shared_ptr<Materials::MaterialTreeNode> nodePtr = mat.second;
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
const Materials::Material* material = nodePtr->getData();
std::shared_ptr<Materials::Material> 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 | Qt::ItemIsDragEnabled
// | Qt::ItemIsDropEnabled);
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
card->setData(QVariant(uuid), Qt::UserRole);
addExpanded(tree, &parent, card);
}
else {
Base::Console().Log("Material folder path '%s'\n", mat.first.toStdString().c_str());
auto node = new QStandardItem(folderIcon, mat.first);
node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
addExpanded(tree, &parent, node);
// node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
auto treeMap = nodePtr->getFolder();
addMaterials(*node, treeMap, folderIcon, icon);
}
@@ -202,13 +360,14 @@ void MaterialSave::showSelectedTree()
if (ui->comboLibrary->count() > 0) {
auto variant = ui->comboLibrary->currentData();
auto library = variant.value<Materials::MaterialLibrary>();
QIcon icon(library.getIconPath());
auto library = variant.value<std::shared_ptr<Materials::MaterialLibrary>>();
QIcon icon(library->getIconPath());
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
_libraryName = library.getName();
_libraryName = library->getName();
_selectedPath = QString::fromStdString("/") + _libraryName;
_selectedFull = _selectedPath;
auto lib = new QStandardItem(library.getName());
auto lib = new QStandardItem(library->getName());
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
@@ -246,6 +405,7 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele
if (indexes.count() == 0) {
Base::Console().Log("Nothing selected\n");
_selectedPath = QString::fromStdString("/") + _libraryName;
_selectedFull = _selectedPath;
_selectedUUID = QString();
Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str());
return;
@@ -258,11 +418,13 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele
if (_selected.isValid()) {
Base::Console().Log("\tuuid %s\n", _selected.toString().toStdString().c_str());
_selectedPath = getPath(item->parent());
_selectedFull = getPath(item);
_selectedUUID = _selected.toString();
_filename = item->text();
}
else {
_selectedPath = getPath(item);
_selectedFull = _selectedPath;
_selectedUUID = QString();
}
}
@@ -282,6 +444,34 @@ void MaterialSave::currentTextChanged(const QString& value)
showSelectedTree();
}
std::shared_ptr<Materials::MaterialLibrary> MaterialSave::currentLibrary()
{
auto variant = ui->comboLibrary->currentData();
return variant.value<std::shared_ptr<Materials::MaterialLibrary>>();
}
void MaterialSave::createFolder(const QString& path)
{
auto library = currentLibrary();
_manager.createFolder(library, path);
}
void MaterialSave::renameFolder(const QString& oldPath, const QString& newPath)
{
auto library = currentLibrary();
_manager.renameFolder(library, oldPath, newPath);
}
void MaterialSave::deleteRecursive(const QString& path)
{
// This will delete files, folders, and any children
auto library = currentLibrary();
_manager.deleteRecursive(library, path);
}
void MaterialSave::onNewFolder(bool checked)
{
Q_UNUSED(checked)
@@ -293,16 +483,53 @@ void MaterialSave::onNewFolder(bool checked)
current = model->index(0, 0);
}
auto item = model->itemFromIndex(current);
// Check for existing folders starting "New Folder" to prevent duplicates
int newCount = 0;
if (item->hasChildren()) {
for (auto i = 0; i < item->rowCount(); i++) {
auto child = item->child(i);
if (child->text().startsWith(tr("New Folder"))) {
newCount++;
}
}
}
// Folders have no associated data
if (item->data(Qt::UserRole).isNull()) {
Base::Console().Log("Add new folder to '%s'\n", item->text().toStdString().c_str());
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
auto node = new QStandardItem(folderIcon, QString::fromStdString("New Folder"));
QString folderName = tr("New Folder");
if (newCount > 0) {
folderName += QString::number(newCount);
}
auto node = new QStandardItem(folderIcon, folderName);
node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
addExpanded(tree, item, node);
// node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
Base::Console().Log("New folder index valid: %s\n",
node->index().isValid() ? "true" : "false");
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
selectionModel->select(node->index(),
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current);
createFolder(getPath(node));
}
}
void MaterialSave::onItemChanged(QStandardItem* item)
{
Base::Console().Log("MaterialSave::onItemChanged('%s')\n", item->text().toStdString().c_str());
QString oldPath = _selectedPath;
_selectedPath = getPath(item);
_selectedFull = _selectedPath;
Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str());
renameFolder(oldPath, _selectedPath);
}
void MaterialSave::onFilename(const QString& text)
{
Base::Console().Log("MaterialSave::onFilename('%s')\n", text.toStdString().c_str());
@@ -310,4 +537,135 @@ void MaterialSave::onFilename(const QString& text)
_filename = text;
}
QString MaterialSave::pathFromIndex(const QModelIndex& index) const
{
auto model = static_cast<const QStandardItemModel*>(index.model());
auto item = model->itemFromIndex(index);
return getPath(item);
}
void MaterialSave::onContextMenu(const QPoint& pos)
{
Base::Console().Log("MaterialSave::onContextMenu(%d,%d)\n", pos.x(), pos.y());
QModelIndex index = ui->treeMaterials->indexAt(pos);
QString path = pathFromIndex(index);
Base::Console().Log("\tindex at (%d,%d)->'%s'\n",
index.row(),
index.column(),
path.toStdString().c_str());
QMenu contextMenu(tr("Context menu"), this);
// QAction action1(tr("Delete"), this);
// action1.setShortcut(Qt::Key_Delete);
// connect(&action1, &QAction::triggered, this, &MaterialSave::onDelete);
contextMenu.addAction(&_deleteAction);
contextMenu.exec(ui->treeMaterials->mapToGlobal(pos));
}
void MaterialSave::onDelete(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("MaterialSave::onDelete()\n");
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
if (!selectionModel->hasSelection()) {
Base::Console().Log("\tNothing selected\n");
return;
}
Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str());
int res = confirmDelete(this);
if (res == QMessageBox::Cancel) {
return;
}
}
int MaterialSave::confirmDelete(QWidget* parent)
{
auto library = currentLibrary();
if (library->isRoot(_selectedFull)) {
return QMessageBox::Cancel;
}
QMessageBox box(parent ? parent : this);
box.setIcon(QMessageBox::Question);
box.setWindowTitle(QObject::tr("Confirm Delete"));
QFileInfo info(_selectedFull);
QString prompt = QObject::tr("Are you sure you want to delete '%1'?").arg(info.fileName());
box.setText(prompt);
if (selectedHasChildren()) {
box.setInformativeText(QObject::tr("Removing this will also remove all contents."));
}
box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Cancel);
box.setEscapeButton(QMessageBox::Cancel);
int res = QMessageBox::Cancel;
box.adjustSize(); // Silence warnings from Qt on Windows
switch (box.exec()) {
case QMessageBox::Ok:
deleteSelected();
res = QMessageBox::Ok;
break;
}
return res;
}
bool MaterialSave::selectedHasChildren()
{
auto tree = ui->treeMaterials;
auto model = static_cast<QStandardItemModel*>(tree->model());
auto current = tree->currentIndex();
if (!current.isValid()) {
current = model->index(0, 0);
}
auto item = model->itemFromIndex(current);
return item->hasChildren();
}
void MaterialSave::deleteSelected()
{
Base::Console().Log("\tDelete selected path '%s'\n", _selectedFull.toStdString().c_str());
auto library = currentLibrary();
if (!library->isRoot(_selectedFull)) {
_manager.deleteRecursive(library, _selectedFull);
removeSelectedFromTree();
}
}
void MaterialSave::removeChildren(QStandardItem* item)
{
while (item->rowCount() > 0) {
auto child = item->child(0);
removeChildren(child);
item->removeRow(0);
}
}
void MaterialSave::removeSelectedFromTree()
{
auto tree = ui->treeMaterials;
auto model = static_cast<QStandardItemModel*>(tree->model());
auto current = tree->currentIndex();
if (current.row() >= 0) {
auto item = model->itemFromIndex(current);
// Remove the children
removeChildren(item);
item->parent()->removeRow(item->row());
}
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
selectionModel->clear();
}
#include "moc_MaterialSave.cpp"

View File

@@ -22,8 +22,9 @@
#ifndef MATGUI_MATERIALSAVE_H
#define MATGUI_MATERIALSAVE_H
// #include <boost/filesystem.hpp>
#include <memory>
#include <QAction>
#include <QDialog>
#include <QItemSelection>
#include <QStandardItem>
@@ -41,39 +42,61 @@ class MaterialSave: public QDialog
Q_OBJECT
public:
explicit MaterialSave(Materials::Material* material, QWidget* parent = nullptr);
MaterialSave(std::shared_ptr<Materials::Material> material, QWidget* parent = nullptr);
~MaterialSave() override;
void setLibraries();
void createModelTree();
void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child);
void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child);
void
addMaterials(QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::MaterialTreeNode*>> modelTree,
const QIcon& folderIcon,
const QIcon& icon);
void addMaterials(
QStandardItem& parent,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>
modelTree,
const QIcon& folderIcon,
const QIcon& icon);
void showSelectedTree();
void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected);
void currentTextChanged(const QString& value);
void onNewFolder(bool checked);
void onItemChanged(QStandardItem* item);
void onFilename(const QString& text);
void onContextMenu(const QPoint& pos);
void onDelete(bool checked);
void onInherited(int state);
void onOk(bool checked);
void onCancel(bool checked);
int confirmOverwrite(const QString& filename);
int confirmNewMaterial();
int confirmCopy();
void accept() override;
void reject() override;
private:
std::unique_ptr<Ui_MaterialSave> ui;
Materials::MaterialManager _manager;
Materials::Material* _material;
std::shared_ptr<Materials::Material> _material;
bool _saveInherited;
QString _selectedPath;
QString _selectedFull;
QString _selectedUUID;
QString _libraryName;
QString _filename;
QAction _deleteAction;
QString getPath(const QStandardItem* item) const;
std::shared_ptr<Materials::MaterialLibrary> currentLibrary();
void createFolder(const QString& path);
void renameFolder(const QString& oldPath, const QString& newPath);
void deleteRecursive(const QString& path);
QString pathFromIndex(const QModelIndex& index) const;
int confirmDelete(QWidget* parent);
bool selectedHasChildren();
void deleteSelected();
void removeChildren(QStandardItem* item);
void removeSelectedFromTree();
};
} // namespace MatGui

View File

@@ -83,6 +83,30 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkDerived">
<property name="text">
<string>Save as Inherited</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="standardButtons">
<property name="orientation">

View File

@@ -25,6 +25,7 @@
#include <QDesktopServices>
#include <QIODevice>
#include <QItemSelectionModel>
#include <QMenu>
#include <QMessageBox>
#include <QString>
#include <QStringList>
@@ -35,6 +36,7 @@
#include <limits>
#include <App/Application.h>
#include <App/License.h>
#include <Base/Interpreter.h>
#include <Base/Quantity.h>
#include <Gui/Application.h>
@@ -61,6 +63,7 @@ using namespace MatGui;
MaterialsEditor::MaterialsEditor(QWidget* parent)
: QDialog(parent)
, ui(new Ui_MaterialsEditor)
, _material(std::make_shared<Materials::Material>())
, _edited(false)
{
ui->setupUi(this);
@@ -72,6 +75,7 @@ MaterialsEditor::MaterialsEditor(QWidget* parent)
createPhysicalTree();
createAppearanceTree();
createPreviews();
setMaterialDefaults();
ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg")));
@@ -88,12 +92,35 @@ MaterialsEditor::MaterialsEditor(QWidget* parent)
this,
&MaterialsEditor::onSave);
connect(ui->editName, &QLineEdit::textEdited, this, &MaterialsEditor::onName);
connect(ui->editAuthor, &QLineEdit::textEdited, this, &MaterialsEditor::onAuthor);
connect(ui->editLicense, &QLineEdit::textEdited, this, &MaterialsEditor::onLicense);
connect(ui->editSourceURL, &QLineEdit::textEdited, this, &MaterialsEditor::onSourceURL);
connect(ui->editSourceReference,
&QLineEdit::textEdited,
this,
&MaterialsEditor::onSourceReference);
connect(ui->editDescription, &QTextEdit::textChanged, this, &MaterialsEditor::onDescription);
connect(ui->buttonURL, &QPushButton::clicked, this, &MaterialsEditor::onURL);
connect(ui->buttonPhysicalAdd, &QPushButton::clicked, this, &MaterialsEditor::onPhysicalAdd);
connect(ui->buttonPhysicalRemove,
&QPushButton::clicked,
this,
&MaterialsEditor::onPhysicalRemove);
connect(ui->buttonAppearanceAdd,
&QPushButton::clicked,
this,
&MaterialsEditor::onAppearanceAdd);
connect(ui->buttonAppearanceRemove,
&QPushButton::clicked,
this,
&MaterialsEditor::onAppearanceRemove);
connect(ui->buttonInheritNew,
&QPushButton::clicked,
this,
&MaterialsEditor::onInheritNewMaterial);
connect(ui->buttonNew, &QPushButton::clicked, this, &MaterialsEditor::onNewMaterial);
connect(ui->buttonFavorite, &QPushButton::clicked, this, &MaterialsEditor::onFavourite);
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
@@ -101,6 +128,13 @@ MaterialsEditor::MaterialsEditor(QWidget* parent)
&QItemSelectionModel::selectionChanged,
this,
&MaterialsEditor::onSelectMaterial);
connect(ui->treeMaterials, &QTreeView::doubleClicked, this, &MaterialsEditor::onDoubleClick);
ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeMaterials,
&QWidget::customContextMenuRequested,
this,
&MaterialsEditor::onContextMenu);
}
void MaterialsEditor::getFavorites()
@@ -144,7 +178,7 @@ void MaterialsEditor::addFavorite(const QString& uuid)
{
// Ensure it is a material. New, unsaved materials will not be
try {
const Materials::Material& material = _materialManager.getMaterial(uuid);
auto material = _materialManager.getMaterial(uuid);
Q_UNUSED(material)
}
catch (const Materials::MaterialNotFound&) {
@@ -227,7 +261,7 @@ void MaterialsEditor::addRecent(const QString& uuid)
{
// Ensure it is a material. New, unsaved materials will not be
try {
const Materials::Material& material = _materialManager.getMaterial(uuid);
auto material = _materialManager.getMaterial(uuid);
Q_UNUSED(material)
}
catch (const Materials::MaterialNotFound&) {
@@ -257,16 +291,46 @@ bool MaterialsEditor::isRecent(const QString& uuid) const
return false;
}
void MaterialsEditor::onName(const QString& text)
{
_material->setName(text);
}
void MaterialsEditor::onAuthor(const QString& text)
{
_material->setAuthor(text);
}
void MaterialsEditor::onLicense(const QString& text)
{
_material->setLicense(text);
}
void MaterialsEditor::onSourceURL(const QString& text)
{
_material->setURL(text);
}
void MaterialsEditor::onSourceReference(const QString& text)
{
_material->setReference(text);
}
void MaterialsEditor::onDescription()
{
_material->setDescription(ui->editDescription->toPlainText());
}
void MaterialsEditor::propertyChange(const QString& property, const QString value)
{
Base::Console().Log("MaterialsEditor::propertyChange(%s) = '%s'\n",
property.toStdString().c_str(),
value.toStdString().c_str());
if (_material.hasPhysicalProperty(property)) {
_material.setPhysicalValue(property, value);
if (_material->hasPhysicalProperty(property)) {
_material->setPhysicalValue(property, value);
}
else if (_material.hasAppearanceProperty(property)) {
_material.setAppearanceValue(property, value);
else if (_material->hasAppearanceProperty(property)) {
_material->setAppearanceValue(property, value);
updatePreview();
}
_edited = true;
@@ -287,12 +351,12 @@ void MaterialsEditor::onPhysicalAdd(bool checked)
{
Q_UNUSED(checked)
ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Physical);
ModelSelect dialog(this, Materials::ModelFilter_Physical);
dialog.setModal(true);
if (dialog.exec() == QDialog::Accepted) {
QString selected = dialog.selectedModel();
Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str());
_material.addPhysical(selected);
_material->addPhysical(selected);
updateMaterial();
}
else {
@@ -300,16 +364,39 @@ void MaterialsEditor::onPhysicalAdd(bool checked)
}
}
void MaterialsEditor::onPhysicalRemove(bool checked)
{
Q_UNUSED(checked)
QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel();
if (selectionModel->hasSelection()) {
const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0);
const QStandardItemModel* treeModel = static_cast<const QStandardItemModel*>(index.model());
// Check we're the material model root.
auto item = treeModel->itemFromIndex(index);
auto group = item->parent();
if (!group) {
QString propertyName = index.data().toString();
QString uuid = _material->getModelByName(propertyName);
_material->removePhysical(uuid);
updateMaterial();
}
}
}
void MaterialsEditor::onAppearanceAdd(bool checked)
{
Q_UNUSED(checked)
ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Appearance);
ModelSelect dialog(this, Materials::ModelFilter_Appearance);
dialog.setModal(true);
if (dialog.exec() == QDialog::Accepted) {
QString selected = dialog.selectedModel();
Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str());
_material.addAppearance(selected);
_material->addAppearance(selected);
updateMaterial();
}
else {
@@ -317,12 +404,35 @@ void MaterialsEditor::onAppearanceAdd(bool checked)
}
}
void MaterialsEditor::onAppearanceRemove(bool checked)
{
Q_UNUSED(checked)
QItemSelectionModel* selectionModel = ui->treeAppearance->selectionModel();
if (selectionModel->hasSelection()) {
const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0);
const QStandardItemModel* treeModel = static_cast<const QStandardItemModel*>(index.model());
// Check we're the material model root.
auto item = treeModel->itemFromIndex(index);
auto group = item->parent();
if (!group) {
QString propertyName = index.data().toString();
QString uuid = _material->getModelByName(propertyName);
_material->removeAppearance(uuid);
updateMaterial();
}
}
}
void MaterialsEditor::onFavourite(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("Favorite\n");
auto selected = _material.getUUID();
auto selected = _material->getUUID();
if (isFavorite(selected)) {
removeFavorite(selected);
}
@@ -331,6 +441,76 @@ void MaterialsEditor::onFavourite(bool checked)
}
}
void MaterialsEditor::setMaterialDefaults()
{
_material->setName(tr("Unnamed"));
std::string Author = App::GetApplication()
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document")
->GetASCII("prefAuthor", "");
_material->setAuthor(QString::fromStdString(Author));
// license stuff
auto paramGrp {App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Document")};
auto index = static_cast<int>(paramGrp->GetInt("prefLicenseType", 0));
const char* name = App::licenseItems.at(index).at(App::posnOfFullName);
// const char* url = App::licenseItems.at(index).at(App::posnOfUrl);
// std::string licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url));
_material->setLicense(QString::fromStdString(name));
// Empty materials will have no parent
_materialManager.dereference(_material);
updateMaterial();
_material->resetEditState();
}
void MaterialsEditor::onNewMaterial(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("New Material\n");
// Ensure data is saved (or discarded) before changing materials
if (_material->getEditState() != Materials::Material::ModelEdit_None) {
// Prompt the user to save or discard changes
Base::Console().Log("*** Material edited!!!\n");
int res = confirmSave(this);
if (res == QMessageBox::Cancel) {
return;
}
}
// Create a new material
_material = std::make_shared<Materials::Material>();
setMaterialDefaults();
}
void MaterialsEditor::onInheritNewMaterial(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("Inherit New Material\n");
// Save the current UUID to use as out parent
auto parent = _material->getUUID();
// Ensure data is saved (or discarded) before changing materials
if (_material->getEditState() != Materials::Material::ModelEdit_None) {
// Prompt the user to save or discard changes
Base::Console().Log("*** Material edited!!!\n");
int res = confirmSave(this);
if (res == QMessageBox::Cancel) {
return;
}
}
// Create a new material
_material = std::make_shared<Materials::Material>();
_material->setParentUUID(parent);
setMaterialDefaults();
}
void MaterialsEditor::onOk(bool checked)
{
Q_UNUSED(checked)
@@ -354,17 +534,18 @@ void MaterialsEditor::onSave(bool checked)
void MaterialsEditor::saveMaterial()
{
MaterialSave dialog(&_material, this);
MaterialSave dialog(_material, this);
dialog.setModal(true);
if (dialog.exec() == QDialog::Accepted) {
_material.resetEditState();
updateMaterialGeneral();
_material->resetEditState();
refreshMaterialTree();
}
}
void MaterialsEditor::accept()
{
addRecent(_material.getUUID());
addRecent(_material->getUUID());
QDialog::accept();
}
@@ -379,15 +560,16 @@ void MaterialsEditor::reject()
void MaterialsEditor::addMaterials(
QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::MaterialTreeNode*>> modelTree,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>
modelTree,
const QIcon& folderIcon,
const QIcon& icon)
{
auto tree = ui->treeMaterials;
for (auto& mat : *modelTree) {
Materials::MaterialTreeNode* nodePtr = mat.second;
std::shared_ptr<Materials::MaterialTreeNode> nodePtr = mat.second;
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
const Materials::Material* material = nodePtr->getData();
auto material = nodePtr->getData();
QString uuid = material->getUUID();
// Base::Console().Log("Material path '%s'\n",
// material->getDirectory().toStdString().c_str());
@@ -429,9 +611,9 @@ void MaterialsEditor::createPhysicalTree()
tree->setModel(model);
QStringList headers;
headers.append(QString::fromStdString("Property"));
headers.append(QString::fromStdString("Value"));
headers.append(QString::fromStdString("Type"));
headers.append(tr("Property"));
headers.append(tr("Value"));
headers.append(tr("Type"));
model->setHorizontalHeaderLabels(headers);
tree->setColumnWidth(0, 250);
@@ -444,6 +626,12 @@ void MaterialsEditor::createPhysicalTree()
tree->setItemDelegateForColumn(1, delegate);
connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange);
// QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel();
// connect(selectionModel,
// &QItemSelectionModel::selectionChanged,
// this,
// &MaterialsEditor::onSelectPhysicalProperty);
}
void MaterialsEditor::createPreviews()
@@ -468,9 +656,9 @@ void MaterialsEditor::createAppearanceTree()
tree->setModel(model);
QStringList headers;
headers.append(QString::fromStdString("Property"));
headers.append(QString::fromStdString("Value"));
headers.append(QString::fromStdString("Type"));
headers.append(tr("Property"));
headers.append(tr("Value"));
headers.append(tr("Type"));
model->setHorizontalHeaderLabels(headers);
tree->setColumnWidth(0, 250);
@@ -490,10 +678,10 @@ void MaterialsEditor::addRecents(QStandardItem* parent)
auto tree = ui->treeMaterials;
for (auto& uuid : _recents) {
try {
const Materials::Material& material = getMaterialManager().getMaterial(uuid);
auto material = getMaterialManager().getMaterial(uuid);
QIcon icon = QIcon(material.getLibrary().getIconPath());
auto card = new QStandardItem(icon, material.getName());
QIcon icon = QIcon(material->getLibrary()->getIconPath());
auto card = new QStandardItem(icon, libraryPath(material));
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
card->setData(QVariant(uuid), Qt::UserRole);
@@ -510,10 +698,10 @@ void MaterialsEditor::addFavorites(QStandardItem* parent)
auto tree = ui->treeMaterials;
for (auto& uuid : _favorites) {
try {
const Materials::Material& material = getMaterialManager().getMaterial(uuid);
auto material = getMaterialManager().getMaterial(uuid);
QIcon icon = QIcon(material.getLibrary().getIconPath());
auto card = new QStandardItem(icon, material.getName());
QIcon icon = QIcon(material->getLibrary()->getIconPath());
auto card = new QStandardItem(icon, libraryPath(material));
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
card->setData(QVariant(uuid), Qt::UserRole);
@@ -530,12 +718,12 @@ void MaterialsEditor::fillMaterialTree()
auto tree = ui->treeMaterials;
auto model = static_cast<QStandardItemModel*>(tree->model());
auto lib = new QStandardItem(QString::fromStdString("Favorites"));
auto lib = new QStandardItem(tr("Favorites"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
addFavorites(lib);
lib = new QStandardItem(QString::fromStdString("Recent"));
lib = new QStandardItem(tr("Recent"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
addRecents(lib);
@@ -549,7 +737,7 @@ void MaterialsEditor::fillMaterialTree()
QIcon icon(library->getIconPath());
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
auto modelTree = _materialManager.getMaterialTree(*library);
auto modelTree = _materialManager.getMaterialTree(library);
addMaterials(*lib, modelTree, folderIcon, icon);
}
}
@@ -582,23 +770,23 @@ void MaterialsEditor::updatePreview() const
QString highlightColor;
QString sectionColor;
if (_material.hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) {
diffuseColor = _material.getAppearanceValueString(QString::fromStdString("DiffuseColor"));
if (_material->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) {
diffuseColor = _material->getAppearanceValueString(QString::fromStdString("DiffuseColor"));
}
else if (_material.hasAppearanceProperty(QString::fromStdString("ViewColor"))) {
diffuseColor = _material.getAppearanceValueString(QString::fromStdString("ViewColor"));
else if (_material->hasAppearanceProperty(QString::fromStdString("ViewColor"))) {
diffuseColor = _material->getAppearanceValueString(QString::fromStdString("ViewColor"));
}
else if (_material.hasAppearanceProperty(QString::fromStdString("Color"))) {
diffuseColor = _material.getAppearanceValueString(QString::fromStdString("Color"));
else if (_material->hasAppearanceProperty(QString::fromStdString("Color"))) {
diffuseColor = _material->getAppearanceValueString(QString::fromStdString("Color"));
}
if (_material.hasAppearanceProperty(QString::fromStdString("SpecularColor"))) {
if (_material->hasAppearanceProperty(QString::fromStdString("SpecularColor"))) {
highlightColor =
_material.getAppearanceValueString(QString::fromStdString("SpecularColor"));
_material->getAppearanceValueString(QString::fromStdString("SpecularColor"));
}
if (_material.hasAppearanceProperty(QString::fromStdString("SectionColor"))) {
sectionColor = _material.getAppearanceValueString(QString::fromStdString("SectionColor"));
if (_material->hasAppearanceProperty(QString::fromStdString("SectionColor"))) {
sectionColor = _material->getAppearanceValueString(QString::fromStdString("SectionColor"));
}
if ((diffuseColor.length() + highlightColor.length()) > 0) {
@@ -678,28 +866,28 @@ void MaterialsEditor::updateMaterialAppearance()
treeModel->clear();
QStringList headers;
headers.append(QString::fromStdString("Property"));
headers.append(QString::fromStdString("Value"));
headers.append(QString::fromStdString("Type"));
headers.append(tr("Property"));
headers.append(tr("Value"));
headers.append(tr("Type"));
treeModel->setHorizontalHeaderLabels(headers);
tree->setColumnWidth(0, 250);
tree->setColumnWidth(1, 250);
tree->setColumnHidden(2, true);
const std::vector<QString>* models = _material.getAppearanceModels();
auto models = _material->getAppearanceModels();
if (models) {
for (auto it = models->begin(); it != models->end(); it++) {
QString uuid = *it;
try {
const Materials::Model& model = getModelManager().getModel(uuid);
QString name = model.getName();
auto model = getModelManager().getModel(uuid);
QString name = model->getName();
auto modelRoot = new QStandardItem(name);
modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
addExpanded(tree, treeModel, modelRoot);
for (auto itp = model.begin(); itp != model.end(); itp++) {
for (auto itp = model->begin(); itp != model->end(); itp++) {
QList<QStandardItem*> items;
QString key = itp->first;
@@ -707,10 +895,10 @@ void MaterialsEditor::updateMaterialAppearance()
propertyItem->setToolTip(itp->second.getDescription());
items.append(propertyItem);
auto valueItem = new QStandardItem(_material.getAppearanceValueString(key));
auto valueItem = new QStandardItem(_material->getAppearanceValueString(key));
valueItem->setToolTip(itp->second.getDescription());
QVariant variant;
variant.setValue(&_material);
variant.setValue(_material);
valueItem->setData(variant);
items.append(valueItem);
@@ -737,10 +925,10 @@ void MaterialsEditor::updateMaterialProperties()
treeModel->clear();
QStringList headers;
headers.append(QString::fromStdString("Property"));
headers.append(QString::fromStdString("Value"));
headers.append(QString::fromStdString("Type"));
headers.append(QString::fromStdString("Units"));
headers.append(tr("Property"));
headers.append(tr("Value"));
headers.append(tr("Type"));
headers.append(tr("Units"));
treeModel->setHorizontalHeaderLabels(headers);
tree->setColumnWidth(0, 250);
@@ -748,19 +936,19 @@ void MaterialsEditor::updateMaterialProperties()
tree->setColumnHidden(2, true);
tree->setColumnHidden(3, true);
const std::vector<QString>* models = _material.getPhysicalModels();
auto models = _material->getPhysicalModels();
if (models) {
for (auto it = models->begin(); it != models->end(); it++) {
QString uuid = *it;
try {
const Materials::Model& model = getModelManager().getModel(uuid);
QString name = model.getName();
auto model = getModelManager().getModel(uuid);
QString name = model->getName();
auto modelRoot = new QStandardItem(name);
modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
addExpanded(tree, treeModel, modelRoot);
for (auto itp = model.begin(); itp != model.end(); itp++) {
for (auto itp = model->begin(); itp != model->end(); itp++) {
QList<QStandardItem*> items;
QString key = itp->first;
@@ -770,10 +958,10 @@ void MaterialsEditor::updateMaterialProperties()
propertyItem->setToolTip(modelProperty.getDescription());
items.append(propertyItem);
auto valueItem = new QStandardItem(_material.getPhysicalValueString(key));
auto valueItem = new QStandardItem(_material->getPhysicalValueString(key));
valueItem->setToolTip(modelProperty.getDescription());
QVariant variant;
variant.setValue(&_material);
variant.setValue(_material);
valueItem->setData(variant);
items.append(valueItem);
@@ -794,17 +982,47 @@ void MaterialsEditor::updateMaterialProperties()
}
}
QString MaterialsEditor::libraryPath(std::shared_ptr<Materials::Material> material) const
{
QString path;
auto library = material->getLibrary();
if (library) {
path = QString::fromStdString("/%1/%2")
.arg(material->getLibrary()->getName())
.arg(material->getDirectory());
}
else {
path = QString::fromStdString("%1").arg(material->getDirectory());
}
return path;
}
void MaterialsEditor::updateMaterialGeneral()
{
QString parentString;
try {
auto parent = _materialManager.getParent(_material);
parentString = libraryPath(parent);
}
catch (const Materials::MaterialNotFound&) {
}
// Update the general information
ui->editName->setText(_material->getName());
ui->editAuthor->setText(_material->getAuthor());
ui->editLicense->setText(_material->getLicense());
ui->editParent->setText(parentString);
ui->editParent->setReadOnly(true);
ui->editSourceURL->setText(_material->getURL());
ui->editSourceReference->setText(_material->getReference());
// ui->editTags->setText(_material->getName());
ui->editDescription->setText(_material->getDescription());
}
void MaterialsEditor::updateMaterial()
{
// Update the general information
ui->editName->setText(_material.getName());
ui->editAuthorLicense->setText(_material.getAuthorAndLicense());
// ui->editParent->setText(_material.getName());
ui->editSourceURL->setText(_material.getURL());
ui->editSourceReference->setText(_material.getReference());
// ui->editTags->setText(_material.getName());
ui->editDescription->setText(_material.getDescription());
updateMaterialGeneral();
updateMaterialProperties();
updateMaterialAppearance();
@@ -830,13 +1048,13 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected,
}
}
if (uuid.isEmpty() || uuid == _material.getUUID()) {
if (uuid.isEmpty() || uuid == _material->getUUID()) {
Base::Console().Log("*** Unchanged material '%s'\n", uuid.toStdString().c_str());
return;
}
// Ensure data is saved (or discarded) before changing materials
if (_material.getEditState() != Materials::Material::ModelEdit_None) {
if (_material->getEditState() != Materials::Material::ModelEdit_None) {
// Prompt the user to save or discard changes
Base::Console().Log("*** Material edited!!!\n");
int res = confirmSave(this);
@@ -847,16 +1065,85 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected,
// Get the selected material
try {
_material = getMaterialManager().getMaterial(uuid);
_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());
Materials::Material empty;
_material = empty;
_material = std::make_shared<Materials::Material>();
}
updateMaterial();
_material.resetEditState();
_material->resetEditState();
}
void MaterialsEditor::onDoubleClick(const QModelIndex& index)
{
Q_UNUSED(index)
Base::Console().Log("MaterialsEditor::onDoubleClick()\n");
accept();
}
void MaterialsEditor::onContextMenu(const QPoint& pos)
{
Base::Console().Log("MaterialsEditor::onContextMenu(%d,%d)\n", pos.x(), pos.y());
// QModelIndex index = ui->treeMaterials->indexAt(pos);
// QString path = pathFromIndex(index);
// Base::Console().Log("\tindex at (%d,%d)->'%s'\n",
// index.row(),
// index.column(),
// path.toStdString().c_str());
QMenu contextMenu(tr("Context menu"), this);
QAction action1(tr("Inherit from"), this);
// action1.setShortcut(Qt::Key_Delete);
connect(&action1, &QAction::triggered, this, &MaterialsEditor::onInherit);
contextMenu.addAction(&action1);
QAction action2(tr("Inherit new material"), this);
// action1.setShortcut(Qt::Key_Delete);
connect(&action2, &QAction::triggered, this, &MaterialsEditor::onInheritNew);
contextMenu.addAction(&action2);
contextMenu.exec(ui->treeMaterials->mapToGlobal(pos));
}
void MaterialsEditor::onInherit(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("MaterialsEditor::onInherit()\n");
// QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
// if (!selectionModel->hasSelection()) {
// Base::Console().Log("\tNothing selected\n");
// return;
// }
// Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str());
// int res = confirmDelete(this);
// if (res == QMessageBox::Cancel) {
// return;
// }
}
void MaterialsEditor::onInheritNew(bool checked)
{
Q_UNUSED(checked)
Base::Console().Log("MaterialsEditor::onInherit()\n");
// QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
// if (!selectionModel->hasSelection()) {
// Base::Console().Log("\tNothing selected\n");
// return;
// }
// Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str());
// int res = confirmDelete(this);
// if (res == QMessageBox::Cancel) {
// return;
// }
}
int MaterialsEditor::confirmSave(QWidget* parent)

View File

@@ -22,10 +22,11 @@
#ifndef MATGUI_MATERIALSEDITOR_H
#define MATGUI_MATERIALSEDITOR_H
#include <boost/filesystem.hpp>
#include <memory>
#include <QDialog>
#include <QDir>
#include <QPoint>
#include <QStandardItem>
#include <QStyledItemDelegate>
#include <QSvgWidget>
@@ -35,8 +36,6 @@
#include <Mod/Material/App/Materials.h>
#include <Mod/Material/App/ModelManager.h>
namespace fs = boost::filesystem;
namespace MatGui
{
@@ -47,14 +46,25 @@ class MaterialsEditor: public QDialog
Q_OBJECT
public:
explicit MaterialsEditor(QWidget* parent = nullptr);
MaterialsEditor(QWidget* parent = nullptr);
~MaterialsEditor() override = default;
void onName(const QString& text);
void onAuthor(const QString& text);
void onLicense(const QString& text);
void onSourceURL(const QString& text);
void onSourceReference(const QString& text);
void onDescription();
void propertyChange(const QString& property, const QString value);
void onInheritNewMaterial(bool checked);
void onNewMaterial(bool checked);
void onFavourite(bool checked);
void onURL(bool checked);
void onPhysicalAdd(bool checked);
void onPhysicalRemove(bool checked);
void onAppearanceAdd(bool checked);
void onAppearanceRemove(bool checked);
void onOk(bool checked);
void onCancel(bool checked);
void onSave(bool checked);
@@ -70,10 +80,15 @@ public:
return _modelManager;
}
QString libraryPath(std::shared_ptr<Materials::Material> material) const;
void updateMaterialAppearance();
void updateMaterialProperties();
void updateMaterialGeneral();
void updateMaterial();
void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected);
void onDoubleClick(const QModelIndex& index);
void onContextMenu(const QPoint& pos);
protected:
int confirmSave(QWidget* parent);
@@ -83,7 +98,7 @@ private:
std::unique_ptr<Ui_MaterialsEditor> ui;
Materials::MaterialManager _materialManager;
Materials::ModelManager _modelManager;
Materials::Material _material;
std::shared_ptr<Materials::Material> _material;
QSvgWidget* _rendered;
QSvgWidget* _vectored;
bool _edited;
@@ -102,6 +117,10 @@ private:
void addRecent(const QString& uuid);
bool isRecent(const QString& uuid) const;
void onInherit(bool checked);
void onInheritNew(bool checked);
void setMaterialDefaults();
void updatePreview() const;
QString getColorHash(const QString& colorString, int colorRange = 255) const;
@@ -115,15 +134,12 @@ private:
void createMaterialTree();
void fillMaterialTree();
void refreshMaterialTree();
void
addMaterials(QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::MaterialTreeNode*>> modelTree,
const QIcon& folderIcon,
const QIcon& icon);
bool isMaterial(const fs::path& p) const
{
return Materials::MaterialManager::isMaterial(p);
}
void addMaterials(
QStandardItem& parent,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>
modelTree,
const QIcon& folderIcon,
const QIcon& icon);
};
} // namespace MatGui

View File

@@ -68,19 +68,40 @@
<property name="bottomMargin">
<number>7</number>
</property>
<item row="3" column="0">
<widget class="QLabel" name="labelParent">
<property name="text">
<string>Parent</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QTextEdit" name="editDescription"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Tags</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelSourceURL">
<property name="text">
<string>Source URL</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="editName"/>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QLabel" name="labelDescription">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="editAuthorLicense"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
@@ -88,54 +109,10 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelSourceReference">
<property name="text">
<string>Source Reference</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelParent">
<property name="text">
<string>Parent</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QTextEdit" name="editDescription"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAuthorLicense">
<property name="text">
<string>Author and License</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="editParent"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Tags</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelSourceURL">
<property name="text">
<string>Source URL</string>
</property>
</widget>
</item>
<item row="5" column="2">
<item row="6" column="2">
<widget class="QLineEdit" name="editTags"/>
</item>
<item row="4" column="2">
<widget class="QLineEdit" name="editSourceReference"/>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="editSourceURL"/>
@@ -155,6 +132,39 @@
</item>
</layout>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="editAuthor"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAuthor">
<property name="text">
<string>Author</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLineEdit" name="editParent"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelSourceReference">
<property name="text">
<string>Source Reference</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLineEdit" name="editSourceReference"/>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="editLicense"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelLicense">
<property name="text">
<string>License</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -172,6 +182,20 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonNew">
<property name="text">
<string>&amp;New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonInheritNew">
<property name="text">
<string>Inherit New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonFavorite">
<property name="text">

View File

@@ -33,6 +33,8 @@
#include <Gui/Command.h>
#include <Gui/WaitCursor.h>
#include <Mod/Material/App/ModelManager.h>
#include "ModelSelect.h"
#include "ui_ModelSelect.h"
@@ -41,7 +43,7 @@ using namespace MatGui;
/* TRANSLATOR MatGui::ModelSelect */
ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter filter)
ModelSelect::ModelSelect(QWidget* parent, Materials::ModelFilter filter)
: QDialog(parent)
, _filter(filter)
, ui(new Ui_ModelSelect)
@@ -69,6 +71,7 @@ ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter f
connect(ui->buttonURL, &QPushButton::clicked, this, &ModelSelect::onURL);
connect(ui->buttonDOI, &QPushButton::clicked, this, &ModelSelect::onDOI);
connect(ui->buttonFavorite, &QPushButton::clicked, this, &ModelSelect::onFavourite);
connect(ui->treeModels, &QTreeView::doubleClicked, this, &ModelSelect::onDoubleClick);
ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false);
ui->buttonFavorite->setEnabled(false);
@@ -232,14 +235,14 @@ void ModelSelect::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStan
void ModelSelect::addModels(
QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::ModelTreeNode*>> modelTree,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::ModelTreeNode>>> modelTree,
const QIcon& icon)
{
auto tree = ui->treeModels;
for (auto& mod : *modelTree) {
Materials::ModelTreeNode* nodePtr = mod.second;
std::shared_ptr<Materials::ModelTreeNode> nodePtr = mod.second;
if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) {
const Materials::Model* model = nodePtr->getData();
auto model = nodePtr->getData();
QString uuid = model->getUUID();
auto card = new QStandardItem(icon, model->getName());
@@ -264,11 +267,11 @@ void ModelSelect::addRecents(QStandardItem* parent)
auto tree = ui->treeModels;
for (auto& uuid : _recents) {
try {
const Materials::Model& model = getModelManager().getModel(uuid);
auto model = getModelManager().getModel(uuid);
if (getModelManager().passFilter(_filter, model.getType())) {
QIcon icon = QIcon(model.getLibrary().getIconPath());
auto card = new QStandardItem(icon, model.getName());
if (getModelManager().passFilter(_filter, model->getType())) {
QIcon icon = QIcon(model->getLibrary()->getIconPath());
auto card = new QStandardItem(icon, model->getName());
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
card->setData(QVariant(uuid), Qt::UserRole);
@@ -286,11 +289,11 @@ void ModelSelect::addFavorites(QStandardItem* parent)
auto tree = ui->treeModels;
for (auto& uuid : _favorites) {
try {
const Materials::Model& model = getModelManager().getModel(uuid);
auto model = getModelManager().getModel(uuid);
if (getModelManager().passFilter(_filter, model.getType())) {
QIcon icon = QIcon(model.getLibrary().getIconPath());
auto card = new QStandardItem(icon, model.getName());
if (getModelManager().passFilter(_filter, model->getType())) {
QIcon icon = QIcon(model->getLibrary()->getIconPath());
auto card = new QStandardItem(icon, model->getName());
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled);
card->setData(QVariant(uuid), Qt::UserRole);
@@ -305,8 +308,6 @@ void ModelSelect::addFavorites(QStandardItem* parent)
void ModelSelect::createModelTree()
{
// Materials::ModelManager modelManager;
auto tree = ui->treeModels;
auto model = new QStandardItemModel();
tree->setModel(model);
@@ -326,17 +327,16 @@ void ModelSelect::refreshModelTree()
void ModelSelect::fillTree()
{
// Materials::ModelManager modelManager;
auto tree = ui->treeModels;
auto model = static_cast<QStandardItemModel*>(tree->model());
model->clear();
auto lib = new QStandardItem(QString::fromStdString("Favorites"));
auto lib = new QStandardItem(tr("Favorites"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
addFavorites(lib);
lib = new QStandardItem(QString::fromStdString("Recent"));
lib = new QStandardItem(tr("Recent"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
addRecents(lib);
@@ -347,7 +347,7 @@ void ModelSelect::fillTree()
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib);
auto modelTree = getModelManager().getModelTree(*library, _filter);
auto modelTree = getModelManager().getModelTree(library, _filter);
addModels(*lib, modelTree, QIcon(library->getIconPath()));
}
}
@@ -355,11 +355,11 @@ void ModelSelect::fillTree()
void ModelSelect::setHeaders(QStandardItemModel* model)
{
QStringList headers;
headers.append(QString::fromStdString("Inherited"));
headers.append(QString::fromStdString("Property"));
headers.append(QString::fromStdString("Units"));
headers.append(QString::fromStdString("Description"));
headers.append(QString::fromStdString("URL"));
headers.append(tr("Inherited"));
headers.append(tr("Property"));
headers.append(tr("Units"));
headers.append(tr("Description"));
headers.append(tr("URL"));
model->setHorizontalHeaderLabels(headers);
}
@@ -388,7 +388,7 @@ void ModelSelect::createModelProperties()
// table->setItemDelegate(new MaterialDelegate(this));
}
void ModelSelect::updateModelProperties(const Materials::Model& model)
void ModelSelect::updateModelProperties(std::shared_ptr<Materials::Model> model)
{
QTableView* table = ui->tableProperties;
QStandardItemModel* tableModel = static_cast<QStandardItemModel*>(table->model());
@@ -397,7 +397,7 @@ void ModelSelect::updateModelProperties(const Materials::Model& model)
setHeaders(tableModel);
setColumnWidths(table);
for (auto itp = model.begin(); itp != model.end(); itp++) {
for (auto itp = model->begin(); itp != model->end(); itp++) {
QList<QStandardItem*> items;
QString key = itp->first;
@@ -428,19 +428,19 @@ void ModelSelect::updateModelProperties(const Materials::Model& model)
void ModelSelect::updateMaterialModel(const QString& uuid)
{
Materials::Model model = getModelManager().getModel(uuid);
auto model = getModelManager().getModel(uuid);
// Update the general information
ui->editName->setText(model.getName());
ui->editURL->setText(model.getURL());
ui->editDOI->setText(model.getDOI());
ui->editDescription->setText(model.getDescription());
ui->editName->setText(model->getName());
ui->editURL->setText(model->getURL());
ui->editDOI->setText(model->getDOI());
ui->editDescription->setText(model->getDescription());
if (model.getType() == Materials::Model::ModelType_Physical) {
ui->tabWidget->setTabText(1, QString::fromStdString("Properties"));
if (model->getType() == Materials::Model::ModelType_Physical) {
ui->tabWidget->setTabText(1, tr("Properties"));
}
else {
ui->tabWidget->setTabText(1, QString::fromStdString("Appearance"));
ui->tabWidget->setTabText(1, tr("Appearance"));
}
updateModelProperties(model);
}
@@ -453,7 +453,7 @@ void ModelSelect::clearMaterialModel()
ui->editDOI->setText(QString::fromStdString(""));
ui->editDescription->setText(QString::fromStdString(""));
ui->tabWidget->setTabText(1, QString::fromStdString("Properties"));
ui->tabWidget->setTabText(1, tr("Properties"));
QTableView* table = ui->tableProperties;
QStandardItemModel* tableModel = static_cast<QStandardItemModel*>(table->model());
@@ -467,6 +467,7 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec
{
Q_UNUSED(deselected);
Base::Console().Log("ModelSelect::onSelectModel()\n");
QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeModels->model());
QModelIndexList indexes = selected.indexes();
for (auto it = indexes.begin(); it != indexes.end(); it++) {
@@ -491,6 +492,14 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec
}
}
void ModelSelect::onDoubleClick(const QModelIndex& index)
{
Q_UNUSED(index)
Base::Console().Log("ModelSelect::onDoubleClick()\n");
accept();
}
void ModelSelect::onURL(bool checked)
{
Q_UNUSED(checked)

View File

@@ -22,7 +22,7 @@
#ifndef MATGUI_MODELSELECT_H
#define MATGUI_MODELSELECT_H
#include <boost/filesystem.hpp>
#include <memory>
#include <QDialog>
#include <QDir>
@@ -31,9 +31,7 @@
#include <QTreeView>
#include <Mod/Material/App/Materials.h>
#include <Mod/Material/App/ModelManager.h>
namespace fs = boost::filesystem;
#include <Mod/Material/App/Model.h>
namespace MatGui
{
@@ -45,15 +43,15 @@ class ModelSelect: public QDialog
Q_OBJECT
public:
explicit ModelSelect(
QWidget* parent = nullptr,
Materials::ModelManager::ModelFilter filter = Materials::ModelManager::ModelFilter_None);
ModelSelect(QWidget* parent = nullptr,
Materials::ModelFilter filter = Materials::ModelFilter_None);
~ModelSelect() override;
void onURL(bool checked);
void onDOI(bool checked);
void onFavourite(bool checked);
void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected);
void onDoubleClick(const QModelIndex& index);
const QString& selectedModel() const
{
return _selected;
@@ -77,9 +75,11 @@ private:
void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child);
void addRecents(QStandardItem* parent);
void addFavorites(QStandardItem* parent);
void addModels(QStandardItem& parent,
const std::shared_ptr<std::map<QString, Materials::ModelTreeNode*>> modelTree,
const QIcon& icon);
void
addModels(QStandardItem& parent,
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::ModelTreeNode>>>
modelTree,
const QIcon& icon);
void updateMaterialModel(const QString& uuid);
void clearMaterialModel();
void createModelTree();
@@ -88,14 +88,14 @@ private:
void setHeaders(QStandardItemModel* model);
void setColumnWidths(QTableView* table);
void updateModelProperties(const Materials::Model& model);
void updateModelProperties(std::shared_ptr<Materials::Model> model);
void createModelProperties();
Materials::ModelManager& getModelManager()
{
return _modelManager;
}
Materials::ModelManager::ModelFilter _filter;
Materials::ModelFilter _filter;
std::unique_ptr<Ui_ModelSelect> ui;
Materials::ModelManager _modelManager;
QString _selected;

View File

@@ -55,10 +55,6 @@
// OpenCasCade
// #include <Mod/Part/App/OpenCascadeAll.h>
// Boost
#include <boost/algorithm/string/predicate.hpp>
#include <boost/regex.hpp>
// Qt Toolkit
#ifndef __QtAll__
#include <Gui/QtAll.h>

View File

@@ -22,13 +22,53 @@
#include "PreCompiled.h"
#include <Gui/MenuManager.h>
#include <Gui/ToolBarManager.h>
#include "Workbench.h"
using namespace MatGui;
#if 0 // needed for Qt's lupdate utility
qApp->translate("Workbench", "&Materials");
qApp->translate("Workbench", "Materials");
#endif
/// @namespace MatGui @class Workbench
TYPESYSTEM_SOURCE(MatGui::Workbench, Gui::StdWorkbench)
Workbench::Workbench() = default;
Workbench::~Workbench() = default;
Gui::MenuItem* Workbench::setupMenuBar() const
{
Gui::MenuItem* root = StdWorkbench::setupMenuBar();
Gui::MenuItem* item = root->findItem("&Windows");
Gui::MenuItem* part = new Gui::MenuItem;
root->insertItem(item, part);
part->setCommand("&Materials");
*part << "Materials_Edit";
return root;
}
Gui::ToolBarItem* Workbench::setupToolBars() const
{
Gui::ToolBarItem* root = StdWorkbench::setupToolBars();
Gui::ToolBarItem* solids = new Gui::ToolBarItem(root);
solids->setCommand("Materials");
*solids << "Materials_Edit";
return root;
}
Gui::ToolBarItem* Workbench::setupCommandBars() const
{
// Part tools
Gui::ToolBarItem* root = new Gui::ToolBarItem;
return root;
}

View File

@@ -39,6 +39,11 @@ class MatGuiExport Workbench: public Gui::StdWorkbench
public:
Workbench();
~Workbench() override;
protected:
Gui::MenuItem* setupMenuBar() const override;
Gui::ToolBarItem* setupToolBars() const override;
Gui::ToolBarItem* setupCommandBars() const override;
};
} // namespace MatGui

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "d1f317f0-5ffa-4798-8ab3-af2ff0b5182c"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Aluminum"
Description: "Defines the Aluminum appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "4151e19c-fd6a-4ca4-83d4-d5e17d76cb9c"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Brass"
Description: "Defines the Brass appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "ae194589-02d4-4e9b-98a7-f523f660d510"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Bronze"
Description: "Defines the Bronze appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a9544b88-dde7-4d05-9bdb-c008a4e88dc1"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Chrome"
Description: "Defines the Chrome appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "524cad9b-b841-4037-9851-badeca7dcee2"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Copper"
Description: "Defines the Copper appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Default Appearance"
Description: "Defines the default appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "54def35f-a6bf-472e-8410-dc9fb4b143cf"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Emerald"
Description: "Defines the Emerald appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "85257e2c-be3f-40a1-b03f-0bd4ba58ca08"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Gold"
Description: "Defines the Gold appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "cddfa21f-0715-49dd-b35b-951c076fa52c"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Jade"
Description: "Defines the Jade appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "d149a177-07f1-4e53-9bad-0b5bf0663600"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Metalized"
Description: "Defines the Metalized appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "c0341eef-0897-4fcf-a7f7-eddf1a2600a5"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Neon GNC"
Description: "Defines the Neon GNC appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "add2d6b2-c8fb-4777-a80a-52bae97300ae"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Neon PHC"
Description: "Defines the Neon PHC appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a004c270-7d2c-4898-bec6-b1120edacea9"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Obsidian"
Description: "Defines the Obsidian appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a61853b9-ec9f-403e-9726-0a938731aecd"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Pewter"
Description: "Defines the Pewter appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "569dccb6-c64b-4dd0-9d3c-1b78f40ad1a5"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Plaster"
Description: "Defines the Plaster appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a74622cd-0e2d-4a96-b8c4-fefcc82ac694"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Plastic"
Description: "Defines the Plastic appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "953261a0-cc48-41f8-a3f9-7b20ae3f9b56"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Ruby"
Description: "Defines the Ruby appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "951b54ae-86b6-46d2-b452-60bd6a3ba1bb"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Satin"
Description: "Defines the Satin appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "591c4c4a-22ba-4a9a-869d-e5610107d69a"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Shiny Plastic"
Description: "Defines the Shiny Plastic appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "62839fb0-d854-4b44-92df-b7249213de49"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Silver"
Description: "Defines the Silver appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "4b849c55-6b3a-4f75-a055-40c0d0324596"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Steel"
Description: "Defines the Steel appearance properties"
AppearanceModels:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a9f54d61-cc98-46df-8734-b0543ceb4e45"
AuthorAndLicense: "(c) 2023 David Carter"
Author: "David Carter"
License: "GPL-2.0-or-later"
Name: "Stone"
Description: "Defines the Stone appearance properties"
AppearanceModels:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "94370b96-c97e-4a3f-83b2-11d7461f7da7"
License: "GPL-2.0-or-later"
Name: "Air"
Description: "Dry air properties at 20 Degrees Celsius and 1 atm"
Models:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "e359c5b5-eae2-42b1-9ef6-edde21d706ee"
License: "GPL-2.0-or-later"
Name: "Argon"
Description: "Argon properties at 20 Degrees Celsius and 1 atm"
Models:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "ef0e4040-a498-48c3-a87b-e996bfd89195"
License: "GPL-2.0-or-later"
Name: "Carbon dioxide"
Description: "Carbon dioxide properties at 20 Degrees Celsius and 1 atm"
Models:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "8d02a797-5e0a-4e40-803a-75fc66de8de6"
License: "GPL-2.0-or-later"
Name: "Nitrogen"
Description: "Nitrogen properties at 20 Degrees Celsius and 1 atm"
Models:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "944a8018-09bf-48f6-a7b3-aa8f6a00a310"
License: "GPL-2.0-or-later"
Name: "None"
Description: "None"
Models:

View File

@@ -1,6 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "7e5559d5-be15-4571-a72f-20c39edd41cf"
License: "GPL-2.0-or-later"
Name: "Water"
Description: "Standard distilled water properties at 20 Degrees Celsius and 1 atm"
ReferenceSource: "''"

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "dba76940-a910-4a3b-ab73-a9f412ac69d9"
AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)"
Author: "Bernd Hahnebach"
License: "CC-BY-3.0"
Name: "Concrete-EN-C35/45"
Description: "Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311075)"
Inherits:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "26042aa5-56e6-4d99-8b63-dd8b9ea5a37a"
AuthorAndLicense: "(c) 2013 Yorik van Havre (CC-BY 3.0)"
Author: "Yorik van Havre"
License: "CC-BY-3.0"
Name: "Concrete"
Description: "A standard C-25 construction concrete"
Inherits:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "57507cd4-d22f-4d86-9794-fdb1ec8cd098"
AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)"
Author: "Bernd Hahnebach"
License: "CC-BY-3.0"
Name: "Reinforcement-Harry"
Description: "Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311705)"
Inherits:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "5c67b675-69a2-4782-902a-bb90c3952f07"
AuthorAndLicense: "Uwe Stöhr, LGPL"
Author: "Uwe Stöhr"
License: "LGPL-2.0-or-later"
Name: "Graphite"
Description: "Typical material properties for pure graphite"
ReferenceSource: "Properties and characteristics of graphite"

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "a02bf9d7-6e3e-4e36-881b-10779ee9f706"
AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)"
Author: "DaviKaur"
License: "CC-BY-3.0"
Name: "Glass-E"
Description: "Glass Fibre"
Models:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "3e3a3e13-04a4-410e-8e36-bbd83ca66847"
AuthorAndLicense: "(c) 2015 Przemo Firszt (CC-BY 3.0)"
Author: "Przemo Firszt"
License: "CC-BY-3.0"
Name: "Glass"
Description: "Generic soda-lime glass"
Models:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "0c4943e0-248b-4df9-88d9-3b4dd84dfc68"
AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)"
Author: "DaviKaur"
License: "CC-BY-3.0"
Name: "Glass-S2"
Description: "Glass Fibre"
Models:

View File

@@ -1,7 +1,7 @@
# File created by ConvertFCMat.py
General:
UUID: "27745e16-2a10-4c8e-bd22-59971806909c"
AuthorAndLicense: "Uwe Stöhr"
Author: "Uwe Stöhr"
Name: "Invar Generic"
Models:
Father:

Some files were not shown because too many files have changed in this diff Show More