Mercurial > molko
comparison tools/map/map.c @ 116:0a6683615c73
cmake: change build system, continue #2487 @3h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 03 Oct 2020 18:32:01 +0200 |
parents | tools/molko-map.c@d4a72fa16225 |
children | 70e6ed74940d |
comparison
equal
deleted
inserted
replaced
115:3bd0d3a39e30 | 116:0a6683615c73 |
---|---|
1 /* | |
2 * molko-map.c -- convert tiled tiled JSON files into custom files | |
3 * | |
4 * Copyright (c) 2020 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 <stdarg.h> | |
21 #include <stdbool.h> | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <stdnoreturn.h> | |
25 #include <string.h> | |
26 | |
27 #include <jansson.h> | |
28 | |
29 static void | |
30 die(const char *fmt, ...) | |
31 { | |
32 assert(fmt); | |
33 | |
34 va_list ap; | |
35 | |
36 va_start(ap, fmt); | |
37 vfprintf(stderr, fmt, ap); | |
38 va_end(ap); | |
39 exit(1); | |
40 } | |
41 | |
42 static bool | |
43 is_layer(const char *name) | |
44 { | |
45 return strcmp(name, "background") == 0 || | |
46 strcmp(name, "foreground") == 0 || | |
47 strcmp(name, "objects") == 0; | |
48 } | |
49 | |
50 static const json_t * | |
51 find_property(const json_t *props, const char *which) | |
52 { | |
53 json_t *value; | |
54 size_t index; | |
55 | |
56 json_array_foreach(props, index, value) { | |
57 if (!json_is_object(value)) | |
58 continue; | |
59 | |
60 const json_t *key = json_object_get(value, "name"); | |
61 | |
62 if (json_is_string(key) && strcmp(json_string_value(key), which) == 0) | |
63 return value; | |
64 } | |
65 | |
66 return NULL; | |
67 } | |
68 | |
69 static void | |
70 write_title(const json_t *props) | |
71 { | |
72 const json_t *prop_title = find_property(props, "title"); | |
73 | |
74 if (!prop_title) | |
75 return; | |
76 | |
77 const json_t *title = json_object_get(prop_title, "value"); | |
78 | |
79 if (title && json_is_string(title)) | |
80 printf("title|%s\n", json_string_value(title)); | |
81 } | |
82 | |
83 static void | |
84 write_origin(const json_t *props) | |
85 { | |
86 const json_t *prop_origin_x = find_property(props, "origin-x"); | |
87 const json_t *prop_origin_y = find_property(props, "origin-y"); | |
88 | |
89 if (!prop_origin_x || !prop_origin_y) | |
90 return; | |
91 | |
92 const json_t *origin_x = json_object_get(prop_origin_x, "value"); | |
93 const json_t *origin_y = json_object_get(prop_origin_y, "value"); | |
94 | |
95 if (!origin_x || !json_is_integer(origin_x) || | |
96 !origin_y || !json_is_integer(origin_y)) | |
97 return; | |
98 | |
99 printf("origin|%lld|%lld\n", json_integer_value(origin_x), | |
100 json_integer_value(origin_y)); | |
101 } | |
102 | |
103 static void | |
104 write_properties(const json_t *props) | |
105 { | |
106 write_title(props); | |
107 write_origin(props); | |
108 } | |
109 | |
110 static void | |
111 write_metadata(const json_t *document) | |
112 { | |
113 json_t *width = json_object_get(document, "width"); | |
114 json_t *height = json_object_get(document, "height"); | |
115 json_t *tilewidth = json_object_get(document, "tilewidth"); | |
116 json_t *tileheight = json_object_get(document, "tileheight"); | |
117 | |
118 if (!width || !json_is_integer(width)) | |
119 die("missing 'width' property\n"); | |
120 if (!height || !json_is_integer(height)) | |
121 die("missing 'height' property\n"); | |
122 if (!tilewidth || !json_is_integer(tilewidth)) | |
123 die("missing 'tilewidth' property\n"); | |
124 if (!tileheight || !json_is_integer(tileheight)) | |
125 die("missing 'tileheight' property\n"); | |
126 | |
127 printf("width|%lld\n", json_integer_value(width)); | |
128 printf("height|%lld\n", json_integer_value(height)); | |
129 printf("tilewidth|%lld\n", json_integer_value(tilewidth)); | |
130 printf("tileheight|%lld\n", json_integer_value(tileheight)); | |
131 } | |
132 | |
133 static void | |
134 write_object_property(int id, const json_t *property) | |
135 { | |
136 assert(json_is_object(property)); | |
137 | |
138 json_t *name = json_object_get(property, "name"); | |
139 json_t *type = json_object_get(property, "type"); | |
140 json_t *value = json_object_get(property, "value"); | |
141 | |
142 if (!name || !json_is_string(name)) | |
143 die("invalid 'name' property in object"); | |
144 if (!type || !json_is_string(type)) | |
145 die("invalid 'type' property in object"); | |
146 if (!value || !json_is_string(value)) | |
147 die("invalid 'value' property in object"); | |
148 | |
149 printf("object-property|%d|%s|%s\n", | |
150 id, | |
151 json_string_value(name), | |
152 json_string_value(value) | |
153 ); | |
154 } | |
155 | |
156 static void | |
157 write_object(const json_t *object) | |
158 { | |
159 assert(json_is_object(object)); | |
160 | |
161 json_t *id = json_object_get(object, "id"); | |
162 json_t *x = json_object_get(object, "x"); | |
163 json_t *y = json_object_get(object, "y"); | |
164 json_t *width = json_object_get(object, "width"); | |
165 json_t *height = json_object_get(object, "height"); | |
166 json_t *type = json_object_get(object, "type"); | |
167 json_t *props = json_object_get(object, "properties"); | |
168 | |
169 if (!id || !json_is_integer(id)) | |
170 die("invalid 'id' property in object\n"); | |
171 if (!x || !json_is_real(x)) | |
172 die("invalid 'x' property in object\n"); | |
173 if (!y || !json_is_real(y)) | |
174 die("invalid 'y' property in object\n"); | |
175 if (!width || !json_is_real(width)) | |
176 die("invalid 'width' property in object\n"); | |
177 if (!height || !json_is_real(height)) | |
178 die("invalid 'height' property in object\n"); | |
179 if (!type || !json_is_string(type)) | |
180 die("invalid 'type' property in object\n"); | |
181 | |
182 /* In tiled, those properties are float but we only use ints in MA */ | |
183 printf("object|%lld|%s|%d|%d|%d|%d\n", | |
184 json_integer_value(id), | |
185 json_string_value(type), | |
186 (int)json_real_value(x), | |
187 (int)json_real_value(y), | |
188 (int)json_real_value(width), | |
189 (int)json_real_value(height) | |
190 ); | |
191 | |
192 if (json_is_array(props)) { | |
193 json_t *prop; | |
194 size_t index; | |
195 | |
196 json_array_foreach(props, index, prop) { | |
197 if (!json_is_object(prop)) | |
198 die("invalid property in object\n"); | |
199 | |
200 write_object_property(json_integer_value(id), prop); | |
201 } | |
202 } | |
203 } | |
204 | |
205 static void | |
206 write_layer(const json_t *layer) | |
207 { | |
208 json_t *objects = json_object_get(layer, "objects"); | |
209 json_t *data = json_object_get(layer, "data"); | |
210 json_t *name = json_object_get(layer, "name"); | |
211 json_t *tile, *object; | |
212 size_t index; | |
213 | |
214 if (!name || !json_is_string(name)) | |
215 die("invalid 'name' property in layer"); | |
216 if (!is_layer(json_string_value(name))) | |
217 die("invalid 'name' layer: %s\n", json_string_value(name)); | |
218 | |
219 printf("layer|%s\n", json_string_value(name)); | |
220 | |
221 /* Only foreground/background have 'data' property */ | |
222 if (json_is_array(data)) { | |
223 json_array_foreach(data, index, tile) { | |
224 if (!json_is_integer(tile)) | |
225 die("invalid 'data' property in layer\n"); | |
226 | |
227 printf("%lld\n", json_integer_value(tile)); | |
228 } | |
229 } | |
230 | |
231 /* Only objects has 'objects' property */ | |
232 if (json_is_array(objects)) { | |
233 json_array_foreach(objects, index, object) { | |
234 if (!json_is_object(object)) | |
235 die("invalid 'objects' property in layer\n"); | |
236 | |
237 write_object(object); | |
238 } | |
239 } | |
240 } | |
241 | |
242 static void | |
243 write_layers(const json_t *layers) | |
244 { | |
245 size_t index; | |
246 json_t *layer; | |
247 | |
248 if (!layers) | |
249 return; | |
250 | |
251 json_array_foreach(layers, index, layer) { | |
252 if (!json_is_object(layer)) | |
253 die("layer is not an object\n"); | |
254 | |
255 write_layer(layer); | |
256 } | |
257 } | |
258 | |
259 static void | |
260 write_tileset(const json_t *tileset) | |
261 { | |
262 json_t *image = json_object_get(tileset, "image"); | |
263 | |
264 if (!image || !json_is_string(image)) | |
265 die("invalid 'image' property in tileset"); | |
266 | |
267 printf("tileset|%s\n", json_string_value(image)); | |
268 } | |
269 | |
270 static void | |
271 write_tilesets(const json_t *tilesets) | |
272 { | |
273 json_t *tileset; | |
274 size_t index; | |
275 | |
276 if (!json_is_array(tilesets)) | |
277 die("invalid 'tilesets' property"); | |
278 | |
279 json_array_foreach(tilesets, index, tileset) { | |
280 if (!json_is_object(tileset)) | |
281 die("invalid tileset"); | |
282 | |
283 write_tileset(tileset); | |
284 } | |
285 } | |
286 | |
287 int | |
288 main(void) | |
289 { | |
290 json_t *document; | |
291 json_error_t error; | |
292 | |
293 document = json_loadf(stdin, 0, &error); | |
294 | |
295 if (!document) | |
296 die("%d:%d: %s\n", error.line, error.column, error.text); | |
297 | |
298 write_properties(json_object_get(document, "properties")); | |
299 write_metadata(document); | |
300 write_layers(json_object_get(document, "layers")); | |
301 write_tilesets(json_object_get(document, "tilesets")); | |
302 | |
303 json_decref(document); | |
304 } |