Continues the work of the material subsystem improvements. Add support for embedded SVG files. These are not the same as image files so need to be handled differently. Add the ability to filter materials in the editor when called from code. This allows programs to select objects supporting specific models, complete models, older models, etc. Updated tests, and refactored code. New models and materials supporting patterns such as used by the TechDraw workbench. fixes #11686 - checks for the presense of a model property before assinging a value. This can happen when a required model definition is not available. --------- Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
419 lines
13 KiB
C++
419 lines
13 KiB
C++
/***************************************************************************
|
|
* 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_MATERIALS_H
|
|
#define MATERIAL_MATERIALS_H
|
|
|
|
#include <memory>
|
|
|
|
#include <QDir>
|
|
#include <QSet>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
#include <QTextStream>
|
|
|
|
#include <App/Application.h>
|
|
#include <Base/BaseClass.h>
|
|
|
|
#include <Mod/Material/MaterialGlobal.h>
|
|
|
|
#include "MaterialValue.h"
|
|
#include "Model.h"
|
|
|
|
namespace Materials
|
|
{
|
|
|
|
class MaterialLibrary;
|
|
|
|
class MaterialsExport MaterialProperty: public ModelProperty
|
|
{
|
|
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
|
|
|
public:
|
|
MaterialProperty();
|
|
MaterialProperty(const MaterialProperty& other);
|
|
explicit MaterialProperty(const ModelProperty& other);
|
|
explicit MaterialProperty(const std::shared_ptr<MaterialProperty>& other);
|
|
~MaterialProperty() override = default;
|
|
|
|
MaterialValue::ValueType getType() const
|
|
{
|
|
return _valuePtr->getType();
|
|
}
|
|
|
|
const QString getModelUUID() const;
|
|
QVariant getValue();
|
|
QVariant getValue() const;
|
|
QList<QVariant> getList()
|
|
{
|
|
return _valuePtr->getList();
|
|
}
|
|
QList<QVariant> getList() const
|
|
{
|
|
return _valuePtr->getList();
|
|
}
|
|
bool isNull() const
|
|
{
|
|
return _valuePtr->isNull();
|
|
}
|
|
std::shared_ptr<MaterialValue> getMaterialValue();
|
|
std::shared_ptr<MaterialValue> getMaterialValue() const;
|
|
QString getString() const;
|
|
QString getYAMLString() const;
|
|
bool getBoolean() const;
|
|
int getInt() const;
|
|
double getFloat() const;
|
|
const Base::Quantity& getQuantity() const;
|
|
const QString getURL() const;
|
|
|
|
MaterialProperty& getColumn(int column);
|
|
const MaterialProperty& getColumn(int column) const;
|
|
MaterialValue::ValueType getColumnType(int column) const;
|
|
QString getColumnUnits(int column) const;
|
|
QVariant getColumnNull(int column) const;
|
|
|
|
void setModelUUID(const QString& uuid);
|
|
void setPropertyType(const QString& type) override;
|
|
void setValue(const QVariant& value);
|
|
void setValue(const QString& value);
|
|
void setValue(const std::shared_ptr<MaterialValue>& value);
|
|
void setString(const QString& value);
|
|
void setBoolean(bool value);
|
|
void setBoolean(int value);
|
|
void setBoolean(const QString& value);
|
|
void setInt(int value);
|
|
void setInt(const QString& value);
|
|
void setFloat(double value);
|
|
void setFloat(const QString& value);
|
|
void setQuantity(const Base::Quantity& value);
|
|
void setQuantity(double value, const QString& units);
|
|
void setQuantity(const QString& value);
|
|
void setList(const QList<QVariant>& value);
|
|
void setURL(const QString& value);
|
|
|
|
MaterialProperty& operator=(const MaterialProperty& other);
|
|
friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property);
|
|
|
|
bool operator==(const MaterialProperty& other) const;
|
|
bool operator!=(const MaterialProperty& other) const
|
|
{
|
|
return !operator==(other);
|
|
}
|
|
|
|
// void save(QTextStream& stream);
|
|
|
|
// Define precision for displaying floating point values
|
|
static int const PRECISION;
|
|
|
|
protected:
|
|
void setType(const QString& type);
|
|
// void setType(MaterialValue::ValueType type) { _valueType = type; }
|
|
void copyValuePtr(const std::shared_ptr<MaterialValue>& value);
|
|
|
|
void addColumn(MaterialProperty& column)
|
|
{
|
|
_columns.push_back(column);
|
|
}
|
|
|
|
private:
|
|
QString _modelUUID;
|
|
std::shared_ptr<MaterialValue> _valuePtr;
|
|
std::vector<MaterialProperty> _columns;
|
|
};
|
|
|
|
class MaterialsExport Material: public Base::BaseClass
|
|
{
|
|
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
|
|
|
public:
|
|
enum ModelEdit
|
|
{
|
|
ModelEdit_None, // No change
|
|
ModelEdit_Alter, // Existing values are changed
|
|
ModelEdit_Extend // New values added
|
|
};
|
|
|
|
Material();
|
|
Material(const std::shared_ptr<MaterialLibrary>& library,
|
|
const QString& directory,
|
|
const QString& uuid,
|
|
const QString& name);
|
|
Material(const Material& other);
|
|
~Material() override = default;
|
|
|
|
std::shared_ptr<MaterialLibrary> getLibrary() const
|
|
{
|
|
return _library;
|
|
}
|
|
QString getDirectory() const
|
|
{
|
|
return _directory;
|
|
}
|
|
QString getUUID() const
|
|
{
|
|
return _uuid;
|
|
}
|
|
QString getName() const
|
|
{
|
|
return _name;
|
|
}
|
|
QString getAuthorAndLicense() const;
|
|
QString getAuthor() const
|
|
{
|
|
return _author;
|
|
}
|
|
QString getLicense() const
|
|
{
|
|
return _license;
|
|
}
|
|
QString getParentUUID() const
|
|
{
|
|
return _parentUuid;
|
|
}
|
|
QString getDescription() const
|
|
{
|
|
return _description;
|
|
}
|
|
QString getURL() const
|
|
{
|
|
return _url;
|
|
}
|
|
QString getReference() const
|
|
{
|
|
return _reference;
|
|
}
|
|
ModelEdit getEditState() const
|
|
{
|
|
return _editState;
|
|
}
|
|
const QSet<QString>& getTags() const
|
|
{
|
|
return _tags;
|
|
}
|
|
const QSet<QString>* getPhysicalModels() const
|
|
{
|
|
return &_physicalUuids;
|
|
}
|
|
const QSet<QString>* getAppearanceModels() const
|
|
{
|
|
return &_appearanceUuids;
|
|
}
|
|
|
|
void setLibrary(const std::shared_ptr<MaterialLibrary>& library)
|
|
{
|
|
_library = library;
|
|
}
|
|
void setDirectory(const QString& directory)
|
|
{
|
|
_directory = directory;
|
|
}
|
|
void setUUID(const QString& uuid)
|
|
{
|
|
_uuid = uuid;
|
|
}
|
|
void setName(const QString& name);
|
|
void setAuthor(const QString& author);
|
|
void setLicense(const QString& license);
|
|
void setParentUUID(const QString& uuid);
|
|
void setDescription(const QString& description);
|
|
void setURL(const QString& url);
|
|
void setReference(const QString& reference);
|
|
|
|
void setEditState(ModelEdit newState);
|
|
void setEditStateAlter()
|
|
{
|
|
setEditState(ModelEdit_Alter);
|
|
}
|
|
void setEditStateExtend()
|
|
{
|
|
setEditState(ModelEdit_Extend);
|
|
}
|
|
void setPropertyEditState(const QString& name);
|
|
void setPhysicalEditState(const QString& name);
|
|
void setAppearanceEditState(const QString& name);
|
|
void resetEditState()
|
|
{
|
|
_editState = ModelEdit_None;
|
|
}
|
|
void addTag(const QString& tag)
|
|
{
|
|
Q_UNUSED(tag);
|
|
}
|
|
void removeTag(const QString& tag)
|
|
{
|
|
Q_UNUSED(tag);
|
|
}
|
|
void addPhysical(const QString& uuid);
|
|
void removePhysical(const QString& uuid);
|
|
void addAppearance(const QString& uuid);
|
|
void removeAppearance(const QString& uuid);
|
|
void clearModels();
|
|
void newUuid();
|
|
|
|
void setPhysicalValue(const QString& name, const QString& value);
|
|
void setPhysicalValue(const QString& name, int value);
|
|
void setPhysicalValue(const QString& name, double value);
|
|
void setPhysicalValue(const QString& name, const Base::Quantity& value);
|
|
void setPhysicalValue(const QString& name, const std::shared_ptr<MaterialValue>& value);
|
|
void setPhysicalValue(const QString& name, const std::shared_ptr<QList<QVariant>>& value);
|
|
|
|
void setAppearanceValue(const QString& name, const QString& value);
|
|
void setAppearanceValue(const QString& name, const std::shared_ptr<MaterialValue>& value);
|
|
void setAppearanceValue(const QString& name, const std::shared_ptr<QList<QVariant>>& value);
|
|
|
|
std::shared_ptr<MaterialProperty> getPhysicalProperty(const QString& name);
|
|
std::shared_ptr<MaterialProperty> getPhysicalProperty(const QString& name) const;
|
|
std::shared_ptr<MaterialProperty> getAppearanceProperty(const QString& name);
|
|
std::shared_ptr<MaterialProperty> getAppearanceProperty(const QString& name) const;
|
|
std::shared_ptr<MaterialProperty> getProperty(const QString& name);
|
|
std::shared_ptr<MaterialProperty> getProperty(const QString& name) const;
|
|
QVariant getPhysicalValue(const QString& name) const;
|
|
Base::Quantity getPhysicalQuantity(const QString& name) const;
|
|
QString getPhysicalValueString(const QString& name) const;
|
|
QVariant getAppearanceValue(const QString& name) const;
|
|
Base::Quantity getAppearanceQuantity(const QString& name) const;
|
|
QString getAppearanceValueString(const QString& name) const;
|
|
bool hasPhysicalProperty(const QString& name) const;
|
|
bool hasAppearanceProperty(const QString& name) const;
|
|
|
|
// Test if the model is defined, and if values are provided for all properties
|
|
bool hasModel(const QString& uuid) const;
|
|
bool hasPhysicalModel(const QString& uuid) const;
|
|
bool hasAppearanceModel(const QString& uuid) const;
|
|
bool isModelComplete(const QString& uuid) const
|
|
{
|
|
return isPhysicalModelComplete(uuid) || isAppearanceModelComplete(uuid);
|
|
}
|
|
bool isPhysicalModelComplete(const QString& uuid) const;
|
|
bool isAppearanceModelComplete(const QString& uuid) const;
|
|
|
|
std::map<QString, std::shared_ptr<MaterialProperty>>& getPhysicalProperties()
|
|
{
|
|
return _physical;
|
|
}
|
|
std::map<QString, std::shared_ptr<MaterialProperty>>& getAppearanceProperties()
|
|
{
|
|
return _appearance;
|
|
}
|
|
|
|
QString getModelByName(const QString& name) const;
|
|
|
|
bool getDereferenced() const
|
|
{
|
|
return _dereferenced;
|
|
}
|
|
void markDereferenced()
|
|
{
|
|
_dereferenced = true;
|
|
}
|
|
bool isOldFormat() const
|
|
{
|
|
return _oldFormat;
|
|
}
|
|
void setOldFormat(bool isOld)
|
|
{
|
|
_oldFormat = isOld;
|
|
}
|
|
|
|
/*
|
|
* Normalize models by removing any inherited models
|
|
*/
|
|
static QStringList normalizeModels(const QStringList& models);
|
|
|
|
/*
|
|
* Set or change the base material for the current material, updating the properties as
|
|
* required.
|
|
*/
|
|
void updateInheritance(const QString& parent);
|
|
/*
|
|
* Return a list of models that are defined in the parent material but not in this one
|
|
*/
|
|
QStringList inheritedMissingModels(const Material& parent) const;
|
|
/*
|
|
* Return a list of models that are defined in this model but not the parent
|
|
*/
|
|
QStringList inheritedAddedModels(const Material& parent) const;
|
|
/*
|
|
* Return a list of properties that have different values from the parent material
|
|
*/
|
|
void inheritedPropertyDiff(const QString& parent);
|
|
|
|
void save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool saveInherited);
|
|
|
|
Material& operator=(const Material& other);
|
|
|
|
protected:
|
|
void addModel(const QString& uuid);
|
|
static void removeUUID(QSet<QString>& uuidList, const QString& uuid);
|
|
|
|
static QVariant
|
|
getValue(const std::map<QString, std::shared_ptr<MaterialProperty>>& propertyList,
|
|
const QString& name);
|
|
static QString
|
|
getValueString(const std::map<QString, std::shared_ptr<MaterialProperty>>& propertyList,
|
|
const QString& name);
|
|
|
|
bool modelChanged(const std::shared_ptr<Material>& parent,
|
|
const std::shared_ptr<Model>& model) const;
|
|
bool modelAppearanceChanged(const std::shared_ptr<Material>& parent,
|
|
const std::shared_ptr<Model>& model) const;
|
|
void saveGeneral(QTextStream& stream) const;
|
|
void saveInherits(QTextStream& stream) const;
|
|
void saveModels(QTextStream& stream, bool saveInherited) const;
|
|
void saveAppearanceModels(QTextStream& stream, bool saveInherited) const;
|
|
|
|
private:
|
|
std::shared_ptr<MaterialLibrary> _library;
|
|
QString _directory;
|
|
QString _uuid;
|
|
QString _name;
|
|
QString _author;
|
|
QString _license;
|
|
QString _parentUuid;
|
|
QString _description;
|
|
QString _url;
|
|
QString _reference;
|
|
QSet<QString> _tags;
|
|
QSet<QString> _physicalUuids;
|
|
QSet<QString> _appearanceUuids;
|
|
QSet<QString> _allUuids; // Includes inherited models
|
|
std::map<QString, std::shared_ptr<MaterialProperty>> _physical;
|
|
std::map<QString, std::shared_ptr<MaterialProperty>> _appearance;
|
|
bool _dereferenced;
|
|
bool _oldFormat;
|
|
ModelEdit _editState;
|
|
};
|
|
|
|
inline QTextStream& operator<<(QTextStream& output, const MaterialProperty& property)
|
|
{
|
|
output << MaterialValue::escapeString(property.getName()) << ":" << property.getYAMLString();
|
|
return output;
|
|
}
|
|
|
|
using MaterialTreeNode = FolderTreeNode<Material>;
|
|
|
|
} // namespace Materials
|
|
|
|
Q_DECLARE_METATYPE(Materials::Material*)
|
|
Q_DECLARE_METATYPE(std::shared_ptr<Materials::Material>)
|
|
|
|
#endif // MATERIAL_MATERIALS_H
|