Core: Convert transparency to alpha (#24891)

* Core: Convert transparency to alpha

Create new `Base::getVersion()` function for extracting a program
version enumeration given a version string.

Convert transparency to alpha value for old project files.

* Base/App: Address review comments

---------

Co-authored-by: wmayer <wmayer@freecad.org>
This commit is contained in:
Chris Hennes
2025-11-17 10:15:19 -06:00
committed by GitHub
parent 11eba3f25c
commit 4d0c35dd2d
4 changed files with 137 additions and 0 deletions

View File

@@ -35,6 +35,7 @@
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Interpreter.h>
#include <Base/ProgramVersion.h>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Quantity.h>
@@ -2226,6 +2227,25 @@ unsigned int PropertyBoolList::getMemSize() const
// PropertyColor
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
namespace
{
/// The definition of "alpha" was corrected in FreeCAD 1.1 -- returns true if the reader is working
/// on a file that pre-dates that correction.
bool readerRequiresAlphaConversion(const Base::XMLReader &reader)
{
return Base::getVersion(reader.ProgramVersion) < Base::Version::v1_1;
}
/// Given a material, invert the alpha channel of all of its colors.
void convertAlphaInMaterial(App::Material& material)
{
material.ambientColor.a = 1.0F - material.ambientColor.a;
material.diffuseColor.a = 1.0F - material.diffuseColor.a;
material.specularColor.a = 1.0F - material.specularColor.a;
material.emissiveColor.a = 1.0F - material.emissiveColor.a;
}
}
TYPESYSTEM_SOURCE(App::PropertyColor, App::Property)
//**************************************************************************
@@ -2367,6 +2387,12 @@ void PropertyColor::Restore(Base::XMLReader& reader)
reader.readElement("PropertyColor");
// get the value of my Attribute
unsigned long rgba = reader.getAttribute<unsigned long>("value");
if (readerRequiresAlphaConversion(reader)) {
// Convert transparency / alpha value
constexpr unsigned long alphaMax = 0xff;
unsigned long alpha = alphaMax - (rgba & alphaMax);
rgba = rgba - (rgba & alphaMax) + alpha;
}
setValue(rgba);
}
@@ -2448,6 +2474,8 @@ void PropertyColorList::Restore(Base::XMLReader& reader)
// initiate a file read
reader.addFile(file.c_str(), this);
}
requiresAlphaConversion = readerRequiresAlphaConversion(reader);
}
}
@@ -2472,6 +2500,11 @@ void PropertyColorList::RestoreDocFile(Base::Reader& reader)
str >> value;
it.setPackedValue(value);
}
if (requiresAlphaConversion) {
for (auto& it : values) {
it.a = 1.0F - it.a;
}
}
setValues(values);
}
@@ -2702,6 +2735,9 @@ void PropertyMaterial::Restore(Base::XMLReader& reader)
_cMat.emissiveColor.setPackedValue(reader.getAttribute<unsigned long>("emissiveColor"));
_cMat.shininess = (float)reader.getAttribute<double>("shininess");
_cMat.transparency = (float)reader.getAttribute<double>("transparency");
if (readerRequiresAlphaConversion(reader)) {
convertAlphaInMaterial(_cMat);
}
if (reader.hasAttribute("image")) {
_cMat.image = reader.getAttribute<const char*>("image");
}
@@ -3247,6 +3283,8 @@ void PropertyMaterialList::Restore(Base::XMLReader& reader)
// initiate a file read
reader.addFile(file.c_str(), this);
}
requiresAlphaConversion = readerRequiresAlphaConversion(reader);
}
}
@@ -3330,6 +3368,7 @@ void PropertyMaterialList::RestoreDocFileV0(uint32_t count, Base::Reader& reader
str >> valueF;
it.transparency = valueF;
}
convertAlpha(values);
setValues(values);
}
@@ -3360,9 +3399,17 @@ void PropertyMaterialList::RestoreDocFileV3(Base::Reader& reader)
readString(str, it.imagePath);
readString(str, it.uuid);
}
convertAlpha(values);
setValues(values);
}
void PropertyMaterialList::convertAlpha(std::vector<App::Material>& materials) const
{
if (requiresAlphaConversion) {
std::ranges::for_each(materials, convertAlphaInMaterial);
}
}
void PropertyMaterialList::readString(Base::InputStream& str, std::string& value)
{
uint32_t uCt {};