Orange branch: Revived hidden treasure, the Groups!
[blender.git] / source / blender / blenloader / intern / readblenentry.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * .blend file reading entry point
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <math.h>
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_ghash.h"
47 #include "BLI_linklist.h"
48
49 #include "DNA_sdna_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_userdef_types.h"
52 #include "DNA_ID.h"
53
54 #include "BKE_utildefines.h" // for ENDB
55
56 #include "BKE_main.h"
57 #include "BKE_library.h" // for free_main
58
59 #include "BLO_readfile.h"
60 #include "BLO_undofile.h"
61
62 #include "readfile.h"
63
64 #include "BLO_readblenfile.h"
65
66         /**
67          * IDType stuff, I plan to move this
68          * out into its own file + prefix, and
69          * make sure all IDType handling goes through
70          * these routines.
71          */
72
73 typedef struct {
74         unsigned short code;
75         char *name;
76         
77         int flags;
78 #define IDTYPE_FLAGS_ISLINKABLE (1<<0)
79 } IDType;
80
81 static IDType idtypes[]= {
82         { ID_AC,                "Action",       IDTYPE_FLAGS_ISLINKABLE}, 
83         { ID_AR,                "Armature", IDTYPE_FLAGS_ISLINKABLE}, 
84         { ID_CA,                "Camera",       IDTYPE_FLAGS_ISLINKABLE}, 
85         { ID_CU,                "Curve",        IDTYPE_FLAGS_ISLINKABLE}, 
86         { ID_GR,                "Group",        IDTYPE_FLAGS_ISLINKABLE}, 
87         { ID_ID,                "ID",           0}, 
88         { ID_IM,                "Image",        IDTYPE_FLAGS_ISLINKABLE}, 
89         { ID_IP,                "Ipo",          IDTYPE_FLAGS_ISLINKABLE}, 
90         { ID_KE,                "Key",          0}, 
91         { ID_LA,                "Lamp",         IDTYPE_FLAGS_ISLINKABLE}, 
92         { ID_LF,                "Life",         0}, 
93         { ID_LI,                "Library",      0}, 
94         { ID_LT,                "Lattice",      IDTYPE_FLAGS_ISLINKABLE}, 
95         { ID_MA,                "Material", IDTYPE_FLAGS_ISLINKABLE}, 
96         { ID_MB,                "Metaball", IDTYPE_FLAGS_ISLINKABLE}, 
97         { ID_ME,                "Mesh",         IDTYPE_FLAGS_ISLINKABLE}, 
98         { ID_OB,                "Object",       IDTYPE_FLAGS_ISLINKABLE}, 
99         { ID_SAMPLE,    "Sample",       0}, 
100         { ID_SCE,               "Scene",        IDTYPE_FLAGS_ISLINKABLE}, 
101         { ID_SCR,               "Screen",       0}, 
102         { ID_SEQ,               "Sequence",     0}, 
103         { ID_SE,                "Sector",       0}, 
104         { ID_SO,                "Sound",        IDTYPE_FLAGS_ISLINKABLE}, 
105         { ID_TE,                "Texture",      IDTYPE_FLAGS_ISLINKABLE}, 
106         { ID_TXT,               "Text",         IDTYPE_FLAGS_ISLINKABLE}, 
107         { ID_VF,                "VFont",        IDTYPE_FLAGS_ISLINKABLE}, 
108         { ID_WO,                "World",        IDTYPE_FLAGS_ISLINKABLE}, 
109         { ID_WV,                "Wave",         0}, 
110 };
111 static int nidtypes= sizeof(idtypes)/sizeof(idtypes[0]);
112
113 /* local prototypes --------------------- */
114 void BLO_blendhandle_print_sizes(BlendHandle *, void *); 
115
116
117 static IDType *idtype_from_name(char *str) 
118 {
119         int i= nidtypes;
120         
121         while (i--)
122                 if (BLI_streq(str, idtypes[i].name))
123                         return &idtypes[i];
124         
125         return NULL;
126 }
127 static IDType *idtype_from_code(int code) 
128 {
129         int i= nidtypes;
130         
131         while (i--)
132                 if (code==idtypes[i].code)
133                         return &idtypes[i];
134         
135         return NULL;
136 }
137
138 static int bheadcode_is_idcode(int code) 
139 {
140         return idtype_from_code(code)?1:0;
141 }
142
143 static int idcode_is_linkable(int code) {
144         IDType *idt= idtype_from_code(code);
145         return idt?(idt->flags&IDTYPE_FLAGS_ISLINKABLE):0;
146 }
147
148 char *BLO_idcode_to_name(int code) 
149 {
150         IDType *idt= idtype_from_code(code);
151         
152         return idt?idt->name:NULL;
153 }
154
155 int BLO_idcode_from_name(char *name) 
156 {
157         IDType *idt= idtype_from_name(name);
158         
159         return idt?idt->code:0;
160 }
161         
162         /* Access routines used by filesel. */
163          
164 BlendHandle *BLO_blendhandle_from_file(char *file) 
165 {
166         BlendReadError err;
167
168         return (BlendHandle*) blo_openblenderfile(file, &err);
169 }
170
171 void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) 
172 {
173         FileData *fd= (FileData*) bh;
174         BHead *bhead;
175
176         fprintf(fp, "[\n");
177         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
178                 if (bhead->code==ENDB)
179                         break;
180                 else {
181                         short *sp= fd->filesdna->structs[bhead->SDNAnr];
182                         char *name= fd->filesdna->types[ sp[0] ];
183                         char buf[4];
184                         
185                         buf[0]= (bhead->code>>24)&0xFF;
186                         buf[1]= (bhead->code>>16)&0xFF;
187                         buf[2]= (bhead->code>>8)&0xFF;
188                         buf[3]= (bhead->code>>0)&0xFF;
189                         
190                         buf[0]= buf[0]?buf[0]:' ';
191                         buf[1]= buf[1]?buf[1]:' ';
192                         buf[2]= buf[2]?buf[2]:' ';
193                         buf[3]= buf[3]?buf[3]:' ';
194                         
195                         fprintf(fp, "['%.4s', '%s', %d, %ld ], \n", buf, name, bhead->nr, bhead->len+sizeof(BHead));
196                 }
197         }
198         fprintf(fp, "]\n");
199 }
200
201 LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype) 
202 {
203         FileData *fd= (FileData*) bh;
204         LinkNode *names= NULL;
205         BHead *bhead;
206
207         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
208                 if (bhead->code==ofblocktype) {
209                         ID *id= (ID*) (bhead+1);
210                         
211                         BLI_linklist_prepend(&names, strdup(id->name+2));
212                 } else if (bhead->code==ENDB)
213                         break;
214         }
215         
216         return names;
217 }
218
219 LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) 
220 {
221         FileData *fd= (FileData*) bh;
222         GHash *gathered= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
223         LinkNode *names= NULL;
224         BHead *bhead;
225         
226         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
227                 if (bhead->code==ENDB) {
228                         break;
229                 } else if (bheadcode_is_idcode(bhead->code)) {
230                         if (idcode_is_linkable(bhead->code)) {
231                                 char *str= BLO_idcode_to_name(bhead->code);
232                                 
233                                 if (!BLI_ghash_haskey(gathered, str)) {
234                                         BLI_linklist_prepend(&names, strdup(str));
235                                         BLI_ghash_insert(gathered, str, NULL);
236                                 }
237                         }
238                 }
239         }
240         
241         BLI_ghash_free(gathered, NULL, NULL);
242         
243         return names;
244 }               
245
246 void BLO_blendhandle_close(BlendHandle *bh) {
247         FileData *fd= (FileData*) bh;
248         
249         blo_freefiledata(fd);
250 }
251
252         /**********/
253
254 BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r) 
255 {
256         BlendFileData *bfd = NULL;
257         FileData *fd;
258                 
259         fd = blo_openblenderfile(file, error_r);
260         if (fd) {
261                 bfd= blo_read_file_internal(fd, error_r);
262                 if (bfd) {
263                         bfd->type= BLENFILETYPE_BLEND;
264                         strcpy(bfd->main->name, file);
265                 }
266                 blo_freefiledata(fd);                   
267         }
268
269         return bfd;     
270 }
271
272 BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r) 
273 {
274         BlendFileData *bfd = NULL;
275         FileData *fd;
276                 
277         fd = blo_openblendermemory(mem, memsize,  error_r);
278         if (fd) {
279                 bfd= blo_read_file_internal(fd, error_r);
280                 if (bfd) {
281                         bfd->type= BLENFILETYPE_BLEND;
282                         strcpy(bfd->main->name, "");
283                 }
284                 blo_freefiledata(fd);                   
285         }
286
287         return bfd;     
288 }
289
290 BlendFileData *BLO_read_from_memfile(MemFile *memfile, BlendReadError *error_r) 
291 {
292         BlendFileData *bfd = NULL;
293         FileData *fd;
294                 
295         fd = blo_openblendermemfile(memfile, error_r);
296         if (fd) {
297                 bfd= blo_read_file_internal(fd, error_r);
298                 if (bfd) {
299                         bfd->type= BLENFILETYPE_BLEND;
300                         strcpy(bfd->main->name, "");
301                 }
302                 blo_freefiledata(fd);                   
303         }
304
305         return bfd;     
306 }
307
308 void BLO_blendfiledata_free(BlendFileData *bfd)
309 {
310         if (bfd->main) {
311                 free_main(bfd->main);
312         }
313         
314         if (bfd->user) {
315                 MEM_freeN(bfd->user);
316         }
317
318         MEM_freeN(bfd);
319 }
320
321 char *BLO_bre_as_string(BlendReadError error) 
322 {
323         switch (error) {
324         case BRE_NONE:
325                 return "No error";
326         
327         case BRE_UNABLE_TO_OPEN:
328                 return "Unable to open";
329         case BRE_UNABLE_TO_READ:
330                 return "Unable to read";
331                 
332         case BRE_OUT_OF_MEMORY:
333                 return "Out of memory";
334         case BRE_INTERNAL_ERROR:
335                 return "<internal error>";
336
337         case BRE_NOT_A_BLEND:
338                 return "File is not a Blender file";
339         case BRE_NOT_A_PUBFILE:
340                 return "File is not a compressed, locked or signed Blender file";
341         case BRE_INCOMPLETE:
342                 return "File incomplete";
343         case BRE_CORRUPT:
344                 return "File corrupt";
345
346         case BRE_TOO_NEW:
347                 return "File needs newer Blender version, please upgrade";
348         case BRE_NOT_ALLOWED:
349                 return "File is locked";
350                                                 
351         case BRE_NO_SCREEN:
352                 return "File has no screen";
353         case BRE_NO_SCENE:
354                 return "File has no scene";
355                 
356         default:
357         case BRE_INVALID:
358                 return "<invalid read error>";
359         }
360 }