Merge pull request #19908 from davesrocketshop/external_modules_part1_pr2
Materials: External Modules Part 1
This commit is contained in:
@@ -29,15 +29,24 @@
|
||||
|
||||
#include <App/CleanupProcess.h>
|
||||
|
||||
#include "MaterialFilterPy.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MaterialManagerPy.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "MaterialManagerLocal.h"
|
||||
#include "ModelManagerLocal.h"
|
||||
#include "PropertyMaterial.h"
|
||||
|
||||
#include "Array2DPy.h"
|
||||
#include "Array3DPy.h"
|
||||
#include "ModelManagerPy.h"
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "ModelPy.h"
|
||||
#include "UUIDsPy.h"
|
||||
#include "PropertyMaterial.h"
|
||||
|
||||
#include "MaterialFilterPy.h"
|
||||
#include "MaterialFilterOptionsPy.h"
|
||||
#include "MaterialLibraryPy.h"
|
||||
#include "MaterialManagerPy.h"
|
||||
#include "MaterialPropertyPy.h"
|
||||
#include "MaterialPy.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
@@ -74,8 +83,13 @@ PyMOD_INIT_FUNC(Materials)
|
||||
|
||||
Base::Console().Log("Loading Material module... done\n");
|
||||
|
||||
Base::Interpreter().addType(&Materials::MaterialManagerPy::Type, module, "MaterialManager");
|
||||
Base::Interpreter().addType(&Materials::Array2DPy::Type, module, "Array2D");
|
||||
Base::Interpreter().addType(&Materials::Array3DPy::Type, module, "Array3D");
|
||||
Base::Interpreter().addType(&Materials::MaterialFilterPy::Type, module, "MaterialFilter");
|
||||
Base::Interpreter().addType(&Materials::MaterialFilterOptionsPy::Type, module, "MaterialFilterOptions");
|
||||
Base::Interpreter().addType(&Materials::MaterialLibraryPy::Type, module, "MaterialLibrary");
|
||||
Base::Interpreter().addType(&Materials::MaterialManagerPy::Type, module, "MaterialManager");
|
||||
Base::Interpreter().addType(&Materials::MaterialPropertyPy::Type, module, "MaterialProperty");
|
||||
Base::Interpreter().addType(&Materials::MaterialPy::Type, module, "Material");
|
||||
Base::Interpreter().addType(&Materials::ModelManagerPy::Type, module, "ModelManager");
|
||||
Base::Interpreter().addType(&Materials::ModelPropertyPy::Type, module, "ModelProperty");
|
||||
@@ -88,22 +102,25 @@ PyMOD_INIT_FUNC(Materials)
|
||||
|
||||
Materials::Material ::init();
|
||||
Materials::MaterialFilter ::init();
|
||||
Materials::MaterialFilterOptions ::init();
|
||||
Materials::MaterialManager ::init();
|
||||
Materials::MaterialManagerLocal ::init();
|
||||
Materials::Model ::init();
|
||||
Materials::ModelManager ::init();
|
||||
Materials::ModelManagerLocal ::init();
|
||||
Materials::ModelUUIDs ::init();
|
||||
|
||||
Materials::LibraryBase ::init();
|
||||
Materials::Library ::init();
|
||||
Materials::MaterialLibrary ::init();
|
||||
Materials::MaterialLibraryLocal ::init();
|
||||
Materials::ModelLibrary ::init();
|
||||
Materials::MaterialExternalLibrary ::init();
|
||||
|
||||
Materials::ModelProperty ::init();
|
||||
Materials::MaterialProperty ::init();
|
||||
|
||||
Materials::MaterialValue ::init();
|
||||
Materials::Material2DArray ::init();
|
||||
Materials::Material3DArray ::init();
|
||||
Materials::Array2D ::init();
|
||||
Materials::Array3D ::init();
|
||||
|
||||
Materials::PropertyMaterial ::init();
|
||||
// clang-format on
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="Array2DPy"
|
||||
Twin="Material2DArray"
|
||||
TwinPointer="Material2DArray"
|
||||
Twin="Array2D"
|
||||
TwinPointer="Array2D"
|
||||
Include="Mod/Material/App/MaterialValue.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
@@ -21,13 +21,19 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Array" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Rows" ReadOnly="true">
|
||||
<Attribute Name="Dimensions" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The number of dimensions in the array, in this case 2.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Dimensions" Type="Int"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Rows" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The number of rows in the array.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Rows" Type="Long"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Columns" ReadOnly="true">
|
||||
<Attribute Name="Columns" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The number of columns in the array.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -43,5 +49,10 @@
|
||||
<UserDocu>Get the value at the given row and column</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the value at the given row and column</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -44,7 +44,7 @@ using namespace Materials;
|
||||
std::string Array2DPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<Array2D object at " << getMaterial2DArrayPtr() << ">";
|
||||
str << "<Array2D object at " << getArray2DPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
@@ -52,7 +52,7 @@ std::string Array2DPy::representation() const
|
||||
PyObject* Array2DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new Array2DPy(new Material2DArray());
|
||||
return new Array2DPy(new Array2D());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
@@ -65,7 +65,7 @@ Py::List Array2DPy::getArray() const
|
||||
{
|
||||
Py::List list;
|
||||
|
||||
auto array = getMaterial2DArrayPtr()->getArray();
|
||||
auto array = getArray2DPtr()->getArray();
|
||||
|
||||
for (auto& row : array) {
|
||||
Py::List rowList;
|
||||
@@ -81,14 +81,29 @@ Py::List Array2DPy::getArray() const
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Long Array2DPy::getDimensions() const
|
||||
{
|
||||
return Py::Long(2);
|
||||
}
|
||||
|
||||
Py::Long Array2DPy::getRows() const
|
||||
{
|
||||
return Py::Long(getMaterial2DArrayPtr()->rows());
|
||||
return Py::Long(getArray2DPtr()->rows());
|
||||
}
|
||||
|
||||
void Array2DPy::setRows(Py::Long arg)
|
||||
{
|
||||
getArray2DPtr()->setRows(arg);
|
||||
}
|
||||
|
||||
Py::Long Array2DPy::getColumns() const
|
||||
{
|
||||
return Py::Long(getMaterial2DArrayPtr()->columns());
|
||||
return Py::Long(getArray2DPtr()->columns());
|
||||
}
|
||||
|
||||
void Array2DPy::setColumns(Py::Long arg)
|
||||
{
|
||||
getArray2DPtr()->setColumns(arg);
|
||||
}
|
||||
|
||||
PyObject* Array2DPy::getRow(PyObject* args)
|
||||
@@ -101,7 +116,7 @@ PyObject* Array2DPy::getRow(PyObject* args)
|
||||
try {
|
||||
Py::List list;
|
||||
|
||||
auto arrayRow = getMaterial2DArrayPtr()->getRow(row);
|
||||
auto arrayRow = getArray2DPtr()->getRow(row);
|
||||
for (auto& column : *arrayRow) {
|
||||
auto quantity =
|
||||
new Base::QuantityPy(new Base::Quantity(column.value<Base::Quantity>()));
|
||||
@@ -126,7 +141,7 @@ PyObject* Array2DPy::getValue(PyObject* args)
|
||||
}
|
||||
|
||||
try {
|
||||
auto value = getMaterial2DArrayPtr()->getValue(row, column);
|
||||
auto value = getArray2DPtr()->getValue(row, column);
|
||||
return new Base::QuantityPy(new Base::Quantity(value.value<Base::Quantity>()));
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
@@ -136,6 +151,28 @@ PyObject* Array2DPy::getValue(PyObject* args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* Array2DPy::setValue(PyObject* args)
|
||||
{
|
||||
int row;
|
||||
int column;
|
||||
PyObject* valueObj;
|
||||
if (PyArg_ParseTuple(args, "iiO!", &row, &column, &PyUnicode_Type, &valueObj)) {
|
||||
Py::String item(valueObj);
|
||||
try {
|
||||
QVariant variant = QVariant::fromValue(Base::Quantity::parse(item.as_string()));
|
||||
getArray2DPtr()->setValue(row, column, variant);
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
PyErr_SetString(PyExc_IndexError, "Invalid array index");
|
||||
return nullptr;
|
||||
}
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Expected (integer, integer, string) arguments");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* Array2DPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="Array3DPy"
|
||||
Twin="Material3DArray"
|
||||
TwinPointer="Material3DArray"
|
||||
Twin="Array3D"
|
||||
TwinPointer="Array3D"
|
||||
Include="Mod/Material/App/MaterialValue.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
@@ -21,17 +21,23 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Array" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Columns" ReadOnly="true">
|
||||
<Attribute Name="Dimensions" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The number of dimensions in the array, in this case 3.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Dimensions" Type="Int"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Columns" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The number of columns in the array.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Columns" Type="Long"/>
|
||||
<Parameter Name="Columns" Type="Int"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Depth" ReadOnly="true">
|
||||
<Attribute Name="Depth" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>The depth of the array (3rd dimension).</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Columns" Type="Long"/>
|
||||
<Parameter Name="Depth" Type="Int"/>
|
||||
</Attribute>
|
||||
<Methode Name="getRows" ReadOnly="true">
|
||||
<Documentation>
|
||||
@@ -48,5 +54,20 @@
|
||||
<UserDocu>Get the column value at the given depth</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setDepthValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the column value at the given depth</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the value at the given depth, row, and column</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setRows" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the number of rows at the given depth</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -44,7 +44,7 @@ using namespace Materials;
|
||||
std::string Array3DPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<Array3D object at " << getMaterial3DArrayPtr() << ">";
|
||||
str << "<Array3D object at " << getArray3DPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
@@ -52,7 +52,7 @@ std::string Array3DPy::representation() const
|
||||
PyObject* Array3DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new Array3DPy(new Material3DArray());
|
||||
return new Array3DPy(new Array3D());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
@@ -64,7 +64,7 @@ int Array3DPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
Py::List Array3DPy::getArray() const
|
||||
{
|
||||
Py::List list;
|
||||
auto array = getMaterial3DArrayPtr()->getArray();
|
||||
auto array = getArray3DPtr()->getArray();
|
||||
|
||||
for (auto& depth : array) {
|
||||
Py::List depthList;
|
||||
@@ -83,24 +83,39 @@ Py::List Array3DPy::getArray() const
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Long Array3DPy::getDimensions() const
|
||||
{
|
||||
return Py::Long(3);
|
||||
}
|
||||
|
||||
Py::Long Array3DPy::getColumns() const
|
||||
{
|
||||
return Py::Long(getMaterial3DArrayPtr()->columns());
|
||||
return Py::Long(getArray3DPtr()->columns());
|
||||
}
|
||||
|
||||
void Array3DPy::setColumns(Py::Long arg)
|
||||
{
|
||||
getArray3DPtr()->setColumns(arg);
|
||||
}
|
||||
|
||||
Py::Long Array3DPy::getDepth() const
|
||||
{
|
||||
return Py::Long(getMaterial3DArrayPtr()->depth());
|
||||
return Py::Long(getArray3DPtr()->depth());
|
||||
}
|
||||
|
||||
void Array3DPy::setDepth(Py::Long arg)
|
||||
{
|
||||
getArray3DPtr()->setDepth(arg);
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::getRows(PyObject* args)
|
||||
{
|
||||
int depth = getMaterial3DArrayPtr()->currentDepth();
|
||||
int depth = getArray3DPtr()->currentDepth();
|
||||
if (!PyArg_ParseTuple(args, "|i", &depth)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return PyLong_FromLong(getMaterial3DArrayPtr()->rows(depth));
|
||||
return PyLong_FromLong(getArray3DPtr()->rows(depth));
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::getValue(PyObject* args)
|
||||
@@ -113,7 +128,7 @@ PyObject* Array3DPy::getValue(PyObject* args)
|
||||
}
|
||||
|
||||
try {
|
||||
auto value = getMaterial3DArrayPtr()->getValue(depth, row, column);
|
||||
auto value = getArray3DPtr()->getValue(depth, row, column);
|
||||
return new Base::QuantityPy(new Base::Quantity(value));
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
@@ -131,7 +146,7 @@ PyObject* Array3DPy::getDepthValue(PyObject* args)
|
||||
}
|
||||
|
||||
try {
|
||||
auto value = getMaterial3DArrayPtr()->getDepthValue(depth);
|
||||
auto value = getArray3DPtr()->getDepthValue(depth);
|
||||
return new Base::QuantityPy(new Base::Quantity(value));
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
@@ -141,6 +156,60 @@ PyObject* Array3DPy::getDepthValue(PyObject* args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::setDepthValue(PyObject* args)
|
||||
{
|
||||
int depth;
|
||||
PyObject* valueObj;
|
||||
if (PyArg_ParseTuple(args, "iO!", &depth, &PyUnicode_Type, &valueObj)) {
|
||||
Py::String item(valueObj);
|
||||
try {
|
||||
getArray3DPtr()->setDepthValue(depth, Base::Quantity::parse(item.as_string()));
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
PyErr_SetString(PyExc_IndexError, "Invalid array index");
|
||||
return nullptr;
|
||||
}
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Expected (integer, string) arguments");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::setValue(PyObject* args)
|
||||
{
|
||||
int depth;
|
||||
int row;
|
||||
int column;
|
||||
PyObject* valueObj;
|
||||
if (PyArg_ParseTuple(args, "iiiO!", &depth, &row, &column, &PyUnicode_Type, &valueObj)) {
|
||||
Py::String item(valueObj);
|
||||
try {
|
||||
getArray3DPtr()->setValue(depth, row, column, Base::Quantity::parse(item.as_string()));
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
PyErr_SetString(PyExc_IndexError, "Invalid array index");
|
||||
return nullptr;
|
||||
}
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Expected (integer, integer, integer, string) arguments");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::setRows(PyObject* args)
|
||||
{
|
||||
int depth;
|
||||
int rows;
|
||||
if (!PyArg_ParseTuple(args, "ii", &depth, &rows)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getArray3DPtr()->setRows(depth, rows);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* Array3DPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -45,10 +45,13 @@ endif()
|
||||
generate_from_xml(Array2DPy)
|
||||
generate_from_xml(Array3DPy)
|
||||
generate_from_xml(MaterialFilterPy)
|
||||
generate_from_xml(MaterialFilterOptionsPy)
|
||||
generate_from_xml(MaterialLibraryPy)
|
||||
generate_from_xml(MaterialManagerPy)
|
||||
generate_from_xml(MaterialPy)
|
||||
generate_from_xml(ModelManagerPy)
|
||||
generate_from_xml(ModelPropertyPy)
|
||||
generate_from_xml(MaterialPropertyPy)
|
||||
generate_from_xml(ModelPy)
|
||||
generate_from_xml(UUIDsPy)
|
||||
|
||||
@@ -58,12 +61,18 @@ SET(Python_SRCS
|
||||
Array2DPyImp.cpp
|
||||
Array3DPy.xml
|
||||
Array3DPyImp.cpp
|
||||
MaterialManagerPy.xml
|
||||
MaterialManagerPyImp.cpp
|
||||
MaterialPy.xml
|
||||
MaterialPyImp.cpp
|
||||
MaterialFilterOptionsPy.xml
|
||||
MaterialFilterOptionsPyImp.cpp
|
||||
MaterialFilterPy.xml
|
||||
MaterialFilterPyImp.cpp
|
||||
MaterialLibraryPy.xml
|
||||
MaterialLibraryPyImp.cpp
|
||||
MaterialManagerPy.xml
|
||||
MaterialManagerPyImp.cpp
|
||||
MaterialPropertyPy.xml
|
||||
MaterialPropertyPyImp.cpp
|
||||
MaterialPy.xml
|
||||
MaterialPyImp.cpp
|
||||
ModelManagerPy.xml
|
||||
ModelManagerPyImp.cpp
|
||||
ModelPropertyPy.xml
|
||||
@@ -79,6 +88,8 @@ SET(Materials_SRCS
|
||||
${Python_SRCS}
|
||||
AppMaterial.cpp
|
||||
FolderTree.h
|
||||
Library.cpp
|
||||
Library.h
|
||||
MaterialConfigLoader.cpp
|
||||
MaterialConfigLoader.h
|
||||
MaterialFilter.cpp
|
||||
@@ -89,6 +100,8 @@ SET(Materials_SRCS
|
||||
MaterialLoader.h
|
||||
MaterialManager.cpp
|
||||
MaterialManager.h
|
||||
MaterialManagerLocal.cpp
|
||||
MaterialManagerLocal.h
|
||||
Materials.cpp
|
||||
Materials.h
|
||||
MaterialValue.cpp
|
||||
@@ -101,12 +114,16 @@ SET(Materials_SRCS
|
||||
ModelLoader.h
|
||||
ModelManager.cpp
|
||||
ModelManager.h
|
||||
ModelManagerLocal.cpp
|
||||
ModelManagerLocal.h
|
||||
ModelUuids.cpp
|
||||
ModelUuids.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
PropertyMaterial.cpp
|
||||
PropertyMaterial.h
|
||||
PyVariants.cpp
|
||||
PyVariants.h
|
||||
trim.h
|
||||
)
|
||||
|
||||
|
||||
@@ -34,15 +34,14 @@ class Uninitialized: public Base::Exception
|
||||
{
|
||||
public:
|
||||
Uninitialized()
|
||||
: Base::Exception("Uninitalized")
|
||||
{}
|
||||
explicit Uninitialized(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit Uninitialized(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~Uninitialized() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -50,17 +49,14 @@ class ModelNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
ModelNotFound()
|
||||
{
|
||||
this->setMessage("Model not found");
|
||||
}
|
||||
: Base::Exception("Model not found")
|
||||
{}
|
||||
explicit ModelNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit ModelNotFound(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~ModelNotFound() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -68,15 +64,14 @@ class InvalidMaterialType: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidMaterialType()
|
||||
: Base::Exception("Invalid material type")
|
||||
{}
|
||||
explicit InvalidMaterialType(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidMaterialType(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidMaterialType() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -84,17 +79,14 @@ class MaterialNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
MaterialNotFound()
|
||||
{
|
||||
this->setMessage("Material not found");
|
||||
}
|
||||
: Base::Exception("Material not found")
|
||||
{}
|
||||
explicit MaterialNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit MaterialNotFound(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~MaterialNotFound() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -102,15 +94,14 @@ class MaterialExists: public Base::Exception
|
||||
{
|
||||
public:
|
||||
MaterialExists()
|
||||
: Base::Exception("Material already exists")
|
||||
{}
|
||||
explicit MaterialExists(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit MaterialExists(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~MaterialExists() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -118,15 +109,14 @@ class MaterialReadError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
MaterialReadError()
|
||||
: Base::Exception("Unable to read material")
|
||||
{}
|
||||
explicit MaterialReadError(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit MaterialReadError(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~MaterialReadError() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -134,17 +124,14 @@ class PropertyNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
PropertyNotFound()
|
||||
{
|
||||
this->setMessage("Property not found");
|
||||
}
|
||||
: Base::Exception("Property not found")
|
||||
{}
|
||||
explicit PropertyNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit PropertyNotFound(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~PropertyNotFound() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -152,53 +139,104 @@ class LibraryNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
LibraryNotFound()
|
||||
{
|
||||
this->setMessage("Library not found");
|
||||
}
|
||||
: Base::Exception("Library not found")
|
||||
{}
|
||||
explicit LibraryNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit LibraryNotFound(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~LibraryNotFound() noexcept override = default;
|
||||
};
|
||||
|
||||
class CreationError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
CreationError()
|
||||
: Base::Exception("Unable to create object")
|
||||
{}
|
||||
explicit CreationError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit CreationError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~CreationError() noexcept override = default;
|
||||
};
|
||||
|
||||
class InvalidModel: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidModel()
|
||||
{
|
||||
this->setMessage("Invalid model");
|
||||
}
|
||||
: Base::Exception("Invalid model")
|
||||
{}
|
||||
explicit InvalidModel(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidModel(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidModel() noexcept override = default;
|
||||
};
|
||||
|
||||
class InvalidMaterial: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidMaterial()
|
||||
: Base::Exception("Invalid material")
|
||||
{}
|
||||
explicit InvalidMaterial(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidMaterial(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidMaterial() noexcept override = default;
|
||||
};
|
||||
|
||||
class InvalidProperty: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidProperty()
|
||||
: Base::Exception("Invalid property")
|
||||
{}
|
||||
explicit InvalidProperty(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidProperty(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidProperty() noexcept override = default;
|
||||
};
|
||||
|
||||
class InvalidLibrary: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidLibrary()
|
||||
: Base::Exception("Invalid library")
|
||||
{}
|
||||
explicit InvalidLibrary(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidLibrary(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidLibrary() noexcept override = default;
|
||||
};
|
||||
|
||||
class InvalidIndex: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidIndex()
|
||||
{
|
||||
this->setMessage("Invalid index");
|
||||
}
|
||||
explicit InvalidIndex(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
: Base::Exception("Invalid index")
|
||||
{}
|
||||
explicit InvalidIndex(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit InvalidIndex(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~InvalidIndex() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -206,15 +244,14 @@ class UnknownValueType: public Base::Exception
|
||||
{
|
||||
public:
|
||||
UnknownValueType()
|
||||
: Base::Exception("Unkown value type")
|
||||
{}
|
||||
explicit UnknownValueType(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit UnknownValueType(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
explicit UnknownValueType(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~UnknownValueType() noexcept override = default;
|
||||
};
|
||||
|
||||
@@ -222,18 +259,62 @@ class DeleteError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
DeleteError()
|
||||
: Base::Exception("Unable to delete object")
|
||||
{}
|
||||
explicit DeleteError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit DeleteError(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
explicit DeleteError(const QString& msg)
|
||||
{
|
||||
this->setMessage(msg.toStdString().c_str());
|
||||
}
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~DeleteError() noexcept override = default;
|
||||
};
|
||||
|
||||
class RenameError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
RenameError()
|
||||
: Base::Exception("Unable to rename object")
|
||||
{}
|
||||
explicit RenameError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit RenameError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~RenameError() noexcept override = default;
|
||||
};
|
||||
|
||||
class ReplacementError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
ReplacementError()
|
||||
: Base::Exception("Unable to replace object")
|
||||
{}
|
||||
explicit ReplacementError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit ReplacementError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~ReplacementError() noexcept override = default;
|
||||
};
|
||||
|
||||
class ConnectionError: public Base::Exception
|
||||
{
|
||||
public:
|
||||
ConnectionError()
|
||||
: Base::Exception("Unable to connect")
|
||||
{}
|
||||
explicit ConnectionError(const char* msg)
|
||||
: Base::Exception(msg)
|
||||
{}
|
||||
explicit ConnectionError(const QString& msg)
|
||||
: Base::Exception(msg.toStdString().c_str())
|
||||
{}
|
||||
~ConnectionError() noexcept override = default;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_EXCEPTIONS_H
|
||||
|
||||
@@ -34,18 +34,21 @@ template<class T>
|
||||
class FolderTreeNode
|
||||
{
|
||||
public:
|
||||
enum NodeType
|
||||
enum class NodeType
|
||||
{
|
||||
UnknownNode,
|
||||
DataNode,
|
||||
FolderNode
|
||||
};
|
||||
|
||||
FolderTreeNode()
|
||||
: _type(NodeType::UnknownNode)
|
||||
{}
|
||||
virtual ~FolderTreeNode() = default;
|
||||
|
||||
NodeType getType() const
|
||||
{
|
||||
// assert(_type == NodeType::DataNode || _type == NodeType::FolderNode);
|
||||
return _type;
|
||||
}
|
||||
void setType(NodeType type)
|
||||
@@ -53,33 +56,47 @@ public:
|
||||
_type = type;
|
||||
}
|
||||
|
||||
const std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> getFolder() const
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> getFolder() const
|
||||
{
|
||||
assert(_type == NodeType::FolderNode);
|
||||
return _folder;
|
||||
}
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> getFolder()
|
||||
{
|
||||
assert(_type == NodeType::FolderNode);
|
||||
return _folder;
|
||||
}
|
||||
std::shared_ptr<T> getData() const
|
||||
{
|
||||
assert(_type == NodeType::DataNode);
|
||||
return _data;
|
||||
}
|
||||
QString getUUID() const
|
||||
{
|
||||
assert(_type == NodeType::DataNode);
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
void setFolder(std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> folder)
|
||||
{
|
||||
setType(FolderNode);
|
||||
setType(NodeType::FolderNode);
|
||||
_folder = folder;
|
||||
}
|
||||
void setData(std::shared_ptr<T> data)
|
||||
{
|
||||
setType(DataNode);
|
||||
setType(NodeType::DataNode);
|
||||
_data = data;
|
||||
}
|
||||
void setUUID(const QString& uuid)
|
||||
{
|
||||
setType(NodeType::DataNode);
|
||||
_uuid = uuid;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeType _type;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<FolderTreeNode<T>>>> _folder;
|
||||
QString _uuid;
|
||||
std::shared_ptr<T> _data;
|
||||
};
|
||||
|
||||
|
||||
141
src/Mod/Material/App/Library.cpp
Normal file
141
src/Mod/Material/App/Library.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "Library.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Library, Base::BaseClass)
|
||||
|
||||
Library::Library(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
: _name(libraryName)
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
{}
|
||||
|
||||
Library::Library(const QString& libraryName, const QString& dir, const QString& icon, bool readOnly)
|
||||
: _name(libraryName)
|
||||
, _directory(QDir::cleanPath(dir))
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
{}
|
||||
|
||||
bool Library::operator==(const Library& library) const
|
||||
{
|
||||
return (getName() == library.getName()) && (_directory == library._directory);
|
||||
}
|
||||
|
||||
void Library::validate(const Library& remote) const
|
||||
{
|
||||
if (getName() != remote.getName()) {
|
||||
throw InvalidLibrary("Library names don't match");
|
||||
}
|
||||
if (getIconPath() != remote.getIconPath()) {
|
||||
Base::Console().Log("Icon path 1 '%s'\n", getIconPath().toStdString().c_str());
|
||||
Base::Console().Log("Icon path 2 '%s'\n", remote.getIconPath().toStdString().c_str());
|
||||
throw InvalidLibrary("Library icon paths don't match");
|
||||
}
|
||||
|
||||
// Local and remote paths will differ
|
||||
if (!remote.getDirectory().isEmpty()) {
|
||||
throw InvalidLibrary("Remote library should not have a path");
|
||||
}
|
||||
|
||||
if (isReadOnly() != remote.isReadOnly()) {
|
||||
throw InvalidLibrary("Library readonly settings don't match");
|
||||
}
|
||||
}
|
||||
|
||||
QString Library::getLocalPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getDirectoryPath();
|
||||
if (!(filePath.endsWith(QStringLiteral("/")) || filePath.endsWith(QStringLiteral("\\")))) {
|
||||
filePath += QStringLiteral("/");
|
||||
}
|
||||
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QStringLiteral("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath += cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath += cleanPath;
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
bool Library::isRoot(const QString& path) const
|
||||
{
|
||||
QString localPath = getLocalPath(path);
|
||||
QString cleanPath = getLocalPath(QStringLiteral(""));
|
||||
return (cleanPath == localPath);
|
||||
}
|
||||
|
||||
QString Library::getRelativePath(const QString& path) const
|
||||
{
|
||||
QString filePath;
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QStringLiteral("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath = cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath = cleanPath;
|
||||
}
|
||||
|
||||
prefix = getDirectoryPath();
|
||||
if (filePath.startsWith(prefix)) {
|
||||
// Remove the library root from the path
|
||||
filePath = filePath.right(filePath.length() - prefix.length());
|
||||
}
|
||||
|
||||
// Remove any leading '/'
|
||||
if (filePath.startsWith(QStringLiteral("/"))) {
|
||||
filePath.remove(0, 1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
QString Library::getLibraryPath(const QString& path, const QString& filename) const
|
||||
{
|
||||
QString filePath(path);
|
||||
if (filePath.endsWith(filename)) {
|
||||
filePath = filePath.left(filePath.length() - filename.length());
|
||||
}
|
||||
if (filePath.endsWith(QStringLiteral("/"))) {
|
||||
filePath = filePath.left(filePath.length() - 1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
114
src/Mod/Material/App/Library.h
Normal file
114
src/Mod/Material/App/Library.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_LIBRARY_H
|
||||
#define MATERIAL_LIBRARY_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialsExport Library: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
Library() = default;
|
||||
Library(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
Library(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
~Library() override = default;
|
||||
|
||||
QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
void setName(const QString& newName)
|
||||
{
|
||||
_name = newName;
|
||||
}
|
||||
bool sameName(const QString& name)
|
||||
{
|
||||
return (_name == name);
|
||||
}
|
||||
|
||||
QString getIconPath() const
|
||||
{
|
||||
return _iconPath;
|
||||
}
|
||||
void setIconPath(const QString& icon)
|
||||
{
|
||||
_iconPath = icon;
|
||||
}
|
||||
bool isReadOnly() const
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
void setReadOnly(bool readOnly)
|
||||
{
|
||||
_readOnly = readOnly;
|
||||
}
|
||||
|
||||
QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
void setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
QString getDirectoryPath() const
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
|
||||
bool operator==(const Library& library) const;
|
||||
bool operator!=(const Library& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
|
||||
QString getLocalPath(const QString& path) const;
|
||||
QString getRelativePath(const QString& path) const;
|
||||
QString getLibraryPath(const QString& path, const QString& filename) const;
|
||||
bool isRoot(const QString& path) const;
|
||||
|
||||
// Validate a remote library against this one (a local library)
|
||||
void validate(const Library& remote) const;
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _iconPath;
|
||||
bool _readOnly;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_LIBRARY_H
|
||||
@@ -1022,7 +1022,7 @@ void MaterialConfigLoader::addLegacy(const QMap<QString, QString>& fcmat,
|
||||
{
|
||||
for (auto const& legacy : fcmat.keys()) {
|
||||
auto name = legacy;
|
||||
int last = name.lastIndexOf(QLatin1String("/"));
|
||||
int last = name.lastIndexOf(QStringLiteral("/"));
|
||||
if (last > 0) {
|
||||
name = name.mid(last + 1);
|
||||
}
|
||||
@@ -1034,7 +1034,7 @@ void MaterialConfigLoader::addLegacy(const QMap<QString, QString>& fcmat,
|
||||
}
|
||||
|
||||
std::shared_ptr<Material>
|
||||
MaterialConfigLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialConfigLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& path)
|
||||
{
|
||||
QString author = getAuthorAndLicense(path); // Place them both in the author field
|
||||
@@ -1056,7 +1056,10 @@ MaterialConfigLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibrary>
|
||||
QString sourceReference = value(fcmat, "ReferenceSource", "");
|
||||
QString sourceURL = value(fcmat, "SourceURL", "");
|
||||
|
||||
std::shared_ptr<Material> finalModel = std::make_shared<Material>(library, path, uuid, name);
|
||||
auto baseLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibrary>&>(library);
|
||||
std::shared_ptr<Material> finalModel =
|
||||
std::make_shared<Material>(baseLibrary, path, uuid, name);
|
||||
finalModel->setOldFormat(true);
|
||||
|
||||
finalModel->setAuthor(author);
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialLibraryLocal;
|
||||
|
||||
class MaterialConfigLoader
|
||||
{
|
||||
public:
|
||||
@@ -45,7 +47,7 @@ public:
|
||||
|
||||
static bool isConfigStyle(const QString& path);
|
||||
static std::shared_ptr<Material>
|
||||
getMaterialFromPath(const std::shared_ptr<MaterialLibrary>& library, const QString& path);
|
||||
getMaterialFromPath(const std::shared_ptr<MaterialLibraryLocal>& library, const QString& path);
|
||||
|
||||
private:
|
||||
static QString value(const QMap<QString, QString>& fcmat,
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialFilterOptions, Base::BaseClass)
|
||||
|
||||
MaterialFilterOptions::MaterialFilterOptions()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
@@ -94,9 +96,8 @@ bool MaterialFilter::modelIncluded(const std::shared_ptr<Material>& material) co
|
||||
|
||||
bool MaterialFilter::modelIncluded(const QString& uuid) const
|
||||
{
|
||||
MaterialManager manager;
|
||||
try {
|
||||
auto material = manager.getMaterial(uuid);
|
||||
auto material = MaterialManager::getManager().getMaterial(uuid);
|
||||
return modelIncluded(material);
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
|
||||
@@ -41,8 +41,9 @@ class Material;
|
||||
* This class is used to set options for a material tree search
|
||||
*
|
||||
*/
|
||||
class MaterialsExport MaterialFilterOptions
|
||||
class MaterialsExport MaterialFilterOptions: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialFilterOptions();
|
||||
|
||||
49
src/Mod/Material/App/MaterialFilterOptionsPy.xml
Normal file
49
src/Mod/Material/App/MaterialFilterOptionsPy.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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="MaterialFilterOptionsPy"
|
||||
Twin="MaterialFilterOptions"
|
||||
TwinPointer="MaterialFilterOptions"
|
||||
Include="Mod/Material/App/MaterialFilter.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material filtering options.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="IncludeFavorites" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include materials marked as favorite.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeFavorites" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="IncludeRecent" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include recently used materials.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeRecent" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="IncludeEmptyFolders" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include empty folders.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeEmptyFolders" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="IncludeEmptyLibraries" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include empty libraries.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeEmptyLibraries" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="IncludeLegacy" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Include materials using the older legacy format.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="IncludeLegacy" Type="Boolean"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
122
src/Mod/Material/App/MaterialFilterOptionsPyImp.cpp
Normal file
122
src/Mod/Material/App/MaterialFilterOptionsPyImp.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023-2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "MaterialFilter.h"
|
||||
|
||||
#include "MaterialFilterOptionsPy.h"
|
||||
|
||||
#include "MaterialFilterOptionsPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// Forward declaration
|
||||
// static PyObject* _pyObjectFromVariant(const QVariant& value);
|
||||
// static Py::List getList(const QVariant& value);
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialFilterOptionsPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<MaterialFilterOptions object at " << getMaterialFilterOptionsPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialFilterOptionsPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialFilterOptionsPy(new MaterialFilterOptions());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialFilterOptionsPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterOptionsPy::getIncludeFavorites() const
|
||||
{
|
||||
return getMaterialFilterOptionsPtr()->includeFavorites();
|
||||
}
|
||||
|
||||
void MaterialFilterOptionsPy::setIncludeFavorites(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterOptionsPtr()->setIncludeFavorites(value);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterOptionsPy::getIncludeRecent() const
|
||||
{
|
||||
return getMaterialFilterOptionsPtr()->includeRecent();
|
||||
}
|
||||
|
||||
void MaterialFilterOptionsPy::setIncludeRecent(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterOptionsPtr()->setIncludeRecent(value);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterOptionsPy::getIncludeEmptyFolders() const
|
||||
{
|
||||
return getMaterialFilterOptionsPtr()->includeEmptyFolders();
|
||||
}
|
||||
|
||||
void MaterialFilterOptionsPy::setIncludeEmptyFolders(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterOptionsPtr()->setIncludeEmptyFolders(value);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterOptionsPy::getIncludeEmptyLibraries() const
|
||||
{
|
||||
return getMaterialFilterOptionsPtr()->includeEmptyLibraries();
|
||||
}
|
||||
|
||||
void MaterialFilterOptionsPy::setIncludeEmptyLibraries(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterOptionsPtr()->setIncludeEmptyLibraries(value);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialFilterOptionsPy::getIncludeLegacy() const
|
||||
{
|
||||
return getMaterialFilterOptionsPtr()->includeLegacy();
|
||||
}
|
||||
|
||||
void MaterialFilterOptionsPy::setIncludeLegacy(const Py::Boolean value)
|
||||
{
|
||||
getMaterialFilterOptionsPtr()->setIncludeLegacy(value);
|
||||
}
|
||||
|
||||
PyObject* MaterialFilterOptionsPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialFilterOptionsPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -41,18 +41,121 @@ using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialLibrary, Materials::LibraryBase)
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialLibrary, Base::BaseClass)
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
: Library(libraryName, icon, readOnly)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: LibraryBase(libraryName, dir, icon)
|
||||
, _readOnly(readOnly)
|
||||
, _materialPathMap(std::make_unique<std::map<QString, std::shared_ptr<Material>>>())
|
||||
: Library(libraryName, dir, icon, readOnly)
|
||||
, _local(false)
|
||||
{}
|
||||
|
||||
void MaterialLibrary::createFolder(const QString& path)
|
||||
bool MaterialLibrary::isLocal() const
|
||||
{
|
||||
return _local;
|
||||
}
|
||||
|
||||
void MaterialLibrary::setLocal(bool local)
|
||||
{
|
||||
_local = local;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const
|
||||
{
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> materialTree =
|
||||
std::make_shared<std::map<QString, std::shared_ptr<MaterialTreeNode>>>();
|
||||
|
||||
auto materials = MaterialManager::getManager().libraryMaterials(getName(), filter, options);
|
||||
for (auto& it : *materials) {
|
||||
auto uuid = std::get<0>(it);
|
||||
auto path = std::get<1>(it);
|
||||
auto filename = std::get<2>(it);
|
||||
|
||||
QStringList list = path.split(QStringLiteral("/"));
|
||||
|
||||
// Start at the root
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> node =
|
||||
materialTree;
|
||||
for (auto& itp : list) {
|
||||
if (!itp.isEmpty()) {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::shared_ptr<MaterialTreeNode> child = std::make_shared<MaterialTreeNode>();
|
||||
child->setUUID(uuid);
|
||||
(*node)[filename] = child;
|
||||
}
|
||||
|
||||
// // Empty folders aren't included in _materialPathMap, so we add them by looking at the file
|
||||
// // system
|
||||
// if (!filter || options.includeEmptyFolders()) {
|
||||
// if (isLocal()) {
|
||||
// auto& materialLibrary =
|
||||
// *(reinterpret_cast<const Materials::MaterialLibraryLocal*>(this));
|
||||
// auto folderList = MaterialLoader::getMaterialFolders(materialLibrary);
|
||||
// for (auto& folder : *folderList) {
|
||||
// QStringList list = folder.split(QStringLiteral("/"));
|
||||
|
||||
// // Start at the root
|
||||
// auto node = materialTree;
|
||||
// for (auto& itp : list) {
|
||||
// // 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;
|
||||
}
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialLibraryLocal, Materials::MaterialLibrary)
|
||||
|
||||
MaterialLibraryLocal::MaterialLibraryLocal(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: MaterialLibrary(libraryName, dir, icon, readOnly)
|
||||
, _materialPathMap(std::make_unique<std::map<QString, std::shared_ptr<Material>>>())
|
||||
{
|
||||
setLocal(true);
|
||||
}
|
||||
|
||||
void MaterialLibraryLocal::createFolder(const QString& path)
|
||||
{
|
||||
QString filePath = getLocalPath(path);
|
||||
|
||||
@@ -65,8 +168,42 @@ void MaterialLibrary::createFolder(const QString& path)
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLibraryLocal::renameFolder(const QString& oldPath, const QString& newPath)
|
||||
{
|
||||
QString filePath = getLocalPath(oldPath);
|
||||
QString newFilePath = getLocalPath(newPath);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void MaterialLibraryLocal::deleteRecursive(const QString& path)
|
||||
{
|
||||
if (isRoot(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString filePath = getLocalPath(path);
|
||||
auto manager = MaterialManager::getManager();
|
||||
|
||||
QFileInfo info(filePath);
|
||||
if (info.isDir()) {
|
||||
deleteDir(manager, filePath);
|
||||
}
|
||||
else {
|
||||
deleteFile(manager, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
// This accepts the filesystem path as returned from getLocalPath
|
||||
void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path)
|
||||
void MaterialLibraryLocal::deleteDir(MaterialManager& manager, const QString& path)
|
||||
{
|
||||
// Remove the children first
|
||||
QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
@@ -105,7 +242,7 @@ void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path)
|
||||
}
|
||||
|
||||
// This accepts the filesystem path as returned from getLocalPath
|
||||
void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path)
|
||||
void MaterialLibraryLocal::deleteFile(MaterialManager& manager, const QString& path)
|
||||
{
|
||||
if (QFile::remove(path)) {
|
||||
// Remove from the map
|
||||
@@ -125,25 +262,7 @@ void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path)
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLibrary::deleteRecursive(const QString& path)
|
||||
{
|
||||
if (isRoot(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString filePath = getLocalPath(path);
|
||||
MaterialManager manager;
|
||||
|
||||
QFileInfo info(filePath);
|
||||
if (info.isDir()) {
|
||||
deleteDir(manager, filePath);
|
||||
}
|
||||
else {
|
||||
deleteFile(manager, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath)
|
||||
void MaterialLibraryLocal::updatePaths(const QString& oldPath, const QString& newPath)
|
||||
{
|
||||
// Update the path map
|
||||
QString op = getRelativePath(oldPath);
|
||||
@@ -162,27 +281,12 @@ void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath
|
||||
_materialPathMap = std::move(pathMap);
|
||||
}
|
||||
|
||||
void MaterialLibrary::renameFolder(const QString& oldPath, const QString& newPath)
|
||||
{
|
||||
QString filePath = getLocalPath(oldPath);
|
||||
QString newFilePath = getLocalPath(newPath);
|
||||
|
||||
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(const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited)
|
||||
std::shared_ptr<Material>
|
||||
MaterialLibraryLocal::saveMaterial(const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited)
|
||||
{
|
||||
QString filePath = getLocalPath(path);
|
||||
QFile file(filePath);
|
||||
@@ -220,7 +324,7 @@ std::shared_ptr<Material> MaterialLibrary::saveMaterial(const std::shared_ptr<Ma
|
||||
return addMaterial(material, path);
|
||||
}
|
||||
|
||||
bool MaterialLibrary::fileExists(const QString& path) const
|
||||
bool MaterialLibraryLocal::fileExists(const QString& path) const
|
||||
{
|
||||
QString filePath = getLocalPath(path);
|
||||
QFileInfo info(filePath);
|
||||
@@ -228,137 +332,41 @@ bool MaterialLibrary::fileExists(const QString& path) const
|
||||
return info.exists();
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialLibrary::addMaterial(const std::shared_ptr<Material>& material,
|
||||
const QString& path)
|
||||
std::shared_ptr<Material>
|
||||
MaterialLibraryLocal::addMaterial(const std::shared_ptr<Material>& material, const QString& path)
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
QFileInfo info(filePath);
|
||||
std::shared_ptr<Material> newMaterial = std::make_shared<Material>(*material);
|
||||
newMaterial->setLibrary(getptr());
|
||||
newMaterial->setDirectory(filePath);
|
||||
newMaterial->setDirectory(getLibraryPath(filePath, info.fileName()));
|
||||
newMaterial->setFilename(info.fileName());
|
||||
|
||||
(*_materialPathMap)[filePath] = newMaterial;
|
||||
|
||||
return newMaterial;
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialLibrary::getMaterialByPath(const QString& path) const
|
||||
std::shared_ptr<Material> MaterialLibraryLocal::getMaterialByPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
try {
|
||||
auto material = _materialPathMap->at(filePath);
|
||||
return material;
|
||||
}
|
||||
catch (std::out_of_range&) {
|
||||
throw MaterialNotFound();
|
||||
|
||||
auto search = _materialPathMap->find(filePath);
|
||||
if (search != _materialPathMap->end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
|
||||
QString MaterialLibrary::getUUIDFromPath(const QString& path) const
|
||||
QString MaterialLibraryLocal::getUUIDFromPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
try {
|
||||
auto material = _materialPathMap->at(filePath);
|
||||
return material->getUUID();
|
||||
}
|
||||
catch (std::out_of_range&) {
|
||||
throw MaterialNotFound();
|
||||
|
||||
auto search = _materialPathMap->find(filePath);
|
||||
if (search != _materialPathMap->end()) {
|
||||
return search->second->getUUID();
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
|
||||
bool MaterialLibrary::materialInTree(const std::shared_ptr<Material>& material,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const
|
||||
{
|
||||
if (!filter) {
|
||||
// If there's no filter we always include
|
||||
return true;
|
||||
}
|
||||
|
||||
// filter out old format files
|
||||
if (material->isOldFormat() && !options.includeLegacy()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// filter based on models
|
||||
return filter->modelIncluded(material);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialLibrary::getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) 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) {
|
||||
auto filename = it.first;
|
||||
auto material = it.second;
|
||||
|
||||
if (materialInTree(material, filter, options)) {
|
||||
QStringList list = filename.split(QStringLiteral("/"));
|
||||
|
||||
// Start at the root
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>> node =
|
||||
materialTree;
|
||||
for (auto& itp : list) {
|
||||
if (itp.endsWith(QStringLiteral(".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
|
||||
if (!filter || options.includeEmptyFolders()) {
|
||||
auto folderList = MaterialLoader::getMaterialFolders(*this);
|
||||
for (auto& folder : *folderList) {
|
||||
QStringList list = folder.split(QStringLiteral("/"));
|
||||
|
||||
// Start at the root
|
||||
auto node = materialTree;
|
||||
for (auto& itp : list) {
|
||||
// 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, Materials::MaterialLibrary)
|
||||
|
||||
MaterialExternalLibrary::MaterialExternalLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: MaterialLibrary(libraryName, dir, icon, readOnly)
|
||||
{}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include "Library.h"
|
||||
#include "Materials.h"
|
||||
#include "Model.h"
|
||||
#include "ModelLibrary.h"
|
||||
@@ -43,29 +44,50 @@ class MaterialManager;
|
||||
class MaterialFilter;
|
||||
class MaterialFilterOptions;
|
||||
|
||||
class MaterialsExport MaterialLibrary: public LibraryBase,
|
||||
public std::enable_shared_from_this<MaterialLibrary>
|
||||
class MaterialsExport MaterialLibrary
|
||||
: public Library,
|
||||
public std::enable_shared_from_this<MaterialLibrary>
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialLibrary() = default;
|
||||
MaterialLibrary(const MaterialLibrary&) = delete;
|
||||
MaterialLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
MaterialLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
MaterialLibrary(const MaterialLibrary&) = delete;
|
||||
~MaterialLibrary() override = default;
|
||||
|
||||
bool operator==(const MaterialLibrary& library) const
|
||||
bool isLocal() const;
|
||||
void setLocal(bool local);
|
||||
|
||||
virtual std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const;
|
||||
|
||||
// Use this to get a shared_ptr for *this
|
||||
std::shared_ptr<MaterialLibrary> getptr()
|
||||
{
|
||||
return LibraryBase::operator==(library);
|
||||
return shared_from_this();
|
||||
}
|
||||
bool operator!=(const MaterialLibrary& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path) const;
|
||||
|
||||
protected:
|
||||
bool _local;
|
||||
};
|
||||
|
||||
class MaterialsExport MaterialLibraryLocal: public MaterialLibrary
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialLibraryLocal() = default;
|
||||
MaterialLibraryLocal(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
~MaterialLibraryLocal() override = default;
|
||||
|
||||
void createFolder(const QString& path);
|
||||
void renameFolder(const QString& oldPath, const QString& newPath);
|
||||
@@ -79,50 +101,39 @@ public:
|
||||
bool fileExists(const QString& path) const;
|
||||
std::shared_ptr<Material> addMaterial(const std::shared_ptr<Material>& material,
|
||||
const QString& path);
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const;
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path) const;
|
||||
|
||||
bool isReadOnly() const
|
||||
bool operator==(const MaterialLibrary& library) const
|
||||
{
|
||||
return _readOnly;
|
||||
return library.isLocal() ? Library::operator==(library) : false;
|
||||
}
|
||||
bool operator!=(const MaterialLibrary& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
|
||||
// Use this to get a shared_ptr for *this
|
||||
std::shared_ptr<MaterialLibrary> getptr()
|
||||
bool operator==(const MaterialLibraryLocal& library) const
|
||||
{
|
||||
return shared_from_this();
|
||||
return Library::operator==(library);
|
||||
}
|
||||
bool operator!=(const MaterialLibraryLocal& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
|
||||
protected:
|
||||
void deleteDir(MaterialManager& manager, const QString& path);
|
||||
void deleteFile(MaterialManager& manager, const QString& path);
|
||||
|
||||
void updatePaths(const QString& oldPath, const QString& newPath);
|
||||
|
||||
QString getUUIDFromPath(const QString& path) const;
|
||||
bool materialInTree(const std::shared_ptr<Material>& material,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const;
|
||||
|
||||
bool _readOnly;
|
||||
std::unique_ptr<std::map<QString, std::shared_ptr<Material>>> _materialPathMap;
|
||||
};
|
||||
|
||||
class MaterialsExport MaterialExternalLibrary: public MaterialLibrary
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialExternalLibrary() = default;
|
||||
MaterialExternalLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
~MaterialExternalLibrary() override = default;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::MaterialLibrary>)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::MaterialLibraryLocal>)
|
||||
|
||||
#endif // MATERIAL_MATERIALLIBRARY_H
|
||||
|
||||
49
src/Mod/Material/App/MaterialLibraryPy.xml
Normal file
49
src/Mod/Material/App/MaterialLibraryPy.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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="MaterialLibraryPy"
|
||||
Twin="MaterialLibrary"
|
||||
TwinPointer="MaterialLibrary"
|
||||
Include="Mod/Material/App/MaterialLibrary.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 library.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="Name" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Name of the library</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Icon" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>String value of the icon.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Icon" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Local directory where the library is located. For non-local libraries this will be empty</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Directory" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="ReadOnly" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>True if the library is local.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ReadOnly" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Local" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>True if the library is local.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Local" Type="Boolean"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
125
src/Mod/Material/App/MaterialLibraryPyImp.cpp
Normal file
125
src/Mod/Material/App/MaterialLibraryPyImp.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023-2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "MaterialLibrary.h"
|
||||
|
||||
#include "MaterialLibraryPy.h"
|
||||
|
||||
#include "MaterialLibraryPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// Forward declaration
|
||||
// static PyObject* _pyObjectFromVariant(const QVariant& value);
|
||||
// static Py::List getList(const QVariant& value);
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialLibraryPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<MaterialLibrary object at " << getMaterialLibraryPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialLibraryPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialLibraryPy(new MaterialLibrary());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialLibraryPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::String MaterialLibraryPy::getName() const
|
||||
{
|
||||
auto filterName = getMaterialLibraryPtr()->getName();
|
||||
return {filterName.toStdString()};
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setName(const Py::String value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setName(QString::fromStdString(value));
|
||||
}
|
||||
|
||||
Py::String MaterialLibraryPy::getIcon() const
|
||||
{
|
||||
auto path = getMaterialLibraryPtr()->getIconPath();
|
||||
return {path.toStdString()};
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setIcon(const Py::String value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setIconPath(QString::fromStdString(value));
|
||||
}
|
||||
|
||||
Py::String MaterialLibraryPy::getDirectory() const
|
||||
{
|
||||
auto path = getMaterialLibraryPtr()->getDirectory();
|
||||
return {path.toStdString()};
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setDirectory(const Py::String value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setDirectory(QString::fromStdString(value));
|
||||
}
|
||||
|
||||
Py::Boolean MaterialLibraryPy::getReadOnly() const
|
||||
{
|
||||
return getMaterialLibraryPtr()->isReadOnly();
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setReadOnly(Py::Boolean value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setReadOnly(value);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialLibraryPy::getLocal() const
|
||||
{
|
||||
return getMaterialLibraryPtr()->isLocal();
|
||||
}
|
||||
|
||||
void MaterialLibraryPy::setLocal(Py::Boolean value)
|
||||
{
|
||||
getMaterialLibraryPtr()->setLocal(value);
|
||||
}
|
||||
|
||||
PyObject* MaterialLibraryPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialLibraryPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
MaterialEntry::MaterialEntry(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialEntry::MaterialEntry(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid)
|
||||
@@ -55,7 +55,7 @@ MaterialEntry::MaterialEntry(const std::shared_ptr<MaterialLibrary>& library,
|
||||
, _uuid(modelUuid)
|
||||
{}
|
||||
|
||||
MaterialYamlEntry::MaterialYamlEntry(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialYamlEntry::MaterialYamlEntry(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid,
|
||||
@@ -98,9 +98,9 @@ std::shared_ptr<QList<QVariant>> MaterialYamlEntry::readImageList(const YAML::No
|
||||
return readList(node, true);
|
||||
}
|
||||
|
||||
std::shared_ptr<Material2DArray> MaterialYamlEntry::read2DArray(const YAML::Node& node, int columns)
|
||||
std::shared_ptr<Array2D> MaterialYamlEntry::read2DArray(const YAML::Node& node, int columns)
|
||||
{
|
||||
auto array2d = std::make_shared<Material2DArray>();
|
||||
auto array2d = std::make_shared<Array2D>();
|
||||
array2d->setColumns(columns);
|
||||
|
||||
if (node.size() == 1 || node.size() == 2) {
|
||||
@@ -126,9 +126,9 @@ std::shared_ptr<Material2DArray> MaterialYamlEntry::read2DArray(const YAML::Node
|
||||
return array2d;
|
||||
}
|
||||
|
||||
std::shared_ptr<Material3DArray> MaterialYamlEntry::read3DArray(const YAML::Node& node, int columns)
|
||||
std::shared_ptr<Array3D> MaterialYamlEntry::read3DArray(const YAML::Node& node, int columns)
|
||||
{
|
||||
auto array3d = std::make_shared<Material3DArray>();
|
||||
auto array3d = std::make_shared<Array3D>();
|
||||
array3d->setColumns(columns - 1); // First column is third dimension
|
||||
|
||||
if (node.size() == 1 || node.size() == 2) {
|
||||
@@ -347,16 +347,16 @@ MaterialLoader::MaterialLoader(
|
||||
: _materialMap(materialMap)
|
||||
, _libraryList(libraryList)
|
||||
{
|
||||
loadLibraries();
|
||||
loadLibraries(libraryList);
|
||||
}
|
||||
|
||||
void MaterialLoader::addLibrary(const std::shared_ptr<MaterialLibrary>& model)
|
||||
void MaterialLoader::addLibrary(const std::shared_ptr<MaterialLibraryLocal>& model)
|
||||
{
|
||||
_libraryList->push_back(model);
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialEntry>
|
||||
MaterialLoader::getMaterialFromYAML(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialLoader::getMaterialFromYAML(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
YAML::Node& yamlroot,
|
||||
const QString& path)
|
||||
{
|
||||
@@ -387,18 +387,20 @@ MaterialLoader::getMaterialFromYAML(const std::shared_ptr<MaterialLibrary>& libr
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialEntry>
|
||||
MaterialLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& path) const
|
||||
{
|
||||
std::shared_ptr<MaterialEntry> model = nullptr;
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
// Used for debugging
|
||||
std::string pathName = path.toStdString();
|
||||
|
||||
if (MaterialConfigLoader::isConfigStyle(path)) {
|
||||
auto material = MaterialConfigLoader::getMaterialFromPath(library, path);
|
||||
auto material = MaterialConfigLoader::getMaterialFromPath(materialLibrary, path);
|
||||
if (material) {
|
||||
(*_materialMap)[material->getUUID()] = library->addMaterial(material, path);
|
||||
(*_materialMap)[material->getUUID()] = materialLibrary->addMaterial(material, path);
|
||||
}
|
||||
|
||||
// Return the nullptr as there are no intermediate steps to take, such
|
||||
@@ -417,7 +419,7 @@ MaterialLoader::getMaterialFromPath(const std::shared_ptr<MaterialLibrary>& libr
|
||||
try {
|
||||
yamlroot = YAML::Load(fin);
|
||||
|
||||
model = getMaterialFromYAML(library, yamlroot, path);
|
||||
model = getMaterialFromYAML(materialLibrary, yamlroot, path);
|
||||
}
|
||||
catch (YAML::Exception const& e) {
|
||||
Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str());
|
||||
@@ -511,7 +513,7 @@ void MaterialLoader::dereference(const std::shared_ptr<Material>& material)
|
||||
dereference(_materialMap, material);
|
||||
}
|
||||
|
||||
void MaterialLoader::loadLibrary(const std::shared_ptr<MaterialLibrary>& library)
|
||||
void MaterialLoader::loadLibrary(const std::shared_ptr<MaterialLibraryLocal>& library)
|
||||
{
|
||||
if (_materialEntryMap == nullptr) {
|
||||
_materialEntryMap = std::make_unique<std::map<QString, std::shared_ptr<MaterialEntry>>>();
|
||||
@@ -541,12 +543,16 @@ void MaterialLoader::loadLibrary(const std::shared_ptr<MaterialLibrary>& library
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLoader::loadLibraries()
|
||||
void MaterialLoader::loadLibraries(
|
||||
const std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>& libraryList)
|
||||
{
|
||||
auto _libraryList = getMaterialLibraries();
|
||||
if (_libraryList) {
|
||||
for (auto& it : *_libraryList) {
|
||||
loadLibrary(it);
|
||||
if (libraryList) {
|
||||
for (auto& it : *libraryList) {
|
||||
if (it->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(it);
|
||||
loadLibrary(materialLibrary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,92 +561,8 @@ void MaterialLoader::loadLibraries()
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialLoader::getMaterialLibraries()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources");
|
||||
bool useBuiltInMaterials = param->GetBool("UseBuiltInMaterials", true);
|
||||
bool useMatFromModules = param->GetBool("UseMaterialsFromWorkbenches", true);
|
||||
bool useMatFromConfigDir = param->GetBool("UseMaterialsFromConfigDir", true);
|
||||
bool useMatFromCustomDir = param->GetBool("UseMaterialsFromCustomDir", true);
|
||||
|
||||
if (useBuiltInMaterials) {
|
||||
QString resourceDir = QString::fromStdString(App::Application::getResourceDir()
|
||||
+ "/Mod/Material/Resources/Materials");
|
||||
auto libData =
|
||||
std::make_shared<MaterialLibrary>(QStringLiteral("System"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/freecad.svg"),
|
||||
true);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
|
||||
if (useMatFromModules) {
|
||||
auto moduleParam = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules");
|
||||
for (auto& group : moduleParam->GetGroups()) {
|
||||
// auto module = moduleParam->GetGroup(group->GetGroupName());
|
||||
auto moduleName = QString::fromStdString(group->GetGroupName());
|
||||
auto materialDir = QString::fromStdString(group->GetASCII("ModuleDir", ""));
|
||||
auto materialIcon = QString::fromStdString(group->GetASCII("ModuleIcon", ""));
|
||||
auto materialReadOnly = group->GetBool("ModuleReadOnly", true);
|
||||
|
||||
if (materialDir.length() > 0) {
|
||||
QDir dir(materialDir);
|
||||
if (dir.exists()) {
|
||||
auto libData = std::make_shared<MaterialLibrary>(moduleName,
|
||||
materialDir,
|
||||
materialIcon,
|
||||
materialReadOnly);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromConfigDir) {
|
||||
QString resourceDir =
|
||||
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 = std::make_shared<MaterialLibrary>(
|
||||
QStringLiteral("User"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/preferences-general.svg"),
|
||||
false);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromCustomDir) {
|
||||
QString resourceDir = QString::fromStdString(param->GetASCII("CustomMaterialsDir", ""));
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData =
|
||||
std::make_shared<MaterialLibrary>(QStringLiteral("Custom"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/user.svg"),
|
||||
false);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<QString>>
|
||||
MaterialLoader::getMaterialFolders(const MaterialLibrary& library)
|
||||
MaterialLoader::getMaterialFolders(const MaterialLibraryLocal& library)
|
||||
{
|
||||
std::shared_ptr<std::list<QString>> pathList = std::make_shared<std::list<QString>>();
|
||||
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
|
||||
|
||||
@@ -33,12 +33,14 @@
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
class MaterialLibrary;
|
||||
class MaterialLibraryLocal;
|
||||
|
||||
class MaterialEntry
|
||||
{
|
||||
public:
|
||||
MaterialEntry() = default;
|
||||
MaterialEntry(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialEntry(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid);
|
||||
@@ -47,7 +49,7 @@ public:
|
||||
virtual void
|
||||
addToTree(std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> materialMap) = 0;
|
||||
|
||||
std::shared_ptr<MaterialLibrary> getLibrary() const
|
||||
std::shared_ptr<MaterialLibraryLocal> getLibrary() const
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
@@ -65,7 +67,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MaterialLibrary> _library;
|
||||
std::shared_ptr<MaterialLibraryLocal> _library;
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _uuid;
|
||||
@@ -74,7 +76,7 @@ protected:
|
||||
class MaterialYamlEntry: public MaterialEntry
|
||||
{
|
||||
public:
|
||||
MaterialYamlEntry(const std::shared_ptr<MaterialLibrary>& library,
|
||||
MaterialYamlEntry(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid,
|
||||
@@ -101,8 +103,8 @@ private:
|
||||
static std::shared_ptr<QList<QVariant>> readList(const YAML::Node& node,
|
||||
bool isImageList = false);
|
||||
static std::shared_ptr<QList<QVariant>> readImageList(const YAML::Node& node);
|
||||
static std::shared_ptr<Material2DArray> read2DArray(const YAML::Node& node, int columns);
|
||||
static std::shared_ptr<Material3DArray> read3DArray(const YAML::Node& node, int columns);
|
||||
static std::shared_ptr<Array2D> read2DArray(const YAML::Node& node, int columns);
|
||||
static std::shared_ptr<Array3D> read3DArray(const YAML::Node& node, int columns);
|
||||
|
||||
YAML::Node _model;
|
||||
};
|
||||
@@ -114,14 +116,14 @@ public:
|
||||
const std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>& libraryList);
|
||||
~MaterialLoader() = default;
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries();
|
||||
static std::shared_ptr<std::list<QString>> getMaterialFolders(const MaterialLibrary& library);
|
||||
static std::shared_ptr<std::list<QString>>
|
||||
getMaterialFolders(const MaterialLibraryLocal& library);
|
||||
static void showYaml(const YAML::Node& yaml);
|
||||
static void
|
||||
dereference(const std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>& materialMap,
|
||||
const std::shared_ptr<Material>& material);
|
||||
static std::shared_ptr<MaterialEntry>
|
||||
getMaterialFromYAML(const std::shared_ptr<MaterialLibrary>& library,
|
||||
getMaterialFromYAML(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
YAML::Node& yamlroot,
|
||||
const QString& path);
|
||||
|
||||
@@ -131,10 +133,11 @@ private:
|
||||
void addToTree(std::shared_ptr<MaterialEntry> model);
|
||||
void dereference(const std::shared_ptr<Material>& material);
|
||||
std::shared_ptr<MaterialEntry>
|
||||
getMaterialFromPath(const std::shared_ptr<MaterialLibrary>& library, const QString& path) const;
|
||||
void addLibrary(const std::shared_ptr<MaterialLibrary>& model);
|
||||
void loadLibrary(const std::shared_ptr<MaterialLibrary>& library);
|
||||
void loadLibraries();
|
||||
getMaterialFromPath(const std::shared_ptr<MaterialLibraryLocal>& library, const QString& path) const;
|
||||
void addLibrary(const std::shared_ptr<MaterialLibraryLocal>& model);
|
||||
void loadLibrary(const std::shared_ptr<MaterialLibraryLocal>& library);
|
||||
void loadLibraries(
|
||||
const std::shared_ptr<std::list<std::shared_ptr<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;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
#include <QMutex>
|
||||
#include <QDirIterator>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <App/Application.h>
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "MaterialConfigLoader.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "MaterialManagerLocal.h"
|
||||
#include "ModelManager.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
@@ -45,100 +46,56 @@ using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
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)
|
||||
|
||||
QMutex MaterialManager::_mutex;
|
||||
MaterialManager* MaterialManager::_manager = nullptr;
|
||||
std::unique_ptr<MaterialManagerLocal> MaterialManager::_localManager;
|
||||
|
||||
MaterialManager::MaterialManager()
|
||||
{}
|
||||
|
||||
MaterialManager::~MaterialManager()
|
||||
{}
|
||||
|
||||
MaterialManager& MaterialManager::getManager()
|
||||
{
|
||||
// TODO: Add a mutex or similar
|
||||
initLibraries();
|
||||
if (!_manager) {
|
||||
initManagers();
|
||||
}
|
||||
return *_manager;
|
||||
}
|
||||
|
||||
void MaterialManager::initLibraries()
|
||||
void MaterialManager::initManagers()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_materialMap == nullptr) {
|
||||
// Load the models first
|
||||
auto manager = std::make_unique<ModelManager>();
|
||||
Q_UNUSED(manager)
|
||||
|
||||
_materialMap = std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
|
||||
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
MaterialLoader loader(_materialMap, _libraryList);
|
||||
if (!_manager) {
|
||||
// Can't use smart pointers for this since the constructor is private
|
||||
_manager = new MaterialManager();
|
||||
}
|
||||
if (!_localManager) {
|
||||
_localManager = std::make_unique<MaterialManagerLocal>();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::cleanup()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_libraryList) {
|
||||
_libraryList->clear();
|
||||
_libraryList = nullptr;
|
||||
}
|
||||
|
||||
if (_materialMap) {
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
it.second->setLibrary(nullptr);
|
||||
}
|
||||
_materialMap->clear();
|
||||
_materialMap = nullptr;
|
||||
if (_localManager) {
|
||||
_localManager->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::refresh()
|
||||
{
|
||||
// This is very expensive and can be improved using observers?
|
||||
cleanup();
|
||||
initLibraries();
|
||||
_localManager->refresh();
|
||||
}
|
||||
|
||||
void MaterialManager::saveMaterial(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited) const
|
||||
{
|
||||
auto newMaterial = library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited);
|
||||
(*_materialMap)[newMaterial->getUUID()] = newMaterial;
|
||||
}
|
||||
|
||||
bool MaterialManager::isMaterial(const fs::path& p) const
|
||||
{
|
||||
if (!fs::is_regular_file(p)) {
|
||||
return false;
|
||||
}
|
||||
// check file extension
|
||||
if (p.extension() == ".FCMat") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialManager::isMaterial(const QFileInfo& file) const
|
||||
{
|
||||
if (!file.isFile()) {
|
||||
return false;
|
||||
}
|
||||
// check file extension
|
||||
if (file.suffix() == QStringLiteral("FCMat")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//=====
|
||||
//
|
||||
// Defaults
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<App::Material> MaterialManager::defaultAppearance()
|
||||
{
|
||||
@@ -149,7 +106,7 @@ std::shared_ptr<App::Material> MaterialManager::defaultAppearance()
|
||||
uint32_t packed = color.getPackedRGB();
|
||||
packed = hGrp->GetUnsigned(parameter, packed);
|
||||
color.setPackedRGB(packed);
|
||||
color.a = 1.0; // The default color sets fully transparent, not opaque
|
||||
color.a = 1.0; // The default color sets fully transparent, not opaque
|
||||
};
|
||||
auto intRandom = [](int min, int max) -> int {
|
||||
static std::mt19937 generator;
|
||||
@@ -187,9 +144,9 @@ std::shared_ptr<Material> MaterialManager::defaultMaterial()
|
||||
MaterialManager manager;
|
||||
|
||||
auto mat = defaultAppearance();
|
||||
auto material = manager.getMaterial(defaultMaterialUUID());
|
||||
auto material = getManager().getMaterial(defaultMaterialUUID());
|
||||
if (!material) {
|
||||
material = manager.getMaterial(QLatin1String("7f9fd73b-50c9-41d8-b7b2-575a030c1eeb"));
|
||||
material = getManager().getMaterial(QStringLiteral("7f9fd73b-50c9-41d8-b7b2-575a030c1eeb"));
|
||||
}
|
||||
if (material->hasAppearanceModel(ModelUUIDs::ModelUUID_Rendering_Basic)) {
|
||||
material->getAppearanceProperty(QStringLiteral("DiffuseColor"))
|
||||
@@ -218,14 +175,178 @@ QString MaterialManager::defaultMaterialUUID()
|
||||
return QString::fromStdString(uuid);
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Library management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialManager::getLibraries()
|
||||
{
|
||||
auto libraries = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
|
||||
auto localLibraries = _localManager->getLibraries();
|
||||
for (auto& local : *localLibraries) {
|
||||
libraries->push_back(local);
|
||||
}
|
||||
|
||||
return libraries;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialManager::getLocalLibraries()
|
||||
{
|
||||
return _localManager->getLibraries();
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialLibrary> MaterialManager::getLibrary(const QString& name) const
|
||||
{
|
||||
return _localManager->getLibrary(name);
|
||||
}
|
||||
|
||||
void MaterialManager::createLibrary(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
{
|
||||
throw CreationError("Local library requires a path");
|
||||
}
|
||||
|
||||
void MaterialManager::createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
_localManager->createLibrary(libraryName, directory, icon, readOnly);
|
||||
}
|
||||
|
||||
void MaterialManager::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
_localManager->renameLibrary(libraryName, newName);
|
||||
}
|
||||
|
||||
void MaterialManager::changeIcon(const QString& libraryName, const QString& icon)
|
||||
{
|
||||
_localManager->changeIcon(libraryName, icon);
|
||||
}
|
||||
|
||||
void MaterialManager::removeLibrary(const QString& libraryName)
|
||||
{
|
||||
_localManager->removeLibrary(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
MaterialManager::libraryMaterials(const QString& libraryName)
|
||||
{
|
||||
return _localManager->libraryMaterials(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
MaterialManager::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
{
|
||||
return _localManager->libraryMaterials(libraryName, filter, options);
|
||||
}
|
||||
|
||||
bool MaterialManager::isLocalLibrary(const QString& libraryName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Folder management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::list<QString>>
|
||||
MaterialManager::getMaterialFolders(const std::shared_ptr<MaterialLibrary>& library) const
|
||||
{
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
return _localManager->getMaterialFolders(materialLibrary);
|
||||
}
|
||||
|
||||
return std::make_shared<std::list<QString>>();
|
||||
}
|
||||
|
||||
void MaterialManager::createFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& path)
|
||||
{
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
_localManager->createFolder(materialLibrary, path);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath)
|
||||
{
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
_localManager->renameFolder(materialLibrary, oldPath, newPath);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::deleteRecursive(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& path)
|
||||
{
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
_localManager->deleteRecursive(materialLibrary, path);
|
||||
}
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Tree management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialManager::getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const
|
||||
{
|
||||
MaterialFilterOptions options;
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialManager::getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options) const
|
||||
{
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
MaterialManager::getMaterialTree(const std::shared_ptr<MaterialLibrary>& library) const
|
||||
{
|
||||
std::shared_ptr<Materials::MaterialFilter> filter;
|
||||
MaterialFilterOptions options;
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Material management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManager::getLocalMaterials() const
|
||||
{
|
||||
return _localManager->getLocalMaterials();
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterial(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
return _materialMap->at(uuid);
|
||||
}
|
||||
catch (std::out_of_range&) {
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
return _localManager->getMaterial(uuid);
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterial(const App::Material& material)
|
||||
@@ -237,65 +358,13 @@ std::shared_ptr<Material> MaterialManager::getMaterial(const App::Material& mate
|
||||
|
||||
std::shared_ptr<Material> MaterialManager::getMaterialByPath(const QString& path) const
|
||||
{
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
|
||||
for (auto& library : *_libraryList) {
|
||||
if (cleanPath.startsWith(library->getDirectory())) {
|
||||
try {
|
||||
return library->getMaterialByPath(cleanPath);
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
// See if it's a new file saved by the old editor
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (MaterialConfigLoader::isConfigStyle(path)) {
|
||||
auto material = MaterialConfigLoader::getMaterialFromPath(library, path);
|
||||
if (material) {
|
||||
(*_materialMap)[material->getUUID()] = library->addMaterial(material, path);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Older workbenches may try files outside the context of a library
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (MaterialConfigLoader::isConfigStyle(path)) {
|
||||
auto material = MaterialConfigLoader::getMaterialFromPath(nullptr, path);
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
return _localManager->getMaterialByPath(path);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
bool MaterialManager::exists(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
auto material = getMaterial(uuid);
|
||||
if (material) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
return false;
|
||||
return _localManager->getMaterialByPath(path, lib);
|
||||
}
|
||||
|
||||
std::shared_ptr<Material>
|
||||
@@ -308,105 +377,69 @@ MaterialManager::getParent(const std::shared_ptr<Material>& material) const
|
||||
return getMaterial(material->getParentUUID());
|
||||
}
|
||||
|
||||
bool MaterialManager::exists(const QString& uuid) const
|
||||
{
|
||||
return _localManager->exists(uuid);
|
||||
}
|
||||
|
||||
bool MaterialManager::exists(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
auto material = getMaterial(uuid);
|
||||
if (material) {
|
||||
return (*material->getLibrary() == *library);
|
||||
}
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
|
||||
return _localManager->exists(materialLibrary, uuid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialLibrary> MaterialManager::getLibrary(const QString& name) const
|
||||
void MaterialManager::remove(const QString& uuid) const
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == name) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
_localManager->remove(uuid);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>
|
||||
MaterialManager::getMaterialLibraries() const
|
||||
void MaterialManager::saveMaterial(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited) const
|
||||
{
|
||||
if (_libraryList == nullptr) {
|
||||
if (_materialMap == nullptr) {
|
||||
_materialMap = std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
|
||||
}
|
||||
_libraryList = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
|
||||
|
||||
// Load the libraries
|
||||
MaterialLoader loader(_materialMap, _libraryList);
|
||||
}
|
||||
return _libraryList;
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
_localManager
|
||||
->saveMaterial(materialLibrary, material, path, overwrite, saveAsCopy, saveInherited);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<QString>>
|
||||
MaterialManager::getMaterialFolders(const std::shared_ptr<MaterialLibrary>& library) const
|
||||
bool MaterialManager::isMaterial(const fs::path& p) const
|
||||
{
|
||||
return MaterialLoader::getMaterialFolders(*library);
|
||||
return _localManager->isMaterial(p);
|
||||
}
|
||||
|
||||
bool MaterialManager::isMaterial(const QFileInfo& file) const
|
||||
{
|
||||
return _localManager->isMaterial(file);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManager::materialsWithModel(const QString& uuid) const
|
||||
{
|
||||
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) {
|
||||
QString key = it.first;
|
||||
auto material = it.second;
|
||||
|
||||
if (material->hasModel(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
return _localManager->materialsWithModel(uuid);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManager::materialsWithModelComplete(const QString& uuid) const
|
||||
{
|
||||
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) {
|
||||
QString key = it.first;
|
||||
auto material = it.second;
|
||||
|
||||
if (material->isModelComplete(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
return _localManager->materialsWithModelComplete(uuid);
|
||||
}
|
||||
|
||||
void MaterialManager::dereference() const
|
||||
{
|
||||
// First clear the inheritences
|
||||
for (auto& it : *_materialMap) {
|
||||
auto material = it.second;
|
||||
material->clearDereferenced();
|
||||
material->clearInherited();
|
||||
}
|
||||
|
||||
// Run the dereference again
|
||||
for (auto& it : *_materialMap) {
|
||||
dereference(it.second);
|
||||
}
|
||||
_localManager->dereference();
|
||||
}
|
||||
|
||||
void MaterialManager::dereference(std::shared_ptr<Material> material) const
|
||||
{
|
||||
MaterialLoader::dereference(_materialMap, material);
|
||||
_localManager->dereference(material);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,14 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include "FolderTree.h"
|
||||
#include "Materials.h"
|
||||
|
||||
#include "MaterialLibrary.h"
|
||||
#include "MaterialFilter.h"
|
||||
#include "MaterialLibrary.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -45,78 +46,78 @@ class Material;
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
class MaterialManagerExternal;
|
||||
class MaterialManagerLocal;
|
||||
class MaterialFilter;
|
||||
class MaterialFilterOptions;
|
||||
|
||||
class MaterialsExport MaterialManager: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialManager();
|
||||
~MaterialManager() override = default;
|
||||
~MaterialManager() override;
|
||||
|
||||
static MaterialManager& getManager();
|
||||
|
||||
static void cleanup();
|
||||
static void refresh();
|
||||
|
||||
// Defaults
|
||||
static std::shared_ptr<App::Material> defaultAppearance();
|
||||
static std::shared_ptr<Material> defaultMaterial();
|
||||
static QString defaultMaterialUUID();
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> getMaterials() const
|
||||
{
|
||||
return _materialMap;
|
||||
}
|
||||
// Library management
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLocalLibraries();
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
void createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
bool isLocalLibrary(const QString& libraryName);
|
||||
|
||||
// Folder management
|
||||
std::shared_ptr<std::list<QString>>
|
||||
getMaterialFolders(const std::shared_ptr<MaterialLibrary>& library) const;
|
||||
void createFolder(const std::shared_ptr<MaterialLibrary>& library, const QString& path);
|
||||
void renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath);
|
||||
void deleteRecursive(const std::shared_ptr<MaterialLibrary>& library, const QString& path);
|
||||
|
||||
// Tree management
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options) const;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library) const;
|
||||
|
||||
// Material management
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> getLocalMaterials() const;
|
||||
std::shared_ptr<Material> getMaterial(const QString& uuid) const;
|
||||
static std::shared_ptr<Material> getMaterial(const App::Material& material);
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path) const;
|
||||
std::shared_ptr<Material> getMaterialByPath(const QString& path, const QString& library) const;
|
||||
std::shared_ptr<Material> getParent(const std::shared_ptr<Material>& material) const;
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
bool exists(const QString& uuid) const;
|
||||
bool exists(const std::shared_ptr<MaterialLibrary>& library, const QString& uuid) const;
|
||||
|
||||
// Library management
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries() const;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter) const
|
||||
{
|
||||
MaterialFilterOptions options;
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options) const
|
||||
{
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>
|
||||
getMaterialTree(const std::shared_ptr<MaterialLibrary>& library) const
|
||||
{
|
||||
std::shared_ptr<Materials::MaterialFilter> filter;
|
||||
MaterialFilterOptions options;
|
||||
return library->getMaterialTree(filter, options);
|
||||
}
|
||||
std::shared_ptr<std::list<QString>>
|
||||
getMaterialFolders(const std::shared_ptr<MaterialLibrary>& library) const;
|
||||
void createFolder(const std::shared_ptr<MaterialLibrary>& library, const QString& path) const
|
||||
{
|
||||
library->createFolder(path);
|
||||
}
|
||||
void renameFolder(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath) const
|
||||
{
|
||||
library->renameFolder(oldPath, newPath);
|
||||
}
|
||||
void deleteRecursive(const std::shared_ptr<MaterialLibrary>& library, const QString& path) const
|
||||
{
|
||||
library->deleteRecursive(path);
|
||||
dereference();
|
||||
}
|
||||
void remove(const QString& uuid) const
|
||||
{
|
||||
_materialMap->erase(uuid);
|
||||
}
|
||||
void remove(const QString& uuid) const;
|
||||
|
||||
void saveMaterial(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const std::shared_ptr<Material>& material,
|
||||
@@ -136,13 +137,15 @@ public:
|
||||
void dereference() const;
|
||||
|
||||
private:
|
||||
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;
|
||||
MaterialManager();
|
||||
static void initManagers();
|
||||
|
||||
static void initLibraries();
|
||||
static MaterialManager* _manager;
|
||||
|
||||
static std::unique_ptr<MaterialManagerLocal> _localManager;
|
||||
static QMutex _mutex;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_MATERIALMANAGER_H
|
||||
#endif // MATERIAL_MATERIALMANAGER_H
|
||||
593
src/Mod/Material/App/MaterialManagerLocal.cpp
Normal file
593
src/Mod/Material/App/MaterialManagerLocal.cpp
Normal file
@@ -0,0 +1,593 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Material.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialConfigLoader.h"
|
||||
#include "MaterialFilter.h"
|
||||
#include "MaterialLibrary.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MaterialManagerLocal.h"
|
||||
#include "ModelManager.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>
|
||||
MaterialManagerLocal::_libraryList = nullptr;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> MaterialManagerLocal::_materialMap =
|
||||
nullptr;
|
||||
QMutex MaterialManagerLocal::_mutex;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialManagerLocal, Base::BaseClass)
|
||||
|
||||
MaterialManagerLocal::MaterialManagerLocal()
|
||||
{
|
||||
// TODO: Add a mutex or similar
|
||||
initLibraries();
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::initLibraries()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_materialMap == nullptr) {
|
||||
// Load the models first
|
||||
ModelManager::getManager();
|
||||
|
||||
_materialMap = std::make_shared<std::map<QString, std::shared_ptr<Material>>>();
|
||||
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = getConfiguredLibraries();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
MaterialLoader loader(_materialMap, _libraryList);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::cleanup()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_libraryList) {
|
||||
_libraryList->clear();
|
||||
_libraryList = nullptr;
|
||||
}
|
||||
|
||||
if (_materialMap) {
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
it.second->setLibrary(nullptr);
|
||||
}
|
||||
_materialMap->clear();
|
||||
_materialMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::refresh()
|
||||
{
|
||||
// This is very expensive and can be improved using observers?
|
||||
cleanup();
|
||||
initLibraries();
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Library management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> MaterialManagerLocal::getLibraries()
|
||||
{
|
||||
if (_libraryList == nullptr) {
|
||||
initLibraries();
|
||||
}
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>
|
||||
MaterialManagerLocal::getMaterialLibraries()
|
||||
{
|
||||
if (_libraryList == nullptr) {
|
||||
initLibraries();
|
||||
}
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
std::shared_ptr<MaterialLibrary> MaterialManagerLocal::getLibrary(const QString& name) const
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal() && library->sameName(name)) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
QDir dir;
|
||||
if (!dir.exists(directory)) {
|
||||
if (!dir.mkpath(directory)) {
|
||||
throw CreationError("Unable to create library path");
|
||||
}
|
||||
}
|
||||
|
||||
auto materialLibrary =
|
||||
std::make_shared<MaterialLibraryLocal>(libraryName, directory, icon, readOnly);
|
||||
_libraryList->push_back(materialLibrary);
|
||||
|
||||
// This needs to be persisted somehow
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal() && library->sameName(libraryName)) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
materialLibrary->setName(newName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::changeIcon(const QString& libraryName, const QString& icon)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal() && library->sameName(libraryName)) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
materialLibrary->setIconPath(icon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::removeLibrary(const QString& libraryName)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal() && library->sameName(libraryName)) {
|
||||
_libraryList->remove(library);
|
||||
|
||||
// At this point we should rebuild the material map
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
MaterialManagerLocal::libraryMaterials(const QString& libraryName)
|
||||
{
|
||||
auto materials = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
auto library = it.second->getLibrary();
|
||||
if (library->sameName(libraryName)) {
|
||||
materials->push_back(std::tuple<QString, QString, QString>(it.first,
|
||||
it.second->getDirectory(),
|
||||
it.second->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return materials;
|
||||
}
|
||||
|
||||
bool MaterialManagerLocal::passFilter(const std::shared_ptr<Material>& material,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const
|
||||
{
|
||||
if (!filter) {
|
||||
// If there's no filter we always include
|
||||
return true;
|
||||
}
|
||||
|
||||
// filter out old format files
|
||||
if (material->isOldFormat() && !options.includeLegacy()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// filter based on models
|
||||
return filter->modelIncluded(material);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
MaterialManagerLocal::libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options)
|
||||
{
|
||||
auto materials = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
|
||||
for (auto& it : *_materialMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
auto library = it.second->getLibrary();
|
||||
if (library->sameName(libraryName)) {
|
||||
if (passFilter(it.second, filter, options)) {
|
||||
materials->push_back(std::tuple<QString, QString, QString>(it.first,
|
||||
it.second->getDirectory(),
|
||||
it.second->getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return materials;
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Folder management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::list<QString>>
|
||||
MaterialManagerLocal::getMaterialFolders(const std::shared_ptr<MaterialLibraryLocal>& library) const
|
||||
{
|
||||
// auto materialLibrary =
|
||||
// reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return MaterialLoader::getMaterialFolders(*library);
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::createFolder(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& path)
|
||||
{
|
||||
library->createFolder(path);
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::renameFolder(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath)
|
||||
{
|
||||
library->renameFolder(oldPath, newPath);
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::deleteRecursive(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& path)
|
||||
{
|
||||
library->deleteRecursive(path);
|
||||
dereference();
|
||||
}
|
||||
|
||||
//=====
|
||||
//
|
||||
// Material management
|
||||
//
|
||||
//=====
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManagerLocal::getLocalMaterials() const
|
||||
{
|
||||
return _materialMap;
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManagerLocal::getMaterial(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
return _materialMap->at(uuid);
|
||||
}
|
||||
catch (std::out_of_range&) {
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManagerLocal::getMaterialByPath(const QString& path) const
|
||||
{
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
if (cleanPath.startsWith(materialLibrary->getDirectory())) {
|
||||
try {
|
||||
return materialLibrary->getMaterialByPath(cleanPath);
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
// See if it's a new file saved by the old editor
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (MaterialConfigLoader::isConfigStyle(path)) {
|
||||
auto material =
|
||||
MaterialConfigLoader::getMaterialFromPath(materialLibrary, path);
|
||||
if (material) {
|
||||
(*_materialMap)[material->getUUID()] =
|
||||
materialLibrary->addMaterial(material, path);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Older workbenches may try files outside the context of a library
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (MaterialConfigLoader::isConfigStyle(path)) {
|
||||
auto material = MaterialConfigLoader::getMaterialFromPath(nullptr, path);
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> MaterialManagerLocal::getMaterialByPath(const QString& path,
|
||||
const QString& lib) const
|
||||
{
|
||||
auto library = getLibrary(lib); // May throw LibraryNotFound
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return materialLibrary->getMaterialByPath(path); // May throw MaterialNotFound
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
bool MaterialManagerLocal::exists(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
auto material = getMaterial(uuid);
|
||||
if (material) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialManagerLocal::exists(const std::shared_ptr<MaterialLibrary>& library,
|
||||
const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
auto material = getMaterial(uuid);
|
||||
if (material && material->getLibrary()->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(
|
||||
*(material->getLibrary()));
|
||||
return (*materialLibrary == *library);
|
||||
}
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::remove(const QString& uuid)
|
||||
{
|
||||
_materialMap->erase(uuid);
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::saveMaterial(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited) const
|
||||
{
|
||||
if (library->isLocal()) {
|
||||
auto newMaterial =
|
||||
library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited);
|
||||
(*_materialMap)[newMaterial->getUUID()] = newMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialManagerLocal::isMaterial(const fs::path& p) const
|
||||
{
|
||||
if (!fs::is_regular_file(p)) {
|
||||
return false;
|
||||
}
|
||||
// check file extension
|
||||
if (p.extension() == ".FCMat") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialManagerLocal::isMaterial(const QFileInfo& file) const
|
||||
{
|
||||
if (!file.isFile()) {
|
||||
return false;
|
||||
}
|
||||
// check file extension
|
||||
if (file.suffix() == QStringLiteral("FCMat")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManagerLocal::materialsWithModel(const QString& uuid) const
|
||||
{
|
||||
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) {
|
||||
QString key = it.first;
|
||||
auto material = it.second;
|
||||
|
||||
if (material->hasModel(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
MaterialManagerLocal::materialsWithModelComplete(const QString& uuid) const
|
||||
{
|
||||
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) {
|
||||
QString key = it.first;
|
||||
auto material = it.second;
|
||||
|
||||
if (material->isModelComplete(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::dereference() const
|
||||
{
|
||||
// First clear the inheritences
|
||||
for (auto& it : *_materialMap) {
|
||||
auto material = it.second;
|
||||
material->clearDereferenced();
|
||||
material->clearInherited();
|
||||
}
|
||||
|
||||
// Run the dereference again
|
||||
for (auto& it : *_materialMap) {
|
||||
dereference(it.second);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManagerLocal::dereference(std::shared_ptr<Material> material) const
|
||||
{
|
||||
MaterialLoader::dereference(_materialMap, material);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>>
|
||||
MaterialManagerLocal::getConfiguredLibraries()
|
||||
{
|
||||
auto libraryList = std::make_shared<std::list<std::shared_ptr<MaterialLibrary>>>();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources");
|
||||
bool useBuiltInMaterials = param->GetBool("UseBuiltInMaterials", true);
|
||||
bool useMatFromModules = param->GetBool("UseMaterialsFromWorkbenches", true);
|
||||
bool useMatFromConfigDir = param->GetBool("UseMaterialsFromConfigDir", true);
|
||||
bool useMatFromCustomDir = param->GetBool("UseMaterialsFromCustomDir", true);
|
||||
|
||||
if (useBuiltInMaterials) {
|
||||
QString resourceDir = QString::fromStdString(App::Application::getResourceDir()
|
||||
+ "/Mod/Material/Resources/Materials");
|
||||
auto libData =
|
||||
std::make_shared<MaterialLibraryLocal>(QStringLiteral("System"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/freecad.svg"),
|
||||
true);
|
||||
libraryList->push_back(libData);
|
||||
}
|
||||
|
||||
if (useMatFromModules) {
|
||||
auto moduleParam = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules");
|
||||
for (auto& group : moduleParam->GetGroups()) {
|
||||
// auto module = moduleParam->GetGroup(group->GetGroupName());
|
||||
auto moduleName = QString::fromStdString(group->GetGroupName());
|
||||
auto materialDir = QString::fromStdString(group->GetASCII("ModuleDir", ""));
|
||||
auto materialIcon = QString::fromStdString(group->GetASCII("ModuleIcon", ""));
|
||||
auto materialReadOnly = group->GetBool("ModuleReadOnly", true);
|
||||
|
||||
if (materialDir.length() > 0) {
|
||||
QDir dir(materialDir);
|
||||
if (dir.exists()) {
|
||||
auto libData = std::make_shared<MaterialLibraryLocal>(moduleName,
|
||||
materialDir,
|
||||
materialIcon,
|
||||
materialReadOnly);
|
||||
libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromConfigDir) {
|
||||
QString resourceDir =
|
||||
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 = std::make_shared<MaterialLibraryLocal>(
|
||||
QStringLiteral("User"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/preferences-general.svg"),
|
||||
false);
|
||||
libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromCustomDir) {
|
||||
QString resourceDir = QString::fromStdString(param->GetASCII("CustomMaterialsDir", ""));
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData = std::make_shared<MaterialLibraryLocal>(
|
||||
QStringLiteral("Custom"),
|
||||
resourceDir,
|
||||
QStringLiteral(":/icons/user.svg"),
|
||||
false);
|
||||
libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return libraryList;
|
||||
}
|
||||
131
src/Mod/Material/App/MaterialManagerLocal.h
Normal file
131
src/Mod/Material/App/MaterialManagerLocal.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALMANAGERLOCAL_H
|
||||
#define MATERIAL_MATERIALMANAGERLOCAL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include "FolderTree.h"
|
||||
#include "Materials.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Material;
|
||||
}
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialLibrary;
|
||||
class MaterialLibraryLocal;
|
||||
class MaterialFilter;
|
||||
class MaterialFilterOptions;
|
||||
|
||||
class MaterialsExport MaterialManagerLocal: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialManagerLocal();
|
||||
~MaterialManagerLocal() override = default;
|
||||
|
||||
static void cleanup();
|
||||
static void refresh();
|
||||
|
||||
// Library management
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getMaterialLibraries();
|
||||
std::shared_ptr<MaterialLibrary> getLibrary(const QString& name) const;
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryMaterials(const QString& libraryName,
|
||||
const std::shared_ptr<MaterialFilter>& filter,
|
||||
const MaterialFilterOptions& options);
|
||||
|
||||
// Folder management
|
||||
std::shared_ptr<std::list<QString>>
|
||||
getMaterialFolders(const std::shared_ptr<MaterialLibraryLocal>& library) const;
|
||||
void createFolder(const std::shared_ptr<MaterialLibraryLocal>& library, const QString& path);
|
||||
void renameFolder(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const QString& oldPath,
|
||||
const QString& newPath);
|
||||
void deleteRecursive(const std::shared_ptr<MaterialLibraryLocal>& library, const QString& path);
|
||||
|
||||
// Material management
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>> getLocalMaterials() 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;
|
||||
bool exists(const QString& uuid) const;
|
||||
bool exists(const std::shared_ptr<MaterialLibrary>& library, const QString& uuid) const;
|
||||
void remove(const QString& uuid);
|
||||
|
||||
void saveMaterial(const std::shared_ptr<MaterialLibraryLocal>& library,
|
||||
const std::shared_ptr<Material>& material,
|
||||
const QString& path,
|
||||
bool overwrite,
|
||||
bool saveAsCopy,
|
||||
bool saveInherited) const;
|
||||
|
||||
bool isMaterial(const fs::path& p) const;
|
||||
bool isMaterial(const QFileInfo& file) const;
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
materialsWithModel(const QString& uuid) const;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Material>>>
|
||||
materialsWithModelComplete(const QString& uuid) const;
|
||||
void dereference(std::shared_ptr<Material> material) const;
|
||||
void dereference() const;
|
||||
|
||||
protected:
|
||||
static std::shared_ptr<std::list<std::shared_ptr<MaterialLibrary>>> getConfiguredLibraries();
|
||||
bool passFilter(const std::shared_ptr<Material>& material,
|
||||
const std::shared_ptr<Materials::MaterialFilter>& filter,
|
||||
const Materials::MaterialFilterOptions& options) const;
|
||||
|
||||
private:
|
||||
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();
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_MATERIALMANAGERLOCAL_H
|
||||
@@ -10,7 +10,7 @@
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
Delete="false">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material descriptions.</UserDocu>
|
||||
|
||||
@@ -47,7 +47,7 @@ std::string MaterialManagerPy::representation() const
|
||||
PyObject* MaterialManagerPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialManagerPy(new MaterialManager());
|
||||
return new MaterialManagerPy(&(MaterialManager::getManager()));
|
||||
}
|
||||
|
||||
// constructor method
|
||||
@@ -136,15 +136,25 @@ PyObject* MaterialManagerPy::inheritMaterial(PyObject* args)
|
||||
|
||||
Py::List MaterialManagerPy::getMaterialLibraries() const
|
||||
{
|
||||
auto libraries = getMaterialManagerPtr()->getMaterialLibraries();
|
||||
auto libraries = getMaterialManagerPtr()->getLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = libraries->begin(); it != libraries->end(); it++) {
|
||||
auto lib = *it;
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
if (lib->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(lib);
|
||||
libTuple.setItem(0, Py::String(materialLibrary->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(materialLibrary->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(materialLibrary->getIconPath().toStdString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
libTuple.setItem(0, Py::String());
|
||||
libTuple.setItem(1, Py::String());
|
||||
libTuple.setItem(2, Py::String());
|
||||
}
|
||||
|
||||
list.append(libTuple);
|
||||
}
|
||||
@@ -156,7 +166,7 @@ Py::Dict MaterialManagerPy::getMaterials() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
auto materials = getMaterialManagerPtr()->getMaterials();
|
||||
auto materials = getMaterialManagerPtr()->getLocalMaterials();
|
||||
|
||||
for (auto it = materials->begin(); it != materials->end(); it++) {
|
||||
QString key = it->first;
|
||||
@@ -284,17 +294,19 @@ PyObject* MaterialManagerPy::save(PyObject* args, PyObject* kwds)
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
void addMaterials(Py::List& list,
|
||||
void addMaterials(MaterialManager *manager,
|
||||
Py::List& list,
|
||||
const std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>& tree)
|
||||
{
|
||||
for (auto& node : *tree) {
|
||||
if (node.second->getType() == MaterialTreeNode::DataNode) {
|
||||
auto material = node.second->getData();
|
||||
if (node.second->getType() == MaterialTreeNode::NodeType::DataNode) {
|
||||
auto uuid = node.second->getUUID();
|
||||
auto material = manager->getMaterial(uuid);
|
||||
PyObject* materialPy = new MaterialPy(new Material(*material));
|
||||
list.append(Py::Object(materialPy, true));
|
||||
}
|
||||
else {
|
||||
addMaterials(list, node.second->getFolder());
|
||||
addMaterials(manager, list, node.second->getFolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,13 +339,13 @@ PyObject* MaterialManagerPy::filterMaterials(PyObject* args, PyObject* kwds)
|
||||
|
||||
auto filter = std::make_shared<MaterialFilter>(*(static_cast<MaterialFilterPy*>(filterPy)->getMaterialFilterPtr()));
|
||||
|
||||
auto libraries = getMaterialManagerPtr()->getMaterialLibraries();
|
||||
auto libraries = getMaterialManagerPtr()->getLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto lib : *libraries) {
|
||||
auto tree = getMaterialManagerPtr()->getMaterialTree(lib, filter, options);
|
||||
if (tree->size() > 0) {
|
||||
addMaterials(list, tree);
|
||||
addMaterials(getMaterialManagerPtr(), list, tree);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
31
src/Mod/Material/App/MaterialPropertyPy.xml
Normal file
31
src/Mod/Material/App/MaterialPropertyPy.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="ModelPropertyPy"
|
||||
Name="MaterialPropertyPy"
|
||||
Twin="MaterialProperty"
|
||||
TwinPointer="MaterialProperty"
|
||||
Include="Mod/Material/App/Materials.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Mod/Material/App/Model.h"
|
||||
FatherNamespace="Materials"
|
||||
Constructor="true"
|
||||
Delete="false">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material property descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="Value" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The value of the material property.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Value" Type="Object"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Empty" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>The property value is undefined.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Empty" Type="Boolean"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
74
src/Mod/Material/App/MaterialPropertyPyImp.cpp
Normal file
74
src/Mod/Material/App/MaterialPropertyPyImp.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/***************************************************************************
|
||||
* 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 "Model.h"
|
||||
#include "PyVariants.h"
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "MaterialPropertyPy.h"
|
||||
|
||||
#include "MaterialPropertyPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialPropertyPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<MaterialProperty object at " << getMaterialPropertyPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialPropertyPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialPropertyPy(new MaterialProperty());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialPropertyPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::Object MaterialPropertyPy::getValue() const
|
||||
{
|
||||
auto value = getMaterialPropertyPtr()->getValue();
|
||||
|
||||
return Py::Object(_pyObjectFromVariant(value), true);
|
||||
}
|
||||
|
||||
Py::Boolean MaterialPropertyPy::getEmpty() const
|
||||
{
|
||||
return getMaterialPropertyPtr()->isEmpty();
|
||||
}
|
||||
|
||||
PyObject* MaterialPropertyPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialPropertyPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="true">
|
||||
<Attribute Name="Directory" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Model directory relative to the library root.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -69,7 +69,7 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Reference" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Parent" ReadOnly="true">
|
||||
<Attribute Name="Parent" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Parent material UUID.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -210,6 +210,17 @@
|
||||
<UserDocu>Set the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="PropertyObjects" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Dictionary of MaterialProperty objects.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="PropertyObjects" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Methode Name="keys" NoArgs="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property keys</UserDocu>
|
||||
|
||||
@@ -36,15 +36,15 @@
|
||||
#include "MaterialLibrary.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "MaterialValue.h"
|
||||
#include "PyVariants.h"
|
||||
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "MaterialPropertyPy.h"
|
||||
|
||||
#include "MaterialPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// Forward declaration
|
||||
static PyObject* _pyObjectFromVariant(const QVariant& value);
|
||||
static Py::List getList(const QVariant& value);
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialPy::representation() const
|
||||
{
|
||||
@@ -68,19 +68,34 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
Py::String MaterialPy::getLibraryName() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return {library ? library->getName().toStdString() : ""};
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return {materialLibrary ? materialLibrary->getName().toStdString() : ""};
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryRoot() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return {library ? library->getDirectoryPath().toStdString() : ""};
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return {materialLibrary ? materialLibrary->getDirectoryPath().toStdString() : ""};
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryIcon() const
|
||||
{
|
||||
auto library = getMaterialPtr()->getLibrary();
|
||||
return {library ? library->getIconPath().toStdString() : ""};
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
return {materialLibrary ? materialLibrary->getIconPath().toStdString() : ""};
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getName() const
|
||||
@@ -98,6 +113,11 @@ Py::String MaterialPy::getDirectory() const
|
||||
return {getMaterialPtr()->getDirectory().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setDirectory(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setDirectory(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getUUID() const
|
||||
{
|
||||
return {getMaterialPtr()->getUUID().toStdString()};
|
||||
@@ -138,6 +158,11 @@ Py::String MaterialPy::getParent() const
|
||||
return {getMaterialPtr()->getParentUUID().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setParent(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setParentUUID(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getAuthorAndLicense() const
|
||||
{
|
||||
return {getMaterialPtr()->getAuthorAndLicense().toStdString()};
|
||||
@@ -438,52 +463,6 @@ Py::Dict MaterialPy::getLegacyProperties() const
|
||||
return dict;
|
||||
}
|
||||
|
||||
static Py::List getList(const QVariant& value)
|
||||
{
|
||||
auto listValue = value.value<QList<QVariant>>();
|
||||
Py::List list;
|
||||
|
||||
for (auto& it : listValue) {
|
||||
list.append(Py::Object(_pyObjectFromVariant(it)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static PyObject* _pyObjectFromVariant(const QVariant& value)
|
||||
{
|
||||
if (value.isNull()) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (value.userType() == qMetaTypeId<Base::Quantity>()) {
|
||||
return new Base::QuantityPy(new Base::Quantity(value.value<Base::Quantity>()));
|
||||
}
|
||||
if (value.userType() == QMetaType::Double) {
|
||||
return PyFloat_FromDouble(value.toDouble());
|
||||
}
|
||||
if (value.userType() == QMetaType::Float) {
|
||||
return PyFloat_FromDouble(value.toFloat());
|
||||
}
|
||||
if (value.userType() == QMetaType::Int) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
if (value.userType() == QMetaType::Long) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
if (value.userType() == QMetaType::Bool) {
|
||||
return Py::new_reference_to(Py::Boolean(value.toBool()));
|
||||
}
|
||||
if (value.userType() == QMetaType::QString) {
|
||||
return PyUnicode_FromString(value.toString().toStdString().c_str());
|
||||
}
|
||||
if (value.userType() == qMetaTypeId<QList<QVariant>>()) {
|
||||
return Py::new_reference_to(getList(value));
|
||||
}
|
||||
|
||||
throw UnknownValueType();
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::getPhysicalValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
@@ -502,13 +481,13 @@ PyObject* MaterialPy::getPhysicalValue(PyObject* args)
|
||||
|
||||
if (property->getType() == MaterialValue::Array2D) {
|
||||
auto value =
|
||||
std::static_pointer_cast<Materials::Material2DArray>(property->getMaterialValue());
|
||||
return new Array2DPy(new Material2DArray(*value));
|
||||
std::static_pointer_cast<Materials::Array2D>(property->getMaterialValue());
|
||||
return new Array2DPy(new Array2D(*value));
|
||||
}
|
||||
if (property->getType() == MaterialValue::Array3D) {
|
||||
auto value =
|
||||
std::static_pointer_cast<Materials::Material3DArray>(property->getMaterialValue());
|
||||
return new Array3DPy(new Material3DArray(*value));
|
||||
std::static_pointer_cast<Materials::Array3D>(property->getMaterialValue());
|
||||
return new Array3DPy(new Array3D(*value));
|
||||
}
|
||||
|
||||
QVariant value = property->getValue();
|
||||
@@ -523,8 +502,7 @@ PyObject* MaterialPy::setPhysicalValue(PyObject* args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->setPhysicalValue(QString::fromStdString(name),
|
||||
QString::fromStdString(value));
|
||||
getMaterialPtr()->setPhysicalValue(QString::fromStdString(name), QString::fromStdString(value));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
@@ -536,7 +514,27 @@ PyObject* MaterialPy::getAppearanceValue(PyObject* args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVariant value = getMaterialPtr()->getAppearanceValue(QString::fromStdString(name));
|
||||
if (!getMaterialPtr()->hasAppearanceProperty(QString::fromStdString(name))) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
auto property = getMaterialPtr()->getAppearanceProperty(QString::fromStdString(name));
|
||||
if (!property) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (property->getType() == MaterialValue::Array2D) {
|
||||
auto value =
|
||||
std::static_pointer_cast<Materials::Array2D>(property->getMaterialValue());
|
||||
return new Array2DPy(new Array2D(*value));
|
||||
}
|
||||
if (property->getType() == MaterialValue::Array3D) {
|
||||
auto value =
|
||||
std::static_pointer_cast<Materials::Array3D>(property->getMaterialValue());
|
||||
return new Array3DPy(new Array3D(*value));
|
||||
}
|
||||
|
||||
QVariant value = property->getValue();
|
||||
return _pyObjectFromVariant(value);
|
||||
}
|
||||
|
||||
@@ -553,6 +551,93 @@ PyObject* MaterialPy::setAppearanceValue(PyObject* args)
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject* MaterialPy::setValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
char* value;
|
||||
PyObject* listObj;
|
||||
PyObject* arrayObj;
|
||||
if (PyArg_ParseTuple(args, "ss", &name, &value)) {
|
||||
getMaterialPtr()->setValue(QString::fromStdString(name), QString::fromStdString(value));
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "sO!", &name, &PyList_Type, &listObj)) {
|
||||
QList<QVariant> variantList;
|
||||
Py::List list(listObj);
|
||||
for (auto itemObj : list) {
|
||||
Py::String item(itemObj);
|
||||
QString value(QString::fromStdString(item.as_string()));
|
||||
QVariant variant = QVariant::fromValue(value);
|
||||
variantList.append(variant);
|
||||
}
|
||||
|
||||
getMaterialPtr()->setValue(QString::fromStdString(name), variantList);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "sO!", &name, &(Array2DPy::Type), &arrayObj)) {
|
||||
auto array = static_cast<Array2DPy*>(arrayObj);
|
||||
auto shared = std::make_shared<Array2D>(*array->getArray2DPtr());
|
||||
|
||||
getMaterialPtr()->setValue(QString::fromStdString(name), shared);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "sO!", &name, &(Array3DPy::Type), &arrayObj)) {
|
||||
auto array = static_cast<Array3DPy*>(arrayObj);
|
||||
auto shared = std::make_shared<Array3D>(*array->getArray3DPtr());
|
||||
|
||||
getMaterialPtr()->setValue(QString::fromStdString(name), shared);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Either a string, a list, or an array are expected");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Dict MaterialPy::getPropertyObjects() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
auto properties = getMaterialPtr()->getPhysicalProperties();
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
|
||||
// if (materialProperty->getType() == MaterialValue::Array2D) {
|
||||
// auto value = std::static_pointer_cast<Materials::Array2D>(
|
||||
// materialProperty->getMaterialValue());
|
||||
// dict.setItem(Py::String(key.toStdString()),
|
||||
// Py::Object(new Array2DPy(new Array2D(*value)), true));
|
||||
// }
|
||||
// else if (materialProperty->getType() == MaterialValue::Array3D) {
|
||||
// auto value = std::static_pointer_cast<Materials::Array3D>(
|
||||
// materialProperty->getMaterialValue());
|
||||
// dict.setItem(Py::String(key.toStdString()),
|
||||
// Py::Object(new Array3DPy(new Array3D(*value)), true));
|
||||
// }
|
||||
// else {
|
||||
dict.setItem(
|
||||
Py::String(key.toStdString()),
|
||||
Py::Object(new MaterialPropertyPy(new MaterialProperty(materialProperty)), true));
|
||||
// }
|
||||
}
|
||||
|
||||
properties = getMaterialPtr()->getAppearanceProperties();
|
||||
for (auto& it : properties) {
|
||||
QString key = it.first;
|
||||
auto materialProperty = it.second;
|
||||
dict.setItem(
|
||||
Py::String(key.toStdString()),
|
||||
Py::Object(new MaterialPropertyPy(new MaterialProperty(materialProperty)), true));
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::keys()
|
||||
{
|
||||
@@ -584,4 +669,4 @@ PyObject* MaterialPy::mapping_subscript(PyObject* self, PyObject* key)
|
||||
{
|
||||
Py::Dict dict = static_cast<MaterialPy*>(self)->getProperties();
|
||||
return Py::new_reference_to(dict.getItem(Py::Object(key)));
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,44 @@ bool MaterialValue::operator==(const MaterialValue& other) const
|
||||
return (_valueType == other._valueType) && (_value == other._value);
|
||||
}
|
||||
|
||||
void MaterialValue::validate(const MaterialValue& other) const
|
||||
{
|
||||
if (_valueType != other._valueType) {
|
||||
throw InvalidProperty("Material property value types don't match");
|
||||
}
|
||||
if (_valueType == Quantity) {
|
||||
auto q1 = _value.value<Base::Quantity>();
|
||||
auto q2 = other._value.value<Base::Quantity>();
|
||||
if (q1.isValid()) {
|
||||
if (!q2.isValid()) {
|
||||
throw InvalidProperty("Invalid remote Material property quantity value");
|
||||
}
|
||||
if (q1.getUserString() != q2.getUserString()) {
|
||||
// Direct comparisons of the quantities may have precision issues
|
||||
// throw InvalidProperty("Material property quantity values don't match");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (q2.isValid()) {
|
||||
throw InvalidProperty("Remote Material property quantity should not have a value");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_valueType == Array2D) {
|
||||
auto a1 = static_cast<const Materials::Array2D*>(this);
|
||||
auto a2 = static_cast<const Materials::Array2D*>(&other);
|
||||
a1->validate(*a2);
|
||||
}
|
||||
else if (_valueType == Array3D) {
|
||||
auto a1 = static_cast<const Materials::Array3D*>(this);
|
||||
auto a2 = static_cast<const Materials::Array3D*>(&other);
|
||||
a1->validate(*a2);
|
||||
}
|
||||
else if (!(_value.isNull() && other._value.isNull()) && (_value != other._value)) {
|
||||
throw InvalidProperty("Material property values don't match");
|
||||
}
|
||||
}
|
||||
|
||||
QString MaterialValue::escapeString(const QString& source)
|
||||
{
|
||||
QString res = source;
|
||||
@@ -205,6 +243,11 @@ void MaterialValue::setList(const QList<QVariant>& value)
|
||||
}
|
||||
|
||||
bool MaterialValue::isNull() const
|
||||
{
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
bool MaterialValue::isEmpty() const
|
||||
{
|
||||
if (_value.isNull()) {
|
||||
return true;
|
||||
@@ -317,24 +360,24 @@ const Base::QuantityFormat MaterialValue::getQuantityFormat()
|
||||
|
||||
//===
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Material2DArray, Materials::MaterialValue)
|
||||
TYPESYSTEM_SOURCE(Materials::Array2D, Materials::MaterialValue)
|
||||
|
||||
Material2DArray::Material2DArray()
|
||||
: MaterialValue(Array2D, Array2D)
|
||||
Array2D::Array2D()
|
||||
: MaterialValue(MaterialValue::Array2D, MaterialValue::Array2D)
|
||||
, _columns(0)
|
||||
{
|
||||
// Initialize separatelt to prevent recursion
|
||||
// setType(Array2D);
|
||||
}
|
||||
|
||||
Material2DArray::Material2DArray(const Material2DArray& other)
|
||||
Array2D::Array2D(const Array2D& other)
|
||||
: MaterialValue(other)
|
||||
, _columns(other._columns)
|
||||
{
|
||||
deepCopy(other);
|
||||
}
|
||||
|
||||
Material2DArray& Material2DArray::operator=(const Material2DArray& other)
|
||||
Array2D& Array2D::operator=(const Array2D& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
@@ -348,7 +391,7 @@ Material2DArray& Material2DArray::operator=(const Material2DArray& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Material2DArray::deepCopy(const Material2DArray& other)
|
||||
void Array2D::deepCopy(const Array2D& other)
|
||||
{
|
||||
// Deep copy
|
||||
for (auto& row : other._rows) {
|
||||
@@ -361,26 +404,55 @@ void Material2DArray::deepCopy(const Material2DArray& other)
|
||||
}
|
||||
}
|
||||
|
||||
bool Material2DArray::isNull() const
|
||||
bool Array2D::isNull() const
|
||||
{
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
bool Array2D::isEmpty() const
|
||||
{
|
||||
return rows() <= 0;
|
||||
}
|
||||
|
||||
void Material2DArray::validateRow(int row) const
|
||||
void Array2D::validateRow(int row) const
|
||||
{
|
||||
if (row < 0 || row >= rows()) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void Material2DArray::validateColumn(int column) const
|
||||
void Array2D::validateColumn(int column) const
|
||||
{
|
||||
if (column < 0 || column >= columns()) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<QVariant>> Material2DArray::getRow(int row) const
|
||||
void Array2D::validate(const Array2D& other) const
|
||||
{
|
||||
if (rows() != other.rows()) {
|
||||
Base::Console().Log("Local row count %d, remote %d\n", rows(), other.rows());
|
||||
throw InvalidProperty("Material property value row counts don't match");
|
||||
}
|
||||
if (columns() != other.columns()) {
|
||||
Base::Console().Log("Local column count %d, remote %d\n", columns(), other.columns());
|
||||
throw InvalidProperty("Material property value column counts don't match");
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < rows(); i++) {
|
||||
for (int j = 0; j < columns(); j++) {
|
||||
if (getValue(i, j) != other.getValue(i, j)) {
|
||||
throw InvalidProperty("Material property values don't match");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const InvalidIndex&) {
|
||||
throw InvalidProperty("Material property value invalid array index");
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<QVariant>> Array2D::getRow(int row) const
|
||||
{
|
||||
validateRow(row);
|
||||
|
||||
@@ -392,7 +464,7 @@ std::shared_ptr<QList<QVariant>> Material2DArray::getRow(int row) const
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<QVariant>> Material2DArray::getRow(int row)
|
||||
std::shared_ptr<QList<QVariant>> Array2D::getRow(int row)
|
||||
{
|
||||
validateRow(row);
|
||||
|
||||
@@ -404,17 +476,17 @@ std::shared_ptr<QList<QVariant>> Material2DArray::getRow(int row)
|
||||
}
|
||||
}
|
||||
|
||||
void Material2DArray::addRow(const std::shared_ptr<QList<QVariant>>& row)
|
||||
void Array2D::addRow(const std::shared_ptr<QList<QVariant>>& row)
|
||||
{
|
||||
_rows.push_back(row);
|
||||
}
|
||||
|
||||
void Material2DArray::insertRow(int index, const std::shared_ptr<QList<QVariant>>& row)
|
||||
void Array2D::insertRow(int index, const std::shared_ptr<QList<QVariant>>& row)
|
||||
{
|
||||
_rows.insert(_rows.begin() + index, row);
|
||||
}
|
||||
|
||||
void Material2DArray::deleteRow(int row)
|
||||
void Array2D::deleteRow(int row)
|
||||
{
|
||||
if (row >= static_cast<int>(_rows.size()) || row < 0) {
|
||||
throw InvalidIndex();
|
||||
@@ -422,7 +494,18 @@ void Material2DArray::deleteRow(int row)
|
||||
_rows.erase(_rows.begin() + row);
|
||||
}
|
||||
|
||||
void Material2DArray::setValue(int row, int column, const QVariant& value)
|
||||
void Array2D::setRows(int rowCount)
|
||||
{
|
||||
while (rows() < rowCount) {
|
||||
auto row = std::make_shared<QList<QVariant>>();
|
||||
for (int i = 0; i < columns(); i++) {
|
||||
row->append(QVariant());
|
||||
}
|
||||
addRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
void Array2D::setValue(int row, int column, const QVariant& value)
|
||||
{
|
||||
validateRow(row);
|
||||
validateColumn(column);
|
||||
@@ -436,7 +519,7 @@ void Material2DArray::setValue(int row, int column, const QVariant& value)
|
||||
}
|
||||
}
|
||||
|
||||
QVariant Material2DArray::getValue(int row, int column) const
|
||||
QVariant Array2D::getValue(int row, int column) const
|
||||
{
|
||||
validateColumn(column);
|
||||
|
||||
@@ -449,7 +532,7 @@ QVariant Material2DArray::getValue(int row, int column) const
|
||||
}
|
||||
}
|
||||
|
||||
void Material2DArray::dumpRow(const std::shared_ptr<QList<QVariant>>& row)
|
||||
void Array2D::dumpRow(const std::shared_ptr<QList<QVariant>>& row)
|
||||
{
|
||||
Base::Console().Log("row: ");
|
||||
for (auto& column : *row) {
|
||||
@@ -458,14 +541,14 @@ void Material2DArray::dumpRow(const std::shared_ptr<QList<QVariant>>& row)
|
||||
Base::Console().Log("\n");
|
||||
}
|
||||
|
||||
void Material2DArray::dump() const
|
||||
void Array2D::dump() const
|
||||
{
|
||||
for (auto& row : _rows) {
|
||||
dumpRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
QString Material2DArray::getYAMLString() const
|
||||
QString Array2D::getYAMLString() const
|
||||
{
|
||||
if (isNull()) {
|
||||
return QString();
|
||||
@@ -511,10 +594,10 @@ QString Material2DArray::getYAMLString() const
|
||||
|
||||
//===
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Material3DArray, Materials::MaterialValue)
|
||||
TYPESYSTEM_SOURCE(Materials::Array3D, Materials::MaterialValue)
|
||||
|
||||
Material3DArray::Material3DArray()
|
||||
: MaterialValue(Array3D, Array3D)
|
||||
Array3D::Array3D()
|
||||
: MaterialValue(MaterialValue::Array3D, MaterialValue::Array3D)
|
||||
, _currentDepth(0)
|
||||
, _columns(0)
|
||||
{
|
||||
@@ -522,26 +605,71 @@ Material3DArray::Material3DArray()
|
||||
// setType(Array3D);
|
||||
}
|
||||
|
||||
bool Material3DArray::isNull() const
|
||||
Array3D::Array3D(const Array3D& other)
|
||||
: MaterialValue(other)
|
||||
, _currentDepth(other._currentDepth)
|
||||
, _columns(other._columns)
|
||||
{
|
||||
deepCopy(other);
|
||||
}
|
||||
|
||||
Array3D& Array3D::operator=(const Array3D& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
MaterialValue::operator=(other);
|
||||
_columns = other._columns;
|
||||
_currentDepth = other._currentDepth;
|
||||
|
||||
deepCopy(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Array3D::deepCopy(const Array3D& other)
|
||||
{
|
||||
// Deep copy
|
||||
_rowMap.clear();
|
||||
for (auto& depthTable : other._rowMap) {
|
||||
auto depth = addDepth(depthTable.first);
|
||||
auto rows = depthTable.second;
|
||||
for (auto row : *rows) {
|
||||
auto newRow = std::make_shared<QList<Base::Quantity>>();
|
||||
for (auto column : *row) {
|
||||
newRow->append(column);
|
||||
}
|
||||
addRow(depth, newRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Array3D::isNull() const
|
||||
{
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
bool Array3D::isEmpty() const
|
||||
{
|
||||
return depth() <= 0;
|
||||
}
|
||||
|
||||
void Material3DArray::validateDepth(int level) const
|
||||
void Array3D::validateDepth(int level) const
|
||||
{
|
||||
if (level < 0 || level >= depth()) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::validateColumn(int column) const
|
||||
void Array3D::validateColumn(int column) const
|
||||
{
|
||||
if (column < 0 || column >= columns()) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::validateRow(int level, int row) const
|
||||
void Array3D::validateRow(int level, int row) const
|
||||
{
|
||||
validateDepth(level);
|
||||
|
||||
@@ -550,8 +678,18 @@ void Material3DArray::validateRow(int level, int row) const
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::validate(const Array3D& other) const
|
||||
{
|
||||
if (depth() != other.depth()) {
|
||||
throw InvalidProperty("Material property value row counts don't match");
|
||||
}
|
||||
if (columns() != other.columns()) {
|
||||
throw InvalidProperty("Material property value column counts don't match");
|
||||
}
|
||||
}
|
||||
|
||||
const std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>&
|
||||
Material3DArray::getTable(const Base::Quantity& depth) const
|
||||
Array3D::getTable(const Base::Quantity& depth) const
|
||||
{
|
||||
for (auto& it : _rowMap) {
|
||||
if (std::get<0>(it) == depth) {
|
||||
@@ -563,7 +701,7 @@ Material3DArray::getTable(const Base::Quantity& depth) const
|
||||
}
|
||||
|
||||
const std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>&
|
||||
Material3DArray::getTable(int depthIndex) const
|
||||
Array3D::getTable(int depthIndex) const
|
||||
{
|
||||
try {
|
||||
return std::get<1>(_rowMap.at(depthIndex));
|
||||
@@ -573,7 +711,7 @@ Material3DArray::getTable(int depthIndex) const
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int depth, int row) const
|
||||
std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int depth, int row) const
|
||||
{
|
||||
validateRow(depth, row);
|
||||
|
||||
@@ -585,13 +723,13 @@ std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int depth, int ro
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int row) const
|
||||
std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int row) const
|
||||
{
|
||||
// Check if we can convert otherwise throw error
|
||||
return getRow(_currentDepth, row);
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int depth, int row)
|
||||
std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int depth, int row)
|
||||
{
|
||||
validateRow(depth, row);
|
||||
|
||||
@@ -603,12 +741,12 @@ std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int depth, int ro
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QList<Base::Quantity>> Material3DArray::getRow(int row)
|
||||
std::shared_ptr<QList<Base::Quantity>> Array3D::getRow(int row)
|
||||
{
|
||||
return getRow(_currentDepth, row);
|
||||
}
|
||||
|
||||
void Material3DArray::addRow(int depth, const std::shared_ptr<QList<Base::Quantity>>& row)
|
||||
void Array3D::addRow(int depth, const std::shared_ptr<QList<Base::Quantity>>& row)
|
||||
{
|
||||
try {
|
||||
getTable(depth)->push_back(row);
|
||||
@@ -618,12 +756,12 @@ void Material3DArray::addRow(int depth, const std::shared_ptr<QList<Base::Quanti
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::addRow(const std::shared_ptr<QList<Base::Quantity>>& row)
|
||||
void Array3D::addRow(const std::shared_ptr<QList<Base::Quantity>>& row)
|
||||
{
|
||||
addRow(_currentDepth, row);
|
||||
}
|
||||
|
||||
int Material3DArray::addDepth(int depth, const Base::Quantity& value)
|
||||
int Array3D::addDepth(int depth, const Base::Quantity& value)
|
||||
{
|
||||
if (depth == this->depth()) {
|
||||
// Append to the end
|
||||
@@ -639,7 +777,7 @@ int Material3DArray::addDepth(int depth, const Base::Quantity& value)
|
||||
return depth;
|
||||
}
|
||||
|
||||
int Material3DArray::addDepth(const Base::Quantity& value)
|
||||
int Array3D::addDepth(const Base::Quantity& value)
|
||||
{
|
||||
auto rowVector = std::make_shared<QList<std::shared_ptr<QList<Base::Quantity>>>>();
|
||||
auto entry = std::make_pair(value, rowVector);
|
||||
@@ -648,13 +786,22 @@ int Material3DArray::addDepth(const Base::Quantity& value)
|
||||
return depth() - 1;
|
||||
}
|
||||
|
||||
void Material3DArray::deleteDepth(int depth)
|
||||
void Array3D::deleteDepth(int depth)
|
||||
{
|
||||
deleteRows(depth); // This may throw an InvalidIndex
|
||||
_rowMap.erase(_rowMap.begin() + depth);
|
||||
}
|
||||
|
||||
void Material3DArray::insertRow(int depth,
|
||||
void Array3D::setDepth(int depthCount)
|
||||
{
|
||||
Base::Quantity dummy;
|
||||
dummy.setInvalid();
|
||||
while (depth() < depthCount) {
|
||||
addDepth(dummy);
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::insertRow(int depth,
|
||||
int row,
|
||||
const std::shared_ptr<QList<Base::Quantity>>& rowData)
|
||||
{
|
||||
@@ -667,12 +814,12 @@ void Material3DArray::insertRow(int depth,
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::insertRow(int row, const std::shared_ptr<QList<Base::Quantity>>& rowData)
|
||||
void Array3D::insertRow(int row, const std::shared_ptr<QList<Base::Quantity>>& rowData)
|
||||
{
|
||||
insertRow(_currentDepth, row, rowData);
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRow(int depth, int row)
|
||||
void Array3D::deleteRow(int depth, int row)
|
||||
{
|
||||
auto table = getTable(depth);
|
||||
if (row >= static_cast<int>(table->size()) || row < 0) {
|
||||
@@ -681,23 +828,23 @@ void Material3DArray::deleteRow(int depth, int row)
|
||||
table->erase(table->begin() + row);
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRow(int row)
|
||||
void Array3D::deleteRow(int row)
|
||||
{
|
||||
deleteRow(_currentDepth, row);
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRows(int depth)
|
||||
void Array3D::deleteRows(int depth)
|
||||
{
|
||||
auto table = getTable(depth);
|
||||
table->clear();
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRows()
|
||||
void Array3D::deleteRows()
|
||||
{
|
||||
deleteRows(_currentDepth);
|
||||
}
|
||||
|
||||
int Material3DArray::rows(int depth) const
|
||||
int Array3D::rows(int depth) const
|
||||
{
|
||||
if (depth < 0 || (depth == 0 && this->depth() == 0)) {
|
||||
return 0;
|
||||
@@ -707,7 +854,21 @@ int Material3DArray::rows(int depth) const
|
||||
return getTable(depth)->size();
|
||||
}
|
||||
|
||||
void Material3DArray::setValue(int depth, int row, int column, const Base::Quantity& value)
|
||||
void Array3D::setRows(int depth, int rowCount)
|
||||
{
|
||||
Base::Quantity dummy;
|
||||
dummy.setInvalid();
|
||||
|
||||
while (rows(depth) < rowCount) {
|
||||
auto row = std::make_shared<QList<Base::Quantity>>();
|
||||
for (int i = 0; i < columns(); i++) {
|
||||
row->append(dummy);
|
||||
}
|
||||
addRow(depth, row);
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::setValue(int depth, int row, int column, const Base::Quantity& value)
|
||||
{
|
||||
validateRow(depth, row);
|
||||
validateColumn(column);
|
||||
@@ -721,12 +882,12 @@ void Material3DArray::setValue(int depth, int row, int column, const Base::Quant
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::setValue(int row, int column, const Base::Quantity& value)
|
||||
void Array3D::setValue(int row, int column, const Base::Quantity& value)
|
||||
{
|
||||
setValue(_currentDepth, row, column, value);
|
||||
}
|
||||
|
||||
void Material3DArray::setDepthValue(int depth, const Base::Quantity& value)
|
||||
void Array3D::setDepthValue(int depth, const Base::Quantity& value)
|
||||
{
|
||||
try {
|
||||
auto oldRows = getTable(depth);
|
||||
@@ -737,13 +898,13 @@ void Material3DArray::setDepthValue(int depth, const Base::Quantity& value)
|
||||
}
|
||||
}
|
||||
|
||||
void Material3DArray::setDepthValue(const Base::Quantity& value)
|
||||
void Array3D::setDepthValue(const Base::Quantity& value)
|
||||
{
|
||||
setDepthValue(_currentDepth, value);
|
||||
}
|
||||
|
||||
|
||||
Base::Quantity Material3DArray::getValue(int depth, int row, int column) const
|
||||
Base::Quantity Array3D::getValue(int depth, int row, int column) const
|
||||
{
|
||||
// getRow validates depth and row. Do that first
|
||||
auto val = getRow(depth, row);
|
||||
@@ -757,12 +918,12 @@ Base::Quantity Material3DArray::getValue(int depth, int row, int column) const
|
||||
}
|
||||
}
|
||||
|
||||
Base::Quantity Material3DArray::getValue(int row, int column) const
|
||||
Base::Quantity Array3D::getValue(int row, int column) const
|
||||
{
|
||||
return getValue(_currentDepth, row, column);
|
||||
}
|
||||
|
||||
Base::Quantity Material3DArray::getDepthValue(int depth) const
|
||||
Base::Quantity Array3D::getDepthValue(int depth) const
|
||||
{
|
||||
validateDepth(depth);
|
||||
|
||||
@@ -774,12 +935,12 @@ Base::Quantity Material3DArray::getDepthValue(int depth) const
|
||||
}
|
||||
}
|
||||
|
||||
int Material3DArray::currentDepth() const
|
||||
int Array3D::currentDepth() const
|
||||
{
|
||||
return _currentDepth;
|
||||
}
|
||||
|
||||
void Material3DArray::setCurrentDepth(int depth)
|
||||
void Array3D::setCurrentDepth(int depth)
|
||||
{
|
||||
validateDepth(depth);
|
||||
|
||||
@@ -794,7 +955,7 @@ void Material3DArray::setCurrentDepth(int depth)
|
||||
}
|
||||
}
|
||||
|
||||
QString Material3DArray::getYAMLString() const
|
||||
QString Array3D::getYAMLString() const
|
||||
{
|
||||
if (isNull()) {
|
||||
return QString();
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
return _value.value<QList<QVariant>>();
|
||||
}
|
||||
virtual bool isNull() const;
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
virtual const QVariant getValueAt(const QVariant& value) const
|
||||
{
|
||||
@@ -111,6 +112,8 @@ public:
|
||||
|
||||
// The precision is based on the value from the original materials editor
|
||||
static const int PRECISION = 6;
|
||||
|
||||
void validate(const MaterialValue& other) const;
|
||||
|
||||
protected:
|
||||
MaterialValue(ValueType type, ValueType inherited);
|
||||
@@ -133,18 +136,19 @@ private:
|
||||
static QMap<QString, ValueType> _typeMap;
|
||||
};
|
||||
|
||||
class MaterialsExport Material2DArray: public MaterialValue
|
||||
class MaterialsExport Array2D: public MaterialValue
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
Material2DArray();
|
||||
Material2DArray(const Material2DArray& other);
|
||||
~Material2DArray() override = default;
|
||||
Array2D();
|
||||
Array2D(const Array2D& other);
|
||||
~Array2D() override = default;
|
||||
|
||||
Material2DArray& operator=(const Material2DArray& other);
|
||||
Array2D& operator=(const Array2D& other);
|
||||
|
||||
bool isNull() const override;
|
||||
bool isEmpty() const override;
|
||||
|
||||
const QList<std::shared_ptr<QList<QVariant>>>& getArray() const
|
||||
{
|
||||
@@ -153,6 +157,7 @@ public:
|
||||
|
||||
void validateRow(int row) const;
|
||||
void validateColumn(int column) const;
|
||||
void validate(const Array2D& other) const;
|
||||
|
||||
std::shared_ptr<QList<QVariant>> getRow(int row) const;
|
||||
std::shared_ptr<QList<QVariant>> getRow(int row);
|
||||
@@ -171,6 +176,7 @@ public:
|
||||
void addRow(const std::shared_ptr<QList<QVariant>>& row);
|
||||
void insertRow(int index, const std::shared_ptr<QList<QVariant>>& row);
|
||||
void deleteRow(int row);
|
||||
void setRows(int rowCount);
|
||||
|
||||
void setValue(int row, int column, const QVariant& value);
|
||||
QVariant getValue(int row, int column) const;
|
||||
@@ -178,7 +184,7 @@ public:
|
||||
QString getYAMLString() const override;
|
||||
|
||||
protected:
|
||||
void deepCopy(const Material2DArray& other);
|
||||
void deepCopy(const Array2D& other);
|
||||
|
||||
QList<std::shared_ptr<QList<QVariant>>> _rows;
|
||||
int _columns;
|
||||
@@ -188,15 +194,19 @@ private:
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
class MaterialsExport Material3DArray: public MaterialValue
|
||||
class MaterialsExport Array3D: public MaterialValue
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
Material3DArray();
|
||||
~Material3DArray() override = default;
|
||||
Array3D();
|
||||
Array3D(const Array3D& other);
|
||||
~Array3D() override = default;
|
||||
|
||||
Array3D& operator=(const Array3D& other);
|
||||
|
||||
bool isNull() const override;
|
||||
bool isEmpty() const override;
|
||||
|
||||
const QList<
|
||||
std::pair<Base::Quantity, std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>>>&
|
||||
@@ -208,6 +218,7 @@ public:
|
||||
void validateDepth(int level) const;
|
||||
void validateColumn(int column) const;
|
||||
void validateRow(int level, int row) const;
|
||||
void validate(const Array3D& other) const;
|
||||
|
||||
const std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>&
|
||||
getTable(const Base::Quantity& depth) const;
|
||||
@@ -245,6 +256,8 @@ public:
|
||||
{
|
||||
_columns = size;
|
||||
}
|
||||
void setDepth(int depthCount);
|
||||
void setRows(int depth, int rowCount);
|
||||
|
||||
void setValue(int depth, int row, int column, const Base::Quantity& value);
|
||||
void setValue(int row, int column, const Base::Quantity& value);
|
||||
@@ -260,6 +273,8 @@ public:
|
||||
QString getYAMLString() const override;
|
||||
|
||||
protected:
|
||||
void deepCopy(const Array3D& other);
|
||||
|
||||
QList<std::pair<Base::Quantity, std::shared_ptr<QList<std::shared_ptr<QList<Base::Quantity>>>>>>
|
||||
_rowMap;
|
||||
int _currentDepth;
|
||||
@@ -269,7 +284,7 @@ protected:
|
||||
} // namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(Materials::MaterialValue)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material2DArray>)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material3DArray>)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Array2D>)
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Array3D>)
|
||||
|
||||
#endif // MATERIAL_MATERIALVALUE_H
|
||||
|
||||
@@ -65,11 +65,11 @@ void MaterialProperty::copyValuePtr(const std::shared_ptr<MaterialValue>& value)
|
||||
{
|
||||
if (value->getType() == MaterialValue::Array2D) {
|
||||
_valuePtr =
|
||||
std::make_shared<Material2DArray>(*(std::static_pointer_cast<Material2DArray>(value)));
|
||||
std::make_shared<Array2D>(*(std::static_pointer_cast<Array2D>(value)));
|
||||
}
|
||||
else if (value->getType() == MaterialValue::Array3D) {
|
||||
_valuePtr =
|
||||
std::make_shared<Material3DArray>(*(std::static_pointer_cast<Material3DArray>(value)));
|
||||
std::make_shared<Array3D>(*(std::static_pointer_cast<Array3D>(value)));
|
||||
}
|
||||
else {
|
||||
_valuePtr = std::make_shared<MaterialValue>(*value);
|
||||
@@ -132,7 +132,7 @@ QString MaterialProperty::getString() const
|
||||
if (value.isNull()) {
|
||||
return {};
|
||||
}
|
||||
return QString(QLatin1String("%L1")).arg(value.toFloat(), 0, 'g', MaterialValue::PRECISION);
|
||||
return QString(QStringLiteral("%L1")).arg(value.toFloat(), 0, 'g', MaterialValue::PRECISION);
|
||||
}
|
||||
return getValue().toString();
|
||||
}
|
||||
@@ -177,7 +177,7 @@ QString MaterialProperty::getDictionaryString() const
|
||||
}
|
||||
if (getType() == MaterialValue::Quantity) {
|
||||
auto quantity = getValue().value<Base::Quantity>();
|
||||
auto string = QString(QLatin1String("%1 %2"))
|
||||
auto string = QString(QStringLiteral("%1 %2"))
|
||||
.arg(quantity.getValue(), 0, 'g', MaterialValue::PRECISION)
|
||||
.arg(QString::fromStdString(quantity.getUnit().getString()));
|
||||
return string;
|
||||
@@ -187,7 +187,7 @@ QString MaterialProperty::getDictionaryString() const
|
||||
if (value.isNull()) {
|
||||
return {};
|
||||
}
|
||||
return QString(QLatin1String("%1")).arg(value.toFloat(), 0, 'g', MaterialValue::PRECISION);
|
||||
return QString(QStringLiteral("%1")).arg(value.toFloat(), 0, 'g', MaterialValue::PRECISION);
|
||||
}
|
||||
return getValue().toString();
|
||||
}
|
||||
@@ -205,12 +205,12 @@ void MaterialProperty::setType(const QString& type)
|
||||
throw UnknownValueType();
|
||||
}
|
||||
if (mappedType == MaterialValue::Array2D) {
|
||||
auto arrayPtr = std::make_shared<Material2DArray>();
|
||||
auto arrayPtr = std::make_shared<Array2D>();
|
||||
arrayPtr->setColumns(columns());
|
||||
_valuePtr = arrayPtr;
|
||||
}
|
||||
else if (mappedType == MaterialValue::Array3D) {
|
||||
auto arrayPtr = std::make_shared<Material3DArray>();
|
||||
auto arrayPtr = std::make_shared<Array3D>();
|
||||
// First column is third dimension
|
||||
arrayPtr->setColumns(columns() - 1);
|
||||
_valuePtr = arrayPtr;
|
||||
@@ -448,6 +448,17 @@ bool MaterialProperty::operator==(const MaterialProperty& other) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialProperty::validate(const MaterialProperty& other) const {
|
||||
_valuePtr->validate(*other._valuePtr);
|
||||
|
||||
if (_columns.size() != other._columns.size()) {
|
||||
throw InvalidProperty("Model property column counts don't match");
|
||||
}
|
||||
for (size_t i = 0; i < _columns.size(); i++) {
|
||||
_columns[i].validate(other._columns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Material, Base::BaseClass)
|
||||
|
||||
Material::Material()
|
||||
@@ -476,6 +487,7 @@ Material::Material(const std::shared_ptr<MaterialLibrary>& library,
|
||||
Material::Material(const Material& other)
|
||||
: _library(other._library)
|
||||
, _directory(other._directory)
|
||||
, _filename(other._filename)
|
||||
, _uuid(other._uuid)
|
||||
, _name(other._name)
|
||||
, _author(other._author)
|
||||
@@ -513,6 +525,31 @@ Material::Material(const Material& other)
|
||||
}
|
||||
}
|
||||
|
||||
QString Material::getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
|
||||
void Material::setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
|
||||
QString Material::getFilename() const
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
||||
void Material::setFilename(const QString& filename)
|
||||
{
|
||||
_filename = filename;
|
||||
}
|
||||
|
||||
QString Material::getFilePath() const
|
||||
{
|
||||
return QDir(_directory + QStringLiteral("/") + _filename).absolutePath();
|
||||
}
|
||||
|
||||
QString Material::getAuthorAndLicense() const
|
||||
{
|
||||
QString authorAndLicense;
|
||||
@@ -521,7 +558,7 @@ QString Material::getAuthorAndLicense() const
|
||||
if (!_author.isNull()) {
|
||||
authorAndLicense = _author;
|
||||
if (!_license.isNull()) {
|
||||
authorAndLicense += QLatin1String(" ") + _license;
|
||||
authorAndLicense += QStringLiteral(" ") + _license;
|
||||
}
|
||||
}
|
||||
else if (!_license.isNull()) {
|
||||
@@ -541,7 +578,7 @@ void Material::addModel(const QString& uuid)
|
||||
|
||||
_allUuids << uuid;
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -641,7 +678,7 @@ void Material::addPhysical(const QString& uuid)
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -688,7 +725,7 @@ void Material::removePhysical(const QString& uuid)
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -718,7 +755,7 @@ void Material::addAppearance(const QString& uuid)
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -759,7 +796,7 @@ void Material::removeAppearance(const QString& uuid)
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -938,6 +975,22 @@ void Material::setValue(const QString& name, const QVariant& value)
|
||||
if (hasPhysicalProperty(name)) {
|
||||
setPhysicalValue(name, value);
|
||||
}
|
||||
else if (hasAppearanceProperty(name)) {
|
||||
setAppearanceValue(name, value);
|
||||
}
|
||||
else {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setValue(const QString& name, const std::shared_ptr<MaterialValue>& value)
|
||||
{
|
||||
if (hasPhysicalProperty(name)) {
|
||||
setPhysicalValue(name, value);
|
||||
}
|
||||
else if (hasAppearanceProperty(name)) {
|
||||
setAppearanceValue(name, value);
|
||||
}
|
||||
else {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
@@ -1045,7 +1098,7 @@ Material::getValueString(const std::map<QString, std::shared_ptr<MaterialPropert
|
||||
if (value.isNull()) {
|
||||
return {};
|
||||
}
|
||||
return QString(QLatin1String("%L1"))
|
||||
return QString(QStringLiteral("%L1"))
|
||||
.arg(value.toFloat(), 0, 'g', MaterialValue::PRECISION);
|
||||
}
|
||||
return property->getValue().toString();
|
||||
@@ -1141,7 +1194,7 @@ bool Material::hasPhysicalModel(const QString& uuid) const
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -1161,7 +1214,7 @@ bool Material::hasAppearanceModel(const QString& uuid) const
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -1181,7 +1234,7 @@ bool Material::isPhysicalModelComplete(const QString& uuid) const
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -1207,7 +1260,7 @@ bool Material::isAppearanceModelComplete(const QString& uuid) const
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
try {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -1252,10 +1305,8 @@ void Material::saveGeneral(QTextStream& stream) const
|
||||
void Material::saveInherits(QTextStream& stream) const
|
||||
{
|
||||
if (!_parentUuid.isEmpty()) {
|
||||
MaterialManager manager;
|
||||
|
||||
try {
|
||||
auto material = manager.getMaterial(_parentUuid);
|
||||
auto material = MaterialManager::getManager().getMaterial(_parentUuid);
|
||||
|
||||
stream << "Inherits:\n";
|
||||
stream << " " << material->getName() << ":\n";
|
||||
@@ -1314,8 +1365,8 @@ void Material::saveModels(QTextStream& stream, bool saveInherited) const
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager modelManager;
|
||||
MaterialManager materialManager;
|
||||
auto modelManager = ModelManager::getManager();
|
||||
auto materialManager = MaterialManager::getManager();
|
||||
|
||||
bool inherited = saveInherited && (_parentUuid.size() > 0);
|
||||
std::shared_ptr<Material> parent;
|
||||
@@ -1368,8 +1419,8 @@ void Material::saveAppearanceModels(QTextStream& stream, bool saveInherited) con
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager modelManager;
|
||||
MaterialManager materialManager;
|
||||
auto modelManager = ModelManager::getManager();
|
||||
auto materialManager = MaterialManager::getManager();
|
||||
|
||||
bool inherited = saveInherited && (_parentUuid.size() > 0);
|
||||
std::shared_ptr<Material> parent;
|
||||
@@ -1421,7 +1472,7 @@ void Material::newUuid()
|
||||
|
||||
QString Material::getModelByName(const QString& name) const
|
||||
{
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
for (auto& it : _allUuids) {
|
||||
try {
|
||||
@@ -1442,8 +1493,7 @@ void Material::save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool s
|
||||
if (saveInherited && !saveAsCopy) {
|
||||
// Check to see if we're an original or if we're already in the list of
|
||||
// models
|
||||
MaterialManager materialManager;
|
||||
if (materialManager.exists(_uuid) && !overwrite) {
|
||||
if (MaterialManager::getManager().exists(_uuid) && !overwrite) {
|
||||
// Make a new version based on the current
|
||||
setParentUUID(_uuid);
|
||||
}
|
||||
@@ -1494,6 +1544,7 @@ Material& Material::operator=(const Material& other)
|
||||
|
||||
_library = other._library;
|
||||
_directory = other._directory;
|
||||
_filename = other._filename;
|
||||
_uuid = other._uuid;
|
||||
_name = other._name;
|
||||
_author = other._author;
|
||||
@@ -1548,20 +1599,20 @@ Material& Material::operator=(const App::Material& other)
|
||||
addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
}
|
||||
|
||||
getAppearanceProperty(QLatin1String("AmbientColor"))->setColor(other.ambientColor);
|
||||
getAppearanceProperty(QLatin1String("DiffuseColor"))->setColor(other.diffuseColor);
|
||||
getAppearanceProperty(QLatin1String("SpecularColor"))->setColor(other.specularColor);
|
||||
getAppearanceProperty(QLatin1String("EmissiveColor"))->setColor(other.emissiveColor);
|
||||
getAppearanceProperty(QLatin1String("Shininess"))->setFloat(other.shininess);
|
||||
getAppearanceProperty(QLatin1String("Transparency"))->setFloat(other.transparency);
|
||||
getAppearanceProperty(QStringLiteral("AmbientColor"))->setColor(other.ambientColor);
|
||||
getAppearanceProperty(QStringLiteral("DiffuseColor"))->setColor(other.diffuseColor);
|
||||
getAppearanceProperty(QStringLiteral("SpecularColor"))->setColor(other.specularColor);
|
||||
getAppearanceProperty(QStringLiteral("EmissiveColor"))->setColor(other.emissiveColor);
|
||||
getAppearanceProperty(QStringLiteral("Shininess"))->setFloat(other.shininess);
|
||||
getAppearanceProperty(QStringLiteral("Transparency"))->setFloat(other.transparency);
|
||||
|
||||
if (!other.image.empty() || !other.imagePath.empty()) {
|
||||
if (!hasAppearanceModel(ModelUUIDs::ModelUUID_Rendering_Texture)) {
|
||||
addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture);
|
||||
}
|
||||
|
||||
getAppearanceProperty(QLatin1String("TextureImage"))->setString(other.image);
|
||||
getAppearanceProperty(QLatin1String("TexturePath"))->setString(other.imagePath);
|
||||
getAppearanceProperty(QStringLiteral("TextureImage"))->setString(other.image);
|
||||
getAppearanceProperty(QStringLiteral("TexturePath"))->setString(other.imagePath);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -1574,7 +1625,7 @@ QStringList Material::normalizeModels(const QStringList& models)
|
||||
{
|
||||
QStringList normalized;
|
||||
|
||||
ModelManager manager;
|
||||
auto manager = ModelManager::getManager();
|
||||
|
||||
for (auto& uuid : models) {
|
||||
auto model = manager.getModel(uuid);
|
||||
@@ -1652,32 +1703,32 @@ App::Material Material::getMaterialAppearance() const
|
||||
App::Material material(App::Material::DEFAULT);
|
||||
|
||||
bool custom = false;
|
||||
if (hasAppearanceProperty(QLatin1String("AmbientColor"))) {
|
||||
material.ambientColor = getAppearanceProperty(QLatin1String("AmbientColor"))->getColor();
|
||||
if (hasAppearanceProperty(QStringLiteral("AmbientColor"))) {
|
||||
material.ambientColor = getAppearanceProperty(QStringLiteral("AmbientColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("DiffuseColor"))) {
|
||||
material.diffuseColor = getAppearanceProperty(QLatin1String("DiffuseColor"))->getColor();
|
||||
if (hasAppearanceProperty(QStringLiteral("DiffuseColor"))) {
|
||||
material.diffuseColor = getAppearanceProperty(QStringLiteral("DiffuseColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("SpecularColor"))) {
|
||||
material.specularColor = getAppearanceProperty(QLatin1String("SpecularColor"))->getColor();
|
||||
if (hasAppearanceProperty(QStringLiteral("SpecularColor"))) {
|
||||
material.specularColor = getAppearanceProperty(QStringLiteral("SpecularColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("EmissiveColor"))) {
|
||||
material.emissiveColor = getAppearanceProperty(QLatin1String("EmissiveColor"))->getColor();
|
||||
if (hasAppearanceProperty(QStringLiteral("EmissiveColor"))) {
|
||||
material.emissiveColor = getAppearanceProperty(QStringLiteral("EmissiveColor"))->getColor();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("Shininess"))) {
|
||||
material.shininess = getAppearanceProperty(QLatin1String("Shininess"))->getFloat();
|
||||
if (hasAppearanceProperty(QStringLiteral("Shininess"))) {
|
||||
material.shininess = getAppearanceProperty(QStringLiteral("Shininess"))->getFloat();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("Transparency"))) {
|
||||
material.transparency = getAppearanceProperty(QLatin1String("Transparency"))->getFloat();
|
||||
if (hasAppearanceProperty(QStringLiteral("Transparency"))) {
|
||||
material.transparency = getAppearanceProperty(QStringLiteral("Transparency"))->getFloat();
|
||||
custom = true;
|
||||
}
|
||||
if (hasAppearanceProperty(QLatin1String("TextureImage"))) {
|
||||
auto property = getAppearanceProperty(QLatin1String("TextureImage"));
|
||||
if (hasAppearanceProperty(QStringLiteral("TextureImage"))) {
|
||||
auto property = getAppearanceProperty(QStringLiteral("TextureImage"));
|
||||
if (!property->isNull()) {
|
||||
Base::Console().Log("Has 'TextureImage'\n");
|
||||
material.image = property->getString().toStdString();
|
||||
@@ -1685,8 +1736,8 @@ App::Material Material::getMaterialAppearance() const
|
||||
|
||||
custom = true;
|
||||
}
|
||||
else if (hasAppearanceProperty(QLatin1String("TexturePath"))) {
|
||||
auto property = getAppearanceProperty(QLatin1String("TexturePath"));
|
||||
else if (hasAppearanceProperty(QStringLiteral("TexturePath"))) {
|
||||
auto property = getAppearanceProperty(QStringLiteral("TexturePath"));
|
||||
if (!property->isNull()) {
|
||||
Base::Console().Log("Has 'TexturePath'\n");
|
||||
material.imagePath = property->getString().toStdString();
|
||||
@@ -1702,3 +1753,98 @@ App::Material Material::getMaterialAppearance() const
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
void Material::validate(const std::shared_ptr<Material>& other) const
|
||||
{
|
||||
|
||||
try {
|
||||
_library->validate(*(other->_library));
|
||||
}
|
||||
catch (const InvalidLibrary& e) {
|
||||
throw InvalidMaterial(e.what());
|
||||
}
|
||||
|
||||
if (_directory != other->_directory) {
|
||||
throw InvalidMaterial("Model directories don't match");
|
||||
}
|
||||
if (!other->_filename.isEmpty()) {
|
||||
throw InvalidMaterial("Remote filename is not empty");
|
||||
}
|
||||
if (_uuid != other->_uuid) {
|
||||
throw InvalidMaterial("Model UUIDs don't match");
|
||||
}
|
||||
if (_name != other->_name) {
|
||||
throw InvalidMaterial("Model names don't match");
|
||||
}
|
||||
if (_author != other->_author) {
|
||||
throw InvalidMaterial("Model authors don't match");
|
||||
}
|
||||
if (_license != other->_license) {
|
||||
throw InvalidMaterial("Model licenses don't match");
|
||||
}
|
||||
if (_parentUuid != other->_parentUuid) {
|
||||
throw InvalidMaterial("Model parents don't match");
|
||||
}
|
||||
if (_description != other->_description) {
|
||||
throw InvalidMaterial("Model descriptions don't match");
|
||||
}
|
||||
if (_url != other->_url) {
|
||||
throw InvalidMaterial("Model URLs don't match");
|
||||
}
|
||||
if (_reference != other->_reference) {
|
||||
throw InvalidMaterial("Model references don't match");
|
||||
}
|
||||
|
||||
if (_tags.size() != other->_tags.size()) {
|
||||
Base::Console().Log("Local tags count %d\n", _tags.size());
|
||||
Base::Console().Log("Remote tags count %d\n", other->_tags.size());
|
||||
throw InvalidMaterial("Material tags counts don't match");
|
||||
}
|
||||
if (!other->_tags.contains(_tags)) {
|
||||
throw InvalidMaterial("Material tags don't match");
|
||||
}
|
||||
|
||||
if (_physicalUuids.size() != other->_physicalUuids.size()) {
|
||||
Base::Console().Log("Local physical model count %d\n", _physicalUuids.size());
|
||||
Base::Console().Log("Remote physical model count %d\n", other->_physicalUuids.size());
|
||||
throw InvalidMaterial("Material physical model counts don't match");
|
||||
}
|
||||
if (!other->_physicalUuids.contains(_physicalUuids)) {
|
||||
throw InvalidMaterial("Material physical models don't match");
|
||||
}
|
||||
|
||||
if (_physicalUuids.size() != other->_physicalUuids.size()) {
|
||||
Base::Console().Log("Local appearance model count %d\n", _physicalUuids.size());
|
||||
Base::Console().Log("Remote appearance model count %d\n", other->_physicalUuids.size());
|
||||
throw InvalidMaterial("Material appearance model counts don't match");
|
||||
}
|
||||
if (!other->_physicalUuids.contains(_physicalUuids)) {
|
||||
throw InvalidMaterial("Material appearance models don't match");
|
||||
}
|
||||
|
||||
if (_allUuids.size() != other->_allUuids.size()) {
|
||||
Base::Console().Log("Local model count %d\n", _allUuids.size());
|
||||
Base::Console().Log("Remote model count %d\n", other->_allUuids.size());
|
||||
throw InvalidMaterial("Material model counts don't match");
|
||||
}
|
||||
if (!other->_allUuids.contains(_allUuids)) {
|
||||
throw InvalidMaterial("Material models don't match");
|
||||
}
|
||||
|
||||
// Need to compare properties
|
||||
if (_physical.size() != other->_physical.size()) {
|
||||
throw InvalidMaterial("Material physical property counts don't match");
|
||||
}
|
||||
for (auto& property : _physical) {
|
||||
auto& remote = other->_physical[property.first];
|
||||
property.second->validate(*remote);
|
||||
}
|
||||
|
||||
if (_appearance.size() != other->_appearance.size()) {
|
||||
throw InvalidMaterial("Material appearance property counts don't match");
|
||||
}
|
||||
for (auto& property : _appearance) {
|
||||
auto& remote = other->_appearance[property.first];
|
||||
property.second->validate(*remote);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@ public:
|
||||
{
|
||||
return _valuePtr->isNull();
|
||||
}
|
||||
bool isEmpty() const
|
||||
{
|
||||
return _valuePtr->isEmpty();
|
||||
}
|
||||
std::shared_ptr<MaterialValue> getMaterialValue();
|
||||
std::shared_ptr<MaterialValue> getMaterialValue() const;
|
||||
QString getString() const;
|
||||
@@ -109,6 +113,10 @@ public:
|
||||
MaterialValue::ValueType getColumnType(int column) const;
|
||||
QString getColumnUnits(int column) const;
|
||||
QVariant getColumnNull(int column) const;
|
||||
const std::vector<MaterialProperty>& getColumns() const
|
||||
{
|
||||
return _columns;
|
||||
}
|
||||
|
||||
void setModelUUID(const QString& uuid);
|
||||
void setPropertyType(const QString& type) override;
|
||||
@@ -140,6 +148,11 @@ public:
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
void validate(const MaterialProperty& other) const;
|
||||
|
||||
// Define precision for displaying floating point values
|
||||
static int const PRECISION;
|
||||
|
||||
protected:
|
||||
void setType(const QString& type);
|
||||
// void setType(MaterialValue::ValueType type) { _valueType = type; }
|
||||
@@ -180,10 +193,9 @@ public:
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
QString getDirectory() const;
|
||||
QString getFilename() const;
|
||||
QString getFilePath() const;
|
||||
QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
@@ -240,10 +252,8 @@ public:
|
||||
{
|
||||
_library = library;
|
||||
}
|
||||
void setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
void setDirectory(const QString& directory);
|
||||
void setFilename(const QString& filename);
|
||||
void setUUID(const QString& uuid)
|
||||
{
|
||||
_uuid = uuid;
|
||||
@@ -303,6 +313,7 @@ public:
|
||||
|
||||
void setValue(const QString& name, const QString& value);
|
||||
void setValue(const QString& name, const QVariant& value);
|
||||
void setValue(const QString& name, const std::shared_ptr<MaterialValue>& value);
|
||||
|
||||
/*
|
||||
* Legacy values are thosed contained in old format files that don't fit in the new
|
||||
@@ -432,6 +443,8 @@ public:
|
||||
return getTypeId() == other.getTypeId() && _uuid == other._uuid;
|
||||
}
|
||||
|
||||
void validate(const std::shared_ptr<Material>& other) const;
|
||||
|
||||
protected:
|
||||
void addModel(const QString& uuid);
|
||||
static void removeUUID(QSet<QString>& uuidList, const QString& uuid);
|
||||
@@ -455,6 +468,7 @@ protected:
|
||||
private:
|
||||
std::shared_ptr<MaterialLibrary> _library;
|
||||
QString _directory;
|
||||
QString _filename;
|
||||
QString _uuid;
|
||||
QString _name;
|
||||
QString _author;
|
||||
|
||||
@@ -101,11 +101,49 @@ bool ModelProperty::operator==(const ModelProperty& other) const
|
||||
return true;
|
||||
}
|
||||
|
||||
return (_name == other._name) && (_displayName == other._displayName) && (_propertyType == other._propertyType)
|
||||
&& (_units == other._units) && (_url == other._url) && (_description == other._description)
|
||||
return (_name == other._name) && (_displayName == other._displayName)
|
||||
&& (_propertyType == other._propertyType) && (_units == other._units)
|
||||
&& (_url == other._url) && (_description == other._description)
|
||||
&& (_inheritance == other._inheritance);
|
||||
}
|
||||
|
||||
void ModelProperty::validate(const ModelProperty& other) const
|
||||
{
|
||||
if (_name != other._name) {
|
||||
throw InvalidProperty("Model names don't match");
|
||||
}
|
||||
if (getDisplayName() != other.getDisplayName()) {
|
||||
Base::Console().Log("Local display name '%s'\n", getDisplayName().toStdString().c_str());
|
||||
Base::Console().Log("Remote display name '%s'\n",
|
||||
other.getDisplayName().toStdString().c_str());
|
||||
throw InvalidProperty("Model display names don't match");
|
||||
}
|
||||
if (_propertyType != other._propertyType) {
|
||||
throw InvalidProperty("Model property types don't match");
|
||||
}
|
||||
if (_units != other._units) {
|
||||
throw InvalidProperty("Model units don't match");
|
||||
}
|
||||
if (_url != other._url) {
|
||||
throw InvalidProperty("Model URLs don't match");
|
||||
}
|
||||
if (_description != other._description) {
|
||||
throw InvalidProperty("Model descriptions don't match");
|
||||
}
|
||||
if (_inheritance != other._inheritance) {
|
||||
throw InvalidProperty("Model inheritance don't match");
|
||||
}
|
||||
|
||||
if (_columns.size() != other._columns.size()) {
|
||||
Base::Console().Log("Local property column count %d\n", _columns.size());
|
||||
Base::Console().Log("Remote property column count %d\n", other._columns.size());
|
||||
throw InvalidProperty("Model property column counts don't match");
|
||||
}
|
||||
for (size_t i = 0; i < _columns.size(); i++) {
|
||||
_columns[i].validate(other._columns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass)
|
||||
|
||||
Model::Model()
|
||||
@@ -129,6 +167,31 @@ Model::Model(std::shared_ptr<ModelLibrary> library,
|
||||
, _doi(doi)
|
||||
{}
|
||||
|
||||
QString Model::getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
|
||||
void Model::setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
|
||||
QString Model::getFilename() const
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
||||
void Model::setFilename(const QString& filename)
|
||||
{
|
||||
_filename = filename;
|
||||
}
|
||||
|
||||
QString Model::getFilePath() const
|
||||
{
|
||||
return QDir(_directory + QStringLiteral("/") + _filename).absolutePath();
|
||||
}
|
||||
|
||||
ModelProperty& Model::operator[](const QString& key)
|
||||
{
|
||||
try {
|
||||
@@ -138,3 +201,54 @@ ModelProperty& Model::operator[](const QString& key)
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::validate(const std::shared_ptr<Model>& other) const
|
||||
{
|
||||
try {
|
||||
_library->validate(*(other->_library));
|
||||
}
|
||||
catch (const InvalidLibrary& e)
|
||||
{
|
||||
throw InvalidModel(e.what());
|
||||
}
|
||||
|
||||
// std::map<QString, ModelProperty> _properties;
|
||||
if (_type != other->_type) {
|
||||
throw InvalidModel("Model types don't match");
|
||||
}
|
||||
if (_name != other->_name) {
|
||||
throw InvalidModel("Model names don't match");
|
||||
}
|
||||
if (_directory != other->_directory) {
|
||||
throw InvalidModel("Model directories don't match");
|
||||
}
|
||||
if (!other->_filename.isEmpty()) {
|
||||
throw InvalidModel("Remote filename is not empty");
|
||||
}
|
||||
if (_uuid != other->_uuid) {
|
||||
throw InvalidModel("Model UUIDs don't match");
|
||||
}
|
||||
if (_description != other->_description) {
|
||||
throw InvalidModel("Model descriptions don't match");
|
||||
}
|
||||
if (_url != other->_url) {
|
||||
throw InvalidModel("Model URLs don't match");
|
||||
}
|
||||
if (_doi != other->_doi) {
|
||||
throw InvalidModel("Model DOIs don't match");
|
||||
}
|
||||
if (_inheritedUuids != other->_inheritedUuids) {
|
||||
throw InvalidModel("Model inherited UUIDs don't match");
|
||||
}
|
||||
|
||||
// Need to compare properties
|
||||
if (_properties.size() != other->_properties.size()) {
|
||||
// Base::Console().Log("Local property count %d\n", _properties.size());
|
||||
// Base::Console().Log("Remote property count %d\n", other->_properties.size());
|
||||
throw InvalidModel("Model property counts don't match");
|
||||
}
|
||||
for (auto& property : _properties) {
|
||||
auto& remote = other->_properties[property.first];
|
||||
property.second.validate(remote);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
void setColumnHeader(const QString& header)
|
||||
void setDisplayName(const QString& header)
|
||||
{
|
||||
_displayName = header;
|
||||
}
|
||||
@@ -143,6 +143,8 @@ public:
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
void validate(const ModelProperty& other) const;
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _displayName;
|
||||
@@ -180,12 +182,12 @@ public:
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
const QString getBase() const
|
||||
QString getBase() const
|
||||
{
|
||||
return (_type == ModelType_Physical) ? QStringLiteral("Model")
|
||||
: QStringLiteral("AppearanceModel");
|
||||
}
|
||||
const QString getName() const
|
||||
QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
@@ -193,27 +195,22 @@ public:
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getDirectoryPath() const
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
const QString getUUID() const
|
||||
QString getDirectory() const;
|
||||
QString getFilename() const;
|
||||
QString getFilePath() const;
|
||||
QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
const QString getDescription() const
|
||||
QString getDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
const QString getURL() const
|
||||
QString getURL() const
|
||||
{
|
||||
return _url;
|
||||
}
|
||||
const QString getDOI() const
|
||||
QString getDOI() const
|
||||
{
|
||||
return _doi;
|
||||
}
|
||||
@@ -230,10 +227,8 @@ public:
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
void setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
void setDirectory(const QString& directory);
|
||||
void setFilename(const QString& filename);
|
||||
void setUUID(const QString& uuid)
|
||||
{
|
||||
_uuid = uuid;
|
||||
@@ -306,11 +301,14 @@ public:
|
||||
return _properties.cend();
|
||||
}
|
||||
|
||||
void validate(const std::shared_ptr<Model>& other) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ModelLibrary> _library;
|
||||
ModelType _type;
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _filename;
|
||||
QString _uuid;
|
||||
QString _description;
|
||||
QString _url;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
@@ -34,79 +36,13 @@
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::LibraryBase, Base::BaseClass)
|
||||
TYPESYSTEM_SOURCE(Materials::ModelLibrary, Materials::Library)
|
||||
|
||||
LibraryBase::LibraryBase(const QString& libraryName, const QString& dir, const QString& icon)
|
||||
: _name(libraryName)
|
||||
, _directory(QDir::cleanPath(dir))
|
||||
, _iconPath(icon)
|
||||
{}
|
||||
|
||||
bool LibraryBase::operator==(const LibraryBase& library) const
|
||||
{
|
||||
return (_name == library._name) && (_directory == library._directory);
|
||||
}
|
||||
|
||||
QString LibraryBase::getLocalPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getDirectoryPath();
|
||||
if (!(filePath.endsWith(QLatin1String("/")) || filePath.endsWith(QLatin1String("\\")))) {
|
||||
filePath += QLatin1String("/");
|
||||
}
|
||||
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QStringLiteral("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath += cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath += cleanPath;
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
bool LibraryBase::isRoot(const QString& path) const
|
||||
{
|
||||
QString localPath = getLocalPath(path);
|
||||
QString cleanPath = getLocalPath(QStringLiteral(""));
|
||||
std::string pLocal = localPath.toStdString();
|
||||
std::string pclean = cleanPath.toStdString();
|
||||
return (cleanPath == localPath);
|
||||
}
|
||||
|
||||
QString LibraryBase::getRelativePath(const QString& path) const
|
||||
{
|
||||
QString filePath;
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QStringLiteral("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath = cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath = cleanPath;
|
||||
}
|
||||
|
||||
prefix = getDirectoryPath();
|
||||
if (filePath.startsWith(prefix)) {
|
||||
// Remove the library root from the path
|
||||
filePath = filePath.right(filePath.length() - prefix.length());
|
||||
}
|
||||
|
||||
// Remove any leading '/'
|
||||
if (filePath.startsWith(QStringLiteral("/"))) {
|
||||
filePath.remove(0, 1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::ModelLibrary, Materials::LibraryBase)
|
||||
|
||||
ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon)
|
||||
: LibraryBase(libraryName, dir, icon)
|
||||
ModelLibrary::ModelLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: Library(libraryName, dir, icon, readOnly)
|
||||
{
|
||||
_modelPathMap = std::make_unique<std::map<QString, std::shared_ptr<Model>>>();
|
||||
}
|
||||
@@ -131,9 +67,11 @@ std::shared_ptr<Model> ModelLibrary::getModelByPath(const QString& path) const
|
||||
std::shared_ptr<Model> ModelLibrary::addModel(const Model& model, const QString& path)
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
QFileInfo info(filePath);
|
||||
std::shared_ptr<Model> newModel = std::make_shared<Model>(model);
|
||||
newModel->setLibrary(getptr());
|
||||
newModel->setDirectory(filePath);
|
||||
newModel->setDirectory(getLibraryPath(filePath, info.fileName()));
|
||||
newModel->setFilename(info.fileName());
|
||||
|
||||
(*_modelPathMap)[filePath] = newModel;
|
||||
|
||||
@@ -158,6 +96,7 @@ ModelLibrary::getModelTree(ModelFilter filter) const
|
||||
for (auto& itp : list) {
|
||||
if (ModelManager::isModel(itp)) {
|
||||
std::shared_ptr<ModelTreeNode> child = std::make_shared<ModelTreeNode>();
|
||||
child->setUUID(model->getUUID());
|
||||
child->setData(model);
|
||||
(*node)[itp] = child;
|
||||
}
|
||||
|
||||
@@ -32,68 +32,28 @@
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include "Library.h"
|
||||
#include "MaterialValue.h"
|
||||
#include "Model.h"
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
// class Model;
|
||||
|
||||
class MaterialsExport LibraryBase: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
LibraryBase() = default;
|
||||
LibraryBase(const QString& libraryName, const QString& dir, const QString& icon);
|
||||
~LibraryBase() override = default;
|
||||
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getDirectoryPath() const
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
const QString getIconPath() const
|
||||
{
|
||||
return _iconPath;
|
||||
}
|
||||
bool operator==(const LibraryBase& library) const;
|
||||
bool operator!=(const LibraryBase& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
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 Library,
|
||||
public std::enable_shared_from_this<ModelLibrary>
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
ModelLibrary();
|
||||
ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon);
|
||||
ModelLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
~ModelLibrary() override = default;
|
||||
|
||||
bool operator==(const ModelLibrary& library) const
|
||||
{
|
||||
return LibraryBase::operator==(library);
|
||||
return Library::operator==(library);
|
||||
}
|
||||
bool operator!=(const ModelLibrary& library) const
|
||||
{
|
||||
@@ -119,4 +79,6 @@ private:
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<Materials::ModelLibrary>)
|
||||
|
||||
#endif // MATERIAL_MODELLIBRARY_H
|
||||
|
||||
@@ -26,118 +26,141 @@
|
||||
#include <QDirIterator>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelLoader.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
#include "ModelManagerLocal.h"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
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)
|
||||
|
||||
QMutex ModelManager::_mutex;
|
||||
ModelManager* ModelManager::_manager = nullptr;
|
||||
std::unique_ptr<ModelManagerLocal> ModelManager::_localManager;
|
||||
|
||||
ModelManager::ModelManager()
|
||||
{}
|
||||
|
||||
ModelManager::~ModelManager()
|
||||
{}
|
||||
|
||||
ModelManager& ModelManager::getManager()
|
||||
{
|
||||
initLibraries();
|
||||
if (!_manager) {
|
||||
initManagers();
|
||||
}
|
||||
|
||||
return *_manager;
|
||||
}
|
||||
|
||||
void ModelManager::initLibraries()
|
||||
void ModelManager::initManagers()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_modelMap == nullptr) {
|
||||
_modelMap = std::make_shared<std::map<QString, std::shared_ptr<Model>>>();
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = std::make_shared<std::list<std::shared_ptr<ModelLibrary>>>();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
if (!_manager) {
|
||||
// Can't use smart pointers for this since the constructor is private
|
||||
_manager = new ModelManager();
|
||||
}
|
||||
if (!_localManager) {
|
||||
_localManager = std::make_unique<ModelManagerLocal>();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelManager::isModel(const QString& file)
|
||||
{
|
||||
// if (!fs::is_regular_file(p))
|
||||
// return false;
|
||||
// check file extension
|
||||
if (file.endsWith(QStringLiteral(".yml"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return ModelManagerLocal::isModel(file);
|
||||
}
|
||||
|
||||
void ModelManager::cleanup()
|
||||
{
|
||||
if (_libraryList) {
|
||||
_libraryList->clear();
|
||||
}
|
||||
|
||||
if (_modelMap) {
|
||||
for (auto& it : *_modelMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
it.second->setLibrary(nullptr);
|
||||
}
|
||||
_modelMap->clear();
|
||||
}
|
||||
return ModelManagerLocal::cleanup();
|
||||
}
|
||||
|
||||
void ModelManager::refresh()
|
||||
{
|
||||
_modelMap->clear();
|
||||
_libraryList->clear();
|
||||
_localManager->refresh();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManager::getLibraries()
|
||||
{
|
||||
return _localManager->getLibraries();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManager::getLocalLibraries()
|
||||
{
|
||||
return _localManager->getLibraries();
|
||||
}
|
||||
|
||||
void ModelManager::createLibrary(const QString& libraryName, const QString& icon, bool readOnly)
|
||||
{}
|
||||
|
||||
void ModelManager::createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
_localManager->createLibrary(libraryName, directory, icon, readOnly);
|
||||
}
|
||||
|
||||
void ModelManager::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
_localManager->renameLibrary(libraryName, newName);
|
||||
}
|
||||
|
||||
void ModelManager::changeIcon(const QString& libraryName, const QString& icon)
|
||||
{
|
||||
_localManager->changeIcon(libraryName, icon);
|
||||
}
|
||||
|
||||
void ModelManager::removeLibrary(const QString& libraryName)
|
||||
{
|
||||
_localManager->removeLibrary(libraryName);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
ModelManager::libraryModels(const QString& libraryName)
|
||||
{
|
||||
return _localManager->libraryModels(libraryName);
|
||||
}
|
||||
|
||||
bool ModelManager::isLocalLibrary(const QString& libraryName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> ModelManager::getModels()
|
||||
{
|
||||
return _localManager->getModels();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> ModelManager::getLocalModels()
|
||||
{
|
||||
return _localManager->getModels();
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManager::getModel(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
if (_modelMap == nullptr) {
|
||||
throw Uninitialized();
|
||||
}
|
||||
|
||||
return _modelMap->at(uuid);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
return _localManager->getModel(uuid);
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManager::getModelByPath(const QString& path) const
|
||||
{
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
|
||||
for (auto& library : *_libraryList) {
|
||||
if (cleanPath.startsWith(library->getDirectory())) {
|
||||
return library->getModelByPath(cleanPath);
|
||||
}
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
return _localManager->getModelByPath(path);
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManager::getModelByPath(const QString& path, const QString& lib) const
|
||||
{
|
||||
auto library = getLibrary(lib); // May throw LibraryNotFound
|
||||
return library->getModelByPath(path); // May throw ModelNotFound
|
||||
return _localManager->getModelByPath(path, lib);
|
||||
}
|
||||
|
||||
std::shared_ptr<ModelLibrary> ModelManager::getLibrary(const QString& name) const
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == name) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
return _localManager->getLibrary(name);
|
||||
}
|
||||
|
||||
bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include <QMutex>
|
||||
@@ -35,26 +36,37 @@
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
class ModelManagerLocal;
|
||||
class ModelManagerExternal;
|
||||
|
||||
class MaterialsExport ModelManager: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
ModelManager();
|
||||
~ModelManager() override = default;
|
||||
~ModelManager() override;
|
||||
|
||||
static ModelManager& getManager();
|
||||
|
||||
static void cleanup();
|
||||
void refresh();
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getModelLibraries()
|
||||
{
|
||||
return _libraryList;
|
||||
}
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getModels()
|
||||
{
|
||||
return _modelMap;
|
||||
}
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLibraries();
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLocalLibraries();
|
||||
void createLibrary(const QString& libraryName, const QString& icon, bool readOnly = true);
|
||||
void createLocalLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryModels(const QString& libraryName);
|
||||
bool isLocalLibrary(const QString& libraryName);
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getModels();
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getLocalModels();
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<ModelTreeNode>>>
|
||||
getModelTree(std::shared_ptr<ModelLibrary> library, ModelFilter filter = ModelFilter_None) const
|
||||
{
|
||||
@@ -69,13 +81,14 @@ public:
|
||||
static bool passFilter(ModelFilter filter, Model::ModelType modelType);
|
||||
|
||||
private:
|
||||
static void initLibraries();
|
||||
ModelManager();
|
||||
static void initManagers();
|
||||
|
||||
static std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> _libraryList;
|
||||
static std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> _modelMap;
|
||||
static ModelManager* _manager;
|
||||
static std::unique_ptr<ModelManagerLocal> _localManager;
|
||||
static QMutex _mutex;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_MODELMANAGER_H
|
||||
#endif // MATERIAL_MODELMANAGER_H
|
||||
219
src/Mod/Material/App/ModelManagerLocal.cpp
Normal file
219
src/Mod/Material/App/ModelManagerLocal.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelLoader.h"
|
||||
#include "ModelManagerLocal.h"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManagerLocal::_libraryList = nullptr;
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> ModelManagerLocal::_modelMap = nullptr;
|
||||
QMutex ModelManagerLocal::_mutex;
|
||||
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::ModelManagerLocal, Base::BaseClass)
|
||||
|
||||
ModelManagerLocal::ModelManagerLocal()
|
||||
{
|
||||
initLibraries();
|
||||
}
|
||||
|
||||
void ModelManagerLocal::initLibraries()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_modelMap == nullptr) {
|
||||
_modelMap = std::make_shared<std::map<QString, std::shared_ptr<Model>>>();
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = std::make_shared<std::list<std::shared_ptr<ModelLibrary>>>();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelManagerLocal::isModel(const QString& file)
|
||||
{
|
||||
// if (!fs::is_regular_file(p))
|
||||
// return false;
|
||||
// check file extension
|
||||
if (file.endsWith(QStringLiteral(".yml"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelManagerLocal::cleanup()
|
||||
{
|
||||
if (_libraryList) {
|
||||
_libraryList->clear();
|
||||
}
|
||||
|
||||
if (_modelMap) {
|
||||
for (auto& it : *_modelMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
it.second->setLibrary(nullptr);
|
||||
}
|
||||
_modelMap->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelManagerLocal::refresh()
|
||||
{
|
||||
_modelMap->clear();
|
||||
_libraryList->clear();
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
}
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> ModelManagerLocal::getLibraries()
|
||||
{
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
void ModelManagerLocal::createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
{
|
||||
QDir dir;
|
||||
if (!dir.exists(directory)) {
|
||||
if (!dir.mkpath(directory)) {
|
||||
throw CreationError("Unable to create library path");
|
||||
}
|
||||
}
|
||||
|
||||
auto modelLibrary = std::make_shared<ModelLibrary>(libraryName, directory, icon, readOnly);
|
||||
_libraryList->push_back(modelLibrary);
|
||||
|
||||
// This needs to be persisted somehow
|
||||
}
|
||||
|
||||
void ModelManagerLocal::renameLibrary(const QString& libraryName, const QString& newName)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == libraryName) {
|
||||
library->setName(newName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void ModelManagerLocal::changeIcon(const QString& libraryName, const QString& icon)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == libraryName) {
|
||||
library->setIconPath(icon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
void ModelManagerLocal::removeLibrary(const QString& libraryName)
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == libraryName) {
|
||||
_libraryList->remove(library);
|
||||
|
||||
// At this point we should rebuild the model map
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
ModelManagerLocal::libraryModels(const QString& libraryName)
|
||||
{
|
||||
auto models = std::make_shared<std::vector<std::tuple<QString, QString, QString>>>();
|
||||
|
||||
for (auto& it : *_modelMap) {
|
||||
// This is needed to resolve cyclic dependencies
|
||||
if (it.second->getLibrary()->getName() == libraryName) {
|
||||
models->push_back(
|
||||
std::tuple<QString, QString, QString>(it.first, it.second->getDirectory(), it.second->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManagerLocal::getModel(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
if (_modelMap == nullptr) {
|
||||
throw Uninitialized();
|
||||
}
|
||||
|
||||
return _modelMap->at(uuid);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManagerLocal::getModelByPath(const QString& path) const
|
||||
{
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
|
||||
for (auto& library : *_libraryList) {
|
||||
if (cleanPath.startsWith(library->getDirectory())) {
|
||||
return library->getModelByPath(cleanPath);
|
||||
}
|
||||
}
|
||||
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> ModelManagerLocal::getModelByPath(const QString& path,
|
||||
const QString& lib) const
|
||||
{
|
||||
auto library = getLibrary(lib); // May throw LibraryNotFound
|
||||
return library->getModelByPath(path); // May throw ModelNotFound
|
||||
}
|
||||
|
||||
std::shared_ptr<ModelLibrary> ModelManagerLocal::getLibrary(const QString& name) const
|
||||
{
|
||||
for (auto& library : *_libraryList) {
|
||||
if (library->getName() == name) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
87
src/Mod/Material/App/ModelManagerLocal.h
Normal file
87
src/Mod/Material/App/ModelManagerLocal.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODELMANAGERLOCAL_H
|
||||
#define MATERIAL_MODELMANAGERLOCAL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "FolderTree.h"
|
||||
#include "Model.h"
|
||||
#include "ModelLibrary.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialsExport ModelManagerLocal: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
ModelManagerLocal();
|
||||
~ModelManagerLocal() override = default;
|
||||
|
||||
static void cleanup();
|
||||
void refresh();
|
||||
|
||||
std::shared_ptr<std::list<std::shared_ptr<ModelLibrary>>> getLibraries();
|
||||
void createLibrary(const QString& libraryName,
|
||||
const QString& directory,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
void renameLibrary(const QString& libraryName, const QString& newName);
|
||||
void changeIcon(const QString& libraryName, const QString& icon);
|
||||
void removeLibrary(const QString& libraryName);
|
||||
std::shared_ptr<std::vector<std::tuple<QString, QString, QString>>>
|
||||
libraryModels(const QString& libraryName);
|
||||
|
||||
std::shared_ptr<std::map<QString, std::shared_ptr<Model>>> getModels()
|
||||
{
|
||||
return _modelMap;
|
||||
}
|
||||
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 QString& file);
|
||||
|
||||
private:
|
||||
static void initLibraries();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_MODELMANAGERLOCAL_H
|
||||
@@ -10,7 +10,7 @@
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
Delete="false">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material model descriptions.</UserDocu>
|
||||
@@ -31,6 +31,12 @@
|
||||
</Documentation>
|
||||
<Parameter Name="ModelLibraries" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LocalModelLibraries" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of local model libraries.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LocalModelLibraries" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Models" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of model libraries.</UserDocu>
|
||||
|
||||
@@ -43,7 +43,7 @@ std::string ModelManagerPy::representation() const
|
||||
PyObject* ModelManagerPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new ModelManagerPy(new ModelManager());
|
||||
return new ModelManagerPy(&(ModelManager::getManager()));
|
||||
}
|
||||
|
||||
// constructor method
|
||||
@@ -116,7 +116,7 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args)
|
||||
|
||||
Py::List ModelManagerPy::getModelLibraries() const
|
||||
{
|
||||
auto libraries = getModelManagerPtr()->getModelLibraries();
|
||||
auto libraries = getModelManagerPtr()->getLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = libraries->begin(); it != libraries->end(); it++) {
|
||||
@@ -125,6 +125,26 @@ Py::List ModelManagerPy::getModelLibraries() const
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
libTuple.setItem(3, Py::Boolean(lib->isReadOnly()));
|
||||
|
||||
list.append(libTuple);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::List ModelManagerPy::getLocalModelLibraries() const
|
||||
{
|
||||
auto libraries = getModelManagerPtr()->getLocalLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = libraries->begin(); it != libraries->end(); it++) {
|
||||
auto lib = *it;
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
libTuple.setItem(3, Py::Boolean(lib->isReadOnly()));
|
||||
|
||||
list.append(libTuple);
|
||||
}
|
||||
|
||||
@@ -15,35 +15,64 @@
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material property descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Attribute Name="Name" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Property name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Type" ReadOnly="true">
|
||||
<Attribute Name="DisplayName" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Property display friendly name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="DisplayName" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Type" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Property type.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Type" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Units" ReadOnly="true">
|
||||
<Attribute Name="Units" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Property units category.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Units" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Attribute Name="URL" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a detailed description of the property.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Attribute Name="Description" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Property description.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Columns" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of array columns.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Columns" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Inheritance" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>UUID of the model in which the property is defined.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Inheritance" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Inherited" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>True if the property is inherited.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Inherited" Type="Boolean"/>
|
||||
</Attribute>
|
||||
<Methode Name="addColumn" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Add a model property column.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
</GenerateModel>
|
||||
@@ -31,19 +31,8 @@ using namespace Materials;
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string ModelPropertyPy::representation() const
|
||||
{
|
||||
ModelPropertyPy::PointerType ptr = getModelPropertyPtr();
|
||||
std::stringstream str;
|
||||
str << "Property [Name=(";
|
||||
str << ptr->getName().toStdString();
|
||||
str << "), Type=(";
|
||||
str << ptr->getPropertyType().toStdString();
|
||||
str << "), Units=(";
|
||||
str << ptr->getUnits().toStdString();
|
||||
str << "), URL=(";
|
||||
str << ptr->getURL().toStdString();
|
||||
str << "), Description=(";
|
||||
str << ptr->getDescription().toStdString();
|
||||
str << ")]";
|
||||
str << "<ModelProperty object at " << getModelPropertyPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
@@ -65,26 +54,97 @@ Py::String ModelPropertyPy::getName() const
|
||||
return Py::String(getModelPropertyPtr()->getName().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setName(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setName(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getDisplayName() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getDisplayName().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setDisplayName(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setDisplayName(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getType() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getPropertyType().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setType(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setPropertyType(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getUnits() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getUnits().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setUnits(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setUnits(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getURL() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getURL().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setURL(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setURL(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getDescription() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getDescription().toStdString());
|
||||
}
|
||||
|
||||
void ModelPropertyPy::setDescription(Py::String arg)
|
||||
{
|
||||
getModelPropertyPtr()->setDescription(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::List ModelPropertyPy::getColumns() const
|
||||
{
|
||||
Py::List list;
|
||||
|
||||
auto columns = getModelPropertyPtr()->getColumns();
|
||||
for (auto& column : columns) {
|
||||
PyObject* modelPropertyPy = new ModelPropertyPy(new ModelProperty(column));
|
||||
list.append(Py::Object(modelPropertyPy, true));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getInheritance() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getInheritance().toStdString());
|
||||
}
|
||||
|
||||
Py::Boolean ModelPropertyPy::getInherited() const
|
||||
{
|
||||
return getModelPropertyPtr()->isInherited();
|
||||
}
|
||||
|
||||
PyObject* ModelPropertyPy::addColumn(PyObject* args)
|
||||
{
|
||||
PyObject* object;
|
||||
if (!PyArg_ParseTuple(args, "O!", &ModelPropertyPy::Type, &object)) {
|
||||
return nullptr;
|
||||
}
|
||||
ModelProperty* property = static_cast<ModelPropertyPy*>(object)->getModelPropertyPtr();
|
||||
|
||||
getModelPropertyPtr()->addColumn(*property);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* ModelPropertyPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
@@ -93,4 +153,4 @@ PyObject* ModelPropertyPy::getCustomAttributes(const char* /*attr*/) const
|
||||
int ModelPropertyPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,19 @@
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryIcon" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Attribute Name="Name" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Model name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="true">
|
||||
<Attribute Name="Type" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Model type.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Type" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Model directory.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -51,19 +57,19 @@
|
||||
</Documentation>
|
||||
<Parameter Name="UUID" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Attribute Name="Description" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Description of the model.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Attribute Name="URL" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a detailed description of the model.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="DOI" ReadOnly="true">
|
||||
<Attribute Name="DOI" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Digital Object Identifier (see https://doi.org/)</UserDocu>
|
||||
</Documentation>
|
||||
@@ -81,5 +87,15 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Properties" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Methode Name="addInheritance" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Add an inherited model.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="addProperty" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Add a model property.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -34,42 +34,8 @@ using namespace Materials;
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string ModelPy::representation() const
|
||||
{
|
||||
ModelPy::PointerType ptr = getModelPtr();
|
||||
std::stringstream str;
|
||||
str << "Property [Name=(";
|
||||
str << ptr->getName().toStdString();
|
||||
str << "), UUID=(";
|
||||
str << ptr->getUUID().toStdString();
|
||||
auto library = ptr->getLibrary();
|
||||
if (library) {
|
||||
str << "), Library Name=(";
|
||||
str << ptr->getLibrary()->getName().toStdString();
|
||||
str << "), Library Root=(";
|
||||
str << ptr->getLibrary()->getDirectoryPath().toStdString();
|
||||
str << "), Library Icon=(";
|
||||
str << ptr->getLibrary()->getIconPath().toStdString();
|
||||
}
|
||||
str << "), Directory=(";
|
||||
str << ptr->getDirectory().toStdString();
|
||||
str << "), URL=(";
|
||||
str << ptr->getURL().toStdString();
|
||||
str << "), DOI=(";
|
||||
str << ptr->getDOI().toStdString();
|
||||
str << "), Description=(";
|
||||
str << ptr->getDescription().toStdString();
|
||||
str << "), Inherits=[";
|
||||
auto& inherited = getModelPtr()->getInheritance();
|
||||
for (auto it = inherited.begin(); it != inherited.end(); it++) {
|
||||
QString uuid = *it;
|
||||
if (it != inherited.begin()) {
|
||||
str << "), UUID=(";
|
||||
}
|
||||
else {
|
||||
str << "UUID=(";
|
||||
}
|
||||
str << uuid.toStdString() << ")";
|
||||
}
|
||||
str << "]]";
|
||||
str << "<Model object at " << getModelPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
@@ -109,9 +75,38 @@ Py::String ModelPy::getName() const
|
||||
return Py::String(getModelPtr()->getName().toStdString());
|
||||
}
|
||||
|
||||
void ModelPy::setName(Py::String arg)
|
||||
{
|
||||
getModelPtr()->setName(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPy::getType() const
|
||||
{
|
||||
auto type = (getModelPtr()->getType() == Model::ModelType_Physical)
|
||||
? "Physical"
|
||||
: "Appearance";
|
||||
|
||||
return Py::String(type);
|
||||
}
|
||||
|
||||
void ModelPy::setType(Py::String arg)
|
||||
{
|
||||
if (arg.as_std_string() == "Appearance") {
|
||||
getModelPtr()->setType(Model::ModelType_Appearance);
|
||||
}
|
||||
else {
|
||||
getModelPtr()->setType(Model::ModelType_Physical);
|
||||
}
|
||||
}
|
||||
|
||||
Py::String ModelPy::getDirectory() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getDirectoryPath().toStdString());
|
||||
return Py::String(getModelPtr()->getDirectory().toStdString());
|
||||
}
|
||||
|
||||
void ModelPy::setDirectory(Py::String arg)
|
||||
{
|
||||
getModelPtr()->setDirectory(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPy::getUUID() const
|
||||
@@ -124,16 +119,31 @@ Py::String ModelPy::getDescription() const
|
||||
return Py::String(getModelPtr()->getDescription().toStdString());
|
||||
}
|
||||
|
||||
void ModelPy::setDescription(Py::String arg)
|
||||
{
|
||||
getModelPtr()->setDescription(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPy::getURL() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getURL().toStdString());
|
||||
}
|
||||
|
||||
void ModelPy::setURL(Py::String arg)
|
||||
{
|
||||
getModelPtr()->setURL(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String ModelPy::getDOI() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getDOI().toStdString());
|
||||
}
|
||||
|
||||
void ModelPy::setDOI(Py::String arg)
|
||||
{
|
||||
getModelPtr()->setDOI(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::List ModelPy::getInherited() const
|
||||
{
|
||||
auto& inherited = getModelPtr()->getInheritance();
|
||||
@@ -148,7 +158,6 @@ Py::List ModelPy::getInherited() const
|
||||
|
||||
Py::Dict ModelPy::getProperties() const
|
||||
{
|
||||
// std::map<std::string, Model*> *models = getModelPtr()->getModels();
|
||||
Py::Dict dict;
|
||||
|
||||
for (auto it = getModelPtr()->begin(); it != getModelPtr()->end(); it++) {
|
||||
@@ -162,6 +171,31 @@ Py::Dict ModelPy::getProperties() const
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* ModelPy::addInheritance(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getModelPtr()->addInheritance(QString::fromStdString(uuid));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* ModelPy::addProperty(PyObject* args)
|
||||
{
|
||||
PyObject* object;
|
||||
if (!PyArg_ParseTuple(args, "O!", &ModelPropertyPy::Type, &object)) {
|
||||
return nullptr;
|
||||
}
|
||||
ModelProperty* property = static_cast<ModelPropertyPy*>(object)->getModelPropertyPtr();
|
||||
|
||||
getModelPtr()->addProperty(*property);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* ModelPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
|
||||
@@ -88,14 +88,12 @@ void PropertyMaterial::Save(Base::Writer& writer) const
|
||||
|
||||
void PropertyMaterial::Restore(Base::XMLReader& reader)
|
||||
{
|
||||
MaterialManager manager;
|
||||
|
||||
// read my Element
|
||||
reader.readElement("PropertyMaterial");
|
||||
// get the value of my Attribute
|
||||
auto uuid = reader.getAttribute("uuid");
|
||||
|
||||
setValue(*manager.getMaterial(QString::fromLatin1(uuid)));
|
||||
setValue(*MaterialManager::getManager().getMaterial(QString::fromLatin1(uuid)));
|
||||
}
|
||||
|
||||
const char* PropertyMaterial::getEditorName() const
|
||||
|
||||
75
src/Mod/Material/App/PyVariants.cpp
Normal file
75
src/Mod/Material/App/PyVariants.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************
|
||||
* 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 <QVariant>
|
||||
|
||||
#include "PyVariants.h"
|
||||
#include "Exceptions.h"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
PyObject* Materials::_pyObjectFromVariant(const QVariant& value)
|
||||
{
|
||||
if (value.isNull()) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (value.userType() == qMetaTypeId<Base::Quantity>()) {
|
||||
return new Base::QuantityPy(new Base::Quantity(value.value<Base::Quantity>()));
|
||||
}
|
||||
if (value.userType() == QMetaType::Double) {
|
||||
return PyFloat_FromDouble(value.toDouble());
|
||||
}
|
||||
if (value.userType() == QMetaType::Float) {
|
||||
return PyFloat_FromDouble(value.toFloat());
|
||||
}
|
||||
if (value.userType() == QMetaType::Int) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
if (value.userType() == QMetaType::Long) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
if (value.userType() == QMetaType::Bool) {
|
||||
return Py::new_reference_to(Py::Boolean(value.toBool()));
|
||||
}
|
||||
if (value.userType() == QMetaType::QString) {
|
||||
return PyUnicode_FromString(value.toString().toStdString().c_str());
|
||||
}
|
||||
if (value.userType() == qMetaTypeId<QList<QVariant>>()) {
|
||||
return Py::new_reference_to(getList(value));
|
||||
}
|
||||
|
||||
throw UnknownValueType();
|
||||
}
|
||||
|
||||
Py::List Materials::getList(const QVariant& value)
|
||||
{
|
||||
auto listValue = value.value<QList<QVariant>>();
|
||||
Py::List list;
|
||||
|
||||
for (auto& it : listValue) {
|
||||
list.append(Py::Object(_pyObjectFromVariant(it)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
42
src/Mod/Material/App/PyVariants.h
Normal file
42
src/Mod/Material/App/PyVariants.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_PYVARIANTS_H
|
||||
#define MATERIAL_PYVARIANTS_H
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
extern MaterialsExport PyObject* _pyObjectFromVariant(const QVariant& value);
|
||||
extern MaterialsExport Py::List getList(const QVariant& value);
|
||||
|
||||
} // namespace Materials
|
||||
|
||||
#endif // MATERIAL_PYVARIANTS_H
|
||||
@@ -199,7 +199,6 @@ Py::String UUIDsPy::getTextureRendering() const
|
||||
|
||||
Py::String UUIDsPy::getAdvancedRendering() const
|
||||
{
|
||||
Base::Console().Log(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString().c_str());
|
||||
return Py::String(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString());
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ Array2D::Array2D(const QString& propertyName,
|
||||
}
|
||||
if (_property) {
|
||||
_value =
|
||||
std::static_pointer_cast<Materials::Material2DArray>(_property->getMaterialValue());
|
||||
std::static_pointer_cast<Materials::Array2D>(_property->getMaterialValue());
|
||||
setWindowTitle(_property->getDisplayName());
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
std::unique_ptr<Ui_Array2D> ui;
|
||||
std::shared_ptr<Materials::Material> _material;
|
||||
std::shared_ptr<Materials::MaterialProperty> _property;
|
||||
std::shared_ptr<Materials::Material2DArray> _value;
|
||||
std::shared_ptr<Materials::Array2D> _value;
|
||||
|
||||
QAction _deleteAction;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ Array3D::Array3D(const QString& propertyName,
|
||||
}
|
||||
if (_property) {
|
||||
_value =
|
||||
std::static_pointer_cast<Materials::Material3DArray>(_property->getMaterialValue());
|
||||
std::static_pointer_cast<Materials::Array3D>(_property->getMaterialValue());
|
||||
}
|
||||
else {
|
||||
_value = nullptr;
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
std::unique_ptr<Ui_Array3D> ui;
|
||||
std::shared_ptr<Materials::Material> _material;
|
||||
std::shared_ptr<Materials::MaterialProperty> _property;
|
||||
std::shared_ptr<Materials::Material3DArray> _value;
|
||||
std::shared_ptr<Materials::Array3D> _value;
|
||||
|
||||
QAction _deleteDepthAction;
|
||||
QAction _delete2DAction;
|
||||
|
||||
@@ -47,7 +47,7 @@ AbstractArrayModel::AbstractArrayModel(QObject* parent)
|
||||
|
||||
|
||||
Array2DModel::Array2DModel(const std::shared_ptr<Materials::MaterialProperty>& property,
|
||||
const std::shared_ptr<Materials::Material2DArray>& value,
|
||||
const std::shared_ptr<Materials::Array2D>& value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
@@ -199,7 +199,7 @@ bool Array2DModel::removeColumns(int column, int count, const QModelIndex& paren
|
||||
//===
|
||||
|
||||
Array3DDepthModel::Array3DDepthModel(const std::shared_ptr<Materials::MaterialProperty>& property,
|
||||
const std::shared_ptr<Materials::Material3DArray>& value,
|
||||
const std::shared_ptr<Materials::Array3D>& value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
@@ -337,7 +337,7 @@ bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex&
|
||||
//===
|
||||
|
||||
Array3DModel::Array3DModel(const std::shared_ptr<Materials::MaterialProperty>& property,
|
||||
const std::shared_ptr<Materials::Material3DArray>& value,
|
||||
const std::shared_ptr<Materials::Array3D>& value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
|
||||
@@ -48,7 +48,7 @@ class Array2DModel: public AbstractArrayModel
|
||||
{
|
||||
public:
|
||||
explicit Array2DModel(const std::shared_ptr<Materials::MaterialProperty>& property = nullptr,
|
||||
const std::shared_ptr<Materials::Material2DArray>& value = nullptr,
|
||||
const std::shared_ptr<Materials::Array2D>& value = nullptr,
|
||||
QObject* parent = nullptr);
|
||||
~Array2DModel() override = default;
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Materials::MaterialProperty> _property;
|
||||
std::shared_ptr<Materials::Material2DArray> _value;
|
||||
std::shared_ptr<Materials::Array2D> _value;
|
||||
};
|
||||
|
||||
class Array3DDepthModel: public AbstractArrayModel
|
||||
@@ -79,7 +79,7 @@ class Array3DDepthModel: public AbstractArrayModel
|
||||
public:
|
||||
explicit Array3DDepthModel(
|
||||
const std::shared_ptr<Materials::MaterialProperty>& property = nullptr,
|
||||
const std::shared_ptr<Materials::Material3DArray>& value = nullptr,
|
||||
const std::shared_ptr<Materials::Array3D>& value = nullptr,
|
||||
QObject* parent = nullptr);
|
||||
~Array3DDepthModel() override = default;
|
||||
|
||||
@@ -106,14 +106,14 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Materials::MaterialProperty> _property;
|
||||
std::shared_ptr<Materials::Material3DArray> _value;
|
||||
std::shared_ptr<Materials::Array3D> _value;
|
||||
};
|
||||
|
||||
class Array3DModel: public AbstractArrayModel
|
||||
{
|
||||
public:
|
||||
explicit Array3DModel(const std::shared_ptr<Materials::MaterialProperty>& property = nullptr,
|
||||
const std::shared_ptr<Materials::Material3DArray>& value = nullptr,
|
||||
const std::shared_ptr<Materials::Array3D>& value = nullptr,
|
||||
QObject* parent = nullptr);
|
||||
~Array3DModel() override = default;
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Materials::MaterialProperty> _property;
|
||||
std::shared_ptr<Materials::Material3DArray> _value;
|
||||
std::shared_ptr<Materials::Array3D> _value;
|
||||
};
|
||||
|
||||
} // namespace MatGui
|
||||
|
||||
@@ -61,8 +61,6 @@ void CmdMaterialEdit::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
|
||||
Base::Console().Log("Material_Edit\n");
|
||||
|
||||
static QPointer<QDialog> dlg = nullptr;
|
||||
if (!dlg) {
|
||||
dlg = new MatGui::MaterialsEditor(Gui::getMainWindow());
|
||||
|
||||
@@ -151,7 +151,7 @@ void DlgInspectAppearance::update(std::vector<Gui::ViewProvider*>& views)
|
||||
ui->editObjectLabel->setText(QString::fromUtf8(labelProp->getValue()));
|
||||
}
|
||||
else {
|
||||
ui->editObjectLabel->setText(QLatin1String(""));
|
||||
ui->editObjectLabel->setText(QStringLiteral(""));
|
||||
}
|
||||
ui->editObjectName->setText(QLatin1String(obj->getNameInDocument()));
|
||||
|
||||
@@ -162,15 +162,15 @@ void DlgInspectAppearance::update(std::vector<Gui::ViewProvider*>& views)
|
||||
ui->editSubShape->setText(QString::fromStdString(subObject.getSubNames()[0]));
|
||||
}
|
||||
else {
|
||||
ui->editSubShape->setText(QLatin1String(""));
|
||||
ui->editSubShape->setText(QStringLiteral(""));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui->editSubShape->setText(QLatin1String(""));
|
||||
ui->editSubShape->setText(QStringLiteral(""));
|
||||
}
|
||||
|
||||
auto subShapeType = QString::fromUtf8(obj->getTypeId().getName());
|
||||
subShapeType.remove(subShapeType.indexOf(QLatin1String("::")), subShapeType.size());
|
||||
subShapeType.remove(subShapeType.indexOf(QStringLiteral("::")), subShapeType.size());
|
||||
ui->editSubShapeType->setText(subShapeType);
|
||||
ui->editShapeType->setText(QString::fromUtf8(obj->getTypeId().getName()));
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ void DlgInspectMaterial::appendClip(QString text)
|
||||
{
|
||||
// Need to add indent
|
||||
QString indent(clipboardIndent * 4, QLatin1Char(' '));
|
||||
clipboardText += indent + text + QLatin1String("\n");
|
||||
clipboardText += indent + text + QStringLiteral("\n");
|
||||
}
|
||||
|
||||
QStandardItem* DlgInspectMaterial::clipItem(QString text)
|
||||
@@ -144,7 +144,7 @@ void DlgInspectMaterial::unindent()
|
||||
|
||||
void DlgInspectMaterial::update(std::vector<Gui::ViewProvider*>& views)
|
||||
{
|
||||
clipboardText = QLatin1String("");
|
||||
clipboardText = QStringLiteral("");
|
||||
clipboardIndent = 0;
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
if (doc) {
|
||||
@@ -166,7 +166,7 @@ void DlgInspectMaterial::update(std::vector<Gui::ViewProvider*>& views)
|
||||
appendClip(tr("Label: ") + QString::fromUtf8(labelProp->getValue()));
|
||||
}
|
||||
else {
|
||||
ui->editObjectLabel->setText(QLatin1String(""));
|
||||
ui->editObjectLabel->setText(QStringLiteral(""));
|
||||
}
|
||||
ui->editObjectName->setText(QLatin1String(obj->getNameInDocument()));
|
||||
appendClip(tr("Internal Name: ") + QString::fromUtf8(obj->getNameInDocument()));
|
||||
@@ -178,15 +178,15 @@ void DlgInspectMaterial::update(std::vector<Gui::ViewProvider*>& views)
|
||||
ui->editSubShape->setText(QString::fromStdString(subObject.getSubNames()[0]));
|
||||
}
|
||||
else {
|
||||
ui->editSubShape->setText(QLatin1String(""));
|
||||
ui->editSubShape->setText(QStringLiteral(""));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui->editSubShape->setText(QLatin1String(""));
|
||||
ui->editSubShape->setText(QStringLiteral(""));
|
||||
}
|
||||
|
||||
auto subShapeType = QString::fromUtf8(obj->getTypeId().getName());
|
||||
subShapeType.remove(subShapeType.indexOf(QLatin1String("::")), subShapeType.size());
|
||||
subShapeType.remove(subShapeType.indexOf(QStringLiteral("::")), subShapeType.size());
|
||||
appendClip(tr("Type: ") + subShapeType);
|
||||
ui->editSubShapeType->setText(subShapeType);
|
||||
appendClip(tr("TypeID: ") + QString::fromUtf8(obj->getTypeId().getName()));
|
||||
@@ -248,7 +248,7 @@ void DlgInspectMaterial::addModels(QTreeView* tree,
|
||||
}
|
||||
else {
|
||||
for (const QString& uuid : *models) {
|
||||
auto model = modelManager.getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
auto name = clipItem(tr("Name: ") + model->getName());
|
||||
addExpanded(tree, parent, name);
|
||||
|
||||
@@ -287,7 +287,7 @@ void DlgInspectMaterial::addModelDetails(QTreeView* tree,
|
||||
}
|
||||
else {
|
||||
for (const QString& inherited : inheritedUuids) {
|
||||
auto inheritedModel = modelManager.getModel(inherited);
|
||||
auto inheritedModel = Materials::ModelManager::getManager().getModel(inherited);
|
||||
|
||||
auto name = clipItem(tr("Name: ") + inheritedModel->getName());
|
||||
addExpanded(tree, inherits, name);
|
||||
@@ -340,10 +340,10 @@ void DlgInspectMaterial::addMaterialDetails(QTreeView* tree,
|
||||
{
|
||||
auto uuid = clipItem(tr("UUID: ") + material.getUUID());
|
||||
addExpanded(tree, parent, uuid);
|
||||
auto library = clipItem(tr("Library: ") + material.getLibrary()->getName());
|
||||
auto library =
|
||||
clipItem(tr("Library: ") + material.getLibrary()->getName());
|
||||
addExpanded(tree, parent, library);
|
||||
auto libraryPath =
|
||||
clipItem(tr("Library Directory: ") + material.getLibrary()->getDirectoryPath());
|
||||
auto libraryPath = clipItem(tr("Library Directory: ") + material.getLibrary()->getDirectoryPath());
|
||||
addExpanded(tree, parent, libraryPath);
|
||||
auto directory = clipItem(tr("Sub Directory: ") + material.getDirectory());
|
||||
addExpanded(tree, parent, directory);
|
||||
@@ -353,7 +353,7 @@ void DlgInspectMaterial::addMaterialDetails(QTreeView* tree,
|
||||
indent();
|
||||
auto parentUUID = material.getParentUUID();
|
||||
if (!parentUUID.isEmpty()) {
|
||||
auto parentMaterial = materialManager.getMaterial(material.getParentUUID());
|
||||
auto parentMaterial = Materials::MaterialManager::getManager().getMaterial(material.getParentUUID());
|
||||
addMaterial(tree, inherits, *parentMaterial);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_DlgInspectMaterial> ui;
|
||||
Materials::MaterialManager materialManager;
|
||||
Materials::ModelManager modelManager;
|
||||
QString clipboardText;
|
||||
int clipboardIndent;
|
||||
|
||||
|
||||
@@ -137,22 +137,23 @@ void MaterialSave::onOk(bool checked)
|
||||
QFileInfo filepath(_selectedPath + QStringLiteral("/") + name
|
||||
+ QStringLiteral(".FCMat"));
|
||||
|
||||
if (library->fileExists(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);
|
||||
Materials::MaterialManager::getManager()
|
||||
.saveMaterial(library, _material, filepath.filePath(), true, false, _saveInherited);
|
||||
accept();
|
||||
return;
|
||||
}
|
||||
|
||||
bool saveAsCopy = false;
|
||||
if (_manager.exists(_material->getUUID())) {
|
||||
if (Materials::MaterialManager::getManager().exists(_material->getUUID())) {
|
||||
// Does it already exist in this library?
|
||||
if (_manager.exists(library, _material->getUUID())) {
|
||||
if (Materials::MaterialManager::getManager().exists(library, _material->getUUID())) {
|
||||
// Confirm saving a new material
|
||||
auto res = confirmNewMaterial();
|
||||
if (res == QMessageBox::Cancel) {
|
||||
@@ -174,7 +175,7 @@ void MaterialSave::onOk(bool checked)
|
||||
}
|
||||
}
|
||||
|
||||
_manager
|
||||
Materials::MaterialManager::getManager()
|
||||
.saveMaterial(library, _material, filepath.filePath(), false, saveAsCopy, _saveInherited);
|
||||
|
||||
accept();
|
||||
@@ -287,12 +288,16 @@ void MaterialSave::reject()
|
||||
|
||||
void MaterialSave::setLibraries()
|
||||
{
|
||||
auto libraries = _manager.getMaterialLibraries();
|
||||
auto libraries = Materials::MaterialManager::getManager().getLibraries();
|
||||
for (auto& library : *libraries) {
|
||||
if (!library->isReadOnly()) {
|
||||
QVariant libraryVariant;
|
||||
libraryVariant.setValue(library);
|
||||
ui->comboLibrary->addItem(library->getName(), libraryVariant);
|
||||
if (library->isLocal()) {
|
||||
auto materialLibrary =
|
||||
reinterpret_cast<const std::shared_ptr<Materials::MaterialLibraryLocal>&>(library);
|
||||
if (!materialLibrary->isReadOnly()) {
|
||||
QVariant libraryVariant;
|
||||
libraryVariant.setValue(materialLibrary);
|
||||
ui->comboLibrary->addItem(materialLibrary->getName(), libraryVariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,7 +332,7 @@ void MaterialSave::addMaterials(
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& mat : *modelTree) {
|
||||
std::shared_ptr<Materials::MaterialTreeNode> nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::NodeType::DataNode) {
|
||||
std::shared_ptr<Materials::Material> material = nodePtr->getData();
|
||||
QString uuid = material->getUUID();
|
||||
|
||||
@@ -368,7 +373,7 @@ void MaterialSave::showSelectedTree()
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
auto modelTree = _manager.getMaterialTree(library);
|
||||
auto modelTree = Materials::MaterialManager::getManager().getMaterialTree(library);
|
||||
addMaterials(*lib, modelTree, folderIcon, icon);
|
||||
}
|
||||
else {
|
||||
@@ -444,14 +449,14 @@ void MaterialSave::createFolder(const QString& path)
|
||||
{
|
||||
auto library = currentLibrary();
|
||||
|
||||
_manager.createFolder(library, path);
|
||||
Materials::MaterialManager::getManager().createFolder(library, path);
|
||||
}
|
||||
|
||||
void MaterialSave::renameFolder(const QString& oldPath, const QString& newPath)
|
||||
{
|
||||
auto library = currentLibrary();
|
||||
|
||||
_manager.renameFolder(library, oldPath, newPath);
|
||||
Materials::MaterialManager::getManager().renameFolder(library, oldPath, newPath);
|
||||
}
|
||||
|
||||
void MaterialSave::deleteRecursive(const QString& path)
|
||||
@@ -459,7 +464,7 @@ void MaterialSave::deleteRecursive(const QString& path)
|
||||
// This will delete files, folders, and any children
|
||||
auto library = currentLibrary();
|
||||
|
||||
_manager.deleteRecursive(library, path);
|
||||
Materials::MaterialManager::getManager().deleteRecursive(library, path);
|
||||
}
|
||||
|
||||
void MaterialSave::onNewFolder(bool checked)
|
||||
@@ -552,9 +557,9 @@ int MaterialSave::confirmDelete(QWidget* parent)
|
||||
{
|
||||
auto library = currentLibrary();
|
||||
|
||||
if (library->isRoot(_selectedFull)) {
|
||||
return QMessageBox::Cancel;
|
||||
}
|
||||
// if (library->isRoot(_selectedFull)) {
|
||||
// return QMessageBox::Cancel;
|
||||
// }
|
||||
|
||||
QMessageBox box(parent ? parent : this);
|
||||
box.setIcon(QMessageBox::Question);
|
||||
@@ -600,10 +605,10 @@ void MaterialSave::deleteSelected()
|
||||
{
|
||||
auto library = currentLibrary();
|
||||
|
||||
if (!library->isRoot(_selectedFull)) {
|
||||
_manager.deleteRecursive(library, _selectedFull);
|
||||
removeSelectedFromTree();
|
||||
}
|
||||
// if (!library->isRoot(_selectedFull)) {
|
||||
// Materials::MaterialManager::getManager().deleteRecursive(library, _selectedFull);
|
||||
// removeSelectedFromTree();
|
||||
// }
|
||||
}
|
||||
|
||||
void MaterialSave::removeChildren(QStandardItem* item)
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class MaterialLibrary;
|
||||
|
||||
class Ui_MaterialSave;
|
||||
|
||||
class MaterialSave: public QDialog
|
||||
@@ -76,7 +78,6 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_MaterialSave> ui;
|
||||
Materials::MaterialManager _manager;
|
||||
std::shared_ptr<Materials::Material> _material;
|
||||
bool _saveInherited;
|
||||
QString _selectedPath;
|
||||
|
||||
@@ -487,7 +487,7 @@ void MaterialTreeWidget::addRecent(const QString& uuid)
|
||||
}
|
||||
// Ensure it is a material. New, unsaved materials will not be
|
||||
try {
|
||||
auto material = _materialManager.getMaterial(uuid);
|
||||
auto material = Materials::MaterialManager::getManager().getMaterial(uuid);
|
||||
Q_UNUSED(material)
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
@@ -555,12 +555,15 @@ void MaterialTreeWidget::fillMaterialTree()
|
||||
addRecents(lib);
|
||||
}
|
||||
|
||||
auto libraries = _materialManager.getMaterialLibraries();
|
||||
auto libraries = Materials::MaterialManager::getManager().getLibraries();
|
||||
for (const auto& library : *libraries) {
|
||||
auto modelTree = _materialManager.getMaterialTree(library, _filter, _filterOptions);
|
||||
auto materialTree =
|
||||
Materials::MaterialManager::getManager().getMaterialTree(library,
|
||||
_filter,
|
||||
_filterOptions);
|
||||
|
||||
bool showLibraries = _filterOptions.includeEmptyLibraries();
|
||||
if (!_filterOptions.includeEmptyLibraries() && modelTree->size() > 0) {
|
||||
if (!_filterOptions.includeEmptyLibraries() && materialTree->size() > 0) {
|
||||
showLibraries = true;
|
||||
}
|
||||
|
||||
@@ -572,7 +575,7 @@ void MaterialTreeWidget::fillMaterialTree()
|
||||
QIcon icon(library->getIconPath());
|
||||
QIcon folderIcon(QStringLiteral(":/icons/folder.svg"));
|
||||
|
||||
addMaterials(*lib, modelTree, folderIcon, icon, param);
|
||||
addMaterials(*lib, materialTree, folderIcon, icon, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -616,8 +619,7 @@ void MaterialTreeWidget::addRecents(QStandardItem* parent)
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
QIcon icon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
@@ -634,8 +636,7 @@ void MaterialTreeWidget::addFavorites(QStandardItem* parent)
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
QIcon icon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, material->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
@@ -657,9 +658,8 @@ void MaterialTreeWidget::addMaterials(
|
||||
auto childParam = param->GetGroup(parent.text().toStdString().c_str());
|
||||
for (auto& mat : *modelTree) {
|
||||
auto nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
auto material = nodePtr->getData();
|
||||
QString uuid = material->getUUID();
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::NodeType::DataNode) {
|
||||
QString uuid = nodePtr->getUUID();
|
||||
|
||||
auto card = new QStandardItem(icon, mat.first);
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
class CommandManager;
|
||||
class WidgetFactoryInst;
|
||||
class MaterialTreeWidgetPy;
|
||||
|
||||
@@ -207,17 +206,13 @@ private:
|
||||
int _recentMax;
|
||||
MaterialTreeWidgetPy* pyTreeWidget {nullptr};
|
||||
|
||||
Materials::MaterialManager _materialManager;
|
||||
|
||||
// friends
|
||||
friend class Gui::WidgetFactoryInst;
|
||||
|
||||
protected:
|
||||
// bool m_Restored = false;
|
||||
|
||||
Materials::MaterialManager& getMaterialManager()
|
||||
{
|
||||
return _materialManager;
|
||||
return Materials::MaterialManager::getManager();
|
||||
}
|
||||
|
||||
void getFavorites();
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/MaterialLibrary.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
#include <Mod/Material/App/ModelUuids.h>
|
||||
|
||||
@@ -89,7 +90,7 @@ void MaterialsEditor::setup()
|
||||
Gui::WaitCursor wc;
|
||||
ui->setupUi(this);
|
||||
|
||||
_warningIcon = QIcon(QLatin1String(":/icons/Warning.svg"));
|
||||
_warningIcon = QIcon(QStringLiteral(":/icons/Warning.svg"));
|
||||
|
||||
getFavorites();
|
||||
getRecents();
|
||||
@@ -108,7 +109,7 @@ void MaterialsEditor::setup()
|
||||
|
||||
resize(width, height);
|
||||
|
||||
ui->buttonURL->setIcon(QIcon(QLatin1String(":/icons/internet-web-browser.svg")));
|
||||
ui->buttonURL->setIcon(QIcon(QStringLiteral(":/icons/internet-web-browser.svg")));
|
||||
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Ok),
|
||||
&QPushButton::clicked,
|
||||
@@ -214,7 +215,7 @@ void MaterialsEditor::addFavorite(const QString& uuid)
|
||||
{
|
||||
// Ensure it is a material. New, unsaved materials will not be
|
||||
try {
|
||||
auto material = _materialManager.getMaterial(uuid);
|
||||
auto material = Materials::MaterialManager::getManager().getMaterial(uuid);
|
||||
Q_UNUSED(material)
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
@@ -299,7 +300,7 @@ void MaterialsEditor::addRecent(const QString& uuid)
|
||||
{
|
||||
// Ensure it is a material. New, unsaved materials will not be
|
||||
try {
|
||||
auto material = _materialManager.getMaterial(uuid);
|
||||
auto material = Materials::MaterialManager::getManager().getMaterial(uuid);
|
||||
Q_UNUSED(material)
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
@@ -429,7 +430,7 @@ void MaterialsEditor::onAppearanceAdd(bool checked)
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
QString selected = dialog.selectedModel();
|
||||
_material->addAppearance(selected);
|
||||
auto model = getModelManager().getModel(selected);
|
||||
auto model = Materials::ModelManager::getManager().getModel(selected);
|
||||
if (selected == Materials::ModelUUIDs::ModelUUID_Rendering_Basic
|
||||
|| model->inherits(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)) {
|
||||
// Add default appearance properties
|
||||
@@ -497,7 +498,7 @@ void MaterialsEditor::setMaterialDefaults()
|
||||
_material->setLicense(QLatin1String(name));
|
||||
|
||||
// Empty materials will have no parent
|
||||
_materialManager.dereference(_material);
|
||||
Materials::MaterialManager::getManager().dereference(_material);
|
||||
|
||||
updateMaterial();
|
||||
_material->resetEditState();
|
||||
@@ -665,18 +666,22 @@ void MaterialsEditor::saveMaterialTree(const Base::Reference<ParameterGrp>& para
|
||||
void MaterialsEditor::addMaterials(
|
||||
QStandardItem& parent,
|
||||
const std::shared_ptr<std::map<QString, std::shared_ptr<Materials::MaterialTreeNode>>>
|
||||
modelTree,
|
||||
materialTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon,
|
||||
const Base::Reference<ParameterGrp>& param)
|
||||
{
|
||||
auto childParam = param->GetGroup(parent.text().toStdString().c_str());
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& mat : *modelTree) {
|
||||
for (auto& mat : *materialTree) {
|
||||
std::shared_ptr<Materials::MaterialTreeNode> nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::NodeType::DataNode) {
|
||||
QString uuid = nodePtr->getUUID();
|
||||
auto material = nodePtr->getData();
|
||||
QString uuid = material->getUUID();
|
||||
if (!material) {
|
||||
material = Materials::MaterialManager::getManager().getMaterial(uuid);
|
||||
nodePtr->setData(material);
|
||||
}
|
||||
|
||||
QIcon matIcon = icon;
|
||||
if (material->isOldFormat()) {
|
||||
@@ -697,7 +702,9 @@ void MaterialsEditor::addMaterials(
|
||||
addExpanded(tree, &parent, node, childParam);
|
||||
node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
auto treeMap = nodePtr->getFolder();
|
||||
addMaterials(*node, treeMap, folderIcon, icon, childParam);
|
||||
// if (treeMap) {
|
||||
addMaterials(*node, treeMap, folderIcon, icon, childParam);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -800,14 +807,15 @@ void MaterialsEditor::addRecents(QStandardItem* parent)
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
// if (material->getLibrary()->isLocal()) {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
addExpanded(tree, parent, card);
|
||||
// }
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
@@ -820,11 +828,10 @@ void MaterialsEditor::addFavorites(QStandardItem* parent)
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material->getLibrary()->getIconPath());
|
||||
auto card = new QStandardItem(icon, libraryPath(material));
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
@@ -856,12 +863,12 @@ void MaterialsEditor::fillMaterialTree()
|
||||
addRecents(lib);
|
||||
}
|
||||
|
||||
auto libraries = getMaterialManager().getMaterialLibraries();
|
||||
auto libraries = getMaterialManager().getLibraries();
|
||||
for (const auto& library : *libraries) {
|
||||
auto modelTree = getMaterialManager().getMaterialTree(library);
|
||||
auto materialTree = getMaterialManager().getMaterialTree(library);
|
||||
|
||||
bool showLibraries = _filterOptions.includeEmptyLibraries();
|
||||
if (!_filterOptions.includeEmptyLibraries() && modelTree->size() > 0) {
|
||||
if (!_filterOptions.includeEmptyLibraries() && materialTree->size() > 0) {
|
||||
showLibraries = true;
|
||||
}
|
||||
|
||||
@@ -873,7 +880,7 @@ void MaterialsEditor::fillMaterialTree()
|
||||
QIcon icon(library->getIconPath());
|
||||
QIcon folderIcon(QStringLiteral(":/icons/folder.svg"));
|
||||
|
||||
addMaterials(*lib, modelTree, folderIcon, icon, param);
|
||||
addMaterials(*lib, materialTree, folderIcon, icon, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,11 +908,11 @@ bool MaterialsEditor::updateTexturePreview() const
|
||||
{
|
||||
bool hasImage = false;
|
||||
QImage image;
|
||||
//double scaling = 99.0;
|
||||
// double scaling = 99.0;
|
||||
if (_material->hasModel(Materials::ModelUUIDs::ModelUUID_Rendering_Texture)) {
|
||||
// First try loading an embedded image
|
||||
try {
|
||||
auto property = _material->getAppearanceProperty(QLatin1String("TextureImage"));
|
||||
auto property = _material->getAppearanceProperty(QStringLiteral("TextureImage"));
|
||||
if (!property->isNull()) {
|
||||
// Base::Console().Log("Has 'TextureImage'\n");
|
||||
auto propertyValue = property->getString();
|
||||
@@ -922,7 +929,7 @@ bool MaterialsEditor::updateTexturePreview() const
|
||||
// If no embedded image, load from a path
|
||||
if (!hasImage) {
|
||||
try {
|
||||
auto property = _material->getAppearanceProperty(QLatin1String("TexturePath"));
|
||||
auto property = _material->getAppearanceProperty(QStringLiteral("TexturePath"));
|
||||
if (!property->isNull()) {
|
||||
// Base::Console().Log("Has 'TexturePath'\n");
|
||||
auto filePath = property->getString();
|
||||
@@ -940,10 +947,10 @@ bool MaterialsEditor::updateTexturePreview() const
|
||||
|
||||
// Apply any scaling
|
||||
try {
|
||||
auto property = _material->getAppearanceProperty(QLatin1String("TextureScaling"));
|
||||
auto property = _material->getAppearanceProperty(QStringLiteral("TextureScaling"));
|
||||
if (!property->isNull()) {
|
||||
//scaling = property->getFloat();
|
||||
// Base::Console().Log("Has 'TextureScaling' = %g\n", scaling);
|
||||
// scaling = property->getFloat();
|
||||
// Base::Console().Log("Has 'TextureScaling' = %g\n", scaling);
|
||||
}
|
||||
}
|
||||
catch (const Materials::PropertyNotFound&) {
|
||||
@@ -959,43 +966,43 @@ bool MaterialsEditor::updateTexturePreview() const
|
||||
|
||||
bool MaterialsEditor::updateMaterialPreview() const
|
||||
{
|
||||
if (_material->hasAppearanceProperty(QLatin1String("AmbientColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QLatin1String("AmbientColor"));
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("AmbientColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QStringLiteral("AmbientColor"));
|
||||
_rendered->setAmbientColor(getColorHash(color, 255));
|
||||
}
|
||||
else {
|
||||
_rendered->resetAmbientColor();
|
||||
}
|
||||
if (_material->hasAppearanceProperty(QLatin1String("DiffuseColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QLatin1String("DiffuseColor"));
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("DiffuseColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QStringLiteral("DiffuseColor"));
|
||||
_rendered->setDiffuseColor(getColorHash(color, 255));
|
||||
}
|
||||
else {
|
||||
_rendered->resetDiffuseColor();
|
||||
}
|
||||
if (_material->hasAppearanceProperty(QLatin1String("SpecularColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QLatin1String("SpecularColor"));
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("SpecularColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QStringLiteral("SpecularColor"));
|
||||
_rendered->setSpecularColor(getColorHash(color, 255));
|
||||
}
|
||||
else {
|
||||
_rendered->resetSpecularColor();
|
||||
}
|
||||
if (_material->hasAppearanceProperty(QLatin1String("EmissiveColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QLatin1String("EmissiveColor"));
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("EmissiveColor"))) {
|
||||
QString color = _material->getAppearanceValueString(QStringLiteral("EmissiveColor"));
|
||||
_rendered->setEmissiveColor(getColorHash(color, 255));
|
||||
}
|
||||
else {
|
||||
_rendered->resetEmissiveColor();
|
||||
}
|
||||
if (_material->hasAppearanceProperty(QLatin1String("Shininess"))) {
|
||||
double value = _material->getAppearanceValue(QLatin1String("Shininess")).toDouble();
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("Shininess"))) {
|
||||
double value = _material->getAppearanceValue(QStringLiteral("Shininess")).toDouble();
|
||||
_rendered->setShininess(value);
|
||||
}
|
||||
else {
|
||||
_rendered->resetShininess();
|
||||
}
|
||||
if (_material->hasAppearanceProperty(QLatin1String("Transparency"))) {
|
||||
double value = _material->getAppearanceValue(QLatin1String("Transparency")).toDouble();
|
||||
if (_material->hasAppearanceProperty(QStringLiteral("Transparency"))) {
|
||||
double value = _material->getAppearanceValue(QStringLiteral("Transparency")).toDouble();
|
||||
_rendered->setTransparency(value);
|
||||
}
|
||||
else {
|
||||
@@ -1065,7 +1072,7 @@ void MaterialsEditor::updateMaterialAppearance()
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
QString uuid = *it;
|
||||
try {
|
||||
auto model = getModelManager().getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
QString name = model->getName();
|
||||
|
||||
auto modelRoot = new QStandardItem(name);
|
||||
@@ -1129,7 +1136,7 @@ void MaterialsEditor::updateMaterialProperties()
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
QString uuid = *it;
|
||||
try {
|
||||
auto model = getModelManager().getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
QString name = model->getName();
|
||||
|
||||
auto modelRoot = new QStandardItem(name);
|
||||
@@ -1177,14 +1184,14 @@ QString MaterialsEditor::libraryPath(const std::shared_ptr<Materials::Material>&
|
||||
QString path;
|
||||
auto library = material->getLibrary();
|
||||
if (library) {
|
||||
path = QStringLiteral("/%1/%2")
|
||||
.arg(material->getLibrary()->getName())
|
||||
.arg(material->getDirectory());
|
||||
}
|
||||
else {
|
||||
path = QStringLiteral("%1").arg(material->getDirectory());
|
||||
path = QStringLiteral("/%1/%2/%3")
|
||||
.arg(library->getName())
|
||||
.arg(material->getDirectory())
|
||||
.arg(material->getName());
|
||||
return path;
|
||||
}
|
||||
|
||||
path = QStringLiteral("%1/%2").arg(material->getDirectory()).arg(material->getName());
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1192,7 +1199,7 @@ void MaterialsEditor::updateMaterialGeneral()
|
||||
{
|
||||
QString parentString;
|
||||
try {
|
||||
auto parent = _materialManager.getParent(_material);
|
||||
auto parent = Materials::MaterialManager::getManager().getParent(_material);
|
||||
parentString = libraryPath(parent);
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
|
||||
@@ -82,11 +82,7 @@ public:
|
||||
|
||||
Materials::MaterialManager& getMaterialManager()
|
||||
{
|
||||
return _materialManager;
|
||||
}
|
||||
Materials::ModelManager& getModelManager()
|
||||
{
|
||||
return _modelManager;
|
||||
return Materials::MaterialManager::getManager();
|
||||
}
|
||||
|
||||
static QString libraryPath(const std::shared_ptr<Materials::Material>& material);
|
||||
@@ -114,8 +110,6 @@ protected:
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_MaterialsEditor> ui;
|
||||
Materials::MaterialManager _materialManager;
|
||||
Materials::ModelManager _modelManager;
|
||||
std::shared_ptr<Materials::Material> _material;
|
||||
AppearancePreview* _rendered;
|
||||
bool _materialSelected;
|
||||
|
||||
@@ -239,7 +239,7 @@ void ModelSelect::addModels(
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& mod : *modelTree) {
|
||||
std::shared_ptr<Materials::ModelTreeNode> nodePtr = mod.second;
|
||||
if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) {
|
||||
if (nodePtr->getType() == Materials::ModelTreeNode::NodeType::DataNode) {
|
||||
auto model = nodePtr->getData();
|
||||
QString uuid = model->getUUID();
|
||||
|
||||
@@ -265,9 +265,9 @@ void ModelSelect::addRecents(QStandardItem* parent)
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
auto model = getModelManager().getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
|
||||
if (getModelManager().passFilter(_filter, model->getType())) {
|
||||
if (Materials::ModelManager::getManager().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
|
||||
@@ -287,9 +287,9 @@ void ModelSelect::addFavorites(QStandardItem* parent)
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
auto model = getModelManager().getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
|
||||
if (getModelManager().passFilter(_filter, model->getType())) {
|
||||
if (Materials::ModelManager::getManager().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
|
||||
@@ -339,13 +339,13 @@ void ModelSelect::fillTree()
|
||||
addExpanded(tree, model, lib);
|
||||
addRecents(lib);
|
||||
|
||||
auto libraries = getModelManager().getModelLibraries();
|
||||
auto libraries = Materials::ModelManager::getManager().getLibraries();
|
||||
for (auto& library : *libraries) {
|
||||
lib = new QStandardItem(library->getName());
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
auto modelTree = getModelManager().getModelTree(library, _filter);
|
||||
auto modelTree = Materials::ModelManager::getManager().getModelTree(library, _filter);
|
||||
addModels(*lib, modelTree, QIcon(library->getIconPath()));
|
||||
}
|
||||
}
|
||||
@@ -426,7 +426,7 @@ void ModelSelect::updateModelProperties(std::shared_ptr<Materials::Model> model)
|
||||
|
||||
void ModelSelect::updateMaterialModel(const QString& uuid)
|
||||
{
|
||||
auto model = getModelManager().getModel(uuid);
|
||||
auto model = Materials::ModelManager::getManager().getModel(uuid);
|
||||
|
||||
// Update the general information
|
||||
ui->editName->setText(model->getName());
|
||||
|
||||
@@ -91,14 +91,9 @@ private:
|
||||
void setColumnWidths(QTableView* table);
|
||||
void updateModelProperties(std::shared_ptr<Materials::Model> model);
|
||||
void createModelProperties();
|
||||
Materials::ModelManager& getModelManager()
|
||||
{
|
||||
return _modelManager;
|
||||
}
|
||||
|
||||
Materials::ModelFilter _filter;
|
||||
std::unique_ptr<Ui_ModelSelect> ui;
|
||||
Materials::ModelManager _modelManager;
|
||||
QString _selected;
|
||||
std::list<QString> _favorites;
|
||||
std::list<QString> _recents;
|
||||
|
||||
@@ -118,3 +118,220 @@ class ModelTestCases(unittest.TestCase):
|
||||
self.assertIn("URL", dir(prop))
|
||||
self.assertIn("Units", dir(prop))
|
||||
self.assertEqual(prop.Name, "Density")
|
||||
|
||||
def testTestModelCompleteness(self):
|
||||
""" Test that the Test model has been loaded correctly """
|
||||
model = self.ModelManager.getModel(self.uuids.TestModel)
|
||||
self.assertIsNotNone(model)
|
||||
self.assertEqual(model.Name, "Test Model")
|
||||
self.assertEqual(model.UUID, "34d0583d-f999-49ba-99e6-aa40bd5c3a6b")
|
||||
self.assertIn("TestString", model.Properties)
|
||||
self.assertEqual(len(model.Properties), 17)
|
||||
prop = model.Properties["TestString"]
|
||||
self.assertIn("Description", dir(prop))
|
||||
self.assertIn("Name", dir(prop))
|
||||
self.assertIn("Type", dir(prop))
|
||||
self.assertIn("URL", dir(prop))
|
||||
self.assertIn("Units", dir(prop))
|
||||
self.assertEqual(prop.Name, "TestString")
|
||||
self.assertEqual(prop.Type, "String")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A String")
|
||||
prop = model.Properties["TestURL"]
|
||||
self.assertEqual(prop.Name, "TestURL")
|
||||
self.assertEqual(prop.Type, "URL")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A URL")
|
||||
prop = model.Properties["TestList"]
|
||||
self.assertEqual(prop.Name, "TestList")
|
||||
self.assertEqual(prop.Type, "List")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A List")
|
||||
prop = model.Properties["TestFileList"]
|
||||
self.assertEqual(prop.Name, "TestFileList")
|
||||
self.assertEqual(prop.Type, "FileList")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A List of file paths")
|
||||
prop = model.Properties["TestImageList"]
|
||||
self.assertEqual(prop.Name, "TestImageList")
|
||||
self.assertEqual(prop.Type, "ImageList")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A List of embedded images")
|
||||
prop = model.Properties["TestInteger"]
|
||||
self.assertEqual(prop.Name, "TestInteger")
|
||||
self.assertEqual(prop.Type, "Integer")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A Integer")
|
||||
prop = model.Properties["TestFloat"]
|
||||
self.assertEqual(prop.Name, "TestFloat")
|
||||
self.assertEqual(prop.Type, "Float")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A Float")
|
||||
prop = model.Properties["TestBoolean"]
|
||||
self.assertEqual(prop.Name, "TestBoolean")
|
||||
self.assertEqual(prop.Type, "Boolean")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A Boolean")
|
||||
prop = model.Properties["TestColor"]
|
||||
self.assertEqual(prop.Name, "TestColor")
|
||||
self.assertEqual(prop.Type, "Color")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A Color")
|
||||
prop = model.Properties["TestFile"]
|
||||
self.assertEqual(prop.Name, "TestFile")
|
||||
self.assertEqual(prop.Type, "File")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A File")
|
||||
prop = model.Properties["TestSVG"]
|
||||
self.assertEqual(prop.Name, "TestSVG")
|
||||
self.assertEqual(prop.Type, "SVG")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "An SVG")
|
||||
prop = model.Properties["TestImage"]
|
||||
self.assertEqual(prop.Name, "TestImage")
|
||||
self.assertEqual(prop.Type, "Image")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "An Image")
|
||||
prop = model.Properties["TestQuantity"]
|
||||
self.assertEqual(prop.Name, "TestQuantity")
|
||||
self.assertEqual(prop.Type, "Quantity")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "kg/m^3")
|
||||
self.assertEqual(prop.Description, "A Quantity")
|
||||
prop = model.Properties["TestMultiLineString"]
|
||||
self.assertEqual(prop.Name, "TestMultiLineString")
|
||||
self.assertEqual(prop.Type, "MultiLineString")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "A string that spans multiple lines")
|
||||
|
||||
prop = model.Properties["TestArray2D"]
|
||||
self.assertEqual(prop.Name, "TestArray2D")
|
||||
self.assertEqual(prop.Type, "2DArray")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "2 Dimensional array showing density with temperature\n")
|
||||
self.assertEqual(len(prop.Columns), 2)
|
||||
col = prop.Columns[0]
|
||||
self.assertIn("Description", dir(col))
|
||||
self.assertIn("Name", dir(col))
|
||||
self.assertIn("Type", dir(col))
|
||||
self.assertIn("URL", dir(col))
|
||||
self.assertIn("Units", dir(col))
|
||||
self.assertEqual(col.Name, "Temperature")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "C")
|
||||
self.assertEqual(col.Description, "Temperature")
|
||||
col = prop.Columns[1]
|
||||
self.assertEqual(col.Name, "Density")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "https://en.wikipedia.org/wiki/Density")
|
||||
self.assertEqual(col.Units, "kg/m^3")
|
||||
self.assertEqual(col.Description, "Density in [FreeCAD Density unit]")
|
||||
|
||||
prop = model.Properties["TestArray2D3Column"]
|
||||
self.assertEqual(prop.Name, "TestArray2D3Column")
|
||||
self.assertEqual(prop.Type, "2DArray")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "2 Dimensional array showing density and initial yield stress with temperature\n")
|
||||
self.assertEqual(len(prop.Columns), 3)
|
||||
col = prop.Columns[0]
|
||||
self.assertEqual(col.Name, "Temperature")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "C")
|
||||
self.assertEqual(col.Description, "Temperature")
|
||||
col = prop.Columns[1]
|
||||
self.assertEqual(col.Name, "Density")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "https://en.wikipedia.org/wiki/Density")
|
||||
self.assertEqual(col.Units, "kg/m^3")
|
||||
self.assertEqual(col.Description, "Density in [FreeCAD Density unit]")
|
||||
col = prop.Columns[2]
|
||||
self.assertEqual(col.Name, "InitialYieldStress")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "kPa")
|
||||
self.assertEqual(col.Description, "Saturation stress for Voce isotropic hardening [FreeCAD Pressure unit]\n")
|
||||
|
||||
prop = model.Properties["TestArray3D"]
|
||||
self.assertEqual(prop.Name, "TestArray3D")
|
||||
self.assertEqual(prop.Type, "3DArray")
|
||||
self.assertEqual(prop.URL, "")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "3 Dimensional array showing stress and strain as a function of temperature\n")
|
||||
self.assertEqual(len(prop.Columns), 3)
|
||||
col = prop.Columns[0]
|
||||
self.assertEqual(col.Name, "Temperature")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "C")
|
||||
self.assertEqual(col.Description, "Temperature")
|
||||
col = prop.Columns[1]
|
||||
self.assertEqual(col.Name, "Stress")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "MPa")
|
||||
self.assertEqual(col.Description, "Stress")
|
||||
col = prop.Columns[2]
|
||||
self.assertEqual(col.Name, "Strain")
|
||||
self.assertEqual(col.Type, "Quantity")
|
||||
self.assertEqual(col.URL, "")
|
||||
self.assertEqual(col.Units, "MPa")
|
||||
self.assertEqual(col.Description, "Strain")
|
||||
|
||||
def testModelInheritance(self):
|
||||
""" Test that the inherited models have been loaded correctly """
|
||||
model = self.ModelManager.getModel(self.uuids.LinearElastic)
|
||||
self.assertIsNotNone(model)
|
||||
self.assertEqual(model.Name, "Linear Elastic")
|
||||
self.assertEqual(model.UUID, "7b561d1d-fb9b-44f6-9da9-56a4f74d7536")
|
||||
self.assertIn("Density", model.Properties)
|
||||
prop = model.Properties["Density"]
|
||||
self.assertEqual(prop.Name, "Density")
|
||||
self.assertEqual(prop.Type, "Quantity")
|
||||
self.assertEqual(prop.URL, "https://en.wikipedia.org/wiki/Density")
|
||||
self.assertEqual(prop.Units, "kg/m^3")
|
||||
self.assertEqual(prop.Description, "Density in [FreeCAD Density unit]")
|
||||
prop = model.Properties["BulkModulus"]
|
||||
self.assertEqual(prop.Name, "BulkModulus")
|
||||
self.assertEqual(prop.DisplayName, "Bulk Modulus")
|
||||
self.assertEqual(prop.Type, "Quantity")
|
||||
self.assertEqual(prop.URL, "https://en.wikipedia.org/wiki/Bulk_modulus")
|
||||
self.assertEqual(prop.Units, "kPa")
|
||||
self.assertEqual(prop.Description, "Bulk modulus in [FreeCAD Pressure unit]")
|
||||
prop = model.Properties["PoissonRatio"]
|
||||
self.assertEqual(prop.Name, "PoissonRatio")
|
||||
self.assertEqual(prop.DisplayName, "Poisson Ratio")
|
||||
self.assertEqual(prop.Type, "Float")
|
||||
self.assertEqual(prop.URL, "https://en.wikipedia.org/wiki/Poisson%27s_ratio")
|
||||
self.assertEqual(prop.Units, "")
|
||||
self.assertEqual(prop.Description, "Poisson's ratio [unitless]")
|
||||
prop = model.Properties["ShearModulus"]
|
||||
self.assertEqual(prop.Name, "ShearModulus")
|
||||
self.assertEqual(prop.DisplayName, "Shear Modulus")
|
||||
self.assertEqual(prop.Type, "Quantity")
|
||||
self.assertEqual(prop.URL, "https://en.wikipedia.org/wiki/Shear_modulus")
|
||||
self.assertEqual(prop.Units, "kPa")
|
||||
self.assertEqual(prop.Description, "Shear modulus in [FreeCAD Pressure unit]")
|
||||
prop = model.Properties["YoungsModulus"]
|
||||
self.assertEqual(prop.Name, "YoungsModulus")
|
||||
self.assertEqual(prop.DisplayName, "Young's Modulus")
|
||||
self.assertEqual(prop.Type, "Quantity")
|
||||
self.assertEqual(prop.URL, "https://en.wikipedia.org/wiki/Young%27s_modulus")
|
||||
self.assertEqual(prop.Units, "kPa")
|
||||
self.assertEqual(prop.Description, "Young's modulus (or E-Module) in [FreeCAD Pressure unit]")
|
||||
@@ -57,12 +57,12 @@ protected:
|
||||
QDir libDir(libPath);
|
||||
libDir.removeRecursively(); // Clear old run data
|
||||
libDir.mkdir(libPath);
|
||||
_library = std::make_shared<Materials::MaterialLibrary>(QStringLiteral("Testing"),
|
||||
_library = std::make_shared<Materials::MaterialLibraryLocal>(QStringLiteral("Testing"),
|
||||
libPath,
|
||||
QStringLiteral(":/icons/preferences-general.svg"),
|
||||
false);
|
||||
_modelManager = new Materials::ModelManager();
|
||||
_materialManager = new Materials::MaterialManager();
|
||||
_modelManager = &(Materials::ModelManager::getManager());
|
||||
_materialManager = &(Materials::MaterialManager::getManager());
|
||||
|
||||
_testMaterialUUID = QStringLiteral("c6c64159-19c1-40b5-859c-10561f20f979");
|
||||
}
|
||||
@@ -70,7 +70,7 @@ protected:
|
||||
// void TearDown() override {}
|
||||
Materials::ModelManager* _modelManager;
|
||||
Materials::MaterialManager* _materialManager;
|
||||
std::shared_ptr<Materials::MaterialLibrary> _library;
|
||||
std::shared_ptr<Materials::MaterialLibraryLocal> _library;
|
||||
QString _testMaterialUUID;
|
||||
};
|
||||
|
||||
@@ -187,17 +187,17 @@ TEST_F(TestMaterialCards, TestColumns)
|
||||
EXPECT_TRUE(testMaterial->hasPhysicalProperty(QStringLiteral("TestArray2D")));
|
||||
auto array2d = testMaterial->getPhysicalProperty(QStringLiteral("TestArray2D"))->getMaterialValue();
|
||||
EXPECT_TRUE(array2d);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material2DArray &>(*array2d).columns(), 2);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array2D &>(*array2d).columns(), 2);
|
||||
|
||||
EXPECT_TRUE(testMaterial->hasPhysicalProperty(QStringLiteral("TestArray2D3Column")));
|
||||
auto array2d3Column = testMaterial->getPhysicalProperty(QStringLiteral("TestArray2D3Column"))->getMaterialValue();
|
||||
EXPECT_TRUE(array2d3Column);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material2DArray &>(*array2d3Column).columns(), 3);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array2D &>(*array2d3Column).columns(), 3);
|
||||
|
||||
EXPECT_TRUE(testMaterial->hasPhysicalProperty(QStringLiteral("TestArray3D")));
|
||||
auto array3d = testMaterial->getPhysicalProperty(QStringLiteral("TestArray3D"))->getMaterialValue();
|
||||
EXPECT_TRUE(array3d);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material3DArray &>(*array3d).columns(), 2);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array3D &>(*array3d).columns(), 2);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -52,8 +52,8 @@ protected:
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
_modelManager = new Materials::ModelManager();
|
||||
_materialManager = new Materials::MaterialManager();
|
||||
_modelManager = &(Materials::ModelManager::getManager());
|
||||
_materialManager = &(Materials::MaterialManager::getManager());
|
||||
|
||||
// Use our test files as a custom directory
|
||||
ParameterGrp::handle hGrp =
|
||||
@@ -74,7 +74,7 @@ protected:
|
||||
|
||||
_materialManager->refresh();
|
||||
|
||||
_library = _materialManager->getLibrary(QLatin1String("Custom"));
|
||||
_library = _materialManager->getLibrary(QStringLiteral("Custom"));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -153,7 +153,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
ASSERT_EQ(tree->size(), 5);
|
||||
|
||||
// Create a basic rendering filter
|
||||
filter->setName(QLatin1String("Basic Appearance"));
|
||||
filter->setName(QStringLiteral("Basic Appearance"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
@@ -166,7 +166,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
|
||||
// Create an advanced rendering filter
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Advanced Appearance"));
|
||||
filter->setName(QStringLiteral("Advanced Appearance"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
@@ -179,7 +179,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
|
||||
// Create a Density filter
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Density"));
|
||||
filter->setName(QStringLiteral("Density"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
@@ -192,7 +192,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
|
||||
// Create a Hardness filter
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Hardness"));
|
||||
filter->setName(QStringLiteral("Hardness"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Hardness);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
@@ -205,7 +205,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
|
||||
// Create a Density and Basic Rendering filter
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Density and Basic Rendering"));
|
||||
filter->setName(QStringLiteral("Density and Basic Rendering"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic);
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density);
|
||||
options.setIncludeLegacy(false);
|
||||
@@ -219,7 +219,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
|
||||
// Create a Linear Elastic filter
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Linear Elastic"));
|
||||
filter->setName(QStringLiteral("Linear Elastic"));
|
||||
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
@@ -231,7 +231,7 @@ TEST_F(TestMaterialFilter, TestFilters)
|
||||
ASSERT_EQ(tree->size(), 0);
|
||||
|
||||
filter->clear();
|
||||
filter->setName(QLatin1String("Linear Elastic"));
|
||||
filter->setName(QStringLiteral("Linear Elastic"));
|
||||
filter->addRequired(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic);
|
||||
options.setIncludeLegacy(false);
|
||||
|
||||
|
||||
@@ -130,9 +130,9 @@ TEST_F(TestMaterialProperties, TestEmpty)
|
||||
|
||||
TEST_F(TestMaterialProperties, TestSingle)
|
||||
{
|
||||
Materials::MaterialProperty prop(modelProp1, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty prop(modelProp1, QStringLiteral("sampleUUID"));
|
||||
EXPECT_EQ(prop.getType(), Materials::MaterialValue::Quantity);
|
||||
EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID"));
|
||||
EXPECT_EQ(prop.getModelUUID(), QStringLiteral("sampleUUID"));
|
||||
EXPECT_TRUE(prop.isNull());
|
||||
auto variant = prop.getValue();
|
||||
EXPECT_TRUE(variant.canConvert<Base::Quantity>());
|
||||
@@ -146,9 +146,9 @@ TEST_F(TestMaterialProperties, TestSingle)
|
||||
void check2DArray(Materials::MaterialProperty& prop)
|
||||
{
|
||||
EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array2D);
|
||||
EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID"));
|
||||
EXPECT_EQ(prop.getModelUUID(), QStringLiteral("sampleUUID"));
|
||||
EXPECT_TRUE(prop.isNull());
|
||||
auto array = std::static_pointer_cast<Materials::Material2DArray>(prop.getMaterialValue());
|
||||
auto array = std::static_pointer_cast<Materials::Array2D>(prop.getMaterialValue());
|
||||
EXPECT_EQ(array->rows(), 0);
|
||||
auto variant = prop.getValue(); // Throw an error?
|
||||
EXPECT_FALSE(variant.canConvert<QString>());
|
||||
@@ -162,20 +162,20 @@ void check2DArray(Materials::MaterialProperty& prop)
|
||||
|
||||
TEST_F(TestMaterialProperties, Test2DArray)
|
||||
{
|
||||
Materials::MaterialProperty prop(modelProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty prop(modelProp, QStringLiteral("sampleUUID"));
|
||||
check2DArray(prop);
|
||||
}
|
||||
|
||||
TEST_F(TestMaterialProperties, Test2DArrayCopy)
|
||||
{
|
||||
Materials::MaterialProperty propBase(modelProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty propBase(modelProp, QStringLiteral("sampleUUID"));
|
||||
Materials::MaterialProperty prop(propBase);
|
||||
check2DArray(prop);
|
||||
}
|
||||
|
||||
TEST_F(TestMaterialProperties, Test2DArrayAssignment)
|
||||
{
|
||||
Materials::MaterialProperty propBase(modelProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty propBase(modelProp, QStringLiteral("sampleUUID"));
|
||||
Materials::MaterialProperty prop;
|
||||
|
||||
prop = propBase;
|
||||
@@ -185,9 +185,9 @@ TEST_F(TestMaterialProperties, Test2DArrayAssignment)
|
||||
void check3DArray(Materials::MaterialProperty& prop)
|
||||
{
|
||||
EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array3D);
|
||||
EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID"));
|
||||
EXPECT_EQ(prop.getModelUUID(), QStringLiteral("sampleUUID"));
|
||||
EXPECT_TRUE(prop.isNull());
|
||||
auto array = std::static_pointer_cast<Materials::Material3DArray>(prop.getMaterialValue());
|
||||
auto array = std::static_pointer_cast<Materials::Array3D>(prop.getMaterialValue());
|
||||
EXPECT_EQ(array->depth(), 0);
|
||||
auto variant = prop.getValue(); // Throw an error?
|
||||
EXPECT_FALSE(variant.canConvert<QString>());
|
||||
@@ -201,20 +201,20 @@ void check3DArray(Materials::MaterialProperty& prop)
|
||||
|
||||
TEST_F(TestMaterialProperties, Test3DArray)
|
||||
{
|
||||
Materials::MaterialProperty prop(model3DProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty prop(model3DProp, QStringLiteral("sampleUUID"));
|
||||
check3DArray(prop);
|
||||
}
|
||||
|
||||
TEST_F(TestMaterialProperties, Test3DArrayCopy)
|
||||
{
|
||||
Materials::MaterialProperty propBase(model3DProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty propBase(model3DProp, QStringLiteral("sampleUUID"));
|
||||
Materials::MaterialProperty prop(propBase);
|
||||
check3DArray(prop);
|
||||
}
|
||||
|
||||
TEST_F(TestMaterialProperties, Test3DArrayAssignment)
|
||||
{
|
||||
Materials::MaterialProperty propBase(model3DProp, QLatin1String("sampleUUID"));
|
||||
Materials::MaterialProperty propBase(model3DProp, QStringLiteral("sampleUUID"));
|
||||
Materials::MaterialProperty prop;
|
||||
|
||||
prop = propBase;
|
||||
|
||||
@@ -172,7 +172,7 @@ TEST_F(TestMaterialValue, TestArray2DType)
|
||||
{
|
||||
EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array2D), Materials::InvalidMaterialType);
|
||||
|
||||
auto mat2 = Materials::Material2DArray();
|
||||
auto mat2 = Materials::Array2D();
|
||||
EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array2D);
|
||||
EXPECT_TRUE(mat2.isNull());
|
||||
EXPECT_EQ(mat2.rows(), 0);
|
||||
@@ -182,7 +182,7 @@ TEST_F(TestMaterialValue, TestArray3DType)
|
||||
{
|
||||
EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array3D), Materials::InvalidMaterialType);
|
||||
|
||||
auto mat2 = Materials::Material3DArray();
|
||||
auto mat2 = Materials::Array3D();
|
||||
mat2.setColumns(2);
|
||||
EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array3D);
|
||||
EXPECT_TRUE(mat2.isNull());
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
#include <QString>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Gui/MetaTypes.h>
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
@@ -58,8 +58,8 @@ class TestMaterial : public ::testing::Test {
|
||||
|
||||
void SetUp() override {
|
||||
Base::Interpreter().runString("import Part");
|
||||
_modelManager = new Materials::ModelManager();
|
||||
_materialManager = new Materials::MaterialManager();
|
||||
_modelManager = &(Materials::ModelManager::getManager());
|
||||
_materialManager = &(Materials::MaterialManager::getManager());
|
||||
}
|
||||
|
||||
// void TearDown() override {}
|
||||
@@ -72,11 +72,11 @@ TEST_F(TestMaterial, TestInstallation)
|
||||
ASSERT_NE(_modelManager, nullptr);
|
||||
|
||||
// We should have loaded at least the system library
|
||||
auto libraries = _materialManager->getMaterialLibraries();
|
||||
auto libraries = _materialManager->getLibraries();
|
||||
ASSERT_GT(libraries->size(), 0);
|
||||
|
||||
// We should have at least one material
|
||||
auto materials = _materialManager->getMaterials();
|
||||
auto materials = _materialManager->getLocalMaterials();
|
||||
ASSERT_GT(materials->size(), 0);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ TEST_F(TestMaterial, TestMaterialsWithModel)
|
||||
|
||||
// All LinearElastic models should be in IsotropicLinearElastic since it is inherited
|
||||
EXPECT_LE(materialsLinearElastic->size(), materials->size());
|
||||
for (auto itp : *materialsLinearElastic) {
|
||||
for (auto &itp : *materialsLinearElastic) {
|
||||
auto mat = itp.first;
|
||||
EXPECT_NO_THROW(materials->at(mat));
|
||||
}
|
||||
@@ -365,17 +365,17 @@ TEST_F(TestMaterial, TestColumns)
|
||||
EXPECT_TRUE(testMaterial.hasPhysicalProperty(QStringLiteral("TestArray2D")));
|
||||
auto array2d = testMaterial.getPhysicalProperty(QStringLiteral("TestArray2D"))->getMaterialValue();
|
||||
EXPECT_TRUE(array2d);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material2DArray &>(*array2d).columns(), 2);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array2D &>(*array2d).columns(), 2);
|
||||
|
||||
EXPECT_TRUE(testMaterial.hasPhysicalProperty(QStringLiteral("TestArray2D3Column")));
|
||||
auto array2d3Column = testMaterial.getPhysicalProperty(QStringLiteral("TestArray2D3Column"))->getMaterialValue();
|
||||
EXPECT_TRUE(array2d3Column);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material2DArray &>(*array2d3Column).columns(), 3);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array2D &>(*array2d3Column).columns(), 3);
|
||||
|
||||
EXPECT_TRUE(testMaterial.hasPhysicalProperty(QStringLiteral("TestArray3D")));
|
||||
auto array3d = testMaterial.getPhysicalProperty(QStringLiteral("TestArray3D"))->getMaterialValue();
|
||||
EXPECT_TRUE(array3d);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Material3DArray &>(*array3d).columns(), 2);
|
||||
EXPECT_EQ(dynamic_cast<Materials::Array3D &>(*array3d).columns(), 2);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -46,7 +46,7 @@ class TestModel : public ::testing::Test {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
_modelManager = new Materials::ModelManager();
|
||||
_modelManager = &(Materials::ModelManager::getManager());
|
||||
}
|
||||
|
||||
// void TearDown() override {}
|
||||
@@ -76,7 +76,7 @@ TEST_F(TestModel, TestInstallation)
|
||||
ASSERT_NE(_modelManager, nullptr);
|
||||
|
||||
// We should have loaded at least the system library
|
||||
auto libraries = _modelManager->getModelLibraries();
|
||||
auto libraries = _modelManager->getLibraries();
|
||||
ASSERT_GT(libraries->size(), 0);
|
||||
|
||||
// We should have at least one model
|
||||
|
||||
Reference in New Issue
Block a user