Merge pull request #11138 from davesrocketshop/material_editor_pr

Material: Material editor enhancements
This commit is contained in:
Chris Hennes
2023-11-01 09:42:43 -05:00
committed by GitHub
220 changed files with 6492 additions and 1613 deletions

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:

View File

@@ -1,7 +1,8 @@
# File created by ConvertFCMat.py
General:
UUID: "0051bddf-6f62-4406-b8c9-569322880564"
AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)"
Author: "M. Münch"
License: "LGPL-2.0-or-later"
Name: "AlMg3F24"
Inherits:
Aluminum:

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