Read back blueprint images
@ -8,7 +8,7 @@ See also the [GUI usage](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/usag
|
||||
```
|
||||
MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
|
||||
|
||||
./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b] [-m map] <.mts|.schematic> [out.mts]
|
||||
./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B] [-m map] <.mts|.schematic> [out.mts]
|
||||
./mtsedit -g <block.png>
|
||||
./mtsedit -t <blockimgs.csv> [blockid]
|
||||
./mtsedit -i [Minetest mods dir]
|
||||
@ -18,7 +18,7 @@ MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
|
||||
-d: dump layers to output
|
||||
-p: save preview
|
||||
-P: save preview, cut structure in half
|
||||
-b: save blueprint
|
||||
-b, -B: save blueprint
|
||||
-m map: replace block type mapping
|
||||
-g: generate slab and stairs from block image
|
||||
-t: generate block images from texture data
|
||||
@ -38,15 +38,17 @@ This will print out mapping and each block as hex values layer by layer.
|
||||
./mtsedit -d structure.mts
|
||||
```
|
||||
|
||||
### Generate blueprint
|
||||
### Generate Blueprint
|
||||
|
||||
Pretty much the same as dump, but instead of dumping the MTS to the console, it saves "structure_bp.png".
|
||||
```
|
||||
./mtsedit -b structure.mts
|
||||
```
|
||||
Each layer will be padded by 1 x 1 pixels of transparency. On the left, there's a black pixel after each layer so
|
||||
Each layer will be padded by 1 x 1 pixels of transparency. On the left, there's a black pixel at each layer start so
|
||||
that programs can detect the dimensions from the image. On the right, there's a red line for the ground layer.
|
||||
|
||||
The `-b` flag will also save a blue background and block legend on the image. `-B` only saves the raw blueprint.
|
||||
|
||||
### Conversion (or Remap)
|
||||
|
||||
You can convert Minecraft NBT Schematics with this tool.
|
||||
|
23
docs/import.md
Normal file
@ -0,0 +1,23 @@
|
||||
Import File Formats
|
||||
===================
|
||||
|
||||
This document describes the format that MTSEdit can import schematics from. For the native format, that can be written too, see
|
||||
the [MTS format](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/mts_format.md).
|
||||
|
||||
Schematic
|
||||
---------
|
||||
|
||||
These are [Minecraft NBT](https://minecraft.gamepedia.com/Schematic_file_format) files, used by many Minecraft-compatible
|
||||
editors. Only the [blocks](https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening/Block_IDs) section is parsed,
|
||||
and only used to import schematics. MTSEdit does not save .schematic files.
|
||||
|
||||
Limitations: rotation info are not imported properly, but works for basic nodes most of the time.
|
||||
|
||||
Blueprint PNG
|
||||
-------------
|
||||
|
||||
MTSEdit is capable to save schematic blueprints to PNG files using the `-b` or `-B` flags. These can be imported too.
|
||||
If blueprint is not detected on the image, then the entire image is read as a one layer blueprint finding the blocks that
|
||||
are closest match in color to each pixel.
|
||||
|
||||
Limitations: rotation info is not stored in blueprint images at all.
|
@ -1,12 +1,8 @@
|
||||
File Formats
|
||||
============
|
||||
MTS File Format
|
||||
===============
|
||||
|
||||
Schematic
|
||||
---------
|
||||
|
||||
These are [Minecraft NBT](https://minecraft.gamepedia.com/Schematic_file_format) files, used by many Minecraft-compatible
|
||||
editors. Only the [blocks](https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening/Block_IDs) section is parsed,
|
||||
and only used to import schematics. MTSEdit does not save .schematic files.
|
||||
This document describes the MTS format native to MTSEdit and the Minetest Engine. For other formats that are supported
|
||||
by MTSEdit to import schematics, see [import formats](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/import.md).
|
||||
|
||||
MTS
|
||||
---
|
||||
|
@ -117,6 +117,7 @@ Main editor window:
|
||||
| <kbd>P</kbd> | save preview PNG |
|
||||
| <kbd>Shift</kbd> + <kbd>P</kbd> | save preview with structure cut in half |
|
||||
| <kbd>E</kbd> | export blueprint PNG |
|
||||
| <kbd>Shift</kbd> + <kbd>E</kbd> | export plain blueprint without legend |
|
||||
| <kbd>R</kbd> | change orientation, rotate entire structure CCW |
|
||||
| <kbd>Shift</kbd> + <kbd>R</kbd> | change orientation, rotate entire structure CW |
|
||||
| <kbd>F</kbd> | flip the entire structure along the Z axis |
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 64 KiB |
@ -41,7 +41,7 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall -Wextra -ansi -pedantic -D_$(PACKAGE)_=1
|
||||
CFLAGS += -Wall -Wextra -ansi -pedantic -D_$(PACKAGE)_=1 -g
|
||||
|
||||
all: configure data.h $(OBJS) $(TARGET)
|
||||
|
||||
|
14
src/blocks.c
@ -244,6 +244,7 @@ void blocks_parse()
|
||||
sc.img_buffer_end = sc.img_buffer_original_end = img + size;
|
||||
ri.bits_per_channel = 8;
|
||||
blocks[j].img = (unsigned char*)stbi__png_load(&sc, &w, &h, &r, 0, &ri);
|
||||
free(img);
|
||||
if(blocks[j].img) {
|
||||
blocks[j].numpar2 = (h >> 5) & PARAM2_MAX;
|
||||
if(r != 4) {
|
||||
@ -275,8 +276,16 @@ void blocks_parse()
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if(n) blocks[j].color = 0xFF000000 | (((b/n) & 0xFF) << 16) | (((g/n) & 0xFF) << 8) | ((r/n) & 0xFF);
|
||||
else blocks[j].color = 0xFFFF0000;
|
||||
if(n) {
|
||||
blocks[j].color = 0xFF000000 | (((b/n) & 0xFF) << 16) | (((g/n) & 0xFF) << 8) | ((r/n) & 0xFF);
|
||||
while(!is_color_unique(blocks[j].color)) {
|
||||
img = (unsigned char*)&blocks[j].color;
|
||||
if(img[1] < 255) img[1]++; /* increase green channel first if we can */
|
||||
else if(img[0] < 255) img[0]++;
|
||||
else if(img[2] < 255) img[2]++;
|
||||
else img[3]--; /* for full white, decrease opacity as last resort */
|
||||
}
|
||||
} else blocks[j].color = 0xFFFF0000;
|
||||
l++;
|
||||
if(!dx || !dz || (!memcmp(s, "Cobblestone", 11) && s[11] != '_' && s[11] != ' ')) {
|
||||
detcube(32, 32, blocks[j].img);
|
||||
@ -284,7 +293,6 @@ void blocks_parse()
|
||||
dz = _y1 - _y0;
|
||||
}
|
||||
}
|
||||
free(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,11 +173,11 @@ int main(int argc, char** argv, char** envp)
|
||||
|
||||
if(argc < 2) {
|
||||
usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
|
||||
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b] [-m map] <.mts|.schematic> [out.mts]\r\n"
|
||||
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B] [-m map] <.mts|.schematic> [out.mts]\r\n"
|
||||
"./mtsedit -g <block.png>\r\n"
|
||||
"./mtsedit -t <blockimgs.csv> [blockid]\r\n"
|
||||
"./mtsedit -i [Minetest mods dir]\r\n"
|
||||
"\r\n -v: %s\r\n -l lang: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -b: %s\r\n -m map: %s\r\n -g: %s\r\n"
|
||||
"\r\n -v: %s\r\n -l lang: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -b, -B: %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",
|
||||
lang[INF_VERB], lang[INF_LANG], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_BPRINT], lang[INF_MAP],
|
||||
lang[INF_GEN], lang[INF_BLK], lang[INF_MOD], lang[INF_OUT]);
|
||||
@ -192,6 +192,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
|
||||
case 'p': opt = 2; break;
|
||||
case 'P': opt = 3; break;
|
||||
case 'b': opt = 4; break;
|
||||
case 'B': opt = 4; shift = 1; break;
|
||||
case 'g': opt = 5; break;
|
||||
case 't': opt = 6; break;
|
||||
case 'i': opt = 7; break;
|
||||
@ -246,10 +247,10 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
|
||||
case 1: ret = mts_dump(); break;
|
||||
case 2:
|
||||
case 3: ret = mts_view(opt-2); break;
|
||||
case 4: ret = mts_blueprint(); break;
|
||||
case 5: ret = stairgen(); break;
|
||||
case 6: ret = blockgen(argv[i+1]); break;
|
||||
case 7: /* handle this in sdl.c, because extern does not know sizeof() */
|
||||
case 4: /* handle these in sdl.c, because extern does not know sizeof() */
|
||||
case 7:
|
||||
case 0:
|
||||
/* start the main user interface */
|
||||
ret = sdlmain(opt);
|
||||
|
@ -55,6 +55,8 @@
|
||||
#define THEME_TABBG 8
|
||||
#define THEME_SAVEACT 9
|
||||
#define THEME_SAVEINACT 10
|
||||
#define THEME_BP_FG 11
|
||||
#define THEME_BP_BG 12
|
||||
|
||||
#define HIST_EMPTY 0
|
||||
#define HIST_NODE 1
|
||||
@ -193,20 +195,23 @@ void detcube(int w, int h, unsigned char *block);
|
||||
int instmod(unsigned char *data, int size);
|
||||
int stairgen();
|
||||
int blockgen(char *blockid);
|
||||
int is_color_unique(uint32_t color);
|
||||
int color2blockid(uint32_t color);
|
||||
|
||||
/* blocks.c */
|
||||
void blocks_getdir(char **argv, char **envp);
|
||||
void blocks_parse();
|
||||
void blocks_free();
|
||||
|
||||
/* schem.c */
|
||||
/* schemimp.c */
|
||||
void schem_load(unsigned char *data, unsigned int size);
|
||||
void bprint_load(unsigned char *data, unsigned int size);
|
||||
|
||||
/* mts.c */
|
||||
void mts_load(unsigned char *data, unsigned int size);
|
||||
int mts_save();
|
||||
int mts_view(int type);
|
||||
int mts_blueprint();
|
||||
int mts_blueprint(int type);
|
||||
int mts_dump();
|
||||
int mts_getbounds(int sanitize, unsigned short *tr, unsigned short *tr2);
|
||||
void mts_layerprob(int diff);
|
||||
|
80
src/mts.c
@ -173,7 +173,7 @@ void mts_load(unsigned char *data, unsigned int size)
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(x = 0; x < mts_x; x++)
|
||||
if(nodes[y+min_y][z+min_z][x+min_x].param2 == 0x20) {
|
||||
gndlayer = currlayer = y+min_y;
|
||||
gndlayer = y+min_y;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param2 = 0;
|
||||
}
|
||||
status = lang[LOADED];
|
||||
@ -414,13 +414,14 @@ int mts_view(int type)
|
||||
/**
|
||||
* Export a PNG blueprint file
|
||||
*/
|
||||
int mts_blueprint()
|
||||
int mts_blueprint(int type)
|
||||
{
|
||||
int i, w, h, x, y, z;
|
||||
char pngfile[MAXPATHLEN], *c;
|
||||
int oldsmax = strmaxw, i, j, k, l, bw, w, h, x, y, z;
|
||||
char pngfile[MAXPATHLEN], *s, *e, *c;
|
||||
unsigned char *buff = NULL;
|
||||
uint32_t *dst;
|
||||
SDL_Surface *bprint;
|
||||
SDL_Surface *oldscr = screen;
|
||||
SDL_Rect rect;
|
||||
FILE *f;
|
||||
|
||||
status = lang[ERR_PREVIEW];
|
||||
@ -428,35 +429,72 @@ int mts_blueprint()
|
||||
if(mix > max) return 1;
|
||||
bound_valid = 0;
|
||||
|
||||
/* calculate dimensions and create images */
|
||||
w = maz - miz + 3;
|
||||
h = (may - miy + 1) * (max - mix + 2) + 3;
|
||||
bprint = SDL_CreateRGBSurface(0, w, h, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
|
||||
memset(bprint->pixels, 0, w * h * 4);
|
||||
dst = (uint32_t*)bprint->pixels;
|
||||
strcpy(pngfile, mtsfile);
|
||||
s = strrchr(pngfile, DIRSEP);
|
||||
if(!s) s = pngfile; else s++;
|
||||
e = strrchr(pngfile, '.');
|
||||
if(!e) e = &pngfile[strlen(pngfile)];
|
||||
|
||||
/* calculate dimensions and create image */
|
||||
bw = maz - miz;
|
||||
h = (may - miy + 1) * (max - mix + 2) + 3;
|
||||
if(!type) {
|
||||
for(i = 1, j = l = 0; i < numblocks; i++)
|
||||
if(blocks[i].numref) {
|
||||
l += font->height;
|
||||
k = mbstrlen(blocks[i].name);
|
||||
if(k > j) j = k;
|
||||
}
|
||||
w = bw + 8 + (4 + j) * (font->width + 1);
|
||||
if(l > h) h = l;
|
||||
h += font->height + 5;
|
||||
} else
|
||||
w = bw + 3;
|
||||
screen = SDL_CreateRGBSurface(0, w, h, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
|
||||
memset(screen->pixels, 0, w * h * 4);
|
||||
dst = (uint32_t*)screen->pixels;
|
||||
if(!type) {
|
||||
for(i = 0; i < w * h; i++) dst[i] = theme[THEME_BP_BG];
|
||||
|
||||
/* print title */
|
||||
for(c = s; c < e; c++)
|
||||
if(*c == '_') *c = ' ';
|
||||
*e = 0; strmaxw = screen->w - 1;
|
||||
i = mbstrlen(s) * (font->width+1);
|
||||
sdlprint((screen->w - (i < screen->w ? i : screen->w)) / 2, 0, THEME_BP_FG, THEME_BP_BG, s);
|
||||
|
||||
/* print legend */
|
||||
rect.x = bw + font->height; rect.y = font->height + 4; rect.w = rect.h = font->height - 2;
|
||||
for(i = 1; i < numblocks; i++)
|
||||
if(blocks[i].numref) {
|
||||
SDL_FillRect(screen, &rect, blocks[i].color);
|
||||
sdlprint(rect.x + 4 + font->height, rect.y, THEME_BP_FG, THEME_BP_BG, blocks[i].name);
|
||||
rect.y += font->height;
|
||||
}
|
||||
i = w * (font->height + 5);
|
||||
} else
|
||||
i = w;
|
||||
/* generate blueprint into surface */
|
||||
for(i = w, y = may; y >= miy; y--, i += w) {
|
||||
for(y = may; y >= miy; y--, i += w) {
|
||||
dst[i] = (y == gndlayer ? 0xFF0000FF : 0xFF000000);
|
||||
for(x = mix; x <= max; x++) {
|
||||
i++;
|
||||
for(z = maz; z >= miz; z--, i++)
|
||||
if(nodes[y][z][x].param0)
|
||||
dst[i] = blocks[nodes[y][z][x].param0].color;
|
||||
dst[i] = (nodes[y][z][x].param0 ? blocks[nodes[y][z][x].param0].color : 0);
|
||||
if(y == gndlayer)
|
||||
dst[i] = 0xFF0000FF;
|
||||
i++;
|
||||
i += w - bw - 2;
|
||||
}
|
||||
dst[i] = y == gndlayer ? 0xFF0000FF : 0xFF000000;
|
||||
}
|
||||
|
||||
/* write result to PNG file */
|
||||
buff = (unsigned char *)stbi_write_png_to_mem(bprint->pixels, bprint->pitch, bprint->w, bprint->h, 4, &i);
|
||||
SDL_FreeSurface(bprint);
|
||||
buff = (unsigned char *)stbi_write_png_to_mem(screen->pixels, screen->pitch, screen->w, screen->h, 4, &i);
|
||||
SDL_FreeSurface(screen);
|
||||
screen = oldscr;
|
||||
strmaxw = oldsmax;
|
||||
if(buff) {
|
||||
strcpy(pngfile, mtsfile);
|
||||
c = strrchr(pngfile, '.');
|
||||
if(!c) c = &pngfile[strlen(pngfile)];
|
||||
strcpy(c, "_bp.png");
|
||||
strcpy(e, "_bp.png");
|
||||
f = fopen(pngfile,"wb");
|
||||
if(f) {
|
||||
fwrite(buff, i, 1, f);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* mtsedit/schem.c
|
||||
* mtsedit/schemimp.c
|
||||
*
|
||||
* Copyright (C) 2019 bzt (bztsrc@gitlab)
|
||||
*
|
||||
@ -23,26 +23,24 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @brief Import a Minecraft NBT .schematic file
|
||||
* @brief Import various non-MTS formats
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* parse an integer, the only type we are interested */
|
||||
#define SCHEM_GETINT(v,t) do{switch(t){case 1:v=d[0];d++;break;case 2:v=(d[0]<<8)|d[1];d+=2;break; \
|
||||
case 3:v=(d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];d+=4;break;}}while(0)
|
||||
|
||||
/**
|
||||
* Load a Minecraft NBT Schematic file
|
||||
*/
|
||||
/* parse an integer, the only dynamic type we are interested in. */
|
||||
#define SCHEM_GETINT(v,t) do{switch(t){case 1:v=d[0];d++;break;case 2:v=(d[0]<<8)|d[1];d+=2;break; \
|
||||
case 3:v=(d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];d+=4;break;}}while(0)
|
||||
void schem_load(unsigned char *data, unsigned int size)
|
||||
{
|
||||
int i, j, k, x, y, z, min_x = 0, min_y = 0, min_z = 0;
|
||||
unsigned char *d, *blk, *blkd = NULL, *end = data + size;
|
||||
|
||||
/* we don't care about that overcomplicated NBT mess */
|
||||
mts_y = mts_z = mts_x = 0;
|
||||
for(d = data; d < end && (!mts_y || !mts_z || !mts_x); d++) {
|
||||
if(!memcmp(d, "\000\006Height", 8)) { d += 8; SCHEM_GETINT(mts_y, d[-9]); d--; } else
|
||||
if(!memcmp(d, "\000\006Length", 8)) { d += 8; SCHEM_GETINT(mts_z, d[-9]); d--; } else
|
||||
@ -54,6 +52,7 @@ void schem_load(unsigned char *data, unsigned int size)
|
||||
min_x = 127 - mts_x / 2;
|
||||
min_y = 127 - mts_y / 2;
|
||||
min_z = 127 - mts_z / 2;
|
||||
gndlayer = min_y;
|
||||
/* now that we know the dimensions, find the blocks data */
|
||||
for(d = data; d < end; d++) {
|
||||
/* it must be type of byte array */
|
||||
@ -70,6 +69,7 @@ void schem_load(unsigned char *data, unsigned int size)
|
||||
for(j = 0; j < 4; j++)
|
||||
if(blocks[i].blockids[j] == *d) { k = i; i = numblocks; break; }
|
||||
if(k) {
|
||||
layerprob[y+min_y] = 127;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param0 = k;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
|
||||
if(blkd)
|
||||
@ -83,3 +83,62 @@ void schem_load(unsigned char *data, unsigned int size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a blueprint from a PNG file (or voxelize any other PNG image)
|
||||
*/
|
||||
void bprint_load(unsigned char *data, unsigned int size)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__result_info ri;
|
||||
int w = 0, h = 0, xs = 1, ys = 0, yg = 0, min_x = 0, min_y = 0, min_z = 0, len, x, y, z;
|
||||
uint32_t *d;
|
||||
|
||||
mts_y = mts_z = mts_x = gndlayer = 0;
|
||||
s.read_from_callbacks = 0;
|
||||
s.img_buffer = s.img_buffer_original = data;
|
||||
s.img_buffer_end = s.img_buffer_original_end = data + size;
|
||||
ri.bits_per_channel = 8;
|
||||
d = (uint32_t*)stbi__png_load(&s, &w, &h, &len, 0, &ri);
|
||||
if(!d || len != 4) return;
|
||||
|
||||
/* detect dimensions */
|
||||
for(y = 0; y < h; y++) {
|
||||
if(d[y*w] == 0xFF000000 || d[y*w] == 0xFF0000FF) {
|
||||
if(!mts_y) {
|
||||
ys = y;
|
||||
for(mts_z = 1; mts_z + 1 < w - 1 && d[y*w+mts_z+1] != theme[THEME_BP_BG]; mts_z++);
|
||||
} else if(mts_y == 1) mts_x = y - ys - 1;
|
||||
if(d[y*w] == 0xFF0000FF) yg = mts_y;
|
||||
mts_y++;
|
||||
}
|
||||
}
|
||||
if(!mts_x) mts_x = h - ys - 2;
|
||||
if(!mts_y) { ys = yg = xs = 0; mts_y = 1; mts_z = w; mts_x = h; }
|
||||
if(mts_x < 1 || mts_y < 1 || mts_z < 1) {
|
||||
mts_y = mts_z = mts_x = 0;
|
||||
return;
|
||||
}
|
||||
if(mts_y > 255) mts_y = 255;
|
||||
if(mts_z > 255) mts_z = 255;
|
||||
if(mts_x > 255) mts_x = 255;
|
||||
blocks[0].numref -= mts_y * mts_z * mts_x;
|
||||
min_x = 127 - mts_x / 2;
|
||||
min_y = 127 + mts_y / 2;
|
||||
min_z = 127 - mts_z / 2;
|
||||
gndlayer = min_y - yg;
|
||||
|
||||
/* read in the layers */
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x && (y*(mts_x+1)+ys+x) < h; x++)
|
||||
for(z = 0; z < mts_z; z++) {
|
||||
nodes[min_y-y][mts_z+min_z-z][x+min_x].param0 = color2blockid(d[(y*(mts_x+1)+ys+x)*w + z + xs]);
|
||||
if(nodes[min_y-y][mts_z+min_z-z][x+min_x].param0) {
|
||||
layerprob[min_y-y] = 127;
|
||||
nodes[min_y-y][mts_z+min_z-z][x+min_x].param1 = 127;
|
||||
blocks[nodes[min_y-z][mts_z+min_z-z][x+min_x].param0].numref++;
|
||||
blocks[0].numref--;
|
||||
}
|
||||
}
|
||||
status = lang[LOADED];
|
||||
}
|
@ -31,7 +31,7 @@
|
||||
#include "data.h"
|
||||
|
||||
uint32_t theme[] = { 0xFFF0F0F0, 0xFFF4F4F4, 0xFFBEBEBE, 0xFF808080, 0xFF5C5C5C, 0xFF4C4C4C, 0xFF454545, 0xFF383838, 0xFF303030,
|
||||
0xFFC00000, 0xFF800000 };
|
||||
0xFFC00000, 0xFF800000, 0xFF7F7F7F, 0xFF3F0000 };
|
||||
|
||||
int quitting = 0, activetool = -1, overtool = -1, activeblock = 0, overblock = -1, palette[16], strmaxw, strsepar = 1;
|
||||
int shift = 0, ctrl = 0, help = 0, systemcursor = 0;
|
||||
@ -325,7 +325,7 @@ void sdldo(int opt)
|
||||
case 9: hist_prepare(HIST_DELZ, cz); mts_delz(cz); hist_commit(); break;
|
||||
case 10: hist_prepare(HIST_ADDX, cx); mts_addx(cx, shift); hist_commit(); break;
|
||||
case 11: hist_prepare(HIST_DELX, cx); mts_delx(cx); hist_commit(); break;
|
||||
case 12: mts_blueprint(); break;
|
||||
case 12: mts_blueprint(shift); break;
|
||||
}
|
||||
SDL_SetCursor(pointer);
|
||||
SDL_ShowCursor(0); systemcursor = 0;
|
||||
@ -345,13 +345,16 @@ int sdlmain(int opt)
|
||||
SDL_Event event, lookahead;
|
||||
|
||||
/* this is tricky, because extern wouldn't know sizeof() */
|
||||
if(opt) return instmod(binary_mtsedit, sizeof(binary_mtsedit));
|
||||
if(opt == 7) return instmod(binary_mtsedit, sizeof(binary_mtsedit));
|
||||
|
||||
/* get our font */
|
||||
font = (psf_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)binary_font_psf_gz + 10,
|
||||
sizeof(binary_font_psf_gz) - 10, 32768, &len, 0);
|
||||
if(!font) error(lang[ERR_MEM]);
|
||||
|
||||
/* as an additional dependency, blueprint needs the font */
|
||||
if(opt) return mts_blueprint(shift);
|
||||
|
||||
/* initialize SDL */
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
fn = strrchr(mtsfile, DIRSEP);
|
||||
|
45
src/util.c
@ -81,7 +81,7 @@ void readschem()
|
||||
if(isdir(mtsfile)) return;
|
||||
|
||||
bound_valid = 0;
|
||||
mts_x = mts_y = mts_z = 0; currlayer = 127;
|
||||
mts_x = mts_y = mts_z = 0;
|
||||
memset(layerprob, 127, sizeof(layerprob));
|
||||
memset(nodes, 0, sizeof(nodes));
|
||||
for(x = 0; x < numblocks; x++) {
|
||||
@ -90,7 +90,7 @@ void readschem()
|
||||
}
|
||||
blocks[0].numref = 256 * 256 * 256;
|
||||
savepal = savemapgen = savebiome = 0;
|
||||
currlayer = cx = cz = 127;
|
||||
currlayer = gndlayer = cx = cz = 127;
|
||||
|
||||
status = lang[ERR_LOAD];
|
||||
f = fopen(mtsfile, "rb");
|
||||
@ -121,7 +121,9 @@ void readschem()
|
||||
/* if it's an MTS file */
|
||||
if(!memcmp(data, "MTSM", 4)) mts_load(data, size); else
|
||||
/* Could be a Minecraft NBT */
|
||||
if(!memcmp(data + 3, "Schematic", 9)) schem_load(data, size);
|
||||
if(!memcmp(data + 3, "Schematic", 9)) schem_load(data, size); else
|
||||
/* Blueprint PNG */
|
||||
if(!memcmp(data, "\x89PNG", 4)) bprint_load(data, size);
|
||||
|
||||
/* make sure that all non-air blocks have their probability set */
|
||||
for(y = 0; y < 256; y++)
|
||||
@ -131,6 +133,7 @@ void readschem()
|
||||
if(!(nodes[y][z][x].param1 & 0x7F)) nodes[y][z][x].param1 |= 127;
|
||||
nodes[y][z][x].param2 &= PARAM2_MAX;
|
||||
}
|
||||
currlayer = gndlayer;
|
||||
}
|
||||
if(data) free(data);
|
||||
}
|
||||
@ -1254,3 +1257,39 @@ int blockgen(char *blockid)
|
||||
printf("mtsedit: %d PNGs, OK. \r\n", o);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if color is not used by any blocks
|
||||
*/
|
||||
int is_color_unique(uint32_t color)
|
||||
{
|
||||
int i;
|
||||
if(color == 0xFF000000 || color == 0xFFFF0000 || color == theme[THEME_BP_BG]) return 0;
|
||||
for(i = 1; i < numblocks - 1; i++)
|
||||
if(blocks[i].color == color) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns block id for the closest color match
|
||||
*/
|
||||
int color2blockid(uint32_t color)
|
||||
{
|
||||
unsigned char *c = (unsigned char*)&color, *d;
|
||||
int i, j, k, ld, diff = 255;
|
||||
|
||||
/* unknown and air blocks */
|
||||
if(color == 0xFFFF0000 || color == theme[THEME_BP_BG] || c[3] < 128 || (!c[0] && !c[1] && !c[2])) return 0;
|
||||
|
||||
for(i = 1, j = 0; i < numblocks; i++) {
|
||||
/* get local maximum */
|
||||
ld = 0; d = (unsigned char*)&blocks[i].color;
|
||||
k = d[0] > c[0] ? d[0] - c[0] : c[0] - d[0]; if(k > ld) ld = k;
|
||||
k = d[1] > c[1] ? d[1] - c[1] : c[1] - d[1]; if(k > ld) ld = k;
|
||||
k = d[2] > c[2] ? d[2] - c[2] : c[2] - d[2]; if(k > ld) ld = k;
|
||||
k = d[3] > c[3] ? d[3] - c[3] : c[3] - d[3]; if(k > ld) ld = k;
|
||||
/* is it smaller than global minimum? */
|
||||
if(ld < diff) { diff = ld; j = i; }
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|