Materials: External Modules Part 1
Refactored code to support local and external material sources This is the first PR in a series to support external modules. External modules allow materials to be stored in external data sources such as databases or web services. No new functionality is introduced in this PR, rather it is a refactoring of code that will allow for changes to be introduced in future PRs. Minor performance improvements have also been made in the model and material managers. The Python API has been enhanced for many data types to allow for modification within Python.
This commit is contained in:
committed by
Chris Hennes
parent
3c4977a2d4
commit
00c57a9d08
@@ -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)
|
||||
@@ -55,31 +58,45 @@ public:
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
143
src/Mod/Material/App/Library.cpp
Normal file
143
src/Mod/Material/App/Library.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/***************************************************************************
|
||||
* 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)
|
||||
, _iconPath(icon)
|
||||
, _readOnly(readOnly)
|
||||
, _directory(QDir::cleanPath(dir))
|
||||
{}
|
||||
|
||||
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(""));
|
||||
std::string pLocal = localPath.toStdString();
|
||||
std::string pclean = cleanPath.toStdString();
|
||||
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 (int 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 (int 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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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