diff --git a/README.md b/README.md index 91d7682..db4d06d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ Minetest MTS Editor =================== -This is a simple editor for [Minetest](https://www.minetest.net) Schematic files -([MTS](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/mts_format.md)) + This is a simple editor for +[Minetest](https://www.minetest.net) Schematic files ([MTS](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/mts_format.md)) ``` MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license @@ -26,8 +26,8 @@ MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license Batch Mode ---------- -You can convert MTS files and generate preview images for them from a script with this tool. -[Read more](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/batch.md). +You can convert MTS files and generate preview images for them from a script with this tool. You can also generate the block +images for the editor. [Read more](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/batch.md). Interactive Mode ---------------- @@ -46,10 +46,54 @@ and capable of generating the blocks.csv for you. -You can install this Minetest mod by running +Installation +------------ + +### Under Linux + +1. download [mtsedit-x86_64-linux.tgz](https://gitlab.com/bztsrc/mtsedit/raw/master/mtsedit-x86_64-linux.tgz) +2. as root, extract it to "/" (if you don't trust it, check the tarball first): "sudo tar -C / -xzvf mtsedit-x86_64-linux.tgz" +3. I guess you know your distro enough to assign a program to an extension. There are many ways, but if your desktop environment +recognizes the MTSEdit application from the installed .desktop file, then file assosiation has already taken care for you. +4. if the MTSEdit application appears in the application menu, but .mts files are not recognized, then as root add the +``` +model/vnd.mts mts schematic +``` +line to "/etc/mime.types". + +### Under Windows + +1. download [mtsedit-i686-win.zip](https://gitlab.com/bztsrc/mtsedit/raw/master/mtsedit-i686-win.zip) +2. unpack it into "C:\\Program Files (x86)" +3. open My Computer, from the "Tools" menu, select "Folder Options" +4. click on "File Types" tab +5. scroll down to "MTS" (if you can't find it, click on "New" button and add it) +6. click on "Change" button +7. click on "Browse..." button +8. choose "C:\\Program Files (x86)\\MTSEdit\\mtsedit.exe" +9. check "Always use the selected program to open this kind of file" +10. click on "Ok" button + +### Under MacOSX + +1. download [mtsedit-intel-macosx.zip](https://gitlab.com/bztsrc/mtsedit/raw/master/mtsedit-intel-macosx.zip) +2. unpack it into "/Applications" +3. in the Finder, find an .mts file +4. pull down the "File" menu and select "Get info" or press Command+I +5. expand the "Open With" submenu +6. choose "MTSEdit.app" +7. click on "Change All..." button + +### Installing the Minetest mod (common to all OS) + +To install the Minetest mod, you can run the following command using your Minetest mods directory as parameter, for example: ``` ./mtsedit -i ~/.minetest/mods ``` +or +``` +mtsedit.exe -i C:\\Program Files (x86)\Minetest\mods +``` Compilation ----------- @@ -90,6 +134,8 @@ Known Bugs Zooming can be slow, because it scales blocks in run-time. Using a cache would require double the memory footprint. I suggest to edit on 100% zoom, as that's using a different, fast blitting function. -Rotations are not handled properly, only the first four, 0 - 3 meaning North, West, South, East. +Rotations are not handled properly, only the first four, 0 - 3 meaning North, West, South, East. Others are only used if there's +a block image for that rotaion, and then they are picked numerically, not necessarily in rotation order (but you can set all +rotations, and they will be saved correctly, it's just you might have to click more to get the one you want). bzt diff --git a/data/Acacia_Bark_Stair_00.png b/data/Acacia_Bark_Stair_00.png index 28e2043..831a191 100644 Binary files a/data/Acacia_Bark_Stair_00.png and b/data/Acacia_Bark_Stair_00.png differ diff --git a/data/Acacia_Bark_Stair_02.png b/data/Acacia_Bark_Stair_02.png index 831a191..28e2043 100644 Binary files a/data/Acacia_Bark_Stair_02.png and b/data/Acacia_Bark_Stair_02.png differ diff --git a/data/Acacia_Stair_00.png b/data/Acacia_Stair_00.png index 881c3bf..5b234c3 100644 Binary files a/data/Acacia_Stair_00.png and b/data/Acacia_Stair_00.png differ diff --git a/data/Acacia_Stair_02.png b/data/Acacia_Stair_02.png index 5b234c3..881c3bf 100644 Binary files a/data/Acacia_Stair_02.png and b/data/Acacia_Stair_02.png differ diff --git a/data/Andesite_Stair_00.png b/data/Andesite_Stair_00.png index ac76f03..ad0d657 100644 Binary files a/data/Andesite_Stair_00.png and b/data/Andesite_Stair_00.png differ diff --git a/data/Andesite_Stair_02.png b/data/Andesite_Stair_02.png index ad0d657..ac76f03 100644 Binary files a/data/Andesite_Stair_02.png and b/data/Andesite_Stair_02.png differ diff --git a/data/Birch_Bark_Stair_00.png b/data/Birch_Bark_Stair_00.png index 3a3f91e..a496f70 100644 Binary files a/data/Birch_Bark_Stair_00.png and b/data/Birch_Bark_Stair_00.png differ diff --git a/data/Birch_Bark_Stair_02.png b/data/Birch_Bark_Stair_02.png index a496f70..3a3f91e 100644 Binary files a/data/Birch_Bark_Stair_02.png and b/data/Birch_Bark_Stair_02.png differ diff --git a/data/Birch_Stair_00.png b/data/Birch_Stair_00.png index 53050bc..2e4e1eb 100644 Binary files a/data/Birch_Stair_00.png and b/data/Birch_Stair_00.png differ diff --git a/data/Birch_Stair_02.png b/data/Birch_Stair_02.png index 2e4e1eb..53050bc 100644 Binary files a/data/Birch_Stair_02.png and b/data/Birch_Stair_02.png differ diff --git a/data/Black_Concrete_Stair_00.png b/data/Black_Concrete_Stair_00.png index a54cd0c..44ec482 100644 Binary files a/data/Black_Concrete_Stair_00.png and b/data/Black_Concrete_Stair_00.png differ diff --git a/data/Black_Concrete_Stair_02.png b/data/Black_Concrete_Stair_02.png index 44ec482..a54cd0c 100644 Binary files a/data/Black_Concrete_Stair_02.png and b/data/Black_Concrete_Stair_02.png differ diff --git a/data/Blue_Concrete_Stair_00.png b/data/Blue_Concrete_Stair_00.png index 2091816..6ca4a64 100644 Binary files a/data/Blue_Concrete_Stair_00.png and b/data/Blue_Concrete_Stair_00.png differ diff --git a/data/Blue_Concrete_Stair_02.png b/data/Blue_Concrete_Stair_02.png index 6ca4a64..2091816 100644 Binary files a/data/Blue_Concrete_Stair_02.png and b/data/Blue_Concrete_Stair_02.png differ diff --git a/data/Brick_Stair_00.png b/data/Brick_Stair_00.png index ce5e4af..ca12790 100644 Binary files a/data/Brick_Stair_00.png and b/data/Brick_Stair_00.png differ diff --git a/data/Brick_Stair_02.png b/data/Brick_Stair_02.png index ca12790..ce5e4af 100644 Binary files a/data/Brick_Stair_02.png and b/data/Brick_Stair_02.png differ diff --git a/data/Brown_Concrete_Stair_00.png b/data/Brown_Concrete_Stair_00.png index 75b058c..5301243 100644 Binary files a/data/Brown_Concrete_Stair_00.png and b/data/Brown_Concrete_Stair_00.png differ diff --git a/data/Brown_Concrete_Stair_02.png b/data/Brown_Concrete_Stair_02.png index 5301243..75b058c 100644 Binary files a/data/Brown_Concrete_Stair_02.png and b/data/Brown_Concrete_Stair_02.png differ diff --git a/data/Cobblestone_Stair_00.png b/data/Cobblestone_Stair_00.png index 1d6a892..3936b8e 100644 Binary files a/data/Cobblestone_Stair_00.png and b/data/Cobblestone_Stair_00.png differ diff --git a/data/Cobblestone_Stair_02.png b/data/Cobblestone_Stair_02.png index 3936b8e..1d6a892 100644 Binary files a/data/Cobblestone_Stair_02.png and b/data/Cobblestone_Stair_02.png differ diff --git a/data/Cracked_Stone_Brick_Stair_00.png b/data/Cracked_Stone_Brick_Stair_00.png index ca462ae..b3d986d 100644 Binary files a/data/Cracked_Stone_Brick_Stair_00.png and b/data/Cracked_Stone_Brick_Stair_00.png differ diff --git a/data/Cracked_Stone_Brick_Stair_02.png b/data/Cracked_Stone_Brick_Stair_02.png index b3d986d..ca462ae 100644 Binary files a/data/Cracked_Stone_Brick_Stair_02.png and b/data/Cracked_Stone_Brick_Stair_02.png differ diff --git a/data/Cyan_Concrete_Stair_00.png b/data/Cyan_Concrete_Stair_00.png index 9a4554b..2c59c31 100644 Binary files a/data/Cyan_Concrete_Stair_00.png and b/data/Cyan_Concrete_Stair_00.png differ diff --git a/data/Cyan_Concrete_Stair_02.png b/data/Cyan_Concrete_Stair_02.png index 2c59c31..9a4554b 100644 Binary files a/data/Cyan_Concrete_Stair_02.png and b/data/Cyan_Concrete_Stair_02.png differ diff --git a/data/Dark_Oak_Bark_Stair_00.png b/data/Dark_Oak_Bark_Stair_00.png index 4942fb8..440c01e 100644 Binary files a/data/Dark_Oak_Bark_Stair_00.png and b/data/Dark_Oak_Bark_Stair_00.png differ diff --git a/data/Dark_Oak_Bark_Stair_02.png b/data/Dark_Oak_Bark_Stair_02.png index 440c01e..4942fb8 100644 Binary files a/data/Dark_Oak_Bark_Stair_02.png and b/data/Dark_Oak_Bark_Stair_02.png differ diff --git a/data/Dark_Oak_Stair_00.png b/data/Dark_Oak_Stair_00.png index fb72111..92ff988 100644 Binary files a/data/Dark_Oak_Stair_00.png and b/data/Dark_Oak_Stair_00.png differ diff --git a/data/Dark_Oak_Stair_02.png b/data/Dark_Oak_Stair_02.png index 92ff988..fb72111 100644 Binary files a/data/Dark_Oak_Stair_02.png and b/data/Dark_Oak_Stair_02.png differ diff --git a/data/Dark_Prismarine_Stair_00.png b/data/Dark_Prismarine_Stair_00.png index 4d21020..59704cc 100644 Binary files a/data/Dark_Prismarine_Stair_00.png and b/data/Dark_Prismarine_Stair_00.png differ diff --git a/data/Dark_Prismarine_Stair_02.png b/data/Dark_Prismarine_Stair_02.png index 59704cc..4d21020 100644 Binary files a/data/Dark_Prismarine_Stair_02.png and b/data/Dark_Prismarine_Stair_02.png differ diff --git a/data/Diorite_Stair_00.png b/data/Diorite_Stair_00.png index 54661dc..b200c3e 100644 Binary files a/data/Diorite_Stair_00.png and b/data/Diorite_Stair_00.png differ diff --git a/data/Diorite_Stair_02.png b/data/Diorite_Stair_02.png index b200c3e..54661dc 100644 Binary files a/data/Diorite_Stair_02.png and b/data/Diorite_Stair_02.png differ diff --git a/data/End_Stone_Brick_Stair_00.png b/data/End_Stone_Brick_Stair_00.png index 62c8848..47ab163 100644 Binary files a/data/End_Stone_Brick_Stair_00.png and b/data/End_Stone_Brick_Stair_00.png differ diff --git a/data/End_Stone_Brick_Stair_02.png b/data/End_Stone_Brick_Stair_02.png index 47ab163..62c8848 100644 Binary files a/data/End_Stone_Brick_Stair_02.png and b/data/End_Stone_Brick_Stair_02.png differ diff --git a/data/Gold_Block_Stair_00.png b/data/Gold_Block_Stair_00.png index dbdbe8e..c9039dd 100644 Binary files a/data/Gold_Block_Stair_00.png and b/data/Gold_Block_Stair_00.png differ diff --git a/data/Gold_Block_Stair_02.png b/data/Gold_Block_Stair_02.png index c9039dd..dbdbe8e 100644 Binary files a/data/Gold_Block_Stair_02.png and b/data/Gold_Block_Stair_02.png differ diff --git a/data/Granite_Stair_00.png b/data/Granite_Stair_00.png index 89db3ed..79680eb 100644 Binary files a/data/Granite_Stair_00.png and b/data/Granite_Stair_00.png differ diff --git a/data/Granite_Stair_02.png b/data/Granite_Stair_02.png index 79680eb..89db3ed 100644 Binary files a/data/Granite_Stair_02.png and b/data/Granite_Stair_02.png differ diff --git a/data/Green_Concrete_Stair_00.png b/data/Green_Concrete_Stair_00.png index 7fa6aa9..3660598 100644 Binary files a/data/Green_Concrete_Stair_00.png and b/data/Green_Concrete_Stair_00.png differ diff --git a/data/Green_Concrete_Stair_02.png b/data/Green_Concrete_Stair_02.png index 3660598..7fa6aa9 100644 Binary files a/data/Green_Concrete_Stair_02.png and b/data/Green_Concrete_Stair_02.png differ diff --git a/data/Grey_Concrete_Stair_00.png b/data/Grey_Concrete_Stair_00.png index 07fa4d8..bd2c00f 100644 Binary files a/data/Grey_Concrete_Stair_00.png and b/data/Grey_Concrete_Stair_00.png differ diff --git a/data/Grey_Concrete_Stair_02.png b/data/Grey_Concrete_Stair_02.png index bd2c00f..07fa4d8 100644 Binary files a/data/Grey_Concrete_Stair_02.png and b/data/Grey_Concrete_Stair_02.png differ diff --git a/data/Ice_Stair_00.png b/data/Ice_Stair_00.png index 036cb3a..209565a 100644 Binary files a/data/Ice_Stair_00.png and b/data/Ice_Stair_00.png differ diff --git a/data/Ice_Stair_02.png b/data/Ice_Stair_02.png index 209565a..036cb3a 100644 Binary files a/data/Ice_Stair_02.png and b/data/Ice_Stair_02.png differ diff --git a/data/Iron_Block_Stair_00.png b/data/Iron_Block_Stair_00.png index e3db262..44fbd5d 100644 Binary files a/data/Iron_Block_Stair_00.png and b/data/Iron_Block_Stair_00.png differ diff --git a/data/Iron_Block_Stair_02.png b/data/Iron_Block_Stair_02.png index 44fbd5d..e3db262 100644 Binary files a/data/Iron_Block_Stair_02.png and b/data/Iron_Block_Stair_02.png differ diff --git a/data/Jungle_Bark_Stair_00.png b/data/Jungle_Bark_Stair_00.png index be04467..1d88d23 100644 Binary files a/data/Jungle_Bark_Stair_00.png and b/data/Jungle_Bark_Stair_00.png differ diff --git a/data/Jungle_Bark_Stair_02.png b/data/Jungle_Bark_Stair_02.png index 1d88d23..be04467 100644 Binary files a/data/Jungle_Bark_Stair_02.png and b/data/Jungle_Bark_Stair_02.png differ diff --git a/data/Jungle_Stair_00.png b/data/Jungle_Stair_00.png index d5cfc3d..803c9ec 100644 Binary files a/data/Jungle_Stair_00.png and b/data/Jungle_Stair_00.png differ diff --git a/data/Jungle_Stair_02.png b/data/Jungle_Stair_02.png index 803c9ec..d5cfc3d 100644 Binary files a/data/Jungle_Stair_02.png and b/data/Jungle_Stair_02.png differ diff --git a/data/Lapis_Lazuli_Stair_00.png b/data/Lapis_Lazuli_Stair_00.png index 66c34c5..0ffd040 100644 Binary files a/data/Lapis_Lazuli_Stair_00.png and b/data/Lapis_Lazuli_Stair_00.png differ diff --git a/data/Lapis_Lazuli_Stair_02.png b/data/Lapis_Lazuli_Stair_02.png index 0ffd040..66c34c5 100644 Binary files a/data/Lapis_Lazuli_Stair_02.png and b/data/Lapis_Lazuli_Stair_02.png differ diff --git a/data/Light_Blue_Concrete_Stair_00.png b/data/Light_Blue_Concrete_Stair_00.png index f078532..b5bff52 100644 Binary files a/data/Light_Blue_Concrete_Stair_00.png and b/data/Light_Blue_Concrete_Stair_00.png differ diff --git a/data/Light_Blue_Concrete_Stair_02.png b/data/Light_Blue_Concrete_Stair_02.png index b5bff52..f078532 100644 Binary files a/data/Light_Blue_Concrete_Stair_02.png and b/data/Light_Blue_Concrete_Stair_02.png differ diff --git a/data/Light_Grey_Concrete_Stair_00.png b/data/Light_Grey_Concrete_Stair_00.png index 7d6e6b6..9937131 100644 Binary files a/data/Light_Grey_Concrete_Stair_00.png and b/data/Light_Grey_Concrete_Stair_00.png differ diff --git a/data/Light_Grey_Concrete_Stair_02.png b/data/Light_Grey_Concrete_Stair_02.png index 9937131..7d6e6b6 100644 Binary files a/data/Light_Grey_Concrete_Stair_02.png and b/data/Light_Grey_Concrete_Stair_02.png differ diff --git a/data/Lime_Concrete_Stair_00.png b/data/Lime_Concrete_Stair_00.png index ce58a81..6a6be1f 100644 Binary files a/data/Lime_Concrete_Stair_00.png and b/data/Lime_Concrete_Stair_00.png differ diff --git a/data/Lime_Concrete_Stair_02.png b/data/Lime_Concrete_Stair_02.png index 6a6be1f..ce58a81 100644 Binary files a/data/Lime_Concrete_Stair_02.png and b/data/Lime_Concrete_Stair_02.png differ diff --git a/data/Magenta_Concrete_Stair_00.png b/data/Magenta_Concrete_Stair_00.png index 5aaa82c..419aa23 100644 Binary files a/data/Magenta_Concrete_Stair_00.png and b/data/Magenta_Concrete_Stair_00.png differ diff --git a/data/Magenta_Concrete_Stair_02.png b/data/Magenta_Concrete_Stair_02.png index 419aa23..5aaa82c 100644 Binary files a/data/Magenta_Concrete_Stair_02.png and b/data/Magenta_Concrete_Stair_02.png differ diff --git a/data/Mossy_Stone_Brick_Stair_00.png b/data/Mossy_Stone_Brick_Stair_00.png index 728d0a0..63ccd71 100644 Binary files a/data/Mossy_Stone_Brick_Stair_00.png and b/data/Mossy_Stone_Brick_Stair_00.png differ diff --git a/data/Mossy_Stone_Brick_Stair_02.png b/data/Mossy_Stone_Brick_Stair_02.png index 63ccd71..728d0a0 100644 Binary files a/data/Mossy_Stone_Brick_Stair_02.png and b/data/Mossy_Stone_Brick_Stair_02.png differ diff --git a/data/Mossy_Stone_Stair_00.png b/data/Mossy_Stone_Stair_00.png index 728d0a0..63ccd71 100644 Binary files a/data/Mossy_Stone_Stair_00.png and b/data/Mossy_Stone_Stair_00.png differ diff --git a/data/Mossy_Stone_Stair_02.png b/data/Mossy_Stone_Stair_02.png index 63ccd71..728d0a0 100644 Binary files a/data/Mossy_Stone_Stair_02.png and b/data/Mossy_Stone_Stair_02.png differ diff --git a/data/Nether_Brick_Stair_00.png b/data/Nether_Brick_Stair_00.png index 5e28ade..b00b78b 100644 Binary files a/data/Nether_Brick_Stair_00.png and b/data/Nether_Brick_Stair_00.png differ diff --git a/data/Nether_Brick_Stair_02.png b/data/Nether_Brick_Stair_02.png index b00b78b..5e28ade 100644 Binary files a/data/Nether_Brick_Stair_02.png and b/data/Nether_Brick_Stair_02.png differ diff --git a/data/Oak_Bark_Stair_00.png b/data/Oak_Bark_Stair_00.png index 5e7ab9c..fec9aa1 100644 Binary files a/data/Oak_Bark_Stair_00.png and b/data/Oak_Bark_Stair_00.png differ diff --git a/data/Oak_Bark_Stair_02.png b/data/Oak_Bark_Stair_02.png index fec9aa1..5e7ab9c 100644 Binary files a/data/Oak_Bark_Stair_02.png and b/data/Oak_Bark_Stair_02.png differ diff --git a/data/Oak_Stair_00.png b/data/Oak_Stair_00.png index aa39618..d9e7988 100644 Binary files a/data/Oak_Stair_00.png and b/data/Oak_Stair_00.png differ diff --git a/data/Oak_Stair_02.png b/data/Oak_Stair_02.png index d9e7988..aa39618 100644 Binary files a/data/Oak_Stair_02.png and b/data/Oak_Stair_02.png differ diff --git a/data/Obsidian_Glass_Stair_00.png b/data/Obsidian_Glass_Stair_00.png index 0365755..98072ca 100644 Binary files a/data/Obsidian_Glass_Stair_00.png and b/data/Obsidian_Glass_Stair_00.png differ diff --git a/data/Obsidian_Glass_Stair_02.png b/data/Obsidian_Glass_Stair_02.png index 98072ca..0365755 100644 Binary files a/data/Obsidian_Glass_Stair_02.png and b/data/Obsidian_Glass_Stair_02.png differ diff --git a/data/Obsidian_Stair_00.png b/data/Obsidian_Stair_00.png index 5725f67..d994453 100644 Binary files a/data/Obsidian_Stair_00.png and b/data/Obsidian_Stair_00.png differ diff --git a/data/Obsidian_Stair_02.png b/data/Obsidian_Stair_02.png index d994453..5725f67 100644 Binary files a/data/Obsidian_Stair_02.png and b/data/Obsidian_Stair_02.png differ diff --git a/data/Orange_Concrete_Stair_00.png b/data/Orange_Concrete_Stair_00.png index e0cdb60..157bd37 100644 Binary files a/data/Orange_Concrete_Stair_00.png and b/data/Orange_Concrete_Stair_00.png differ diff --git a/data/Orange_Concrete_Stair_02.png b/data/Orange_Concrete_Stair_02.png index 157bd37..e0cdb60 100644 Binary files a/data/Orange_Concrete_Stair_02.png and b/data/Orange_Concrete_Stair_02.png differ diff --git a/data/Pink_Concrete_Stair_00.png b/data/Pink_Concrete_Stair_00.png index 890d145..9e5c7c7 100644 Binary files a/data/Pink_Concrete_Stair_00.png and b/data/Pink_Concrete_Stair_00.png differ diff --git a/data/Pink_Concrete_Stair_02.png b/data/Pink_Concrete_Stair_02.png index 9e5c7c7..890d145 100644 Binary files a/data/Pink_Concrete_Stair_02.png and b/data/Pink_Concrete_Stair_02.png differ diff --git a/data/Polished_Andesite_Stair_00.png b/data/Polished_Andesite_Stair_00.png index 652418d..98c4d05 100644 Binary files a/data/Polished_Andesite_Stair_00.png and b/data/Polished_Andesite_Stair_00.png differ diff --git a/data/Polished_Andesite_Stair_02.png b/data/Polished_Andesite_Stair_02.png index 98c4d05..652418d 100644 Binary files a/data/Polished_Andesite_Stair_02.png and b/data/Polished_Andesite_Stair_02.png differ diff --git a/data/Polished_Diorite_Stair_00.png b/data/Polished_Diorite_Stair_00.png index 1353877..e463340 100644 Binary files a/data/Polished_Diorite_Stair_00.png and b/data/Polished_Diorite_Stair_00.png differ diff --git a/data/Polished_Diorite_Stair_02.png b/data/Polished_Diorite_Stair_02.png index e463340..1353877 100644 Binary files a/data/Polished_Diorite_Stair_02.png and b/data/Polished_Diorite_Stair_02.png differ diff --git a/data/Polished_Granite_Stair_00.png b/data/Polished_Granite_Stair_00.png index a7dd548..5a8d42b 100644 Binary files a/data/Polished_Granite_Stair_00.png and b/data/Polished_Granite_Stair_00.png differ diff --git a/data/Polished_Granite_Stair_02.png b/data/Polished_Granite_Stair_02.png index 5a8d42b..a7dd548 100644 Binary files a/data/Polished_Granite_Stair_02.png and b/data/Polished_Granite_Stair_02.png differ diff --git a/data/Prismarine_Brick_Stair_00.png b/data/Prismarine_Brick_Stair_00.png index 1fdca89..d47766a 100644 Binary files a/data/Prismarine_Brick_Stair_00.png and b/data/Prismarine_Brick_Stair_00.png differ diff --git a/data/Prismarine_Brick_Stair_02.png b/data/Prismarine_Brick_Stair_02.png index d47766a..1fdca89 100644 Binary files a/data/Prismarine_Brick_Stair_02.png and b/data/Prismarine_Brick_Stair_02.png differ diff --git a/data/Prismarine_Stair_00.png b/data/Prismarine_Stair_00.png index 57a815c..23f1ae3 100644 Binary files a/data/Prismarine_Stair_00.png and b/data/Prismarine_Stair_00.png differ diff --git a/data/Prismarine_Stair_02.png b/data/Prismarine_Stair_02.png index 23f1ae3..57a815c 100644 Binary files a/data/Prismarine_Stair_02.png and b/data/Prismarine_Stair_02.png differ diff --git a/data/Purple_Concrete_Stair_00.png b/data/Purple_Concrete_Stair_00.png index be9589b..d6e2683 100644 Binary files a/data/Purple_Concrete_Stair_00.png and b/data/Purple_Concrete_Stair_00.png differ diff --git a/data/Purple_Concrete_Stair_02.png b/data/Purple_Concrete_Stair_02.png index d6e2683..be9589b 100644 Binary files a/data/Purple_Concrete_Stair_02.png and b/data/Purple_Concrete_Stair_02.png differ diff --git a/data/Purpur_Stair_00.png b/data/Purpur_Stair_00.png index 3c653be..a613c65 100644 Binary files a/data/Purpur_Stair_00.png and b/data/Purpur_Stair_00.png differ diff --git a/data/Purpur_Stair_02.png b/data/Purpur_Stair_02.png index a613c65..3c653be 100644 Binary files a/data/Purpur_Stair_02.png and b/data/Purpur_Stair_02.png differ diff --git a/data/Quartz_Stair_00.png b/data/Quartz_Stair_00.png index 8079ecd..695ea0f 100644 Binary files a/data/Quartz_Stair_00.png and b/data/Quartz_Stair_00.png differ diff --git a/data/Quartz_Stair_02.png b/data/Quartz_Stair_02.png index 695ea0f..8079ecd 100644 Binary files a/data/Quartz_Stair_02.png and b/data/Quartz_Stair_02.png differ diff --git a/data/Red_Concrete_Stair_00.png b/data/Red_Concrete_Stair_00.png index 24f66b0..7b0c630 100644 Binary files a/data/Red_Concrete_Stair_00.png and b/data/Red_Concrete_Stair_00.png differ diff --git a/data/Red_Concrete_Stair_02.png b/data/Red_Concrete_Stair_02.png index 7b0c630..24f66b0 100644 Binary files a/data/Red_Concrete_Stair_02.png and b/data/Red_Concrete_Stair_02.png differ diff --git a/data/Red_Nether_Brick_Stair_00.png b/data/Red_Nether_Brick_Stair_00.png index bac3277..873a899 100644 Binary files a/data/Red_Nether_Brick_Stair_00.png and b/data/Red_Nether_Brick_Stair_00.png differ diff --git a/data/Red_Nether_Brick_Stair_02.png b/data/Red_Nether_Brick_Stair_02.png index 873a899..bac3277 100644 Binary files a/data/Red_Nether_Brick_Stair_02.png and b/data/Red_Nether_Brick_Stair_02.png differ diff --git a/data/Red_Sandstone_Stair_00.png b/data/Red_Sandstone_Stair_00.png index 8476976..10df6da 100644 Binary files a/data/Red_Sandstone_Stair_00.png and b/data/Red_Sandstone_Stair_00.png differ diff --git a/data/Red_Sandstone_Stair_02.png b/data/Red_Sandstone_Stair_02.png index 10df6da..8476976 100644 Binary files a/data/Red_Sandstone_Stair_02.png and b/data/Red_Sandstone_Stair_02.png differ diff --git a/data/Sandstone_Stair_00.png b/data/Sandstone_Stair_00.png index 24cc321..ff58c68 100644 Binary files a/data/Sandstone_Stair_00.png and b/data/Sandstone_Stair_00.png differ diff --git a/data/Sandstone_Stair_02.png b/data/Sandstone_Stair_02.png index ff58c68..24cc321 100644 Binary files a/data/Sandstone_Stair_02.png and b/data/Sandstone_Stair_02.png differ diff --git a/data/Smooth_Quartz_Stair_00.png b/data/Smooth_Quartz_Stair_00.png index 68d1ac2..00e2bcd 100644 Binary files a/data/Smooth_Quartz_Stair_00.png and b/data/Smooth_Quartz_Stair_00.png differ diff --git a/data/Smooth_Quartz_Stair_02.png b/data/Smooth_Quartz_Stair_02.png index 00e2bcd..68d1ac2 100644 Binary files a/data/Smooth_Quartz_Stair_02.png and b/data/Smooth_Quartz_Stair_02.png differ diff --git a/data/Smooth_Red_Sandstone_Stair_00.png b/data/Smooth_Red_Sandstone_Stair_00.png index 5ca3992..0d0f91e 100644 Binary files a/data/Smooth_Red_Sandstone_Stair_00.png and b/data/Smooth_Red_Sandstone_Stair_00.png differ diff --git a/data/Smooth_Red_Sandstone_Stair_02.png b/data/Smooth_Red_Sandstone_Stair_02.png index 0d0f91e..5ca3992 100644 Binary files a/data/Smooth_Red_Sandstone_Stair_02.png and b/data/Smooth_Red_Sandstone_Stair_02.png differ diff --git a/data/Smooth_Sandstone_Stair_00.png b/data/Smooth_Sandstone_Stair_00.png index 365b9b4..6f6e7b4 100644 Binary files a/data/Smooth_Sandstone_Stair_00.png and b/data/Smooth_Sandstone_Stair_00.png differ diff --git a/data/Smooth_Sandstone_Stair_02.png b/data/Smooth_Sandstone_Stair_02.png index 6f6e7b4..365b9b4 100644 Binary files a/data/Smooth_Sandstone_Stair_02.png and b/data/Smooth_Sandstone_Stair_02.png differ diff --git a/data/Spruce_Bark_Stair_00.png b/data/Spruce_Bark_Stair_00.png index d111877..09ca58d 100644 Binary files a/data/Spruce_Bark_Stair_00.png and b/data/Spruce_Bark_Stair_00.png differ diff --git a/data/Spruce_Bark_Stair_02.png b/data/Spruce_Bark_Stair_02.png index 09ca58d..d111877 100644 Binary files a/data/Spruce_Bark_Stair_02.png and b/data/Spruce_Bark_Stair_02.png differ diff --git a/data/Spruce_Stair_00.png b/data/Spruce_Stair_00.png index 8ad3a6a..5ab4df6 100644 Binary files a/data/Spruce_Stair_00.png and b/data/Spruce_Stair_00.png differ diff --git a/data/Spruce_Stair_02.png b/data/Spruce_Stair_02.png index 5ab4df6..8ad3a6a 100644 Binary files a/data/Spruce_Stair_02.png and b/data/Spruce_Stair_02.png differ diff --git a/data/Stone_Brick_Stair_00.png b/data/Stone_Brick_Stair_00.png index ca462ae..4a66f92 100644 Binary files a/data/Stone_Brick_Stair_00.png and b/data/Stone_Brick_Stair_00.png differ diff --git a/data/Stone_Brick_Stair_02.png b/data/Stone_Brick_Stair_02.png index 4a66f92..ca462ae 100644 Binary files a/data/Stone_Brick_Stair_02.png and b/data/Stone_Brick_Stair_02.png differ diff --git a/data/Stone_Stair_00.png b/data/Stone_Stair_00.png index b8de57d..9a8875d 100644 Binary files a/data/Stone_Stair_00.png and b/data/Stone_Stair_00.png differ diff --git a/data/Stone_Stair_02.png b/data/Stone_Stair_02.png index 9a8875d..b8de57d 100644 Binary files a/data/Stone_Stair_02.png and b/data/Stone_Stair_02.png differ diff --git a/data/White_Concrete_Stair_00.png b/data/White_Concrete_Stair_00.png index e3abc81..4d277db 100644 Binary files a/data/White_Concrete_Stair_00.png and b/data/White_Concrete_Stair_00.png differ diff --git a/data/White_Concrete_Stair_02.png b/data/White_Concrete_Stair_02.png index 4d277db..e3abc81 100644 Binary files a/data/White_Concrete_Stair_02.png and b/data/White_Concrete_Stair_02.png differ diff --git a/data/Yellow_Concrete_Stair_00.png b/data/Yellow_Concrete_Stair_00.png index 2abbf91..b8b9d55 100644 Binary files a/data/Yellow_Concrete_Stair_00.png and b/data/Yellow_Concrete_Stair_00.png differ diff --git a/data/Yellow_Concrete_Stair_02.png b/data/Yellow_Concrete_Stair_02.png index b8b9d55..2abbf91 100644 Binary files a/data/Yellow_Concrete_Stair_02.png and b/data/Yellow_Concrete_Stair_02.png differ diff --git a/docs/batch.md b/docs/batch.md index f19529b..a8d5e1d 100644 --- a/docs/batch.md +++ b/docs/batch.md @@ -49,7 +49,7 @@ With uppercase "P", you can cut the structure in half to peek inside. ### Generate Pictures for Slab and Stairs This wasn't a planned feature, but I needed quick and dirty tool to generate differently rotated and cut block images from -a block node image. +a cube block node image. ``` ./mtsedit -g Gold_Block_00.png @@ -67,5 +67,14 @@ This one was intended. With the [MTSEdit Minetest Mod](https://gitlab.com/bztsrc ./mtsedit -t ~/.minetest/worlds/MyWorld/blockimgs.csv ``` This will generate the block images as well as the slab and stair images into the CURRENT WORKING directory. You can then select -what you need and copy those to the `data` directory on your system. +what you need and copy those to the `data` directory on your system. I would suggest to run this command in a new, empty directory, +because it will generate a lot of PNGs. And by a lot, I mean A LOT (in magnitude of thousands probably). Alternatively you can +specify a block id (canonical name) and only that particular block's images will be generated: +``` +./mtsedit -t ~/.minetest/worlds/MyWorld/blockimgs.csv Crafting_Table +``` +If you specify a block node (drawing type normal) then it's slab, double slab and stair variants will be generated to, if they +are defined in the blockimgs.csv. There's no need to call `-t` with "Cobblestone_Stair" for example, just with "Cobblestone". +In order to work, the block types must be names like this: ends with "_Slab"; starts with "Double_" and ends with "_Slab"; or +ends with "_Stair". diff --git a/docs/blocks.md b/docs/blocks.md index 53c81f5..4c28fc9 100644 --- a/docs/blocks.md +++ b/docs/blocks.md @@ -48,12 +48,14 @@ Each block type may have more, but must have at least one image in the `data` di ``` The first part "block type" cames from the canonical name (1st coloumn), but with spaces converted to underscores '\_'. The second part, "param2" is a hexa-decimal value and represents the orientation. If the block has only one image, then it must be -"00", meaning block's image when the block is facing North. Other values are: "01" rotated by 90 degrees counter-clockwise -(facing West), "02" rotated by 180 degrees (faces South), "03" rotated by 90 degrees clock-wise (faces East). Values "04"-"1F" -are only used for blocks that can be rotated upside-down too, like stairs, but I honestly have no clue how. +"00", meaning block's image when the block is facing North. Other values are: "01" rotated by 90 degrees clockwise (facing East), +"02" rotated by 180 degrees (faces South), "03" rotated by 90 degrees counter-clockwise (faces West). Values "04"-"1F" +are only used for blocks that can be rotated upside-down too, like stairs, but I honestly have no clue how. MTSEdit wouldn't +care, it will simply allow all rotations for which there's an image. Hint: the MTSEdit tool can generate slab and stair images from block pictures using the `-g` option. This will only generate the -first 4 orientation, a slab, and a mirrored verion of the original block. +first 4 orientation, a slab, and a mirrored verion of the original block. The `-t` uses the textures from the game, and it can +generate much more variants. Translations ------------ @@ -63,3 +65,17 @@ provide translation files in the `data` directory. These are plain text files, b lines each of "(1st coloumn)=(translated name)". As with blocks.csv, the lines are ended by a newline '\\n' character, '\\r' is optional. +Texture Data CSV +---------------- + +Saved in blockimgs.csv by the [MTSEdit Minetest Mod](https://gitlab.com/bztsrc/mtsedit/tree/master/mt-mod), and read by the +`-t` option. The coloumns are as follows: +- canonical name (same as block.csv's 1st coloum) +- block's technical name (same as one of the mapping coloumns) +- drawtype (normal,plantlike,raillike etc. where to put the textures on the cube) +- paramtype2 (none,regular,facedir,wallmounted etc. rotation options) +- node_box type (if any) +- directory of the textures +- list of texture file names +- an "|" pipe separator +- list of overlay texture file names diff --git a/docs/mts_format.md b/docs/mts_format.md index c3658d1..7fab4b7 100644 --- a/docs/mts_format.md +++ b/docs/mts_format.md @@ -70,13 +70,13 @@ right. This aligns with the Lua API place_schematics(rotation=0). Probability values in `param1` are encoded on 8-bits. They are indexed the same way as block IDs. Version 3 ranges from 0 to 0xFF, while version 4 uses the same values as for layer probability, from 0 to 0x7F. According to the spec, in version 4 bit 7 means node -force placement, but I haven't seen any MTS files yet with that bit set. +force placement, but I haven't seen any MTS files yet with that bit set. MTSEdit supports that force placement bit however. Rotation information is stored in `param2`. This is the worst documented part of the MTS files. It sometimes has large values, -but MTSEdit will simply ignore those. What I could make out from C++ source, orentation is as follows: 0 means normal orientation -(block faces North), 1 means rotated by 90 degrees (faces West), 2 means rotated by 180 degrees (faces South), and 3 means rotated -by 90 degrees counter clock-wise (faces East). I have absoultely no idea what 4-31 supposed to mean, right now MTSEdit only handles -4. I would like add support for the rest if someone could explain what they mean. +what I could make out from C++ source, orentation is as follows: 0 means normal orientation (block faces North), 1 means rotated +by 90 degrees (faces East), 2 means rotated by 180 degrees (faces South), and 3 means rotated by 90 degrees counter clock-wise +(faces West). I have absoultely no idea what 4-31 supposed to mean, but MTSEdit will allow those if you provide images for those +rotations. #### Addition to the MTS Specification diff --git a/docs/usage.md b/docs/usage.md index 8c69f3a..99199b8 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -38,7 +38,7 @@ If that parameter is a directory, then MTSEdit will start with the "Load Schemat You can find the toolbar `A` on the left. The icons are: -1. Load / Reload Structure +1. Load Structure 2. Save As 3. Save Preview 4. Layer Operations (small icons) @@ -91,8 +91,8 @@ Main editor window: | Shift + left | rotate the current block counter clock-wise | | Shift + right | rotate the current block clock-wise | | + / - | change current layer's probability | -| L | (re)load schematic | -| S | save schematic | +| L | open load schematic window | +| S | quick save schematic to current file | | Shift + S | open save as window | | P | save preview PNG | | Shift + P | save preview with structure cut in half | diff --git a/etc/Info.plist b/etc/Info.plist new file mode 100644 index 0000000..664a012 --- /dev/null +++ b/etc/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + MTSEdit + CFBundleExecutable + mtsedit + CFBundleGetInfoString + 1.0.0, Copyright 2019 bzt + CFBundleIconFile + mtsedit.icns + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + MTSEdit + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + NSHumanReadableCopyright + Copyright 2019 bzt + NSPrincipalClass + NSApplication + CGDisableCoalescedUpdates + + + diff --git a/etc/mtsedit.desktop b/etc/mtsedit.desktop new file mode 100644 index 0000000..3d03c16 --- /dev/null +++ b/etc/mtsedit.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Name=MTSEdit +Name[en_US]=MTSEdit +GenericName=Minetest Schematic Editor +GenericName[en_US]=Minetest Schematic Editor +Comment=Edit and convert MTS schematic files +Exec=mtsedit %F +TryExec=mtsedit ~/.minetest/worlds +Terminal=false +Type=Application +Icon=mtsedit +Categories=Graphics;3DGraphics;Editor; +MimeType=model/vnd.mts;application/x-minetest-schematic; + diff --git a/etc/mtsedit.icns b/etc/mtsedit.icns new file mode 100644 index 0000000..da32d13 Binary files /dev/null and b/etc/mtsedit.icns differ diff --git a/etc/mtsedit.ico b/etc/mtsedit.ico new file mode 100644 index 0000000..8bbc76b Binary files /dev/null and b/etc/mtsedit.ico differ diff --git a/etc/mtsedit.png b/etc/mtsedit.png new file mode 100644 index 0000000..20ab3af Binary files /dev/null and b/etc/mtsedit.png differ diff --git a/etc/resource.rc b/etc/resource.rc new file mode 100644 index 0000000..df0f2e8 --- /dev/null +++ b/etc/resource.rc @@ -0,0 +1,35 @@ +#include + +// Win32 application icon. +#define IDI_APPICON 101 +IDI_APPICON ICON "mtsedit.ico" + +// Executable version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "bzt@gitlab" + VALUE "FileDescription", "MineTest Schematic Editor" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "Win32App" + VALUE "LegalCopyright", "©2019 bzt@gitlab" + VALUE "OriginalFilename", "mtsedit.exe" + VALUE "ProductName", "MTSEdit" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END diff --git a/mt-mod/README.md b/mt-mod/README.md index b92e956..9c2ae91 100644 --- a/mt-mod/README.md +++ b/mt-mod/README.md @@ -50,15 +50,21 @@ In the chat window issue the following command ``` /mtsedit export Minetest Game ``` -Where the argument is one of the coloumns in block.csv, so called node palette. If the csv exists, then this mod will read -it, and it will only update that particular one coloumn. If the file does not exists, then it will be created. If it exists, -but there's no such coloumn as specified in the argument, then a new node palette will be created. +Where the argument is one of the coloumns in block.csv, so called node palette. If the blocks.csv exists in the world directory, +then this mod will read it, and it will only update that particular one coloumn. If the file does not exists, then it will be +created. If it exists, but there's no such coloumn as specified in the argument, then a new node palette will be created. The Lua script tries to figure out which node is which, but because you can enable lots of mods in Minetest (each allowed to register it's own node types), that's not an easy task. It does a pretty decent job though, usually about 80% of the records are correct, and only 20% percent requires manual fixing. For Mineclone2, I've provided an almost entirely complete blocks.csv, which also contains the Minecraft NBT .schematic files' Block IDs. +To export node texture data, use +``` +/mtsedit imgs +``` +This will save blockimgs.csv in the world directory. + ### Importing MTS files For that, enter chat and run diff --git a/mt-mod/mtsedit/init.lua b/mt-mod/mtsedit/init.lua index cc4da22..335d578 100644 --- a/mt-mod/mtsedit/init.lua +++ b/mt-mod/mtsedit/init.lua @@ -260,6 +260,16 @@ function mtsedit.imgs() else file:write(","..t["drawtype"]) end + if (t["paramtype2"] == nil) then + file:write(",regular") + else + file:write(","..t["paramtype2"]) + end + if (t["node_box"] == nil or t["node_box"]["type"] == nil) then + file:write(",") + else + file:write(","..t["node_box"]["type"].."") + end if (t["mod_origin"] == nil or t["mod_origin"] == "") then file:write(",") else @@ -276,6 +286,18 @@ function mtsedit.imgs() else file:write(","..string.format("%q", t["tiles"].."")) end + file:write(",|") + if (type(t["overlay_tiles"]) == "table") then + for _,tile in pairs(t["overlay_tiles"]) do + if (type(tile) == "table") then + file:write(","..string.format("%q", table.concat(tile,","))) + else + file:write(","..string.format("%q", tile.."")) + end + end + elseif (t["overlay_tiles"] ~= nil) then + file:write(","..string.format("%q", t["tiles"].."")) + end file:write("\r\n") end end @@ -370,6 +392,7 @@ minetest.register_tool("mtsedit:place", { description = S("Place the loaded structure"), inventory_image = "mtsedit_place.png", range = 8.0, + light_source = 14, on_use = function(itemstack, user, pointed_thing) local name = user:get_player_name() local pos = user:get_pos() diff --git a/mtsedit-i686-win.zip b/mtsedit-i686-win.zip new file mode 100644 index 0000000..7fb89cf Binary files /dev/null and b/mtsedit-i686-win.zip differ diff --git a/mtsedit-x86_64-linux.tgz b/mtsedit-x86_64-linux.tgz new file mode 100644 index 0000000..f6bef8e Binary files /dev/null and b/mtsedit-x86_64-linux.tgz differ diff --git a/src/Makefile b/src/Makefile index 53bc47b..328317e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,12 @@ # --- set these according to your configuration --- +LINUXSDL = /usr/include/SDL2 MINGWSDL = ../.. MACSDL = ~/Library/Frameworks/SDL.framework/Versions/A/Headers # ------------------------------------------------- TARGET = mtsedit SRCS = $(filter-out bin2h.c,$(wildcard *.c)) +OBJS = $(SRCS:.c=.o) CFLAGS = -Wall -Wextra -ansi -pedantic @@ -12,28 +14,32 @@ CFLAGS = -Wall -Wextra -ansi -pedantic ifneq ("$(wildcard $(MACSDL)/SDL.h)","") CFLAGS += -I/usr/include/SDL2 -I$(MACSDL) LIBS = -framework SDL +PACKAGE = MacOSX else ifneq ("$(wildcard /Library/Frameworks/SDL*)","") CFLAGS += -I/usr/include/SDL2 -I/Library/Frameworks/SDL*/Versions/A/Headers LIBS = -framework SDL +PACKAGE = MacOSX else # Linux -ifneq ("$(wildcard /usr/include/SDL2/SDL.h)","") -CFLAGS += -I/usr/include/SDL2 +ifneq ("$(wildcard $(LINUXSDL)/SDL.h)","") +CFLAGS += -I$(LINUXSDL) LIBS = -lSDL2 +PACKAGE = Linux else # Windows MinGW ifneq ("$(wildcard $(MINGWSDL)/i686-w64-mingw32/include/SDL2/SDL.h)","") CFLAGS += -I$(MINGWSDL)/i686-w64-mingw32/include/SDL2 LIBDIRS = -static-libgcc -L$(MINGWSDL)/i686-w64-mingw32/lib LIBS = -lSDL2 -luser32 +OBJS += resource.o +PACKAGE = Win +CC = gcc endif endif endif endif -OBJS = $(SRCS:.c=.o) - all: configure data.h $(OBJS) $(TARGET) configure: @@ -55,7 +61,10 @@ endif data.h: bin2h.c icons.png font.psf.gz @$(CC) bin2h.c -o bin2h ./bin2h icons.png font.psf.gz ../mt-mod/mtsedit >data.h - @rm bin2h + @rm bin2h bin2h.exe 2>/dev/null || true + +resource.o: + windres -i ../etc/resource.rc -o resource.o %: %.c main.h lang.h data.h $(CC) $(CFLAGS) $< -c $@ @@ -67,21 +76,34 @@ install: $(TARGET) install -m 755 -g bin $(TARGET) /usr/bin @mkdir -p /usr/share/mtsedit cp ../data/* /usr/share/mtsedit + cp -r ../mt-mod/mtsedit ~/.minetest/mods package: -ifeq ("$(LIBDIRS)","") - @mkdir usr usr/bin usr/share usr/share/mtsedit +ifeq ("$(PACKAGE)","Linux") + @mkdir usr usr/bin usr/share usr/share/mtsedit usr/share/applications usr/share/icons usr/share/icons/hicolor usr/share/icons/hicolor/32x32 usr/share/icons/hicolor/32x32/apps @cp $(TARGET) usr/bin @cp -r ../data/* usr/share/mtsedit + @cp ../etc/mtsedit.desktop usr/share/applications + @cp ../etc/mtsedit.png usr/share/icons/hicolor/32x32/apps tar -czvf ../$(TARGET)-x86_64-linux.tgz usr @rm -rf usr else +ifeq ("$(PACKAGE)","Win") @mkdir MTSEdit - @ln -s ../../data MTSEdit/data - @ln -s ../$(TARGET).exe MTSEdit/$(TARGET).exe - @ln -s ../SDL2.dll MTSEdit/SDL2.dll - zip $(TARGET)-i686-win.zip MTSEdit || true + @cp $(TARGET).exe MTSEdit/$(TARGET).exe + @cp $(MINGWSDL)/i686-w64-mingw32/bin/SDL2.dll MTSEdit/SDL2.dll + @cp -r ../data MTSEdit/data + zip $(TARGET)-i686-win.zip MTSEdit @rm -rf MTSEdit +else + @mkdir MTSEdit.app MTSEdit.app/Contents MTSEdit.app/Contents/MacOS MTSEdit.app/Contents/Resources + @cp $(TARGET) MTSEdir.app/Contents/MacOS + @cp ../etc/Info.list MTSEdit.app/Contents + @cp ../etc/mtsedit.icns MTSEdit.app/Contents/Resources + @cp -r ../data MTSEdit.app/Contents/Resources + zip $(TARGET)-intel-macosx.zip MTSEdit + @rm -rf MTSEdit.app +endif endif clean: diff --git a/src/blocks.c b/src/blocks.c index da99d0f..27f8174 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -41,7 +41,7 @@ void blocks_getdir(char **argv, char **envp) { FILE *f; int i; - char **env = envp; + char **env = envp, *p; /* find our data directory. Environment variable takes preference */ for(env = envp; env && *env; env++) { @@ -91,7 +91,12 @@ void blocks_getdir(char **argv, char **envp) strcpy(path, "/usr/local/share/mtsedit/blocks.csv"); f = fopen(path, "r"); if(f) { path[strlen(path)-10] = 0; fclose(f); } - else { free(path); path = NULL; } + else { + strcpy(path, "/Applications/MTSEdit.app/Contents/Resources/data/blocks.csv"); + f = fopen(path, "r"); + if(f) { path[strlen(path)-10] = 0; fclose(f); } + else { free(path); path = NULL; } + } } } #endif @@ -100,14 +105,14 @@ void blocks_getdir(char **argv, char **envp) path = (char*)malloc(strlen(argv[0])+256); if(!path) error(lang[ERR_MEM]); strcpy(path, argv[0]); - home = strrchr(path, DIRSEP); - if(home) home++; else { sprintf(path, ".%c", DIRSEP); home = path + 2; } - sprintf(home, "data%cblocks.csv", DIRSEP); + p = strrchr(path, DIRSEP); + if(p) p++; else { sprintf(path, ".%c", DIRSEP); p = path + 2; } + sprintf(p, "data%cblocks.csv", DIRSEP); f = fopen(path, "r"); if(f) { path[strlen(path)-10] = 0; fclose(f); } else { /* last resort, development repository or /opt/mtsedit/bin, data in parent directory */ - sprintf(home, "..%cdata%cblocks.csv", DIRSEP, DIRSEP); + sprintf(p, "..%cdata%cblocks.csv", DIRSEP, DIRSEP); f = fopen(path, "r"); if(f) { path[strlen(path)-10] = 0; fclose(f); } else { free(path); path = NULL; } diff --git a/src/edit.c b/src/edit.c index be4bc44..2f32d78 100644 --- a/src/edit.c +++ b/src/edit.c @@ -392,47 +392,18 @@ void edit_key(SDL_Event *event) */ void edit_rotate(int y, int z, int x, int ccw) { - unsigned char rot_table[24 * 4] = { - 0, 1, 2, 3, - 1, 2, 3, 0, - 2, 3, 0, 1, - 3, 0, 1, 2, - 4, 13, 10, 19, - 5, 14, 11, 16, - 6, 15, 8, 17, - 7, 12, 9, 18, - 8, 17, 6, 15, - 9, 18, 7, 12, - 10, 19, 4, 13, - 11, 16, 5, 14, - 12, 9, 18, 7, - 13, 10, 19, 4, - 14, 11, 16, 5, - 15, 8, 17, 6, - 16, 5, 14, 11, - 17, 6, 15, 8, - 18, 7, 12, 9, - 19, 4, 13, 10, - 20, 23, 22, 21, - 21, 20, 23, 22, - 22, 21, 20, 23, - 23, 22, 21, 20}; unsigned char oldparam2 = nodes[y][z][x].param2; if(!nodes[y][z][x].param0) return; if(ccw) { - if(nodes[y][z][x].param2 < 4) nodes[y][z][x].param2++; - else if(nodes[y][z][x].param2 == 3 && !blocks[nodes[y][z][x].param0].img[4]) nodes[y][z][x].param2 = 0; - else { - /* this is the code from Minetest engine. But I don't trust it. */ - nodes[y][z][x].param2 &= 0x1F; - nodes[y][z][x].param2 |= rot_table[((nodes[y][z][x].param2 % 24) * 4) + 1]; - } + if(nodes[y][z][x].param2 >= 31) + nodes[y][z][x].param2 = 0; + else + nodes[y][z][x].param2++; } else { if(nodes[y][z][x].param2 > 0) nodes[y][z][x].param2--; - else if(blocks[nodes[y][z][x].param0].img[3]) nodes[y][z][x].param2 = 3; - else if(blocks[nodes[y][z][x].param0].img[1]) nodes[y][z][x].param2 = 1; - else nodes[y][z][x].param2 = 0; + else for(nodes[y][z][x].param2 = 31; nodes[y][z][x].param2 && !blocks[nodes[y][z][x].param0].img[nodes[y][z][x].param2]; + nodes[y][z][x].param2--); } if(!blocks[nodes[y][z][x].param0].img[nodes[y][z][x].param2]) nodes[y][z][x].param2 = nodes[y][z][x].param2 == 3 && blocks[nodes[y][z][x].param0].img[1] ? 1 : 0; diff --git a/src/hist.c b/src/hist.c index b7a9807..075f321 100644 --- a/src/hist.c +++ b/src/hist.c @@ -46,7 +46,11 @@ void hist_prepare(int type, int volume) if(type > HIST_NODE) mts_getbounds(0, NULL, NULL); switch(type) { - case HIST_NODE: volume = 0; break; + case HIST_NODE: + case HIST_ROTCW: + case HIST_ROTCCW: + case HIST_FLIP: + volume = 0; break; case HIST_BRUSH: if(volume < 1) volume = (may - miy + 1) * (maz - miz + 1) * (max - mix + 1); histcurr.data.multiple.entry = (hist_t*)malloc(volume * sizeof(hist_t)); @@ -295,6 +299,9 @@ int hist_undo() } break; case HIST_ADDX: mts_delx(history[histtop].x); break; + case HIST_ROTCW: mts_rotate(1); break; + case HIST_ROTCCW: mts_rotate(0); break; + case HIST_FLIP: mts_flip(); break; } histtop++; status = nodes[currlayer][cz][cx].param0 ? blocks[nodes[currlayer][cz][cx].param0].name : NULL; @@ -360,6 +367,9 @@ int hist_redo() } break; case HIST_DELX: mts_delx(history[histtop].x); break; + case HIST_ROTCW: mts_rotate(0); break; + case HIST_ROTCCW: mts_rotate(1); break; + case HIST_FLIP: mts_flip(); break; } status = nodes[currlayer][cz][cx].param0 ? blocks[nodes[currlayer][cz][cx].param0].name : NULL; return 1; diff --git a/src/load.c b/src/load.c index aa176d0..73f4a54 100644 --- a/src/load.c +++ b/src/load.c @@ -40,7 +40,7 @@ extern char cur[2]; */ void load_do() { - char *fn, d = loadfiles[loadpos][0] == DIRSEP; + char *fn, d = loadfiles[loadpos][0] == '/'; if(isdir(mtsfile)) { fn = mtsfile + strlen(mtsfile); if(fn[-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; } @@ -49,7 +49,7 @@ void load_do() if(!fn) fn = mtsfile; else fn++; *fn = 0; } - if(!mtsfile[0] || (mtsfile[0] == '.' && mtsfile[1] == DIRSEP && !mtsfile[2])) { + if(!mtsfile[0] || (mtsfile[0] == '.' && (!mtsfile[1] || (mtsfile[1] == DIRSEP && !mtsfile[2])))) { getcwd(mtsfile, MAXPATHLEN); fn = mtsfile + strlen(mtsfile); if(fn[-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; } @@ -59,7 +59,11 @@ void load_do() fn = strrchr(mtsfile, DIRSEP); if(!fn) fn = mtsfile; else fn++; *fn = 0; - if(!mtsfile[0]) strcpy(mtsfile, "."); + if(!mtsfile[0]) { + getcwd(mtsfile, MAXPATHLEN); + fn = mtsfile + strlen(mtsfile); + if(fn[-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; } + } } else strcpy(fn, loadfiles[loadpos] + d); freedir(loadmax, &loadfiles); @@ -101,7 +105,7 @@ void load_redraw() if(!loadfiles) loadmax = listdir(mtsfile, &loadfiles, 1); for(i = loadscr; i < loadmax && (rect.y + (int)font->height) < j; i++, rect.y += font->height) { - if(loadfiles[i][0] == DIRSEP) { + if(loadfiles[i][0] == '/') { strsep = 0; sdlprint(44, rect.y, loadfld == 1 && loadpos == i ? THEME_INPUT : THEME_INACT, THEME_INPBG, "\002\003"); strsep = 1; diff --git a/src/main.c b/src/main.c index d6d564f..1d7cb0c 100644 --- a/src/main.c +++ b/src/main.c @@ -43,7 +43,6 @@ char **lang = &dict[0][1]; * Windows workaround */ #ifdef __WIN32__ -#include /* these two functions were borrowed from sdl_windows_main.c */ static void UnEscapeQuotes(char *arg) @@ -129,11 +128,9 @@ static int ParseCommandLine(char *cmdline, char **argv) /* Windows entry point */ int APIENTRY WinMain(_unused HINSTANCE hInstance, _unused HINSTANCE hPrevInstance, _unused LPSTR lpCmdLine, _unused int nCmdShow) { - OPENFILENAME ofn; char *cmdline = GetCommandLine(); int ret, argc = ParseCommandLine(cmdline, NULL); char **argv = SDL_stack_alloc(char*, argc+2); - char fn[1024]; ParseCommandLine(cmdline, argv); if(!argv[1]) { argc++; @@ -173,7 +170,7 @@ int main(int argc, char** argv, char** envp) usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n" "./mtsedit [-v] [-d|-p|-P] [-m map] <.mts|.schematic> [out.mts]\r\n" "./mtsedit -g \r\n" - "./mtsedit -t \r\n" + "./mtsedit -t [blockid]\r\n" "./mtsedit -i [Minetest mods dir]\r\n" "\r\n -v: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -m map: %s\r\n -g: %s\r\n -t: %s\r\n" " -i: %s\r\n out.mts: %s\r\n", @@ -208,7 +205,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license mts_x = mts_y = mts_z = 0; if(i+1 <= argc && argv[i+1] && !opt) opt = 7; - if(opt && opt != 4 && opt != 6) { + if(opt && (opt < 5 || opt == 7)) { blocks_parse(); readschem(); if(!mts_y || !mts_y || !mts_x) @@ -231,7 +228,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license case 2: case 3: ret = mts_view(opt-2); break; case 4: ret = stairgen(); break; - case 5: ret = blockgen(); break; + case 5: ret = blockgen(argv[i+1]); break; case 6: case 0: /* start the main user interface */ diff --git a/src/main.h b/src/main.h index f8d0f66..1faefa4 100644 --- a/src/main.h +++ b/src/main.h @@ -54,27 +54,34 @@ #define THEME_SAVEACT 9 #define THEME_SAVEINACT 10 -#define HIST_EMPTY 0 -#define HIST_NODE 1 -#define HIST_BRUSH 2 -#define HIST_ADDY 3 -#define HIST_DELY 4 -#define HIST_ADDZ 5 -#define HIST_DELZ 6 -#define HIST_ADDX 7 -#define HIST_DELX 8 +#define HIST_EMPTY 0 +#define HIST_NODE 1 +#define HIST_BRUSH 2 +#define HIST_ADDY 3 +#define HIST_DELY 4 +#define HIST_ADDZ 5 +#define HIST_DELZ 6 +#define HIST_ADDX 7 +#define HIST_DELX 8 +#define HIST_ROTCW 9 +#define HIST_ROTCCW 10 +#define HIST_FLIP 11 #include +#include #include +#include #include #include #include "stb_image.h" #include "lang.h" +/* must be 768 at least */ #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif #ifdef __WIN32__ +#include #define DIRSEP '\\' #else #define DIRSEP '/' @@ -178,7 +185,7 @@ void freedir(int n, char ***files); void detcube(int w, int h, unsigned char *block); int instmod(unsigned char *data, int size); int stairgen(); -int blockgen(); +int blockgen(char *blockid); /* blocks.c */ void blocks_getdir(char **argv, char **envp); diff --git a/src/sdl.c b/src/sdl.c index 704890a..0733a79 100644 --- a/src/sdl.c +++ b/src/sdl.c @@ -297,8 +297,12 @@ void sdldo(int opt) case 1: mts_save(); activetool = -1; activeblock = 0; break; case 2: mts_view(shift); break; case 3: - case 4: mts_rotate(4-opt); i = cx; if(opt == 3) { cx = cz; cz = 255 - i; } else { cx = 255 - cz; cz = i; } break; - case 5: mts_flip(); break; + case 4: + hist_prepare(opt == 4 ? HIST_ROTCCW : HIST_ROTCW, 0); + mts_rotate(4-opt); i = cx; if(opt == 3) { cx = cz; cz = 255 - i; } else { cx = 255 - cz; cz = i; } + hist_commit(); + break; + case 5: hist_prepare(HIST_FLIP, 0); mts_flip(); hist_commit(); break; case 6: hist_prepare(HIST_ADDY, currlayer); mts_addy(currlayer, shift); hist_commit(); break; case 7: hist_prepare(HIST_DELY, currlayer); mts_dely(currlayer); hist_commit(); break; case 8: hist_prepare(HIST_ADDZ, cz); mts_addz(cz, shift); hist_commit(); break; diff --git a/src/util.c b/src/util.c index 9052f52..f07ee80 100644 --- a/src/util.c +++ b/src/util.c @@ -32,6 +32,8 @@ #include #include +#define TMPSIZE 80 + /* cube coordinates */ int x0,x1,x2, y0,y1,y2,y3,y4; int verbose = 0; @@ -120,12 +122,16 @@ void readschem() /* Could be a Minecraft NBT */ if(!memcmp(data + 3, "Schematic", 9)) schem_load(data, size); - /* make sure that all non-air blocks have their probability set */ + /* make sure that all non-air blocks have their probability set, and we have only rotations with image */ for(y = 0; y < 256; y++) for(z = 0; z < 256; z++) for(x = 0; x < 256; x++) - if(nodes[y][z][x].param0 && !nodes[y][z][x].param1) - nodes[y][z][x].param1 = 127; + if(nodes[y][z][x].param0) { + if(!(nodes[y][z][x].param1 & 0x7F)) nodes[y][z][x].param1 |= 127; + if(!blocks[nodes[y][z][x].param0].img[nodes[y][z][x].param2]) + nodes[y][z][x].param2 = !blocks[nodes[y][z][x].param0].img[nodes[y][z][x].param2 & 1] ? 0 : + nodes[y][z][x].param2 & 1; + } } if(data) free(data); } @@ -152,6 +158,15 @@ void errorcsv(int line) sprintf(msg, "blocks.csv(%d): %s", line, lang[ERR_CSV]); } +/** + * IMGCSV error + */ +void errorimgcsv(int line) +{ + char msg[1024]; + sprintf(msg, "blockimgs.csv(%d): %s", line, lang[ERR_IMGCSV]); +} + /** * Convert an ascii hex value int integer */ @@ -210,7 +225,7 @@ int listdir(char *path, char ***files, int type) break; case 1: strcpy(fn, de->d_name); - if(isdir(tmp)) c = DIRSEP; + if(isdir(tmp)) c = '/'; else if((i < 5 || strcmp(de->d_name + i - 4, ".mts")) && (i < 11 || strcmp(de->d_name + i - 4, ".schematic"))) continue; @@ -285,7 +300,7 @@ int instmod(unsigned char *data, int size) if(!un) error(lang[ERR_MEM]); end = b + s; -#ifdef __WIN32__ +#ifndef __WIN32__ if(mtsfile[0] == '~') { strcpy(tmp, home); strcat(tmp, mtsfile + 1); @@ -306,7 +321,13 @@ int instmod(unsigned char *data, int size) error(msg); } while(b < end) { +#ifndef __WIN32__ i = strlen((char*)b) + 1; +#else + for(i = 0; b[i]; i++) + if(b[i] == '/') b[i] = '\\'; + i++; +#endif j = (b[i + 1] << 8) | b[i]; strcpy(fn, (char*)b); d = strrchr(fn, DIRSEP); @@ -542,10 +563,711 @@ int stairgen() } /** - * Generate block, slab and stair pictures from textures + * Resample and save block image */ -int blockgen() +typedef struct tColorRGBA { + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; +} tColorRGBA; +int savepng(char *name, int num, SDL_Surface *src) { - printf("not implemented yet, sorry\n"); + int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, lx, ly, dgap, l; + tColorRGBA *c00, *c01, *c10, *c11, *csp, *dp; + unsigned char *img; + char path[MAXPATHLEN]; + FILE *f; + SDL_Surface *dst = SDL_CreateRGBSurface(0, 32, 32, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000); + + /* resample */ + /** + * This is from SDL_gfx, but I don't wanted to introduce a new dependency just because + * of a single function. Heavily optimized, all non-used code-paths removed, plus I hate + * that I can't give exact destination dimensions to zoomSurfaceRGBA() + */ + sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); + sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); + + if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) error(lang[ERR_MEM]); + if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { + free(sax); + error(lang[ERR_MEM]); + } + + csp = (tColorRGBA *) src->pixels; + dp = (tColorRGBA *) dst->pixels; + + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) { + *csax = csx; + csax++; + csx &= 0xffff; + csx += sx; + } + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) { + *csay = csy; + csay++; + csy &= 0xffff; + csy += sy; + } + + dgap = dst->pitch - dst->w * 4; + + csay = say; + ly = 0; + for (y = 0; y < dst->h; y++) { + c00 = csp; + c01 = csp; + c01++; + c10 = csp; + c10 += src->pitch/4; + c11 = c10; + c11++; + + csax = sax; + lx = 0; + for (x = 0; x < dst->w; x++) { + ex = (*csax & 0xffff); + ey = (*csay & 0xffff); + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + + csax++; + if (*csax > 0) + { + sstep = (*csax >> 16); + lx += sstep; + if (lx <= src->w) + { + c00 += sstep; + c01 += sstep; + c10 += sstep; + c11 += sstep; + } + } + + dp++; + } + + csay++; + if (*csay > 0) + { + sstep = (*csay >> 16); + ly += sstep; + if (ly < src->h) + { + csp += (sstep * (src->pitch/4)); + } + } + + dp = (tColorRGBA *) ((Uint8 *) dp + dgap); + } + free(sax); + free(say); + + /* save png */ +#if 1 + img = (unsigned char *)stbi_write_png_to_mem(src->pixels, src->pitch, src->w, src->h, 4, &l); +#else + img = (unsigned char *)stbi_write_png_to_mem(dst->pixels, dst->pitch, dst->w, dst->h, 4, &l); +#endif + SDL_FreeSurface(dst); + if(img) { + sprintf(path, "%s_%02X.png",name,num); + if(verbose) + printf("mtsedit: %s\r\n", path); + f = fopen(path,"wb"); + if(f) { fwrite(img, l, 1, f); fclose(f); } + free(img); + return 1; + } + return 0; +} + +/** + * Mix two pixels + */ +void mixpixel(unsigned char *a, unsigned char *b, unsigned int i) +{ + unsigned int c[4]; + c[0] = b[0] * i / 255; if(c[0] > 255) c[0] = 255; + c[1] = b[1] * i / 255; if(c[1] > 255) c[1] = 255; + c[2] = b[2] * i / 255; if(c[2] > 255) c[2] = 255; + a[0] = (c[0]*b[3] + (256 - a[3])*a[0])>>8; + a[1] = (c[1]*b[3] + (256 - a[3])*a[1])>>8; + a[2] = (c[2]*b[3] + (256 - a[3])*a[2])>>8; + a[3] = (b[3]*b[3] + (256 - a[3])*a[3])>>8; +} + +/** + * Isometric blit + */ +void blitiso(unsigned char *from, int quadrant, unsigned char *to, int rotation, int x, int y) +{ + int i, j, ox, oy, sx, sy; + + x += 8; y += 4; + switch(quadrant) { + /* XX + * XX (full) */ + case 0: sx = sy = 32; ox = oy = 0; break; + /* X. + * .. */ + case 1: sx = sy = 16; ox = oy = 0; break; + /* .X + * .. */ + case 2: sx = sy = 16; ox = 16; oy = 0; break; + /* .. + * X. */ + case 3: sx = sy = 16; oy = 16; ox = 0; break; + /* .. + * .X */ + case 4: sx = sy = 16; ox = oy = 16; break; + /* .. + * __ (slabs) */ + case 5: sx = 32; sy = 8; ox = 0; oy = 24; break; + } + + switch(rotation) { + /* .N. + * XXN + * .X. */ + case 0: + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j-1)*4, from + (oy+j-i)*32*4 + (ox+i)*4, 383); + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j)*4, from + (oy+j-i)*32*4 + (ox+i)*4, 383); + } + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4+(x+2*sx-(2*i+sx-j)-1)*4, from + (oy+sy-j-1+i)*32*4+(ox+sx-i-1)*4, 383); + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4+(x+2*sx-(2*i+sx-j))*4, from + (oy+sy-j-1+i)*32*4+(ox+sx-i-1)*4, 383); + } + break; + /* .X. + * XXN + * .N. */ + case 1: + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j-1)*4, from + (oy+sy-i-1)*32*4 + (ox+j-i)*4, 383); + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j)*4, from + (oy+sy-i-1)*32*4 + (ox+j-i)*4, 383); + } + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j)-1)*4, from + (oy+i)*32*4 + (ox+sx-(j-i)-1)*4, 383); + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j))*4, from + (oy+i)*32*4 + (ox+sx-(j-i)-1)*4, 383); + } + break; + /* .X. + * NXX + * .N. */ + case 2: + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j-1)*4, from + (oy+sy-j+i-1)*32*4 + (ox+sx-i-1)*4, 383); + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j)*4, from + (oy+sy-j+i-1)*32*4 + (ox+sx-i-1)*4, 383); + } + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j)-1)*4, from + (oy+j-i)*32*4 + (ox+i)*4, 383); + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j))*4, from + (oy+j-i)*32*4 + (ox+i)*4, 383); + } + break; + /* .N. + * NXX + * .X. */ + case 3: + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j-1)*4, from + (oy+i)*32*4 + (ox+sx-(j-i)-1)*4, 383); + mixpixel(to + (y+j/2)*TMPSIZE*4 + (x+2*i+sx-j)*4, from + (oy+i)*32*4 + (ox+sx-(j-i)-1)*4, 383); + } + for(j = 0; j < sy; j++) + for(i = 0; i <= j; i++) { + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j)-1)*4, from + (oy+sy-i-1)*32*4 + (ox+j-i)*4, 383); + mixpixel(to + (y+sy-j/2-1)*TMPSIZE*4 + (x+2*sx-(2*i+sx-j))*4, from + (oy+sy-i-1)*32*4 + (ox+j-i)*4, 383); + } + break; + /* X. + * XX + * .X */ + case 4: + for(j = 0; j < sy*2; j++) + for(i = 0; i < sx; i++) + mixpixel(to + (y+j*5/8+i/2)*TMPSIZE*4 + (x+i)*4, from + (oy+j/2)*32*4 + (ox+i)*4, 255); + break; + /* .X + * XX + * X. */ + case 5: + for(j = 0; j < sy*2; j++) + for(i = 0; i < sx; i++) + mixpixel(to + (y+j*5/8+sy/2-i/2-1)*TMPSIZE*4 + (x+i)*4, from + (oy+j/2)*32*4 + (ox+i)*4, 128); + break; + /* XX + * XX */ + default: + for(j = 0; j < sy; j++) + for(i = 0; i < sx; i++) + mixpixel(to + (y+j)*TMPSIZE*4 + (x+i)*4, from + (oy+j)*32*4 + (ox+i)*4, 255); + break; + } +} + +/** + * Generate block, slab and stair pictures from textures + */ +int blockgen(char *blockid) +{ + stbi__context sc; + stbi__result_info ri; + FILE *f; + unsigned char *img, *raw, *top, *bottom, *north, *south, *west, *east, out[TMPSIZE * (TMPSIZE+16) * 4]; + unsigned int size, *tmp; + char *data, c, *s, *e, **paths = NULL, path[MAXPATHLEN]; + int w, h, l, r, p = 0, np = 0, i, j = 0, k = 0, o = 0, sl, ds, st; + SDL_Rect src, dst; + + fg = SDL_CreateRGBSurfaceFrom(NULL, 32, 32, 32, 32*4, 0xFF, 0xFF00, 0xFF0000, 0xFF000000); + src.x = src.y = dst.x = dst.y = 0; dst.w = dst.h = 32; + + f = fopen(mtsfile, "rb"); + if(f) { + fseek(f, 0L, SEEK_END); + size = (unsigned int)ftell(f); + fseek(f, 0L, SEEK_SET); + data = (char*)malloc(size + 1); + if(!data) error(lang[ERR_MEM]); + fread(data, size, 1, f); + data[size] = 0; + fclose(f); + } else { + fprintf(stderr, "mtsedit: %s: %s\r\n", lang[ERR_IMGCSV], mtsfile); + return 1; + } + + for(s = blockid; s && *s; s++) + if(*s == ' ' || *s == '\'') *s = '_'; + e = data; + while(*e) { + if(e == data || *e == '\r' || *e == '\n') { + while(*e == '\r' || *e == '\n') e++; + if(!*e) break; + /* get canonical name */ + if(*e == '\"') { e++; c = '\"'; } else c = ','; + for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++) + if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; } + while(*s <= ' ') s++; + while(*(e-1) <= ' ') e--; + j = numblocks++; + blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t)); + if(!blocks) error(lang[ERR_MEM]); + memset(&blocks[j], 0, sizeof(mtsblock_t)); + blocks[j].blocknames = (char**)malloc(16 * sizeof(char*)); + if(!blocks[j].blocknames) error(lang[ERR_MEM]); + memset(blocks[j].blocknames, 0, 16 * sizeof(char*)); + blocks[j].name = (char*)malloc((int)(e - s) + 1); + if(!blocks[j].name) error(lang[ERR_MEM]); + for(i = 0; i < (int)(e - s); i++) + blocks[j].name[i] = s[i] == ' ' || s[i] == '\'' ? '_' : s[i]; + while(i > 0 && (blocks[j].name[i-1] == '(' || blocks[j].name[i-1] == '_')) i--; + blocks[j].name[i] = 0; + /* get technical name, drawtype, paramtype2, node_box type */ + for(k = 0; k < 4; k++) { + while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++; + if(*e != ',' && *e != ';' && *e != '\t') errorimgcsv(j+1); + e++; + while(*e == ' ') e++; + if(*e == '\"') { e++; c = '\"'; } else c = ','; + for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++) + if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; } + while(*s <= ' ') s++; + while(*(e-1) <= ' ') e--; + blocks[j].blocknames[k] = (char*)malloc(e - s + 1); + if(!blocks[j].blocknames[k]) error(lang[ERR_MEM]); + memcpy(blocks[j].blocknames[k], s, e - s + 1); + blocks[j].blocknames[k][e - s] = 0; + } + /* get directory */ + while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++; + if(*e != ',' && *e != ';' && *e != '\t') errorimgcsv(j+1); + e++; + while(*e == ' ') e++; + if(*e == '\"') { e++; c = '\"'; } else c = ','; + for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++) + if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; } + while(*s <= ' ') s++; + while(*(e-1) <= ' ') e--; + memcpy(path, s, e - s + 1); + k = e - s; + if(path[k-1] != DIRSEP) { path[k++] = DIRSEP; path[k] = 0; } + strcpy(path + k, "textures"); k += 8; + path[k++] = DIRSEP; path[k] = 0; + for(k = 0, o = -1; k < np; k++) + if(!strcmp(paths[k], path)) { o = k; break; } + if(o == -1) { + paths = (char**)realloc(paths, (np + 1) * sizeof(char*)); + if(!paths) error(lang[ERR_MEM]); + paths[np] = (char*)malloc(strlen(path) + 1); + if(!paths[np]) error(lang[ERR_MEM]); + strcpy(paths[np], path); + np++; + } + while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++; + k = 0; o = 0; + } + /* read textures */ + while(*e == ' ') e++; + if(*e != ',' && *e != ';' && *e != '\t') errorimgcsv(j+1); + e++; + while(*e == ' ') e++; + if(!*e) errorimgcsv(j+1); + if(*e == '\"') { e++; c = '\"'; } else c = ','; + for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++) + if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; } + while(*s <= ' ') s++; + while(*(e-1) <= ' ') e--; + /* switch to overlay textures */ + if(s[0] == '|') { k = 10; continue; } + /* read in the texture filenames */ + if(e != s) { + for(i = 0; i < e - s && s[i] != '^'; i++); + blocks[j].blocknames[k + 4] = (char*)malloc(i + 1); + if(!blocks[j].blocknames[k + 4]) error(lang[ERR_MEM]); + memcpy(blocks[j].blocknames[k + 4], s, i); + blocks[j].blocknames[k + 4][i] = 0; + } + k++; if(k > 15) errorimgcsv(j+1); + while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++; + } + /* we have all possible paths, read in the textures */ + for(i = 0; i < j; i++) { + /* filter out what we can't or don't want to handle */ + if(blockid && strcasecmp(blockid, blocks[i].name)) continue; + s = strrchr(blocks[i].name, '_'); + if(s && (!strcmp(s, "_Slab") || !strcmp(s, "_Stair"))) continue; + if(!strcmp(blocks[i].blocknames[1], "nodebox") || !strcmp(blocks[i].blocknames[1], "mesh")) continue; + /* get tiles */ + for(k = 0; k < 6; k++) { + if(blocks[i].blocknames[k + 4] && blocks[i].blocknames[k + 4][0]) + for(l = 0; l < np && !blocks[i].img[k]; l++) { + strcpy(path, paths[l]); + strcat(path, blocks[i].blocknames[k + 4]); + f = fopen(path, "rb"); + if(f) { + if(verbose && blockid) printf("mtsedit: texture %s\n",path); + fseek(f, 0L, SEEK_END); + size = (unsigned int)ftell(f); + fseek(f, 0L, SEEK_SET); + img = (unsigned char*)malloc(size); + if(!img) error(lang[ERR_MEM]); + fread(img, size, 1, f); + fclose(f); + sc.read_from_callbacks = 0; + sc.img_buffer = sc.img_buffer_original = img; + sc.img_buffer_end = sc.img_buffer_original_end = img + size; + ri.bits_per_channel = 8; + raw = (unsigned char*)stbi__png_load(&sc, &w, &h, &r, 0, &ri); + if(raw) { + /* convert grayscale, alpha grayscale and RGB to RGBA */ + if(r != 4) { + tmp = (unsigned int *)malloc(w * h * 4); + if(!tmp) error(lang[ERR_MEM]); + for(l = 0; l < w * h; l++) + switch(r) { + case 1: tmp[l] = 0xFF000000 | (raw[l] << 16) | (raw[l] << 8) | (raw[l]); break; + case 2: tmp[l] = (raw[(l<<1)+1]<<24) | (raw[l<<1]<<16) | (raw[l<<1]<<8) | (raw[l<<1]); break; + case 3: tmp[l] = 0xFF000000 | (raw[l*3+2] << 16) | (raw[l*3+1] << 8) | (raw[l*3]); break; + } + free(raw); + raw = (unsigned char*)tmp; + } + /* rescale to 32x32 */ + fg->pixels = (unsigned char *)malloc(32 * 32 * 4); + if(!fg->pixels) error(lang[ERR_MEM]); + memset(fg->pixels, 0, 32 * 32 * 4); + blk = SDL_CreateRGBSurfaceFrom(raw, w, h, 32, w*4, 0xFF, 0xFF00, 0xFF0000, 0xFF000000); + src.w = w; src.h = h; + SDL_BlitScaled(blk, &src, fg, &dst); + SDL_FreeSurface(blk); + free(raw); + blocks[i].img[k] = (unsigned char *)fg->pixels; + blocks[i].numref++; + } + free(img); + } + } + /* get overlays */ + if(blocks[i].img[k] && blocks[i].blocknames[k + 10] && blocks[i].blocknames[k + 10][0]) + for(l = o = 0; l < np && !o; l++) { + strcpy(path, paths[l]); + strcat(path, blocks[i].blocknames[k + 10]); + f = fopen(path, "rb"); + if(f) { + fseek(f, 0L, SEEK_END); + size = (unsigned int)ftell(f); + fseek(f, 0L, SEEK_SET); + img = (unsigned char*)malloc(size); + if(!img) error(lang[ERR_MEM]); + fread(img, size, 1, f); + fclose(f); + sc.read_from_callbacks = 0; + sc.img_buffer = sc.img_buffer_original = img; + sc.img_buffer_end = sc.img_buffer_original_end = img + size; + ri.bits_per_channel = 8; + raw = (unsigned char*)stbi__png_load(&sc, &w, &h, &r, 0, &ri); + if(raw) { + /* convert grayscale, alpha grayscale and RGB to RGBA */ + if(r != 4) { + tmp = (unsigned int *)malloc(w * h * 4); + if(!tmp) error(lang[ERR_MEM]); + for(l = 0; l < w * h; l++) + switch(r) { + case 1: tmp[l] = 0xFF000000 | (raw[l] << 16) | (raw[l] << 8) | (raw[l]); break; + case 2: tmp[l] = (raw[(l<<1)+1]<<24) | (raw[l<<1]<<16) | (raw[l<<1]<<8) | (raw[l<<1]); break; + case 3: tmp[l] = 0xFF000000 | (raw[l*3+2] << 16) | (raw[l*3+1] << 8) | (raw[l*3]); break; + } + free(raw); + raw = (unsigned char*)tmp; + } + /* rescale to 32x32 */ + blk = SDL_CreateRGBSurfaceFrom(raw, w, h, 32, w*4, 0xFF, 0xFF00, 0xFF0000, 0xFF000000); + src.w = w; src.h = h; + /* blit overlay to original texture */ + SDL_BlitScaled(blk, &src, fg, &dst); + SDL_FreeSurface(blk); + free(raw); + o = 1; + } + free(img); + } + } + } + if(blocks[i].img[0]) p++; + } + SDL_FreeSurface(fg); + blk = SDL_CreateRGBSurfaceFrom(out, TMPSIZE, TMPSIZE, 32, TMPSIZE*4, 0xFF, 0xFF00, 0xFF0000, 0xFF000000); + /* ok, now we have all the textures loaded. The blocks array looks like this: + * name = canonical block id name (like "Acacia_Bark_Stair") + * blocknames[0] = block's technical name (like "mcl_core:bedrock") + * blocknames[1] = drawtype + * blocknames[2] = paramtype2 + * blocknames[3] = node_box type + * blocknames[4] - [9] = tile names (like "acacia.png^[transformR90") + * blocknames[10] - [15] = overlay tile names + * img[0] - img[5] = uncompressed tiles, scaled to 32x32 RGBA, overlay images applied + * numref = number of textures */ + for(i = k = o = 0; i < j; i++) { + if(!blocks[i].img[0]) continue; + if(!verbose) { + k++; + printf("%3d%% %s \r", k*100/p, blocks[i].name); + } + /* construct block images */ + memset(out, 0, sizeof(out)); + if(!strcmp(blocks[i].blocknames[1], "plantlike") || !strcmp(blocks[i].blocknames[1], "firelike")) { + blitiso(blocks[i].img[0], 0, out, 4, 16,8); + blitiso(blocks[i].img[0], 0, out, 5, 16,8); + o += savepng(blocks[i].name,0,blk); + } else + if(!strcmp(blocks[i].blocknames[1], "raillike")) { + blitiso(blocks[i].img[0], 0, out, 0, 0,40); + o += savepng(blocks[i].name,0,blk); + memset(out, 0, sizeof(out)); + blitiso(blocks[i].img[0], 0, out, 1, 0,40); + o += savepng(blocks[i].name,1,blk); + } else + if(!strcmp(blocks[i].blocknames[1], "normal") || !strcmp(blocks[i].blocknames[1], "glasslike")) { + /* get side textures */ + top = blocks[i].img[0]; + bottom = blocks[i].img[1] ? blocks[i].img[1] : blocks[i].img[0]; + west = blocks[i].img[2] ? blocks[i].img[2] : blocks[i].img[0]; + east = blocks[i].img[3] ? blocks[i].img[3] : west; + north = blocks[i].img[4] ? blocks[i].img[4] : west; + south = blocks[i].img[5] ? blocks[i].img[5] : west; + /* faces south */ + blitiso(bottom, 0, out, 0, 0,39); + blitiso(west, 0, out, 5, 0,0); + blitiso(north, 0, out, 4, 32,0); + blitiso(east, 0, out, 5, 32,16); + blitiso(south, 0, out, 4, 0,16); + blitiso(top, 0, out, 0, 0,0); + o += savepng(blocks[i].name,0,blk); + if(blocks[i].numref > 1) { + /* faces east */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 1, 0,39); + blitiso(south, 0, out, 5, 0,0); + blitiso(west, 0, out, 4, 32,0); + blitiso(north, 0, out, 5, 32,16); + blitiso(east, 0, out, 4, 0,16); + blitiso(top, 0, out, 1, 0,0); + o += savepng(blocks[i].name,1,blk); + /* faces north */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 2, 0,39); + blitiso(east, 0, out, 5, 0,0); + blitiso(south, 0, out, 4, 32,0); + blitiso(west, 0, out, 5, 32,16); + blitiso(north, 0, out, 4, 0,16); + blitiso(top, 0, out, 2, 0,0); + o += savepng(blocks[i].name,2,blk); + /* faces west */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 3, 0,39); + blitiso(north, 0, out, 5, 0,0); + blitiso(east, 0, out, 4, 32,0); + blitiso(south, 0, out, 5, 32,16); + blitiso(west, 0, out, 4, 0,16); + blitiso(top, 0, out, 3, 0,0); + o += savepng(blocks[i].name,3,blk); + } + /* check if we need togenerate slabs and stairs for this block */ + /* FIXME: this assumes no block ids are longer than 255 bytes, hopefully true */ + sprintf(path, "%s_Slab", blocks[i].name); + sprintf(path+256, "Double_%s_Slab", blocks[i].name); + sprintf(path+512, "%s_Stair", blocks[i].name); + for(sl = ds = st = l = 0; l < j; l++) { + if(!strcmp(blocks[l].name, path)) sl = 1; + if(!strcmp(blocks[l].name, path+256)) ds = 1; + if(!strcmp(blocks[l].name, path+512)) st = 1; + } + if(sl) { + /* slab */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 0, 0,39); + blitiso(west, 5, out, 5, 0,41); + blitiso(north, 5, out, 4, 32,30); + blitiso(east, 5, out, 5, 32,58); + blitiso(south, 5, out, 4, 0,46); + blitiso(top, 0, out, 0, 0,29); + o += savepng(path,0,blk); + } + if(ds) { + /* double slab */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 0, 0,39); + blitiso(west, 3, out, 5, 0,28); + blitiso(west, 4, out, 5, 16,20); + blitiso(north, 3, out, 4, 32,20); + blitiso(north, 4, out, 4, 48,28); + blitiso(east, 4, out, 5, 48,36); + blitiso(east, 3, out, 5, 32,44); + blitiso(south, 4, out, 4, 16,44); + blitiso(south, 3, out, 4, 0,36); + blitiso(top, 0, out, 0, 0,20); + o += savepng(path+256,0,blk); + } + if(st) { + /* stairs */ + memset(out, 0, sizeof(out)); + /* north */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 0, 0,39); + blitiso(west, 3, out, 5, 0,28); + blitiso(west, 4, out, 5, 16,20); + blitiso(north, 3, out, 4, 32,20); + blitiso(north, 4, out, 4, 48,28); + blitiso(east, 4, out, 5, 48,36); + blitiso(east, 3, out, 5, 32,44); + blitiso(south, 4, out, 4, 16,44); + blitiso(south, 3, out, 4, 0,36); + blitiso(top, 1, out, 0, 16,36); + blitiso(top, 2, out, 0, 0,28); + blitiso(west, 2, out, 5, 16,1); + blitiso(north, 1, out, 4, 32,1); + blitiso(north, 2, out, 4, 48,9); + blitiso(east, 2, out, 5, 48,17); + blitiso(south, 2, out, 4, 32,17); + blitiso(south, 1, out, 4, 16,9); + blitiso(top, 4, out, 0, 16,0); + blitiso(top, 3, out, 0, 32,8); + o += savepng(path+512,0,blk); + /* east */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 1, 0,39); + blitiso(south, 3, out, 5, 0,28); + blitiso(south, 4, out, 5, 16,20); + blitiso(west, 3, out, 4, 32,20); + blitiso(west, 4, out, 4, 48,28); + blitiso(north, 4, out, 5, 48,36); + blitiso(north, 3, out, 5, 32,44); + blitiso(east, 4, out, 4, 16,44); + blitiso(east, 3, out, 4, 0,36); + blitiso(top, 3, out, 1, 16,20); + blitiso(top, 4, out, 1, 0,28); + blitiso(south, 1, out, 5, 32,9); + blitiso(south, 2, out, 5, 16,17); + blitiso(west, 2, out, 4, 48,9); + blitiso(north, 2, out, 5, 48,18); + blitiso(north, 1, out, 5, 32,26); + blitiso(east, 2, out, 4, 16,26); + blitiso(top, 1, out, 1, 32,8); + blitiso(top, 2, out, 1, 16,16); + o += savepng(path+512,1,blk); + /* south */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 2, 0,39); + blitiso(east, 3, out, 5, 0,28); + blitiso(east, 4, out, 5, 16,20); + blitiso(south, 3, out, 4, 32,20); + blitiso(south, 4, out, 4, 48,28); + blitiso(west, 4, out, 5, 48,36); + blitiso(west, 3, out, 5, 32,44); + blitiso(north, 4, out, 4, 16,44); + blitiso(north, 3, out, 4, 0,36); + blitiso(top, 1, out, 2, 16,20); + blitiso(top, 2, out, 2, 32,28); + blitiso(east, 1, out, 5, 0,9); + blitiso(south, 1, out, 4, 16,9); + blitiso(south, 2, out, 4, 32,17); + blitiso(west, 1, out, 5, 32,25); + blitiso(north, 2, out, 4, 16,25); + blitiso(north, 1, out, 4, 0,17); + blitiso(top, 3, out, 2, 0,8); + blitiso(top, 4, out, 2, 16,16); + o += savepng(path+512,2,blk); + /* west */ + memset(out, 0, sizeof(out)); + blitiso(bottom, 0, out, 3, 0,39); + blitiso(north, 3, out, 5, 0,28); + blitiso(north, 4, out, 5, 16,20); + blitiso(east, 3, out, 4, 32,20); + blitiso(east, 4, out, 4, 48,28); + blitiso(south, 4, out, 5, 48,36); + blitiso(south, 3, out, 5, 32,44); + blitiso(west, 4, out, 4, 16,44); + blitiso(west, 3, out, 4, 0,36); + blitiso(top, 1, out, 3, 32,28); + blitiso(top, 2, out, 3, 16,36); + blitiso(north, 1, out, 5, 0,9); + blitiso(north, 2, out, 5, 16,1); + blitiso(east, 1, out, 4, 32,1); + blitiso(south, 2, out, 5, 32,9); + blitiso(south, 1, out, 5, 16,17); + blitiso(west, 1, out, 4, 0,17); + blitiso(top, 3, out, 3, 0,8); + blitiso(top, 4, out, 3, 16,0); + o += savepng(path+512,3,blk); + } + } + } + if(!verbose) + printf("mtsedit: %d PNGs, OK. \r\n", o); return 0; }