Material: Material editor enhancements (#11764)

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>
This commit is contained in:
David Carter
2024-01-06 19:11:53 -05:00
committed by GitHub
parent 08612d4489
commit d9017bcca3
87 changed files with 3894 additions and 655 deletions

View File

@@ -148,60 +148,23 @@ void MaterialProperty::setPropertyType(const QString& type)
void MaterialProperty::setType(const QString& type)
{
if (type == QString::fromStdString("String")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::String);
auto mappedType = MaterialValue::mapType(type);
if (mappedType == MaterialValue::None) {
throw UnknownValueType();
}
else if (type == QString::fromStdString("Boolean")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Boolean);
}
else if (type == QString::fromStdString("Integer")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Integer);
}
else if (type == QString::fromStdString("Float")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Float);
}
else if (type == QString::fromStdString("URL")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::URL);
}
else if (type == QString::fromStdString("Quantity")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Quantity);
}
else if (type == QString::fromStdString("Color")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Color);
}
else if (type == QString::fromStdString("File")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::File);
}
else if (type == QString::fromStdString("Image")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::Image);
}
else if (type == QString::fromStdString("List")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::List);
}
else if (type == QString::fromStdString("FileList")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::FileList);
}
else if (type == QString::fromStdString("ImageList")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::ImageList);
}
else if (type == QString::fromStdString("MultiLineString")) {
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::MultiLineString);
}
else if (type == QString::fromStdString("2DArray")) {
if (mappedType == MaterialValue::Array2D) {
auto arrayPtr = std::make_shared<Material2DArray>();
arrayPtr->setColumns(columns());
_valuePtr = arrayPtr;
}
else if (type == QString::fromStdString("3DArray")) {
else if (mappedType == MaterialValue::Array3D) {
auto arrayPtr = std::make_shared<Material3DArray>();
// First column is third dimension
arrayPtr->setColumns(columns() - 1);
_valuePtr = arrayPtr;
}
else {
// Error. Throw something
_valuePtr = std::make_shared<MaterialValue>(MaterialValue::None);
throw UnknownValueType();
_valuePtr = std::make_shared<MaterialValue>(mappedType);
}
}
@@ -457,16 +420,16 @@ Material::Material(const Material& other)
, _editState(other._editState)
{
for (auto& it : other._tags) {
_tags.push_back(it);
_tags.insert(it);
}
for (auto& it : other._physicalUuids) {
_physicalUuids.push_back(it);
_physicalUuids.insert(it);
}
for (auto& it : other._appearanceUuids) {
_appearanceUuids.push_back(it);
_appearanceUuids.insert(it);
}
for (auto& it : other._allUuids) {
_allUuids.push_back(it);
_allUuids.insert(it);
}
for (auto& it : other._physical) {
MaterialProperty prop(it.second);
@@ -498,7 +461,7 @@ QString Material::getAuthorAndLicense() const
void Material::addModel(const QString& uuid)
{
for (QString& modelUUID : _allUuids) {
for (const auto& modelUUID : qAsConst(_allUuids)) {
if (modelUUID == uuid) {
return;
}
@@ -582,9 +545,9 @@ void Material::setEditState(ModelEdit newState)
}
}
void Material::removeUUID(QStringList& uuidList, const QString& uuid)
void Material::removeUUID(QSet<QString>& uuidList, const QString& uuid)
{
uuidList.removeAll(uuid);
uuidList.remove(uuid);
}
void Material::addPhysical(const QString& uuid)
@@ -605,7 +568,7 @@ void Material::addPhysical(const QString& uuid)
removeUUID(_physicalUuids, it);
}
_physicalUuids.push_back(uuid);
_physicalUuids.insert(uuid);
addModel(uuid);
setEditStateExtend();
@@ -637,7 +600,7 @@ void Material::removePhysical(const QString& uuid)
// If it's an inherited model, do nothing
bool inherited = true;
for (auto& it : _physicalUuids) {
for (const auto& it : qAsConst(_physicalUuids)) {
if (it == uuid) {
inherited = false;
break;
@@ -689,7 +652,7 @@ void Material::addAppearance(const QString& uuid)
removeUUID(_appearanceUuids, it);
}
_appearanceUuids.push_back(uuid);
_appearanceUuids.insert(uuid);
addModel(uuid);
setEditStateExtend();
@@ -715,7 +678,7 @@ void Material::removeAppearance(const QString& uuid)
// If it's an inherited model, do nothing
bool inherited = true;
for (auto& it : _appearanceUuids) {
for (const auto& it : qAsConst(_appearanceUuids)) {
if (it == uuid) {
inherited = false;
break;
@@ -790,56 +753,72 @@ void Material::setPhysicalValue(const QString& name, const QString& value)
{
setPhysicalEditState(name);
_physical[name]->setValue(value); // may not be a string type, conversion may be required
if (hasPhysicalProperty(name)) {
_physical[name]->setValue(value); // may not be a string type, conversion may be required
}
}
void Material::setPhysicalValue(const QString& name, int value)
{
setPhysicalEditState(name);
_physical[name]->setInt(value);
if (hasPhysicalProperty(name)) {
_physical[name]->setInt(value);
}
}
void Material::setPhysicalValue(const QString& name, double value)
{
setPhysicalEditState(name);
_physical[name]->setFloat(value);
if (hasPhysicalProperty(name)) {
_physical[name]->setFloat(value);
}
}
void Material::setPhysicalValue(const QString& name, const Base::Quantity& value)
{
setPhysicalEditState(name);
_physical[name]->setQuantity(value);
if (hasPhysicalProperty(name)) {
_physical[name]->setQuantity(value);
}
}
void Material::setPhysicalValue(const QString& name, const std::shared_ptr<MaterialValue>& value)
{
setPhysicalEditState(name);
_physical[name]->setValue(value);
if (hasPhysicalProperty(name)) {
_physical[name]->setValue(value);
}
}
void Material::setPhysicalValue(const QString& name, const std::shared_ptr<QList<QVariant>>& value)
{
setPhysicalEditState(name);
_physical[name]->setList(*value);
if (hasPhysicalProperty(name)) {
_physical[name]->setList(*value);
}
}
void Material::setAppearanceValue(const QString& name, const QString& value)
{
setAppearanceEditState(name);
_appearance[name]->setValue(value); // may not be a string type, conversion may be required
if (hasAppearanceProperty(name)) {
_appearance[name]->setValue(value); // may not be a string type, conversion may be required
}
}
void Material::setAppearanceValue(const QString& name, const std::shared_ptr<MaterialValue>& value)
{
setAppearanceEditState(name);
_appearance[name]->setValue(value);
if (hasAppearanceProperty(name)) {
_appearance[name]->setValue(value);
}
}
void Material::setAppearanceValue(const QString& name,
@@ -847,7 +826,9 @@ void Material::setAppearanceValue(const QString& name,
{
setAppearanceEditState(name);
_appearance[name]->setList(*value);
if (hasAppearanceProperty(name)) {
_appearance[name]->setList(*value);
}
}
std::shared_ptr<MaterialProperty> Material::getPhysicalProperty(const QString& name)
@@ -890,6 +871,28 @@ std::shared_ptr<MaterialProperty> Material::getAppearanceProperty(const QString&
}
}
std::shared_ptr<MaterialProperty> Material::getProperty(const QString& name)
{
if (hasPhysicalProperty(name)) {
return getPhysicalProperty(name);
}
if (hasAppearanceProperty(name)) {
return getAppearanceProperty(name);
}
throw PropertyNotFound();
}
std::shared_ptr<MaterialProperty> Material::getProperty(const QString& name) const
{
if (hasPhysicalProperty(name)) {
return getPhysicalProperty(name);
}
if (hasAppearanceProperty(name)) {
return getAppearanceProperty(name);
}
throw PropertyNotFound();
}
QVariant
Material::getValue(const std::map<QString, std::shared_ptr<MaterialProperty>>& propertyList,
const QString& name)
@@ -1295,7 +1298,8 @@ QString Material::getModelByName(const QString& name) const
void Material::save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool saveInherited)
{
if (saveInherited && !saveAsCopy) {
// Check to see if we're an original or if we're already in the list of models
// 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) {
// Make a new version based on the current
@@ -1304,6 +1308,11 @@ void Material::save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool s
}
}
// Prevent self inheritance
if (_parentUuid == _uuid) {
_parentUuid = QString();
}
if (saveAsCopy) {
// Save it in the same format as the parent
if (_parentUuid.isEmpty()) {
@@ -1315,8 +1324,8 @@ void Material::save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool s
}
else {
if (!overwrite) {
// Creating a new derived model when overwriting sets itself as a parent,
// that will no longer exist because it's been overwritten
// Creating a new derived model when overwriting sets itself as a
// parent, that will no longer exist because it's been overwritten
newUuid();
}
}
@@ -1358,19 +1367,19 @@ Material& Material::operator=(const Material& other)
_tags.clear();
for (auto& it : other._tags) {
_tags.push_back(it);
_tags.insert(it);
}
_physicalUuids.clear();
for (auto& it : other._physicalUuids) {
_physicalUuids.push_back(it);
_physicalUuids.insert(it);
}
_appearanceUuids.clear();
for (auto& it : other._appearanceUuids) {
_appearanceUuids.push_back(it);
_appearanceUuids.insert(it);
}
_allUuids.clear();
for (auto& it : other._allUuids) {
_allUuids.push_back(it);
_allUuids.insert(it);
}
// Create copies of the properties rather than modify the originals
@@ -1420,14 +1429,15 @@ QStringList Material::normalizeModels(const QStringList& models)
}
/*
* Set or change the base material for the current material, updating the properties as
* required.
* Set or change the base material for the current material, updating the
* properties as required.
*/
void Material::updateInheritance([[maybe_unused]] const QString& parent)
{}
/*
* Return a list of models that are defined in the parent material but not in this one
* Return a list of models that are defined in the parent material but not in
* this one
*/
QStringList Material::inheritedMissingModels(const Material& parent) const
{
@@ -1457,7 +1467,8 @@ QStringList Material::inheritedAddedModels(const Material& parent) const
}
/*
* Return a list of properties that have different values from the parent material
* Return a list of properties that have different values from the parent
* material
*/
void Material::inheritedPropertyDiff([[maybe_unused]] const QString& parent)
{}