aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend_sdna.c
diff options
context:
space:
mode:
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.c467
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
33static 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
51BlendSdna *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
169static 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
186void 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
211const 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
222const 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
237static 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
308BlendSdnaPropData *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
321BlendSdnaData *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
387void 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
399static 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
439gboolean 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
447gboolean 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