From 90063037c4b8365a8f99333ccbc280823e16588d Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 9 May 2026 12:39:38 -0700 Subject: [PATCH] feat(editor): add --gen-texture-plaid translucent-bands pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 65th procedural texture: 2 sets of parallel "translucent" bands — one horizontal, one vertical — overlaid on a base. Each band contributes 0.5 alpha, so where bands cross both half-alphas combine for the darkest color (the unmistakable plaid grid intersection). Distinct from --gen-texture-tartan (3-4 colors with asymmetric stripe pitches) — this is the simple symmetric 2-color variant. Distinct from --gen-texture-checker (hard binary squares) — plaid uses 3-tone alpha-blend gradient. Useful for pub-table cloths, country-tavern napery, dwarven formal-attire trim, picnic blankets, peasant-clothier swatches. Default 24-stride / 8-band reads as classic country-checked at 256x256. First procedural texture to also use the new printPngWrote helper from this batch. --- tools/editor/cli_arg_required.cpp | 1 + tools/editor/cli_gen_texture.cpp | 52 +++++++++++++++++++++++++++++++ tools/editor/cli_help.cpp | 2 ++ 3 files changed, 55 insertions(+) diff --git a/tools/editor/cli_arg_required.cpp b/tools/editor/cli_arg_required.cpp index 9de95ab7..6bd8067d 100644 --- a/tools/editor/cli_arg_required.cpp +++ b/tools/editor/cli_arg_required.cpp @@ -99,6 +99,7 @@ const char* const kArgRequired[] = { "--gen-texture-camo", "--gen-texture-snake-skin", "--gen-texture-mesh-screen", "--gen-texture-bamboo", "--gen-texture-blueprint", "--gen-texture-rust-streaks", + "--gen-texture-plaid", "--validate-glb", "--info-glb", "--info-glb-tree", "--info-glb-bytes", "--validate-jsondbc", "--check-glb-bounds", "--validate-stl", "--validate-png", "--validate-blp", diff --git a/tools/editor/cli_gen_texture.cpp b/tools/editor/cli_gen_texture.cpp index 0b746dbc..aa6e73a4 100644 --- a/tools/editor/cli_gen_texture.cpp +++ b/tools/editor/cli_gen_texture.cpp @@ -3500,6 +3500,57 @@ int handleKnit(int& i, int argc, char** argv) { return 0; } +int handlePlaid(int& i, int argc, char** argv) { + // Plaid: two sets of parallel "translucent" bands (one + // horizontal, one vertical) overlaid on a bg. Where bands + // cross, both half-alphas combine for the darkest color — + // that's the plaid grid intersection. Distinct from + // --gen-texture-tartan (3-4 colors, asymmetric stripes) — + // this is the simple 2-color symmetric variant. + std::string outPath = argv[++i]; + std::string bgHex = argv[++i]; + std::string bandHex = argv[++i]; + int stride = 24; + int bandW = 8; + int W = 256, H = 256; + parseOptInt(i, argc, argv, stride); + parseOptInt(i, argc, argv, bandW); + parseOptInt(i, argc, argv, W); + parseOptInt(i, argc, argv, H); + if (W < 1 || H < 1 || W > 8192 || H > 8192 || + stride < 2 || stride > 1024 || + bandW < 1 || bandW * 2 >= stride) { + std::fprintf(stderr, + "gen-texture-plaid: invalid dims (W/H 1..8192, " + "stride 2..1024, bandW 1..stride/2)\n"); + return 1; + } + uint8_t br_, bg_, bb_, pr_, pg_, pb_; + if (!parseHexOrError(bgHex, br_, bg_, bb_, "gen-texture-plaid")) return 1; + if (!parseHexOrError(bandHex, pr_, pg_, pb_, + "gen-texture-plaid")) return 1; + std::vector pixels(static_cast(W) * H * 3, 0); + for (int y = 0; y < H; ++y) { + bool yInBand = (y % stride) < bandW; + for (int x = 0; x < W; ++x) { + bool xInBand = (x % stride) < bandW; + // Each band contributes 0.5 alpha. 0 bands = bg, 1 band + // = half-blended, 2 bands = full plaid color. + float alpha = 0.5f * (xInBand ? 1.0f : 0.0f) + + 0.5f * (yInBand ? 1.0f : 0.0f); + uint8_t r = static_cast(br_ + alpha * (pr_ - br_)); + uint8_t g = static_cast(bg_ + alpha * (pg_ - bg_)); + uint8_t b = static_cast(bb_ + alpha * (pb_ - bb_)); + setPixelRGB(pixels, W, x, y, r, g, b); + } + } + if (!savePngOrError(outPath, W, H, pixels, "gen-texture-plaid")) return 1; + printPngWrote(outPath, W, H); + std::printf(" bg/band : %s / %s\n", bgHex.c_str(), bandHex.c_str()); + std::printf(" bands : stride=%d, bandW=%d\n", stride, bandW); + return 0; +} + int handleRustStreaks(int& i, int argc, char** argv) { // Vertical rust drips on a metal base. Each streak is a // vertical band of varying width (hash-derived) starting at a @@ -4767,6 +4818,7 @@ constexpr TextureEntry kTextureTable[] = { {"--gen-texture-bamboo", 3, handleBamboo}, {"--gen-texture-blueprint", 3, handleBlueprint}, {"--gen-texture-rust-streaks", 3, handleRustStreaks}, + {"--gen-texture-plaid", 3, handlePlaid}, }; } // namespace diff --git a/tools/editor/cli_help.cpp b/tools/editor/cli_help.cpp index bc90b8e1..e14b88d8 100644 --- a/tools/editor/cli_help.cpp +++ b/tools/editor/cli_help.cpp @@ -163,6 +163,8 @@ void printUsage(const char* argv0) { std::printf(" Blueprint: minor + major grid lines (technical drawing / drafting paper / engineer's table)\n"); std::printf(" --gen-texture-rust-streaks [streakCount] [seed] [W H]\n"); std::printf(" Rust streaks: vertical drip bands fading down from hash-jittered tops (weathered metal / hull stains)\n"); + std::printf(" --gen-texture-plaid [stride] [bandW] [W H]\n"); + std::printf(" Plaid: 2 sets of crossed translucent bands; intersections darken via combined half-alpha\n"); std::printf(" --add-texture-to-zone [renameTo]\n"); std::printf(" Copy an existing PNG into (optionally renaming it on the way in)\n"); std::printf(" --gen-mesh [size]\n");