Material: Expanded Python API (#13829)
Expands the Python API to allow for material creation. With test cases.
This commit is contained in:
@@ -47,5 +47,10 @@
|
||||
<UserDocu>Get a list of materials implementing the specified model, with values for all properties</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="save" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>Save the material in the specified library</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateMaterial>
|
||||
|
||||
@@ -84,7 +84,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
|
||||
if (!libPath.isEmpty()) {
|
||||
try {
|
||||
auto material =
|
||||
getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()), libPath);
|
||||
getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()),
|
||||
libPath);
|
||||
return new MaterialPy(new Material(*material));
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
@@ -98,7 +99,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
|
||||
}
|
||||
|
||||
try {
|
||||
auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()));
|
||||
auto material =
|
||||
getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()));
|
||||
return new MaterialPy(new Material(*material));
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
@@ -195,3 +197,64 @@ PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args)
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::save(PyObject* args, PyObject* kwds)
|
||||
{
|
||||
char* libraryName {};
|
||||
PyObject* obj {};
|
||||
char* path {};
|
||||
PyObject* overwrite = Py_False;
|
||||
PyObject* saveAsCopy = Py_False;
|
||||
PyObject* saveInherited = Py_False;
|
||||
static char* kwds_save[] =
|
||||
{"library", "material", "path", "overwrite", "saveAsCopy", "saveInherited", nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args,
|
||||
kwds,
|
||||
"etOet|O!O!O!",
|
||||
kwds_save,
|
||||
"utf-8", &libraryName,
|
||||
&obj,
|
||||
"utf-8", &path,
|
||||
&PyBool_Type, &overwrite,
|
||||
&PyBool_Type, &saveAsCopy,
|
||||
&PyBool_Type, &saveInherited)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Base::Console().Log("library name %s\n", libraryName);
|
||||
Base::Console().Log("path %s\n", path);
|
||||
|
||||
MaterialPy* material;
|
||||
if (QLatin1String(obj->ob_type->tp_name) == QLatin1String("Materials.Material")) {
|
||||
material = static_cast<MaterialPy*>(obj);
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError, "Material expected not '%s'", obj->ob_type->tp_name);
|
||||
return nullptr;
|
||||
}
|
||||
if (!material) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid material object");
|
||||
return nullptr;
|
||||
}
|
||||
auto sharedMaterial = std::make_shared<Material>(*(material->getMaterialPtr()));
|
||||
|
||||
std::shared_ptr<MaterialLibrary> library;
|
||||
try {
|
||||
library = getMaterialManagerPtr()->getLibrary(QString::fromUtf8(libraryName));
|
||||
}
|
||||
catch (const LibraryNotFound&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Unknown library");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
getMaterialManagerPtr()->saveMaterial(library,
|
||||
sharedMaterial,
|
||||
QString::fromUtf8(path),
|
||||
PyObject_IsTrue(overwrite),
|
||||
PyObject_IsTrue(saveAsCopy),
|
||||
PyObject_IsTrue(saveInherited));
|
||||
material->getMaterialPtr()->setUUID(sharedMaterial->getUUID()); // Make sure they match
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryIcon" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Attribute Name="Name" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Model name.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -47,23 +47,23 @@
|
||||
</Attribute>
|
||||
<Attribute Name="UUID" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Unique model identifier.</UserDocu>
|
||||
<UserDocu>Unique model identifier. This is only valid after the material is saved.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="UUID" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Attribute Name="Description" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Description of the material.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Attribute Name="URL" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a material reference.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Reference" ReadOnly="true">
|
||||
<Attribute Name="Reference" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Reference for material data.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -81,13 +81,13 @@
|
||||
</Documentation>
|
||||
<Parameter Name="AuthorAndLicense" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Author" ReadOnly="true">
|
||||
<Attribute Name="Author" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Author information.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Author" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="License" ReadOnly="true">
|
||||
<Attribute Name="License" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>License information.</UserDocu>
|
||||
</Documentation>
|
||||
@@ -111,11 +111,31 @@
|
||||
</Documentation>
|
||||
<Parameter Name="Tags" Type="List"/>
|
||||
</Attribute>
|
||||
<Methode Name="addPhysicalModel" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Add the physical model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="removePhysicalModel" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Remove the physical model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasPhysicalModel" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the physical model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="addAppearanceModel" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Add the appearance model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="removeAppearanceModel" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Remove the appearance model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasAppearanceModel" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the appearance model with the given UUID</UserDocu>
|
||||
@@ -175,10 +195,20 @@
|
||||
<UserDocu>Get the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setPhysicalValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getAppearanceValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setAppearanceValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
@@ -48,43 +48,8 @@ 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
|
||||
{
|
||||
MaterialPy::PointerType ptr = getMaterialPtr();
|
||||
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();
|
||||
// str << "), DOI=(";
|
||||
// str << ptr->getDOI();
|
||||
// str << "), Description=(";
|
||||
// str << ptr->getDescription();
|
||||
// str << "), Inherits=[";
|
||||
// const std::vector<std::string> &inherited = getMaterialPtr()->getInheritance();
|
||||
// for (auto it = inherited.begin(); it != inherited.end(); it++)
|
||||
// {
|
||||
// std::string uuid = *it;
|
||||
// if (it != inherited.begin())
|
||||
// str << "), UUID=(";
|
||||
// else
|
||||
// str << "UUID=(";
|
||||
// str << uuid << ")";
|
||||
// }
|
||||
// str << "]]";
|
||||
str << ")]";
|
||||
|
||||
std::ostringstream str;
|
||||
str << "<Material at " << getMaterialPtr() << ">";
|
||||
return str.str();
|
||||
}
|
||||
|
||||
@@ -123,6 +88,11 @@ Py::String MaterialPy::getName() const
|
||||
return {getMaterialPtr()->getName().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setName(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setName(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getDirectory() const
|
||||
{
|
||||
return {getMaterialPtr()->getDirectory().toStdString()};
|
||||
@@ -138,16 +108,31 @@ Py::String MaterialPy::getDescription() const
|
||||
return {getMaterialPtr()->getDescription().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setDescription(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setDescription(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getURL() const
|
||||
{
|
||||
return {getMaterialPtr()->getURL().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setURL(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setURL(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getReference() const
|
||||
{
|
||||
return {getMaterialPtr()->getReference().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setReference(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setReference(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getParent() const
|
||||
{
|
||||
return {getMaterialPtr()->getParentUUID().toStdString()};
|
||||
@@ -163,11 +148,21 @@ Py::String MaterialPy::getAuthor() const
|
||||
return {getMaterialPtr()->getAuthor().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setAuthor(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setAuthor(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLicense() const
|
||||
{
|
||||
return {getMaterialPtr()->getLicense().toStdString()};
|
||||
}
|
||||
|
||||
void MaterialPy::setLicense(Py::String arg)
|
||||
{
|
||||
getMaterialPtr()->setLicense(QString::fromStdString(arg));
|
||||
}
|
||||
|
||||
Py::List MaterialPy::getPhysicalModels() const
|
||||
{
|
||||
auto models = getMaterialPtr()->getPhysicalModels();
|
||||
@@ -214,6 +209,30 @@ int MaterialPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::addPhysicalModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->addPhysical(QString::fromStdString(uuid));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::removePhysicalModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->removePhysical(QString::fromStdString(uuid));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasPhysicalModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
@@ -225,6 +244,30 @@ PyObject* MaterialPy::hasPhysicalModel(PyObject* args)
|
||||
return PyBool_FromLong(hasProperty ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::addAppearanceModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->addAppearance(QString::fromStdString(uuid));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::removeAppearanceModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->removeAppearance(QString::fromStdString(uuid));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasAppearanceModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
@@ -472,6 +515,20 @@ PyObject* MaterialPy::getPhysicalValue(PyObject* args)
|
||||
return _pyObjectFromVariant(value);
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::setPhysicalValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
char* value;
|
||||
if (!PyArg_ParseTuple(args, "ss", &name, &value)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->setPhysicalValue(QString::fromStdString(name),
|
||||
QString::fromStdString(value));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::getAppearanceValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
@@ -482,3 +539,17 @@ PyObject* MaterialPy::getAppearanceValue(PyObject* args)
|
||||
QVariant value = getMaterialPtr()->getAppearanceValue(QString::fromStdString(name));
|
||||
return _pyObjectFromVariant(value);
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::setAppearanceValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
char* value;
|
||||
if (!PyArg_ParseTuple(args, "ss", &name, &value)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
getMaterialPtr()->setAppearanceValue(QString::fromStdString(name),
|
||||
QString::fromStdString(value));
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ bool LibraryBase::operator==(const LibraryBase& library) const
|
||||
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 = QString::fromStdString("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
|
||||
@@ -285,6 +285,7 @@ set(MaterialTest_Files
|
||||
materialtests/__init__.py
|
||||
materialtests/TestModels.py
|
||||
materialtests/TestMaterials.py
|
||||
materialtests/TestMaterialCreation.py
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(MaterialTest ALL
|
||||
|
||||
@@ -28,3 +28,4 @@ import Materials
|
||||
|
||||
from materialtests.TestModels import ModelTestCases
|
||||
from materialtests.TestMaterials import MaterialTestCases
|
||||
from materialtests.TestMaterialCreation import MaterialCreationTestCases
|
||||
|
||||
137
src/Mod/Material/materialtests/TestMaterialCreation.py
Normal file
137
src/Mod/Material/materialtests/TestMaterialCreation.py
Normal file
@@ -0,0 +1,137 @@
|
||||
#**************************************************************************
|
||||
# Copyright (c) 2023 David Carter <dcarter@davidcarter.ca> *
|
||||
# *
|
||||
# This file is part of the FreeCAD CAx development system. *
|
||||
# *
|
||||
# This program is free software; you can redistribute it and/or modify *
|
||||
# it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# as published by the Free Software Foundation; either version 2 of *
|
||||
# the License, or (at your option) any later version. *
|
||||
# for detail see the LICENCE text file. *
|
||||
# *
|
||||
# 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 Library General Public License for more details. *
|
||||
# *
|
||||
# You should have received a copy of the GNU Library General Public *
|
||||
# License along with FreeCAD; if not, write to the Free Software *
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# USA *
|
||||
#**************************************************************************
|
||||
|
||||
"""
|
||||
Test module for FreeCAD material cards and APIs
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import FreeCAD
|
||||
import Materials
|
||||
|
||||
import os
|
||||
|
||||
parseQuantity = FreeCAD.Units.parseQuantity
|
||||
|
||||
class MaterialCreationTestCases(unittest.TestCase):
|
||||
"""
|
||||
Test class for FreeCAD material creation and APIs
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
""" Setup function to initialize test data """
|
||||
self.ModelManager = Materials.ModelManager()
|
||||
self.MaterialManager = Materials.MaterialManager()
|
||||
self.uuids = Materials.UUIDs()
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
material = self.MaterialManager.getMaterialByPath("Example/Frakenstein.FCMat", "User")
|
||||
os.remove(material.LibraryRoot + "/Example/Frakenstein.FCMat")
|
||||
try:
|
||||
os.rmdir(material.LibraryRoot + "/Example")
|
||||
except OSError:
|
||||
# Can't remove directories that aren't empty
|
||||
pass
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
def checkNewMaterial(self, material):
|
||||
""" Check the state of a newly created material """
|
||||
self.assertEqual(len(material.UUID), 0)
|
||||
self.assertEqual(len(material.Name), 0)
|
||||
self.assertEqual(len(material.Author), 0)
|
||||
self.assertEqual(len(material.License), 0)
|
||||
self.assertEqual(len(material.Description), 0)
|
||||
self.assertEqual(len(material.URL), 0)
|
||||
self.assertEqual(len(material.Reference), 0)
|
||||
self.assertEqual(len(material.Parent), 0)
|
||||
self.assertEqual(len(material.Tags), 0)
|
||||
|
||||
def testCreateMaterial(self):
|
||||
""" Create a material with properties """
|
||||
material = Materials.Material()
|
||||
self.checkNewMaterial(material)
|
||||
|
||||
material.Name = "Frankenstein"
|
||||
material.Author = "Mary Shelley"
|
||||
material.License = "CC-BY-3.0"
|
||||
material.Description = "The sad story of a boy afraid of fire"
|
||||
material.URL = "https://www.example.com"
|
||||
material.Reference = "ISBN 978-1673287882"
|
||||
|
||||
# UUID isn't valid until the file is saved
|
||||
self.assertEqual(material.UUID, '')
|
||||
|
||||
self.assertEqual(material.Name, "Frankenstein")
|
||||
self.assertEqual(material.Author, "Mary Shelley")
|
||||
self.assertEqual(material.License, "CC-BY-3.0")
|
||||
self.assertEqual(material.Description, "The sad story of a boy afraid of fire")
|
||||
self.assertEqual(material.URL, "https://www.example.com")
|
||||
self.assertEqual(material.Reference, "ISBN 978-1673287882")
|
||||
|
||||
self.assertEqual(len(material.PhysicalModels), 0)
|
||||
self.assertEqual(len(material.AppearanceModels), 0)
|
||||
|
||||
material.addAppearanceModel(self.uuids.TextureRendering)
|
||||
self.assertEqual(len(material.AppearanceModels), 1)
|
||||
# TextureRendering inherits BasicRendering
|
||||
self.assertTrue(material.hasAppearanceModel(self.uuids.BasicRendering))
|
||||
self.assertTrue(material.hasAppearanceModel(self.uuids.TextureRendering))
|
||||
|
||||
# Colors are tuples of 3 (rgb) or 4 (rgba) values between 0 and 1
|
||||
# All values are set with strings
|
||||
material.setAppearanceValue("DiffuseColor", "(1.0, 1.0, 1.0)")
|
||||
material.setAppearanceValue("SpecularColor", "(0, 0, 0, 1.0)")
|
||||
|
||||
self.assertEqual(material.AppearanceProperties["DiffuseColor"], "(1.0, 1.0, 1.0)")
|
||||
self.assertEqual(material.getAppearanceValue("DiffuseColor"), "(1.0, 1.0, 1.0)")
|
||||
|
||||
self.assertEqual(material.AppearanceProperties["SpecularColor"], "(0, 0, 0, 1.0)")
|
||||
self.assertEqual(material.getAppearanceValue("SpecularColor"), "(0, 0, 0, 1.0)")
|
||||
|
||||
# Properties without a value will return None
|
||||
self.assertIsNone(material.getAppearanceValue("AmbientColor"))
|
||||
self.assertIsNone(material.getAppearanceValue("EmissiveColor"))
|
||||
self.assertIsNone(material.getAppearanceValue("Shininess"))
|
||||
self.assertIsNone(material.getAppearanceValue("Transparency"))
|
||||
self.assertIsNone(material.getAppearanceValue("TexturePath"))
|
||||
self.assertIsNone(material.getAppearanceValue("TextureImage"))
|
||||
self.assertIsNone(material.getAppearanceValue("TextureScaling"))
|
||||
|
||||
material.addPhysicalModel(self.uuids.Density)
|
||||
self.assertEqual(len(material.PhysicalModels), 1)
|
||||
self.assertTrue(material.hasPhysicalModel(self.uuids.Density))
|
||||
|
||||
# Quantity properties require units
|
||||
material.setPhysicalValue("Density", "99.9 kg/m^3")
|
||||
self.assertEqual(material.getPhysicalValue("Density").UserString, parseQuantity("99.90 kg/m^3").UserString)
|
||||
|
||||
# MaterialManager is unaware of the material until it is saved
|
||||
self.MaterialManager.save("User", material, "Example/Frakenstein.FCMat")
|
||||
|
||||
# Now the UUID is valid
|
||||
uuid = material.UUID
|
||||
self.assertEqual(len(material.UUID), 36)
|
||||
self.assertIn(uuid, self.MaterialManager.Materials)
|
||||
self.assertIsNotNone(self.MaterialManager.getMaterialByPath("Example/Frakenstein.FCMat", "User"))
|
||||
self.assertIsNotNone(self.MaterialManager.getMaterial(uuid))
|
||||
Reference in New Issue
Block a user