Materials: Default units (#20909)

Improves handling and assignment of default units

When creating a material without specifying units, no units are
currently assigned. This commit will assign the default units when none are
given, or throw an error when incompatible units are given. In the
latter case, the units are set to the property defaults.

This commit also incidentally fixed an issue when saving the material that
resulted in accessing an uninitialized pointer.
This commit is contained in:
David Carter
2025-05-05 16:31:25 +00:00
committed by GitHub
parent fe7d3e9071
commit 8abb9f0128
6 changed files with 90 additions and 12 deletions

View File

@@ -283,7 +283,20 @@ QVariant MaterialProperty::getColumnNull(int column) const
void MaterialProperty::setValue(const QVariant& value)
{
_valuePtr->setValue(value);
if (_valuePtr->getType() == MaterialValue::Quantity && value.canConvert<Base::Quantity>()) {
// Ensure the units are set correctly
auto quantity = value.value<Base::Quantity>();
if (quantity.isValid()) {
setQuantity(quantity);
}
else {
// Set a default value with default units
setValue(QStringLiteral("0"));
}
}
else {
_valuePtr->setValue(value);
}
}
void MaterialProperty::setValue(const QString& value)
@@ -386,6 +399,20 @@ void MaterialProperty::setFloat(const QString& value)
void MaterialProperty::setQuantity(const Base::Quantity& value)
{
auto quantity = value;
if (quantity.isDimensionless()) {
// Assign the default units when none are provided.
//
// This needs to be parsed rather than just setting units. Otherwise we get mm->m conversion
// errors, etc
quantity = Base::Quantity::parse(quantity.getUserString() + getUnits().toStdString());
}
else {
auto propertyUnit = Base::Quantity::parse(getUnits().toStdString()).getUnit();
auto units = quantity.getUnit();
if (propertyUnit != units) {
throw Base::ValueError("Incompatible material units");
}
}
quantity.setFormat(MaterialValue::getQuantityFormat());
_valuePtr->setValue(QVariant(QVariant::fromValue(quantity)));
}