From 19b6443fb47475044eb620655556abf49bcf13f6 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Wed, 30 Sep 2026 03:43:30 -0500 Subject: [PATCH] fix(ugc): metal look only from the client's material types LU Toolbox's metallic table also has colors the client's Materials.xml types shinyPlastic, such as 131, the grey of many baseplates, so whole baseplates went into S88_Metal_Model. Metal now comes from the Materials.xml types (shinySteel) and the settings' colors only; the table still gives colors. Co-Authored-By: Claude Opus 5.5 --- dUgcServer/Bricks/UgcPalette.cpp | 4 ---- dUgcServer/Bricks/UgcPalette.h | 1 - dUgcServer/Model/UgcModel.cpp | 1 - dUgcServer/Model/UgcModel.h | 8 ++++---- docs/UgcServer.md | 8 +++++--- tests/dUgcTests/UgcTests.cpp | 9 +++++---- 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/dUgcServer/Bricks/UgcPalette.cpp b/dUgcServer/Bricks/UgcPalette.cpp index 1cbd8105d..7b2d8c34a 100644 --- a/dUgcServer/Bricks/UgcPalette.cpp +++ b/dUgcServer/Bricks/UgcPalette.cpp @@ -171,10 +171,6 @@ namespace UgcPalette { return Transparent().contains(id); } - bool IsMetallic(uint32_t id) { - return Metallic().contains(id); - } - std::optional Glow(uint32_t id) { const auto it = GlowColors().find(id); return it != GlowColors().end() ? std::optional(it->second) : std::nullopt; diff --git a/dUgcServer/Bricks/UgcPalette.h b/dUgcServer/Bricks/UgcPalette.h index 4a1a053c3..2c90de290 100644 --- a/dUgcServer/Bricks/UgcPalette.h +++ b/dUgcServer/Bricks/UgcPalette.h @@ -18,7 +18,6 @@ namespace UgcPalette { std::optional Linear(uint32_t id, bool icon = false); bool IsTransparent(uint32_t id); - bool IsMetallic(uint32_t id); // The glow color (linear) of a glowing material, nullopt for the others std::optional Glow(uint32_t id); diff --git a/dUgcServer/Model/UgcModel.cpp b/dUgcServer/Model/UgcModel.cpp index 92f8a8a44..152d76c00 100644 --- a/dUgcServer/Model/UgcModel.cpp +++ b/dUgcServer/Model/UgcModel.cpp @@ -204,7 +204,6 @@ namespace UgcModel { eLook LookOf(uint32_t id, const UgcBricks::Material& material, const LookRules& rules) { if (const auto color = rules.colors.find(id); color != rules.colors.end()) return color->second; if (rules.paletteGlow && UgcPalette::Glow(id)) return eLook::GLOW; - if (rules.paletteMetallic && UgcPalette::IsMetallic(id)) return eLook::METAL; const auto type = rules.materialTypes.find(material.type); return type != rules.materialTypes.end() ? type->second : eLook::PLASTIC; } diff --git a/dUgcServer/Model/UgcModel.h b/dUgcServer/Model/UgcModel.h index 605faf6e2..f4956af1a 100644 --- a/dUgcServer/Model/UgcModel.h +++ b/dUgcServer/Model/UgcModel.h @@ -81,15 +81,15 @@ namespace UgcModel { }; /** - * Which colors have which look, from the client's data: a Materials.xml MaterialType (brickdb.zip) and LU Toolbox's - * metallic and glow colors (UgcPalette), and colors named in the settings. A named color wins, then glow over metal; - * transparent bricks are plastic unless their color is glitter. + * Which colors have which look, from the client's data: a Materials.xml MaterialType (brickdb.zip), LU Toolbox's + * glow colors (UgcPalette) and colors named in the settings. A named color wins, then glow; transparent bricks are + * plastic unless their color is glitter. LU Toolbox's metallic table is not a look: it has colors the client types + * shinyPlastic (131, 139, 179, 183, 184, ...), plastic in the client's data. */ struct LookRules { std::map colors; // LEGO color ids given a look by the settings (brushed_colors, glitter_colors) std::map materialTypes{ { "shinySteel", eLook::METAL }, { "brushedSteel", eLook::BRUSHED }, { "matteSteel", eLook::BRUSHED }, { "glitter", eLook::GLITTER } }; - bool paletteMetallic{ true }; // LU Toolbox's Metallic colors (UgcPalette::IsMetallic) are METAL bool paletteGlow{ true }; // its glow colors (UgcPalette::Glow) are GLOW }; diff --git a/docs/UgcServer.md b/docs/UgcServer.md index 20e4954a1..c309c97cb 100644 --- a/docs/UgcServer.md +++ b/docs/UgcServer.md @@ -452,9 +452,11 @@ all of its levels, so each look needs a group of its own. | `satin_whiten` | 20 | Percent: how far satin colors are moved towards white (in linear RGB, after the color variation). | Which color has which look is data, not a list in the code (`UgcModel::LookOf`): glow is LU Toolbox's glow table -(`UgcPalette::Glow`: 50, 294, 329, 9000-9027), metal is LU Toolbox's metallic table (`UgcPalette::IsMetallic`) plus -the Materials.xml types above (the clients checked have 8 or 14 `shinySteel` colors, and 1 or 3 `glitter` ones: 129, -341, 351), glitter is the `glitter` type plus `glitter_colors`. Pearl stays plastic (the client has no shader for it). +(`UgcPalette::Glow`: 50, 294, 329, 9000-9027), metal is the Materials.xml types above (the clients checked have 8 or +14 `shinySteel` colors, and 1 or 3 `glitter` ones: 129, 341, 351), glitter is the `glitter` type plus +`glitter_colors`. LU Toolbox's metallic table only colors bricks, it gives no look: most of it is `shinyPlastic` in the +client's Materials.xml (131, the grey of many baseplates, is plastic in the client's brick colors too), and it put +whole baseplates in `S88_Metal_Model`. Pearl stays plastic (the client has no shader for it). Only opaque bricks get metal and glow: a transparent glowing color (294 with the brick database palette, alpha 150) stays in `S01_Alpha_Model`. Transparent bricks can be glitter (every glitter color the clients have is transparent: 341 and 351 have alpha 150, 129 is in `transparent_colors`). diff --git a/tests/dUgcTests/UgcTests.cpp b/tests/dUgcTests/UgcTests.cpp index 382466aa5..36152f370 100644 --- a/tests/dUgcTests/UgcTests.cpp +++ b/tests/dUgcTests/UgcTests.cpp @@ -476,7 +476,7 @@ TEST(UgcPalette, ColorVariationMatchesLuToolbox) { EXPECT_FALSE(UgcPalette::IsTransparent(21)); EXPECT_TRUE(UgcPalette::Glow(9013).has_value()); EXPECT_FALSE(UgcPalette::Glow(21).has_value()); - EXPECT_TRUE(UgcPalette::IsMetallic(309)); + EXPECT_TRUE(UgcPalette::Linear(309).has_value()); // LU Toolbox's metallic colors are colors, not looks EXPECT_FALSE(UgcPalette::Linear(123456).has_value()); EXPECT_NEAR(UgcPalette::LinearToSrgb(*UgcPalette::Linear(1, true)).r, 0.7f, 1e-5f); EXPECT_NEAR(UgcPalette::LinearToSrgb(red).r * 255.0f, 222.0f, 0.5f); // LDD's bright red @@ -1146,7 +1146,8 @@ TEST(UgcShaders, LooksComeFromTheColorData) { EXPECT_EQ(UgcModel::LookOf(21, plastic, rules), UgcModel::eLook::PLASTIC); EXPECT_EQ(UgcModel::LookOf(5000, steel, rules), UgcModel::eLook::METAL); // a Materials.xml shinySteel EXPECT_EQ(UgcModel::LookOf(5000, brushed, rules), UgcModel::eLook::BRUSHED); - EXPECT_EQ(UgcModel::LookOf(183, plastic, rules), UgcModel::eLook::METAL); // LU Toolbox's metallic, shinyPlastic in Materials.xml + EXPECT_EQ(UgcModel::LookOf(183, plastic, rules), UgcModel::eLook::PLASTIC); // LU Toolbox's metallic, shinyPlastic in Materials.xml + EXPECT_EQ(UgcModel::LookOf(131, plastic, rules), UgcModel::eLook::PLASTIC); // the same (a grey that is often a whole baseplate) EXPECT_EQ(UgcModel::LookOf(329, plastic, rules), UgcModel::eLook::GLOW); // LU Toolbox's glow colors EXPECT_EQ(UgcModel::LookOf(50, plastic, rules), UgcModel::eLook::GLOW); EXPECT_EQ(UgcModel::LookOf(9016, plastic, rules), UgcModel::eLook::GLOW); @@ -1158,13 +1159,12 @@ TEST(UgcShaders, LooksComeFromTheColorData) { EXPECT_EQ(UgcModel::LookOf(150, steel, named), UgcModel::eLook::METAL); UgcModel::LookRules none; none.materialTypes.clear(); - none.paletteMetallic = false; EXPECT_EQ(UgcModel::LookOf(5000, steel, none), UgcModel::eLook::PLASTIC); EXPECT_EQ(UgcModel::LookOf(150, steel, none), UgcModel::eLook::PLASTIC); // Built: opaque vertices get their color's look, transparent bricks none (their glow stays with them) UgcBricks::BrickLibrary library(MakeRes(), 0); - library.SetMaterials({ { 5000, brushed } }); + library.SetMaterials({ { 150, steel }, { 5000, brushed } }); std::string error; const auto model = UgcModel::Build(UgcModel::ParseLxfml(R"( @@ -1189,6 +1189,7 @@ TEST(UgcShaders, LooksComeFromTheColorData) { TEST(UgcShaders, WritesAGroupPerLookWithEveryLevel) { UgcBricks::BrickLibrary library(MakeRes(), 0); + library.SetMaterials({ { 150, { 152, 155, 153, 255, "shinySteel" } } }); // the client's Materials.xml entry auto settings = SmallSettings(); settings.build.colorVariation = 0.0f; settings.shaders.metal = 88;