From 25d822afd24a50cb60d0da8ee50dadeff6800009 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 27 Jun 2025 12:09:44 -0400 Subject: [PATCH] Static wall autotile support --- .../mindustry/world/blocks/TileBitmask.java | 11 ++++++ .../world/blocks/environment/Floor.java | 5 +-- .../world/blocks/environment/StaticWall.java | 36 +++++++++++++++---- tools/src/mindustry/tools/Generators.java | 28 ++++++++++----- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/core/src/mindustry/world/blocks/TileBitmask.java b/core/src/mindustry/world/blocks/TileBitmask.java index f911469267..b8ebacf6a9 100644 --- a/core/src/mindustry/world/blocks/TileBitmask.java +++ b/core/src/mindustry/world/blocks/TileBitmask.java @@ -1,5 +1,8 @@ package mindustry.world.blocks; +import arc.*; +import arc.graphics.g2d.*; + public class TileBitmask{ /** Autotile bitmasks for 8-directional sprites (see tile-gen)*/ public static final int[] values = { @@ -20,4 +23,12 @@ public class TileBitmask{ 3, 0, 3, 0, 15, 42, 15, 12, 3, 0, 3, 0, 15, 42, 15, 12, 2, 1, 2, 1, 9, 45, 9, 19, 2, 1, 2, 1, 14, 18, 14, 13, }; + + public static TextureRegion[] load(String name){ + var regions = new TextureRegion[47]; + for(int i = 0; i < 47; i++){ + regions[i] = Core.atlas.find(name + "-" + i); + } + return regions; + } } diff --git a/core/src/mindustry/world/blocks/environment/Floor.java b/core/src/mindustry/world/blocks/environment/Floor.java index 7b9f9ebe3f..343c94f50b 100644 --- a/core/src/mindustry/world/blocks/environment/Floor.java +++ b/core/src/mindustry/world/blocks/environment/Floor.java @@ -141,10 +141,7 @@ public class Floor extends Block{ } if(autotile){ - autotileRegions = new TextureRegion[47]; - for(int i = 0; i < 47; i++){ - autotileRegions[i] = Core.atlas.find(name + "-" + i); - } + autotileRegions = TileBitmask.load(name); } if(Core.atlas.has(name + "-edge")){ diff --git a/core/src/mindustry/world/blocks/environment/StaticWall.java b/core/src/mindustry/world/blocks/environment/StaticWall.java index c65c8a186b..a287b2a419 100644 --- a/core/src/mindustry/world/blocks/environment/StaticWall.java +++ b/core/src/mindustry/world/blocks/environment/StaticWall.java @@ -8,12 +8,17 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.graphics.*; import mindustry.world.*; +import mindustry.world.blocks.*; import static mindustry.Vars.*; public class StaticWall extends Prop{ public @Load("@-large") TextureRegion large; public TextureRegion[][] split; + /** If true, this wall uses autotiling; variants are not supported. See https://github.com/GglLfr/tile-gen*/ + public boolean autotile; + + protected TextureRegion[] autotileRegions; public StaticWall(String name){ super(name); @@ -30,15 +35,28 @@ public class StaticWall extends Prop{ @Override public void drawBase(Tile tile){ - int rx = tile.x / 2 * 2; - int ry = tile.y / 2 * 2; + if(autotile){ + int bits = 0; - if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Point2.pack(rx, ry)) < 0.5 && split.length >= 2 && split[0].length >= 2){ - Draw.rect(split[tile.x % 2][1 - tile.y % 2], tile.worldx(), tile.worldy()); - }else if(variants > 0){ - Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + for(int i = 0; i < 8; i++){ + Tile other = tile.nearby(Geometry.d8[i]); + if(other != null && other.block() == this){ + bits |= (1 << i); + } + } + + Draw.rect(autotileRegions[TileBitmask.values[bits]], tile.worldx(), tile.worldy()); }else{ - Draw.rect(region, tile.worldx(), tile.worldy()); + int rx = tile.x / 2 * 2; + int ry = tile.y / 2 * 2; + + if(Core.atlas.isFound(large) && eq(rx, ry) && Mathf.randomSeed(Point2.pack(rx, ry)) < 0.5 && split.length >= 2 && split[0].length >= 2){ + Draw.rect(split[tile.x % 2][1 - tile.y % 2], tile.worldx(), tile.worldy()); + }else if(variants > 0){ + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + }else{ + Draw.rect(region, tile.worldx(), tile.worldy()); + } } //draw ore on top @@ -59,6 +77,10 @@ public class StaticWall extends Prop{ } } } + + if(autotile){ + autotileRegions = TileBitmask.load(name); + } } @Override diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 8fbda7d9f8..a7c46b41e6 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -70,23 +70,32 @@ public class Generators{ ObjectMap gens = new ObjectMap<>(); generate("autotiles", () -> { - for(Floor floor : content.blocks().select(b -> b.isFloor() && b.asFloor().autotile).as()){ - Fi basePath = new Fi("../../../assets-raw/sprites_out/blocks/environment/" + floor.name + "-autotile.png"); + for(Block block : content.blocks().select(b -> (b.isFloor() && b.asFloor().autotile) || (b instanceof StaticWall && ((StaticWall)b).autotile))){ + Fi basePath = new Fi("../../../assets-raw/sprites_out/blocks/environment/" + block.name + "-autotile.png"), iconPath = basePath.parent().child(block.name + ".png"); if(basePath.exists()){ //theoretically this might not finish in time, but I doubt that will ever happen mainExecutor.submit(() -> { try{ - ImageTileGenerator.generate(basePath, floor.name, new Fi("../../../assets-raw/sprites_out/blocks/environment/" + floor.name)); + ImageTileGenerator.generate(basePath, block.name, new Fi("../../../assets-raw/sprites_out/blocks/environment/" + block.name)); }catch(Throwable e){ - Log.err("Failed to autotile: " + floor.name, e); + Log.err("Failed to autotile: " + block.name, e); }finally{ //the raw autotile source image must never be included, it isn't useful basePath.delete(); } }); + + if(!iconPath.exists()){ + //save the bottom right region as the "main" sprite for previews + Pixmap out = new Pixmap(basePath); + Pixmap cropped = out.crop(96, 96, 32, 32); + iconPath.writePng(cropped); + out.dispose(); + gens.put(block, cropped); + } }else{ - Log.warn("Autotile floor '@' not found: @", floor.name, basePath.absolutePath()); + Log.warn("Autotile floor '@' not found: @", block.name, basePath.absolutePath()); } } }); @@ -819,14 +828,15 @@ public class Generators{ }); generate("edges", () -> { - content.blocks().each(b -> b instanceof Floor && !(b instanceof OverlayFloor), floor -> { + content.blocks().each(b -> b instanceof Floor && !(b instanceof OverlayFloor) && !b.isAir(), floor -> { if(has(floor.name + "-edge") || floor.blendGroup != floor){ return; } try{ - Pixmap image = gens.get(floor, get(floor.getGeneratedIcons()[0])); + Pixmap image = gens.get(floor); + if(image == null) image = get(floor.getGeneratedIcons()[0]); Pixmap edge = get("edge-stencil"); Pixmap result = new Pixmap(edge.width, edge.height); @@ -838,7 +848,9 @@ public class Generators{ save(result, "../blocks/environment/" + floor.name + "-edge"); - }catch(Exception ignored){} + }catch(Exception e){ + Log.err("Failed to generate edge for " + floor, e); + } }); });