feat(dashboard): glitter sparkles and flecks in the UGC 3D views

The UGC page's model view now draws the glitter sparkle shapes (look
SPARKLE) flashing as the client's Distortion Directional shader makes
them: two layers of sparkles sliding at the client's rates (a tile in
24 s at three quarters the scale, a tile in 48 s), shown only where both
have one. Flecks are drawn as flat flakes of the fleck size and varied
brightness (addGlitter in scenery-core.js), no longer drifting (the game
never moves them). The LXFML views (the UGC page's second view, the
property and zone views) draw both on the glitter colors from
window.LDD_GLITTER, which now carries every glitter setting and is no
longer cached, so changing a glitter setting on the settings page
previews on any model's LXFML view without making it again.

Check in the dashboard (not the game): open a glitter model on the UGC
page; both views show still flecks and sparkles flashing on the glitter
bricks only; change glitter_sparkle_amount / glitter_fleck_size in the
settings and reopen the model: the LXFML view follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 00:39:35 -05:00
parent aab161038e
commit e42fd45c1f
5 changed files with 128 additions and 35 deletions

View File

@@ -457,7 +457,7 @@ void RegisterClientAssetRoutes() {
Route(eHTTPMethod::GET, "/api/bricks/materials.js", 0,
"The brick colours (MatID -> [r, g, b, a]) from Materials.xml in the client's res/brickdb.zip, as a script setting "
"window.LDD_MATERIALS for the 3D viewers, and window.LDD_GLITTER: the colours the UGC server makes glitter with its settings "
"(shader_glitter on: glitter_material_types and glitter_colors) and the glitter's glitter_size and glitter_density. "
"(shader_glitter on: glitter_material_types and glitter_colors) and the glitter's settings (flecks, and sparkles when shader_glitter_sparkle is on). "
"The colours are read once; an empty table when the client's brick database can't be read",
[](HTTPReply& reply, const HTTPContext&) {
// Read on first use (thread-safe static init); the client only changes with a restart
@@ -505,11 +505,17 @@ void RegisterClientAssetRoutes() {
{ "flecks", GeneralUtils::TryParse<uint32_t>(UgcRoutes::Setting("glitter_density").value_or("")).value_or(80) },
{ "fleckSize", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_fleck_size").value_or("")).value_or(0.05f) },
{ "fleckOpacity", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_fleck_opacity").value_or("")).value_or(80.0f) },
{ "speed", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_speed").value_or("")).value_or(1.0f) } };
{ "speed", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_speed").value_or("")).value_or(1.0f) },
{ "sparkles", GeneralUtils::TryParse<uint32_t>(UgcRoutes::Setting("shader_glitter_sparkle").value_or("")).value_or(79) != 0 },
{ "sparkleSize", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_sparkle_size").value_or("")).value_or(0.1f) },
{ "sparkleAmount", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_sparkle_amount").value_or("")).value_or(5.0f) },
{ "sparkleTint", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_sparkle_tint").value_or("")).value_or(30.0f) },
{ "sparkleBrightness", GeneralUtils::TryParse<float>(UgcRoutes::Setting("glitter_sparkle_brightness").value_or("")).value_or(100.0f) } };
reply.status = eHTTPStatusCode::OK;
reply.message = colours.script + "window.LDD_GLITTER = " + settings.dump() + ";\n";
reply.contentType = eContentType::TEXT_JAVASCRIPT;
reply.headers.push_back("Cache-Control: private, max-age=3600");
// Not kept: the glitter settings change from the settings page, and the preview should follow
reply.headers.push_back("Cache-Control: private, no-cache");
});
Route(eHTTPMethod::GET, "/api/icon/:lot", 0, "PNG icon for an item LOT (requires client_location and ImageMagick)",