feat(ugc): color_brightness and transparent_colors

color_brightness (percent, default 100: unchanged) scales the models' vertex
colors, not the icons', for servers where the made models look brighter than
they should. transparent_colors names color ids drawn transparent whatever
Materials.xml says: 129 (Tr. Bright Bluish Violet with Glitter) has alpha
255 there, so it came out opaque; a named color gets transparent_opacity.
Both default to off, so models come out byte for byte as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-28 11:07:07 -05:00
parent 2384f46a57
commit 41d336878a
7 changed files with 60 additions and 3 deletions

View File

@@ -247,7 +247,8 @@ namespace UgcModel {
for (size_t index = 0; index < design->size(); index++) {
const auto id = index < part.materials.size() ? part.materials[index] : (part.materials.empty() ? 0 : part.materials[0]);
const auto toolboxId = materialOf(index);
transparent = transparent && (luToolbox && inToolbox(toolboxId) ? UgcPalette::IsTransparent(toolboxId) : library.GetMaterial(luToolbox ? toolboxId : id).Transparent());
const auto named = options.transparentColors.contains(luToolbox ? toolboxId : id);
transparent = transparent && (named || (luToolbox && inToolbox(toolboxId) ? UgcPalette::IsTransparent(toolboxId) : library.GetMaterial(luToolbox ? toolboxId : id).Transparent()));
}
auto& mesh = transparent ? model.transparent : model.opaque;
if (transparent) model.transparentBricks.push_back(mesh.indices.size());
@@ -263,7 +264,7 @@ namespace UgcModel {
colorId = materialOf(index);
const auto material = library.GetMaterial(colorId);
linear = UgcPalette::SrgbToLinear(glm::vec3(material.r, material.g, material.b) / 255.0f);
if (transparent) alpha = material.a / 255.0f;
if (transparent) alpha = material.a < 255 ? material.a / 255.0f : std::clamp(options.transparentOpacity / 100.0f, 0.0f, 1.0f);
} else if (luToolbox) {
colorId = materialOf(index);
linear = *UgcPalette::Linear(colorId, options.icon);
@@ -275,12 +276,13 @@ namespace UgcModel {
colorId = index < part.materials.size() ? part.materials[index] : (part.materials.empty() ? 0 : part.materials[0]);
const auto material = library.GetMaterial(colorId);
linear = UgcPalette::SrgbToLinear(glm::vec3(material.r, material.g, material.b) / 255.0f);
if (transparent) alpha = material.a / 255.0f;
if (transparent) alpha = material.a < 255 ? material.a / 255.0f : std::clamp(options.transparentOpacity / 100.0f, 0.0f, 1.0f);
}
if (options.colorVariation > 0.0f) {
const float variation = options.colorVariation * (luToolbox ? UgcPalette::VariationScale(colorId) : 1.0f);
linear = UgcPalette::ApplyVariation(linear, variation, UgcPalette::BrickRandom(options.seed, brick, colorId));
}
if (!options.icon && options.brightness != 100.0f) linear *= std::max(options.brightness, 0.0f) / 100.0f;
const glm::vec4 color(UgcPalette::LinearToSrgb(linear), alpha);
anyGlow = anyGlow || glow != glm::vec3(0.0f);
const auto look = transparent ? eLook::PLASTIC : LookOf(colorId, library.GetMaterial(colorId), options.looks);

View File

@@ -3,6 +3,7 @@
#include <array>
#include <cstdint>
#include <map>
#include <set>
#include <optional>
#include <string>
#include <string_view>
@@ -93,6 +94,8 @@ namespace UgcModel {
float colorVariation{ 5.0f }; // percent, 0: none (LU Toolbox: Apply Color Variation, 5%)
uint64_t seed{}; // of the variation's random numbers
float transparentOpacity{ 58.82f }; // percent, transparent bricks' vertex alpha (LU Toolbox palette only)
float brightness{ 100.0f }; // percent, the models' vertex colors (not icons'); 100: as the palette has them
std::set<uint32_t> transparentColors; // color ids drawn transparent whatever Materials.xml says (129: its alpha is 255)
bool icon{}; // the icon renderer's color corrections
uint32_t lod{}; // brickprimitives level
LookRules looks; // which colors are metal and glow (Mesh::looks)

View File

@@ -79,6 +79,15 @@ namespace {
settings.build.palette = Game::config->GetValue("color_palette") == "brickdb" ? UgcModel::ePalette::BRICKDB : UgcModel::ePalette::LU_TOOLBOX;
settings.build.colorVariation = std::clamp(Setting<float>("color_variation", 5.0f), 0.0f, 100.0f);
settings.build.transparentOpacity = std::clamp(Setting<float>("transparent_opacity", 58.82f), 0.0f, 100.0f);
settings.build.brightness = std::clamp(Setting<float>("color_brightness", 100.0f), 0.0f, 200.0f);
{
std::stringstream stream(Game::config->GetValue("transparent_colors"));
std::string id;
while (std::getline(stream, id, ',')) {
std::erase_if(id, [](unsigned char c) { return std::isspace(c); });
if (const auto color = GeneralUtils::TryParse<uint32_t>(id)) settings.build.transparentColors.insert(*color);
}
}
const auto lods = ParseLods(Game::config->GetValue("lods").empty() ? "0,2" : Game::config->GetValue("lods"));
if (!lods.empty()) settings.lods = lods;
settings.lodDistances.lod0 = Setting<float>("lod_distance_0", 0.0f);