diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c new file mode 100644 index 0000000..058832a --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c | |||
@@ -0,0 +1,467 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /* | ||
4 | libg3d - 3D object loading library | ||
5 | |||
6 | Copyright (C) 2005-2009 Markus Dahms <mad@automagically.de> | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <string.h> | ||
24 | #include <stdlib.h> | ||
25 | |||
26 | #include <g3d/debug.h> | ||
27 | |||
28 | #include "imp_blend_def.h" | ||
29 | #include "imp_blend_types.h" | ||
30 | #include "imp_blend_sdna.h" | ||
31 | #include "imp_blend_read.h" | ||
32 | |||
33 | static gboolean sdna_prop_check_array(BlendSdnaProperty *sprop) | ||
34 | { | ||
35 | gchar *ob; | ||
36 | guint32 n; | ||
37 | |||
38 | while(TRUE) { | ||
39 | ob = strrchr(sprop->name, '['); | ||
40 | if(ob == NULL) | ||
41 | return TRUE; | ||
42 | n = atoi(ob + 1); | ||
43 | if(n == 0) | ||
44 | return FALSE; | ||
45 | sprop->nitems *= n; | ||
46 | *ob = '\0'; | ||
47 | } | ||
48 | return FALSE; | ||
49 | } | ||
50 | |||
51 | BlendSdna *blend_sdna_read_dna1(G3DStream *stream, guint32 flags, gint32 len) | ||
52 | { | ||
53 | BlendSdna *sdna; | ||
54 | BlendSdnaProperty *sprop; | ||
55 | BlendSdnaStruct *sstruct; | ||
56 | guint32 code, n, n2, nn, m, t; | ||
57 | gint32 i, j; | ||
58 | gchar buf[2048], *bufp, c, **aptr; | ||
59 | |||
60 | code = blend_read_uint(stream, flags); | ||
61 | len -= 4; | ||
62 | if(code != MKID('S','D','N','A')) { | ||
63 | g_warning("Blend: DNA1: no SDNA"); | ||
64 | g3d_stream_skip(stream, len); | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | sdna = g_new0(BlendSdna, 1); | ||
69 | |||
70 | while(len > 0) { | ||
71 | code = blend_read_uint(stream, flags); | ||
72 | len -= 4; | ||
73 | |||
74 | switch(code) { | ||
75 | case MKID('N','A','M','E'): | ||
76 | case MKID('T','Y','P','E'): | ||
77 | n = blend_read_uint(stream, flags); | ||
78 | len -= 4; | ||
79 | if(code == MKID('T','Y','P','E')) { | ||
80 | g_debug("\\ TYPE: %d types", n); | ||
81 | sdna->n_types = n; | ||
82 | sdna->type_names = g_new0(gchar *, n); | ||
83 | sdna->type_sizes = g_new0(guint32, n); | ||
84 | aptr = sdna->type_names; | ||
85 | } else { | ||
86 | g_debug("\\ NAME: %d names", n); | ||
87 | sdna->n_names = n; | ||
88 | sdna->names = g_new0(gchar *, n); | ||
89 | aptr = sdna->names; | ||
90 | } | ||
91 | m = 0; | ||
92 | for(i = 0; i < n; i ++) { | ||
93 | bufp = buf; | ||
94 | do { | ||
95 | c = *bufp = g3d_stream_read_int8(stream); | ||
96 | bufp ++; | ||
97 | len --; | ||
98 | m ++; | ||
99 | } while(c != '\0'); | ||
100 | aptr[i] = g_strdup(buf); | ||
101 | #if DEBUG > 2 | ||
102 | g_debug("\\ %s", buf); | ||
103 | #endif | ||
104 | } | ||
105 | m %= 4; | ||
106 | if(m > 0) { | ||
107 | /* padding */ | ||
108 | g3d_stream_skip(stream, 4 - m); | ||
109 | len -= (4 - m); | ||
110 | } | ||
111 | break; | ||
112 | case MKID('T','L','E','N'): | ||
113 | g_debug("\\ TLEN: %d type sizes", sdna->n_types); | ||
114 | for(i = 0; i < sdna->n_types; i ++) { | ||
115 | m = blend_read_short(stream, flags); | ||
116 | len -= 2; | ||
117 | #if DEBUG > 2 | ||
118 | g_debug("\\ %d", m); | ||
119 | #endif | ||
120 | sdna->type_sizes[i] = m; | ||
121 | } | ||
122 | m = sdna->n_types % 2; | ||
123 | if(m > 0) { | ||
124 | g3d_stream_skip(stream, 2); | ||
125 | len -= 2; | ||
126 | } | ||
127 | break; | ||
128 | case MKID('S','T','R','C'): | ||
129 | n = blend_read_uint(stream, flags); | ||
130 | g_debug("\\ STRC: %d structs", n); | ||
131 | len -= 4; | ||
132 | for(i = 0; i < n; i ++) { | ||
133 | t = blend_read_short(stream, flags); | ||
134 | n2 = blend_read_short(stream, flags); | ||
135 | len -= 4; | ||
136 | sstruct = g_new0(BlendSdnaStruct, 1); | ||
137 | sstruct->tid = t; | ||
138 | sstruct->name = sdna->type_names[t]; | ||
139 | sstruct->size = sdna->type_sizes[t]; | ||
140 | sdna->structs = g_slist_append(sdna->structs, sstruct); | ||
141 | for(j = 0; j < n2; j ++) { | ||
142 | t = blend_read_short(stream, flags); | ||
143 | nn = blend_read_short(stream, flags); | ||
144 | len -= 4; | ||
145 | sprop = g_new0(BlendSdnaProperty, 1); | ||
146 | sprop->name = g_strdup(sdna->names[nn]); | ||
147 | sprop->tname = sdna->type_names[t]; | ||
148 | sprop->tid = t; | ||
149 | sprop->tsize = sdna->type_sizes[t]; | ||
150 | sprop->ptr = | ||
151 | (sprop->name[0] == '*') || | ||
152 | (sprop->name[0] == '('); | ||
153 | sprop->nitems = 1; | ||
154 | sdna_prop_check_array(sprop); | ||
155 | sstruct->properties = g_slist_append( | ||
156 | sstruct->properties, sprop); | ||
157 | } | ||
158 | } | ||
159 | break; | ||
160 | default: | ||
161 | g_warning("Blend: DNA1: unexpected section 0x%x", code); | ||
162 | return sdna; | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | return sdna; | ||
167 | } | ||
168 | |||
169 | static void blend_sdna_struct_free(BlendSdnaStruct *sstruct) | ||
170 | { | ||
171 | GSList *item, *next; | ||
172 | BlendSdnaProperty *sprop; | ||
173 | |||
174 | item = sstruct->properties; | ||
175 | while(item) { | ||
176 | sprop = item->data; | ||
177 | next = item->next; | ||
178 | g_free(sprop->name); | ||
179 | g_free(sprop); | ||
180 | g_slist_free_1(item); | ||
181 | item = next; | ||
182 | } | ||
183 | g_free(sstruct); | ||
184 | } | ||
185 | |||
186 | void blend_sdna_cleanup(BlendSdna *sdna) | ||
187 | { | ||
188 | GSList *item, *next; | ||
189 | BlendSdnaStruct *sstruct; | ||
190 | |||
191 | g_return_if_fail(sdna != NULL); | ||
192 | |||
193 | /* names */ | ||
194 | g_free(sdna->names); | ||
195 | /* types */ | ||
196 | g_free(sdna->type_names); | ||
197 | g_free(sdna->type_sizes); | ||
198 | /* structs */ | ||
199 | item = sdna->structs; | ||
200 | while(item) { | ||
201 | sstruct = item->data; | ||
202 | next = item->next; | ||
203 | blend_sdna_struct_free(sstruct); | ||
204 | g_slist_free_1(next); | ||
205 | item = next; | ||
206 | } | ||
207 | /* sdna */ | ||
208 | g_free(sdna); | ||
209 | } | ||
210 | |||
211 | const BlendSdnaStruct *blend_sdna_get_struct_by_id(BlendSdna *sdna, | ||
212 | guint32 sdnanr) | ||
213 | { | ||
214 | g_return_val_if_fail(sdnanr < g_slist_length(sdna->structs), NULL); | ||
215 | |||
216 | if(sdnanr < 10) | ||
217 | return NULL; | ||
218 | |||
219 | return g_slist_nth_data(sdna->structs, sdnanr); | ||
220 | } | ||
221 | |||
222 | const BlendSdnaStruct *blend_sdna_get_struct_by_tid(BlendSdna *sdna, | ||
223 | guint32 tid) | ||
224 | { | ||
225 | GSList *item; | ||
226 | BlendSdnaStruct *sstruct; | ||
227 | |||
228 | for(item = sdna->structs; item != NULL; item = item->next) { | ||
229 | sstruct = item->data; | ||
230 | if(sstruct->tid == tid) | ||
231 | return sstruct; | ||
232 | } | ||
233 | |||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | static inline void sdna_data_read_basic_types(BlendSdna *sdna, | ||
238 | BlendSdnaPropData *spdata, BlendGlobal *global, gsize *r) | ||
239 | { | ||
240 | gint32 i; | ||
241 | |||
242 | g_return_if_fail(spdata->sprop->nitems > 0); | ||
243 | |||
244 | switch(spdata->type) { | ||
245 | case T_CHAR: | ||
246 | spdata->ival = g_new0(gint32, spdata->sprop->nitems); | ||
247 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
248 | spdata->ival[i] = g3d_stream_read_int8(global->stream); | ||
249 | (*r) -= spdata->sprop->nitems; | ||
250 | break; | ||
251 | case T_UCHAR: | ||
252 | spdata->uval = g_new0(guint32, spdata->sprop->nitems); | ||
253 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
254 | spdata->uval[i] = g3d_stream_read_int8(global->stream); | ||
255 | (*r) -= spdata->sprop->nitems; | ||
256 | break; | ||
257 | case T_SHORT: /* FIXME: BE/LE */ | ||
258 | spdata->ival = g_new0(gint32, spdata->sprop->nitems); | ||
259 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
260 | spdata->ival[i] = g3d_stream_read_int16_le(global->stream); | ||
261 | (*r) -= spdata->sprop->nitems * 2; | ||
262 | break; | ||
263 | case T_USHORT: | ||
264 | spdata->uval = g_new0(guint32, spdata->sprop->nitems); | ||
265 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
266 | spdata->uval[i] = g3d_stream_read_int16_le(global->stream); | ||
267 | (*r) -= spdata->sprop->nitems * 2; | ||
268 | break; | ||
269 | case T_INT: /* FIXME: 32/64 bit */ | ||
270 | spdata->ival = g_new0(gint32, spdata->sprop->nitems); | ||
271 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
272 | spdata->ival[i] = g3d_stream_read_int32_le(global->stream); | ||
273 | (*r) -= spdata->sprop->nitems * 4; | ||
274 | break; | ||
275 | case T_LONG: | ||
276 | spdata->ival = g_new0(gint32, spdata->sprop->nitems); | ||
277 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
278 | spdata->ival[i] = g3d_stream_read_int32_le(global->stream); | ||
279 | (*r) -= spdata->sprop->nitems * 4; | ||
280 | break; | ||
281 | case T_ULONG: | ||
282 | spdata->uval = g_new0(guint32, spdata->sprop->nitems); | ||
283 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
284 | spdata->uval[i] = g3d_stream_read_int32_le(global->stream); | ||
285 | (*r) -= spdata->sprop->nitems * 4; | ||
286 | break; | ||
287 | case T_FLOAT: | ||
288 | spdata->fval = g_new0(G3DFloat, spdata->sprop->nitems); | ||
289 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
290 | spdata->fval[i] = g3d_stream_read_float_le(global->stream); | ||
291 | (*r) -= spdata->sprop->nitems * 4; | ||
292 | break; | ||
293 | case T_DOUBLE: | ||
294 | spdata->fval = g_new0(G3DFloat, spdata->sprop->nitems); | ||
295 | for(i = 0; i < spdata->sprop->nitems; i ++) | ||
296 | spdata->fval[i] = g3d_stream_read_double_le(global->stream); | ||
297 | (*r) -= spdata->sprop->nitems * 8; | ||
298 | break; | ||
299 | case T_VOID: | ||
300 | g_warning("SDNA: non-pointer void type"); | ||
301 | break; | ||
302 | case T_STRUCT: | ||
303 | /* handled elsewhere */ | ||
304 | break; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | BlendSdnaPropData *blend_sdna_get_property(BlendSdnaData *sdata, | ||
309 | const gchar *name, BlendSdnaPropType type) | ||
310 | { | ||
311 | BlendSdnaPropData *spdata; | ||
312 | |||
313 | spdata = g_hash_table_lookup(sdata->prophash, name); | ||
314 | if(!spdata) | ||
315 | return NULL; | ||
316 | if(spdata->type != type) | ||
317 | return NULL; | ||
318 | return spdata; | ||
319 | } | ||
320 | |||
321 | BlendSdnaData *blend_sdna_data_read(BlendSdna *sdna, | ||
322 | const BlendSdnaStruct *sstruct, BlendGlobal *global, gsize *r, | ||
323 | guint32 level) | ||
324 | { | ||
325 | BlendSdnaData *sdata; | ||
326 | BlendSdnaProperty *sprop; | ||
327 | BlendSdnaPropData *spdata; | ||
328 | const BlendSdnaStruct *substruct; | ||
329 | GSList *pitem; | ||
330 | |||
331 | sdata = g_new0(BlendSdnaData, 1); | ||
332 | sdata->sstruct = sstruct; | ||
333 | sdata->prophash = g_hash_table_new(g_str_hash, g_str_equal); | ||
334 | |||
335 | #if DEBUG > BLEND_DEBUG_STRUCT | ||
336 | g_debug("|%s{ /* %s */", | ||
337 | debug_pad(level * 2), sstruct->name); | ||
338 | #endif | ||
339 | |||
340 | for(pitem = sstruct->properties; pitem != NULL; pitem = pitem->next) { | ||
341 | sprop = pitem->data; | ||
342 | spdata = g_new0(BlendSdnaPropData, 1); | ||
343 | spdata->name = g_strdup(sprop->name); | ||
344 | spdata->sprop = sprop; | ||
345 | g_hash_table_insert(sdata->prophash, spdata->name, spdata); | ||
346 | spdata->type = (sprop->tid < 10) ? sprop->tid : 0xFF; | ||
347 | |||
348 | if(sprop->ptr) { | ||
349 | spdata->pval = g_new0(guint32, 1); | ||
350 | spdata->pval[0] = g3d_stream_read_int32_le(global->stream); | ||
351 | (*r) -= 4; | ||
352 | #if DEBUG > BLEND_DEBUG_STRUCT | ||
353 | g_debug("|%s %-10s %-10s = 0x%08x; /* len = %d */", | ||
354 | debug_pad(level * 2), | ||
355 | sprop->tname, sprop->name, spdata->pval[0], *r); | ||
356 | #endif | ||
357 | continue; | ||
358 | } | ||
359 | |||
360 | if(spdata->type == T_STRUCT) { | ||
361 | substruct = blend_sdna_get_struct_by_tid(sdna, sprop->tid); | ||
362 | #if DEBUG > BLEND_DEBUG_STRUCT | ||
363 | g_debug("|%s %-10s %-10s = /* %s */", | ||
364 | debug_pad(level * 2), | ||
365 | sprop->tname, sprop->name, | ||
366 | substruct ? substruct->name : "(unknown)"); | ||
367 | #endif | ||
368 | if(substruct) | ||
369 | spdata->structval = blend_sdna_data_read(sdna, | ||
370 | substruct, global, r, level + 1); | ||
371 | else { | ||
372 | g3d_stream_skip(global->stream, sprop->tsize); | ||
373 | (*r) -= sprop->tsize; | ||
374 | } | ||
375 | } else { | ||
376 | sdna_data_read_basic_types(sdna, spdata, global, r); | ||
377 | } | ||
378 | } /* properties */ | ||
379 | |||
380 | #if DEBUG > BLEND_DEBUG_STRUCT | ||
381 | g_debug("|%s};", debug_pad(level * 2)); | ||
382 | #endif | ||
383 | |||
384 | return sdata; | ||
385 | } | ||
386 | |||
387 | void blend_sdna_data_free(BlendSdnaData *sdata) | ||
388 | { | ||
389 | /* TODO: free BlendSdnaPropData nodes */ | ||
390 | g_hash_table_destroy(sdata->prophash); | ||
391 | g_free(sdata); | ||
392 | } | ||
393 | |||
394 | /*****************************************************************************/ | ||
395 | /* debugging code */ | ||
396 | |||
397 | #if DEBUG > 0 | ||
398 | |||
399 | static void blend_sdna_dump_spdata_cb(gpointer key, gpointer value, | ||
400 | gpointer user_data) | ||
401 | { | ||
402 | BlendSdnaPropData *spdata = value; | ||
403 | guint32 *levelp = user_data; | ||
404 | |||
405 | #define DUMP_FORMAT "|%s %-10s %-10s [%03d]" | ||
406 | #define DUMP_ARGS debug_pad(*levelp), \ | ||
407 | spdata->sprop->tname, spdata->name, spdata->sprop->nitems | ||
408 | |||
409 | if(spdata->sprop->ptr) { | ||
410 | g_debug(DUMP_FORMAT " = 0x%08x;", DUMP_ARGS, spdata->pval[0]); | ||
411 | return; | ||
412 | } | ||
413 | switch(spdata->type) { | ||
414 | case T_CHAR: | ||
415 | case T_SHORT: | ||
416 | case T_INT: | ||
417 | case T_LONG: | ||
418 | g_debug(DUMP_FORMAT " = %i;", DUMP_ARGS, spdata->ival[0]); | ||
419 | break; | ||
420 | case T_UCHAR: | ||
421 | case T_USHORT: | ||
422 | case T_ULONG: | ||
423 | g_debug(DUMP_FORMAT " = %u;", DUMP_ARGS, spdata->uval[0]); | ||
424 | break; | ||
425 | case T_FLOAT: | ||
426 | case T_DOUBLE: | ||
427 | g_debug(DUMP_FORMAT " = %f;", DUMP_ARGS, spdata->fval[0]); | ||
428 | break; | ||
429 | case T_STRUCT: | ||
430 | g_debug(DUMP_FORMAT " =", DUMP_ARGS); | ||
431 | blend_sdna_dump_data(spdata->structval, *levelp + 1); | ||
432 | break; | ||
433 | default: | ||
434 | g_debug(DUMP_FORMAT ";", DUMP_ARGS); | ||
435 | break; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | gboolean blend_sdna_dump_data(BlendSdnaData *sdata, guint32 level) | ||
440 | { | ||
441 | g_debug("|%s{ /* %s */", debug_pad(level), sdata->sstruct->name); | ||
442 | g_hash_table_foreach(sdata->prophash, blend_sdna_dump_spdata_cb, &level); | ||
443 | g_debug("|%s},", debug_pad(level)); | ||
444 | return TRUE; | ||
445 | } | ||
446 | |||
447 | gboolean blend_sdna_dump_struct(BlendSdna *sdna, guint32 sdnanr) | ||
448 | { | ||
449 | const BlendSdnaStruct *sstruct; | ||
450 | BlendSdnaProperty *sprop; | ||
451 | GSList *pitem; | ||
452 | |||
453 | sstruct = blend_sdna_get_struct_by_id(sdna, sdnanr); | ||
454 | if(!sstruct) | ||
455 | return FALSE; | ||
456 | sstruct = g_slist_nth_data(sdna->structs, sdnanr); | ||
457 | g_debug("| struct %s { /* %d */", sstruct->name, sstruct->size); | ||
458 | for(pitem = sstruct->properties; pitem != NULL; pitem = pitem->next) { | ||
459 | sprop = pitem->data; | ||
460 | g_debug("| \t%-16s %-24s;", sprop->tname, sprop->name); | ||
461 | } | ||
462 | g_debug("| };"); | ||
463 | |||
464 | return TRUE; | ||
465 | } | ||
466 | |||
467 | #endif | ||