Split up turtle textures (#1813)
Turtles currently read their textures from a single 128x128 sprite sheet. Most of this texture is unused which means we end up wasting a lot of the block texture atlas[^1]. This change splits up the turtle textures into individual 32x32 textures[^2], one for each side, and then an additional backpack texture. I'm very sorry to any resource pack artists out there. The tools/update-resources.py script will update existing packs, but does not (currently) handle non-standard resolutions. [^1]: It used to be worse: https://github.com/dan200/ComputerCraft/issues/145 [^2]: Turtle textures are a bit weird, in that they mostly *look* 16x16, but have some detail in places.
| @@ -98,7 +98,6 @@ abstract class MergeTrees : DefaultTask() { | ||||
|         } | ||||
| 
 | ||||
|         val sharedFiles = files.entries.asSequence().filter { (_, v) -> v.found == sources.size }.map { (k, _) -> k }.toList() | ||||
|         println(sharedFiles) | ||||
| 
 | ||||
|         // Copy shared files to the common directory | ||||
|         fsOperations.sync { | ||||
|   | ||||
| @@ -1 +1,12 @@ | ||||
| {"parent": "computercraft:block/turtle_base", "textures": {"texture": "computercraft:block/turtle_advanced"}} | ||||
| { | ||||
|   "parent": "computercraft:block/turtle_base", | ||||
|   "textures": { | ||||
|     "back": "computercraft:block/turtle_advanced_back", | ||||
|     "backpack": "computercraft:block/turtle_advanced_backpack", | ||||
|     "bottom": "computercraft:block/turtle_advanced_bottom", | ||||
|     "front": "computercraft:block/turtle_advanced_front", | ||||
|     "left": "computercraft:block/turtle_advanced_left", | ||||
|     "right": "computercraft:block/turtle_advanced_right", | ||||
|     "top": "computercraft:block/turtle_advanced_top" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1 +1,12 @@ | ||||
| {"parent": "computercraft:block/turtle_base", "textures": {"texture": "computercraft:block/turtle_normal"}} | ||||
| { | ||||
|   "parent": "computercraft:block/turtle_base", | ||||
|   "textures": { | ||||
|     "back": "computercraft:block/turtle_normal_back", | ||||
|     "backpack": "computercraft:block/turtle_normal_backpack", | ||||
|     "bottom": "computercraft:block/turtle_normal_bottom", | ||||
|     "front": "computercraft:block/turtle_normal_front", | ||||
|     "left": "computercraft:block/turtle_normal_left", | ||||
|     "right": "computercraft:block/turtle_normal_right", | ||||
|     "top": "computercraft:block/turtle_normal_top" | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -38,6 +38,9 @@ import static net.minecraft.data.models.model.TextureMapping.getBlockTexture; | ||||
| 
 | ||||
| class BlockModelProvider { | ||||
|     private static final TextureSlot CURSOR = TextureSlot.create("cursor"); | ||||
|     private static final TextureSlot LEFT = TextureSlot.create("left"); | ||||
|     private static final TextureSlot RIGHT = TextureSlot.create("right"); | ||||
|     private static final TextureSlot BACKPACK = TextureSlot.create("backpack"); | ||||
| 
 | ||||
|     private static final ModelTemplate COMPUTER_ON = new ModelTemplate( | ||||
|         Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/computer_on")), | ||||
| @@ -58,7 +61,7 @@ class BlockModelProvider { | ||||
|     private static final ModelTemplate TURTLE = new ModelTemplate( | ||||
|         Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_base")), | ||||
|         Optional.empty(), | ||||
|         TextureSlot.TEXTURE | ||||
|         TextureSlot.FRONT, TextureSlot.BACK, TextureSlot.TOP, TextureSlot.BOTTOM, LEFT, RIGHT, BACKPACK | ||||
|     ); | ||||
|     private static final ModelTemplate TURTLE_UPGRADE_LEFT = new ModelTemplate( | ||||
|         Optional.of(new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/turtle_upgrade_base_left")), | ||||
| @@ -167,7 +170,16 @@ class BlockModelProvider { | ||||
|     } | ||||
| 
 | ||||
|     private static void registerTurtle(BlockModelGenerators generators, TurtleBlock block) { | ||||
|         var model = TURTLE.create(block, TextureMapping.defaultTexture(block), generators.modelOutput); | ||||
|         var model = TURTLE.create(block, new TextureMapping() | ||||
|                 .put(TextureSlot.FRONT, getBlockTexture(block, "_front")) | ||||
|                 .put(TextureSlot.BACK, getBlockTexture(block, "_back")) | ||||
|                 .put(TextureSlot.TOP, getBlockTexture(block, "_top")) | ||||
|                 .put(TextureSlot.BOTTOM, getBlockTexture(block, "_bottom")) | ||||
|                 .put(LEFT, getBlockTexture(block, "_left")) | ||||
|                 .put(RIGHT, getBlockTexture(block, "_right")) | ||||
|                 .put(BACKPACK, getBlockTexture(block, "_backpack")), | ||||
|             generators.modelOutput | ||||
|         ); | ||||
|         generators.blockStateOutput.accept( | ||||
|             MultiVariantGenerator.multiVariant(block, Variant.variant().with(VariantProperties.MODEL, model)) | ||||
|                 .with(createHorizontalFacingDispatch()) | ||||
|   | ||||
| @@ -2,30 +2,30 @@ | ||||
|     "parent": "block/block", | ||||
|     "render_type": "translucent", | ||||
|     "textures": { | ||||
|         "particle": "#texture" | ||||
|         "particle": "#front" | ||||
|     }, | ||||
|     "elements": [ | ||||
|         { | ||||
|             "from": [ 2, 2, 2 ], | ||||
|             "to": [ 14, 14, 13 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 5.75, 2.75, 2.75, 0 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 8.75, 0, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "north": { "uv": [ 11.5, 5.75, 8.5, 2.75 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 5.75, 5.75, 2.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 8.5, 5.75, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 2.75, 5.75, 0, 2.75 ], "texture": "#texture" } | ||||
|                 "down": { "uv": [ 0, 0, 12, 11 ], "texture": "#bottom" }, | ||||
|                 "up": { "uv": [ 0, 0, 12, 11 ], "texture": "#top" }, | ||||
|                 "north": { "uv": [ 0, 0, 12, 12 ], "texture": "#front" }, | ||||
|                 "south": { "uv": [ 0, 0, 12, 12 ], "texture": "#back" }, | ||||
|                 "west": { "uv": [ 0, 0, 11, 12 ], "texture": "#left" }, | ||||
|                 "east": { "uv": [ 0, 0, 11, 12 ], "texture": "#right" } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 3, 6, 13 ], | ||||
|             "to": [ 13, 13, 15 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 11.75, 0.5, 9.25, 0 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 14.25, 0, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 11.75, 2.25, 9.25, 0.5 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 12.25, 2.25, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 9.25, 2.25, 8.75, 0.5 ], "texture": "#texture" } | ||||
|                 "down": { "uv": [ 2, 9, 12, 11 ], "texture": "#backpack" }, | ||||
|                 "up": { "uv": [ 2, 0, 12, 2 ], "texture": "#backpack" }, | ||||
|                 "south": { "uv": [ 2, 2, 12, 9 ], "texture": "#backpack" }, | ||||
|                 "west": { "uv": [ 0, 2, 2, 9 ], "texture": "#backpack" }, | ||||
|                 "east": { "uv": [ 12, 2, 14, 9 ], "texture": "#backpack" } | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
|   | ||||
| @@ -1,53 +1,67 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_base", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_colour" | ||||
|         "texture": "computercraft:block/turtle_colour", | ||||
|         "body_back": "computercraft:block/turtle_colour_body_back", | ||||
|         "body_backpack": "computercraft:block/turtle_colour_body_backpack", | ||||
|         "body_bottom": "computercraft:block/turtle_colour_body_bottom", | ||||
|         "body_front": "computercraft:block/turtle_colour_body_front", | ||||
|         "body_left": "computercraft:block/turtle_colour_body_left", | ||||
|         "body_right": "computercraft:block/turtle_colour_body_right", | ||||
|         "body_top": "computercraft:block/turtle_colour_body_top", | ||||
|         "frame_back": "computercraft:block/turtle_colour_frame_back", | ||||
|         "frame_backpack": "computercraft:block/turtle_colour_frame_backpack", | ||||
|         "frame_bottom": "computercraft:block/turtle_colour_frame_bottom", | ||||
|         "frame_front": "computercraft:block/turtle_colour_frame_front", | ||||
|         "frame_left": "computercraft:block/turtle_colour_frame_left", | ||||
|         "frame_right": "computercraft:block/turtle_colour_frame_right", | ||||
|         "frame_top": "computercraft:block/turtle_colour_frame_top" | ||||
|     }, | ||||
|     "elements": [ | ||||
|         { | ||||
|             "from": [ 2, 2, 2 ], | ||||
|             "to": [ 14, 14, 13 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 5.75, 8.5, 2.75, 5.75 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "up": { "uv": [ 8.75, 5.75, 5.75, 8.5 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "north": { "uv": [ 11.5, 11.5, 8.5, 8.5 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "south": { "uv": [ 5.75, 11.5, 2.75, 8.5 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "west": { "uv": [ 8.5, 11.5, 5.75, 8.555 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "east": { "uv": [ 2.75, 11.5, 0, 8.5 ], "texture": "#texture", "tintindex": 0 } | ||||
|                 "down": { "uv": [ 0, 0, 12, 11 ], "texture": "#body_bottom", "tintindex": 0 }, | ||||
|                 "up": { "uv": [ 0, 0, 12, 11 ], "texture": "#body_top", "tintindex": 0 }, | ||||
|                 "north": { "uv": [ 0, 0, 12, 12 ], "texture": "#body_front", "tintindex": 0 }, | ||||
|                 "south": { "uv": [ 0, 0, 12, 12 ], "texture": "#body_back", "tintindex": 0 }, | ||||
|                 "west": { "uv": [ 0, 0, 11, 12 ], "texture": "#body_left", "tintindex": 0 }, | ||||
|                 "east": { "uv": [ 0, 0, 11, 12 ], "texture": "#body_right", "tintindex": 0 } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 3, 6, 13 ], | ||||
|             "to": [ 13, 13, 15 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 11.75, 6.25, 9.25, 5.75 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "up": { "uv": [ 14.25, 5.75, 11.75, 6.25 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "south": { "uv": [ 11.75, 8, 9.25, 6.25 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "west": { "uv": [ 12.25, 8, 11.75, 6.25 ], "texture": "#texture", "tintindex": 0 }, | ||||
|                 "east": { "uv": [ 9.25, 8, 8.75, 6.25 ], "texture": "#texture", "tintindex": 0 } | ||||
|                 "down": { "uv": [ 2, 9, 12, 11 ], "texture": "#body_backpack", "tintindex": 0 }, | ||||
|                 "up": { "uv": [ 2, 0, 12, 2 ], "texture": "#body_backpack", "tintindex": 0 }, | ||||
|                 "south": { "uv": [ 2, 2, 12, 9 ], "texture": "#body_backpack", "tintindex": 0 }, | ||||
|                 "west": { "uv": [ 0, 2, 2, 9 ], "texture": "#body_backpack", "tintindex": 0 }, | ||||
|                 "east": { "uv": [ 12, 2, 14, 9 ], "texture": "#body_backpack", "tintindex": 0 } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 2, 2, 2 ], | ||||
|             "to": [ 14, 14, 13 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 5.75, 2.75, 2.75, 0 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 8.75, 0, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "north": { "uv": [ 11.5, 5.75, 8.5, 2.75 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 5.75, 5.75, 2.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 8.5, 5.75, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 2.75, 5.75, 0, 2.75 ], "texture": "#texture" } | ||||
|                 "down": { "uv": [ 0, 0, 12, 11 ], "texture": "#frame_bottom" }, | ||||
|                 "up": { "uv": [ 0, 0, 12, 11 ], "texture": "#frame_top" }, | ||||
|                 "north": { "uv": [ 0, 0, 12, 12 ], "texture": "#frame_front" }, | ||||
|                 "south": { "uv": [ 0, 0, 12, 12 ], "texture": "#frame_back" }, | ||||
|                 "west": { "uv": [ 0, 0, 11, 12 ], "texture": "#frame_left" }, | ||||
|                 "east": { "uv": [ 0, 0, 11, 12 ], "texture": "#frame_right" } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 3, 6, 13 ], | ||||
|             "to": [ 13, 13, 15 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 11.75, 0.5, 9.25, 0 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 14.25, 0, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 11.75, 2.25, 9.25, 0.5 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 12.25, 2.25, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 9.25, 2.25, 8.75, 0.5 ], "texture": "#texture" } | ||||
|                 "down": { "uv": [ 2, 9, 12, 11 ], "texture": "#frame_backpack" }, | ||||
|                 "up": { "uv": [ 2, 0, 12, 2 ], "texture": "#frame_backpack" }, | ||||
|                 "south": { "uv": [ 2, 2, 12, 9 ], "texture": "#frame_backpack" }, | ||||
|                 "west": { "uv": [ 0, 2, 2, 9 ], "texture": "#frame_backpack" }, | ||||
|                 "east": { "uv": [ 12, 2, 14, 9 ], "texture": "#frame_backpack" } | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
|   | ||||
| @@ -1,6 +1,35 @@ | ||||
| { | ||||
|     "parent": "computercraft:block/turtle_overlay", | ||||
|     "parent": "block/block", | ||||
|     "textures": { | ||||
|         "texture": "computercraft:block/turtle_elf_overlay" | ||||
|     } | ||||
| } | ||||
|       "back": "computercraft:block/turtle_elf_overlay_back", | ||||
|       "backpack": "computercraft:block/turtle_elf_overlay_backpack", | ||||
|       "front": "computercraft:block/turtle_elf_overlay_front", | ||||
|       "left": "computercraft:block/turtle_elf_overlay_left", | ||||
|       "right": "computercraft:block/turtle_elf_overlay_right", | ||||
|       "top": "computercraft:block/turtle_elf_overlay_top" | ||||
|     }, | ||||
|     "elements": [ | ||||
|         { | ||||
|             "from": [ 2, 2, 2 ], | ||||
|             "to": [ 14, 14, 13 ], | ||||
|             "faces": { | ||||
|                 "up": { "uv": [ 0, 0, 12, 11 ], "texture": "#top" }, | ||||
|                 "north": { "uv": [ 0, 0, 12, 12 ], "texture": "#front" }, | ||||
|                 "south": { "uv": [ 0, 0, 12, 12 ], "texture": "#back" }, | ||||
|                 "west": { "uv": [ 0, 0, 11, 12 ], "texture": "#left" }, | ||||
|                 "east": { "uv": [ 0, 0, 11, 12 ], "texture": "#right" } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 3, 6, 13 ], | ||||
|             "to": [ 13, 13, 15 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 2, 9, 12, 11 ], "texture": "#backpack" }, | ||||
|                 "up": { "uv": [ 2, 0, 12, 2 ], "texture": "#backpack" }, | ||||
|                 "south": { "uv": [ 2, 2, 12, 9 ], "texture": "#backpack" }, | ||||
|                 "west": { "uv": [ 0, 2, 2, 9 ], "texture": "#backpack" }, | ||||
|                 "east": { "uv": [ 12, 2, 14, 9 ], "texture": "#backpack" } | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
|   } | ||||
|   | ||||
| @@ -1,43 +0,0 @@ | ||||
| { | ||||
|     "parent": "block/block", | ||||
|     "textures": { | ||||
|         "particle": "#texture" | ||||
|     }, | ||||
|     "elements": [ | ||||
|         { | ||||
|             "from": [ 2, 2, 2 ], | ||||
|             "to": [ 14, 14, 13 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 2.75, 0, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 5.75, 0, 8.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "north": { "uv": [ 8.5, 5.75, 11.5, 2.75 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 2.75, 5.75, 5.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 0, 5.75, 2.75, 2.75 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 5.75, 5.75, 8.5, 2.75 ], "texture": "#texture" } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 3, 6, 13 ], | ||||
|             "to": [ 13, 13, 15 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 9.25, 0, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 11.75, 0, 14.25, 0.5 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 9.25, 2.25, 11.75, 0.5 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 8.75, 2.25, 9.25, 0.5 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 11.75, 2.25, 12.25, 0.5 ], "texture": "#texture" } | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "from": [ 1.5, 1.5, 1.5 ], | ||||
|             "to": [ 14.5, 14.5, 13.5 ], | ||||
|             "faces": { | ||||
|                 "down": { "uv": [ 2.75, 8, 5.75, 10.75 ], "texture": "#texture" }, | ||||
|                 "up": { "uv": [ 5.75, 8, 8.75, 10.75 ], "texture": "#texture" }, | ||||
|                 "north": { "uv": [ 8.5, 13.75, 11.5, 10.75 ], "texture": "#texture" }, | ||||
|                 "south": { "uv": [ 2.75, 13.75, 5.75, 10.75 ], "texture": "#texture" }, | ||||
|                 "west": { "uv": [ 0, 13.75, 2.75, 10.75 ], "texture": "#texture" }, | ||||
|                 "east": { "uv": [ 5.75, 13.75, 8.5, 10.75 ], "texture": "#texture" } | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| } | ||||
| Before Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 533 B | 
| After Width: | Height: | Size: 489 B | 
| After Width: | Height: | Size: 421 B | 
| After Width: | Height: | Size: 495 B | 
| After Width: | Height: | Size: 502 B | 
| After Width: | Height: | Size: 517 B | 
| After Width: | Height: | Size: 490 B | 
| Before Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 258 B | 
| After Width: | Height: | Size: 229 B | 
| After Width: | Height: | Size: 361 B | 
| After Width: | Height: | Size: 247 B | 
| After Width: | Height: | Size: 292 B | 
| After Width: | Height: | Size: 253 B | 
| After Width: | Height: | Size: 168 B | 
| After Width: | Height: | Size: 235 B | 
| After Width: | Height: | Size: 191 B | 
| After Width: | Height: | Size: 233 B | 
| After Width: | Height: | Size: 203 B | 
| After Width: | Height: | Size: 225 B | 
| After Width: | Height: | Size: 184 B | 
| After Width: | Height: | Size: 185 B | 
| Before Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 338 B | 
| After Width: | Height: | Size: 483 B | 
| After Width: | Height: | Size: 234 B | 
| After Width: | Height: | Size: 233 B | 
| After Width: | Height: | Size: 272 B | 
| After Width: | Height: | Size: 590 B | 
| Before Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 397 B | 
| After Width: | Height: | Size: 287 B | 
| After Width: | Height: | Size: 350 B | 
| After Width: | Height: | Size: 410 B | 
| After Width: | Height: | Size: 408 B | 
| After Width: | Height: | Size: 393 B | 
| After Width: | Height: | Size: 340 B | 
| Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 186 B | 
| Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 154 B | 
							
								
								
									
										51
									
								
								tools/update-resources.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						| @@ -76,6 +76,45 @@ def unstitch_corners(input_file: pathlib.Path, family: str): | ||||
|         sidebar.save(output_dir / f"sidebar_{family}.png") | ||||
|  | ||||
|  | ||||
| def unstitch_turtle(input_file: pathlib.Path, family: str, *, dy: int = 0): | ||||
|     input = Image.open(input_file) | ||||
|     output_dir = input_file.parent | ||||
|  | ||||
|     fragments = [ | ||||
|         ("bottom", 22, 0, 24, 22, Image.Transpose.ROTATE_180), | ||||
|         ("top", 46, 0, 24, 22, Image.Transpose.FLIP_LEFT_RIGHT), | ||||
|         ("right", 0, 22, 22, 24, Image.Transpose.ROTATE_180), | ||||
|         ("back", 22, 22, 24, 24, Image.Transpose.ROTATE_180), | ||||
|         ("left", 46, 22, 22, 24, Image.Transpose.ROTATE_180), | ||||
|         ("front", 68, 22, 24, 24, Image.Transpose.ROTATE_180), | ||||
|     ] | ||||
|  | ||||
|     for suffix, x, y, w, h, transform in fragments: | ||||
|         if family == "elf_overlay" and suffix == "bottom": | ||||
|             continue | ||||
|  | ||||
|         slice = input.crop(box(x, dy + y, w, h)).transpose(transform) | ||||
|  | ||||
|         fragment = Image.new("RGBA", (32, 32)) | ||||
|         fragment.paste(slice) | ||||
|         fragment.save(output_dir / f"turtle_{family}_{suffix}.png") | ||||
|  | ||||
|     backpack = Image.new("RGBA", (32, 32)) | ||||
|     backpack.paste( | ||||
|         input.crop(box(70, dy + 4, 28, 14)).transpose(Image.Transpose.ROTATE_180), | ||||
|         (0, 4), | ||||
|     ) | ||||
|     backpack.paste( | ||||
|         input.crop(box(74, dy + 0, 20, 4)).transpose(Image.Transpose.ROTATE_180), | ||||
|         (4, 18), | ||||
|     ) | ||||
|     backpack.paste( | ||||
|         input.crop(box(94, dy + 0, 20, 4)).transpose(Image.Transpose.FLIP_LEFT_RIGHT), | ||||
|         (4, 0), | ||||
|     ) | ||||
|     backpack.save(output_dir / f"turtle_{family}_backpack.png") | ||||
|  | ||||
|  | ||||
| def main() -> None: | ||||
|     spec = argparse.ArgumentParser() | ||||
|     spec.add_argument("dir", type=pathlib.Path) | ||||
| @@ -97,6 +136,18 @@ def main() -> None: | ||||
|             unstitch_corners(path, family) | ||||
|             transformed.append(path) | ||||
|  | ||||
|     for family in ("normal", "advanced", "elf_overlay"): | ||||
|         path = texture_path / "block" / f"turtle_{family}.png" | ||||
|         if path.exists(): | ||||
|             unstitch_turtle(path, family) | ||||
|             transformed.append(path) | ||||
|  | ||||
|     path = texture_path / "block" / f"turtle_colour.png" | ||||
|     if path.exists(): | ||||
|         unstitch_turtle(path, "colour_frame") | ||||
|         unstitch_turtle(path, "colour_body", dy=46) | ||||
|         transformed.append(path) | ||||
|  | ||||
|     if len(transformed) == 0: | ||||
|         print("No files were transformed") | ||||
|         return | ||||
|   | ||||
 Jonathan Coates
					Jonathan Coates