comparison mlk-map/mlk-map.c @ 435:556c8e2ff995

misc: move tools/* in /
author David Demelier <markand@malikania.fr>
date Sun, 16 Oct 2022 08:31:01 +0200
parents src/tools/map/mlk-map.c@38cf60f5a1c4
children 773a082f0b91
comparison
equal deleted inserted replaced
434:4e78f045e8c0 435:556c8e2ff995
1 /*
2 * main.c -- convert tiled tiled JSON files into custom files
3 *
4 * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20 #include <limits.h>
21 #include <stdarg.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <jansson.h>
28
29 #include <mlk/util/util.h>
30
31 static void
32 die(const char *fmt, ...)
33 {
34 assert(fmt);
35
36 va_list ap;
37
38 va_start(ap, fmt);
39 vfprintf(stderr, fmt, ap);
40 va_end(ap);
41 exit(1);
42 }
43
44 static bool
45 is_layer(const char *name)
46 {
47 return strcmp(name, "background") == 0 ||
48 strcmp(name, "foreground") == 0 ||
49 strcmp(name, "above") == 0 ||
50 strcmp(name, "actions") == 0;
51 }
52
53 static const json_t *
54 find_property(const json_t *props, const char *which)
55 {
56 const json_t *obj;
57 size_t index;
58
59 json_array_foreach(props, index, obj) {
60 if (!json_is_object(obj))
61 continue;
62
63 const json_t *key = json_object_get(obj, "name");
64 const json_t *value = json_object_get(obj, "value");
65
66 if (json_is_string(key) && value && strcmp(json_string_value(key), which) == 0)
67 return value;
68 }
69
70 return NULL;
71 }
72
73 static void
74 write_title(const json_t *props)
75 {
76 const json_t *prop_title = find_property(props, "title");
77
78 if (prop_title && json_is_string(prop_title))
79 printf("title|%s\n", json_string_value(prop_title));
80 }
81
82 static void
83 write_origin(const json_t *props)
84 {
85 const json_t *prop_origin_x = find_property(props, "origin-x");
86 const json_t *prop_origin_y = find_property(props, "origin-y");
87
88 if (!prop_origin_x || !json_is_integer(prop_origin_x) ||
89 !prop_origin_y || !json_is_integer(prop_origin_y))
90 return;
91
92 printf("origin|%d|%d\n",
93 (int)json_integer_value(prop_origin_x),
94 (int)json_integer_value(prop_origin_y));
95 }
96
97 static void
98 write_properties(const json_t *props)
99 {
100 write_title(props);
101 write_origin(props);
102 }
103
104 static void
105 write_dimensions(const json_t *document)
106 {
107 json_t *width = json_object_get(document, "width");
108 json_t *height = json_object_get(document, "height");
109
110 if (!width || !json_is_integer(width))
111 die("missing 'width' property\n");
112 if (!height || !json_is_integer(height))
113 die("missing 'height' property\n");
114
115 printf("columns|%d\n", (int)json_integer_value(width));
116 printf("rows|%d\n", (int)json_integer_value(height));
117 }
118
119 static void
120 write_object(const json_t *object)
121 {
122 assert(json_is_object(object));
123
124 json_t *x = json_object_get(object, "x");
125 json_t *y = json_object_get(object, "y");
126 json_t *width = json_object_get(object, "width");
127 json_t *height = json_object_get(object, "height");
128 json_t *props = json_object_get(object, "properties");
129 const json_t *exec, *block;
130
131 if (!x || !json_is_number(x))
132 die("invalid 'x' property in object\n");
133 if (!y || !json_is_number(y))
134 die("invalid 'y' property in object\n");
135 if (!width || !json_is_number(width))
136 die("invalid 'width' property in object\n");
137 if (!height || !json_is_number(height))
138 die("invalid 'height' property in object\n");
139
140 /* This is optional and set to 0 if not present. */
141 block = find_property(props, "block");
142
143 /* In tiled, those properties are float but we only use ints in MA */
144 printf("%d|%d|%d|%d|%d",
145 (int)json_integer_value(x),
146 (int)json_integer_value(y),
147 (int)json_integer_value(width),
148 (int)json_integer_value(height),
149 (int)json_is_true(block)
150 );
151
152 if ((exec = find_property(props, "exec")) && json_is_string(exec))
153 printf("|%s", json_string_value(exec));
154
155 printf("\n");
156 }
157
158 static void
159 write_layer(const json_t *layer)
160 {
161 json_t *objects = json_object_get(layer, "objects");
162 json_t *data = json_object_get(layer, "data");
163 json_t *name = json_object_get(layer, "name");
164 json_t *tile, *object;
165 size_t index;
166
167 if (!name || !json_is_string(name))
168 die("invalid 'name' property in layer");
169 if (!is_layer(json_string_value(name)))
170 die("invalid 'name' layer: %s\n", json_string_value(name));
171
172 printf("layer|%s\n", json_string_value(name));
173
174 /* Only foreground/background have 'data' property */
175 if (json_is_array(data)) {
176 json_array_foreach(data, index, tile) {
177 if (!json_is_integer(tile))
178 die("invalid 'data' property in layer\n");
179
180 printf("%d\n", (int)json_integer_value(tile));
181 }
182 }
183
184 /* Only objects has 'objects' property */
185 if (json_is_array(objects)) {
186 json_array_foreach(objects, index, object) {
187 if (!json_is_object(object))
188 die("invalid 'objects' property in layer\n");
189
190 write_object(object);
191 }
192 }
193 }
194
195 static void
196 write_layers(const json_t *layers)
197 {
198 size_t index;
199 json_t *layer;
200
201 if (!layers)
202 return;
203
204 json_array_foreach(layers, index, layer) {
205 if (!json_is_object(layer))
206 die("layer is not an object\n");
207
208 write_layer(layer);
209 }
210 }
211
212 static void
213 write_tileset(const json_t *tilesets)
214 {
215 char path[PATH_MAX];
216 char filename[FILENAME_MAX] = {0}, *ext;
217 const json_t *tileset, *source;
218
219 if (json_array_size(tilesets) != 1)
220 die("map must contain exactly one tileset");
221
222 tileset = json_array_get(tilesets, 0);
223 source = json_object_get(tileset, "source");
224
225 if (!json_is_string(source))
226 die("invalid 'source' property in tileset\n");
227
228 /* We need to replace the .json extension to .tileset. */
229 snprintf(path, sizeof (path), "%s", json_string_value(source));
230 snprintf(filename, sizeof (filename), "%s", util_basename(path));
231
232 if (!(ext = strstr(filename, ".json")))
233 die("could not determine tileset extension");
234
235 *ext = '\0';
236
237 printf("tileset|%s.tileset\n", filename);
238 }
239
240 int
241 main(void)
242 {
243 json_t *document;
244 json_error_t error;
245
246 document = json_loadf(stdin, 0, &error);
247
248 if (!document)
249 die("%d:%d: %s\n", error.line, error.column, error.text);
250
251 write_properties(json_object_get(document, "properties"));
252 write_dimensions(document);
253 write_layers(json_object_get(document, "layers"));
254 write_tileset(json_object_get(document, "tilesets"));
255
256 json_decref(document);
257 }