Second itteration of global undo system. Now based on:
[blender-staging.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 #ifdef WIN32
39 #include "BLI_winstuff.h"
40 #endif
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <math.h>
46
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_ghash.h"
51 #include "BLI_linklist.h"
52
53 #include "DNA_sdna_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_userdef_types.h"
56 #include "DNA_ID.h"
57
58 #include "BKE_utildefines.h" // for ENDB
59
60 #include "BKE_main.h"
61 #include "BKE_library.h" // for free_main
62
63 #include "BLO_readfile.h"
64 #include "BLO_undofile.h"
65
66 #include "readfile.h"
67
68 #include "BLO_readblenfile.h"
69
70         /**
71          * IDType stuff, I plan to move this
72          * out into its own file + prefix, and
73          * make sure all IDType handling goes through
74          * these routines.
75          */
76
77 typedef struct {
78         unsigned short code;
79         char *name;
80         
81         int flags;
82 #define IDTYPE_FLAGS_ISLINKABLE (1<<0)
83 } IDType;
84
85 static IDType idtypes[]= {
86         { ID_AC,                "Action",       IDTYPE_FLAGS_ISLINKABLE}, 
87         { ID_AR,                "Armature", IDTYPE_FLAGS_ISLINKABLE}, 
88         { ID_CA,                "Camera",       IDTYPE_FLAGS_ISLINKABLE}, 
89         { ID_CU,                "Curve",        IDTYPE_FLAGS_ISLINKABLE}, 
90         { ID_GR,                "Group",        0}, 
91         { ID_ID,                "ID",           0}, 
92         { ID_IK,                "Ika",          IDTYPE_FLAGS_ISLINKABLE}, 
93         { ID_IM,                "Image",        IDTYPE_FLAGS_ISLINKABLE}, 
94         { ID_IP,                "Ipo",          IDTYPE_FLAGS_ISLINKABLE}, 
95         { ID_KE,                "Key",          0}, 
96         { ID_LA,                "Lamp",         IDTYPE_FLAGS_ISLINKABLE}, 
97         { ID_LF,                "Life",         0}, 
98         { ID_LI,                "Library",      0}, 
99         { ID_LT,                "Lattice",      IDTYPE_FLAGS_ISLINKABLE}, 
100         { ID_MA,                "Material", IDTYPE_FLAGS_ISLINKABLE}, 
101         { ID_MB,                "Metaball", IDTYPE_FLAGS_ISLINKABLE}, 
102         { ID_ME,                "Mesh",         IDTYPE_FLAGS_ISLINKABLE}, 
103         { ID_OB,                "Object",       IDTYPE_FLAGS_ISLINKABLE}, 
104         { ID_SAMPLE,    "Sample",       0}, 
105         { ID_SCE,               "Scene",        IDTYPE_FLAGS_ISLINKABLE}, 
106         { ID_SCR,               "Screen",       0}, 
107         { ID_SEQ,               "Sequence",     0}, 
108         { ID_SE,                "Sector",       0}, 
109         { ID_SO,                "Sound",        IDTYPE_FLAGS_ISLINKABLE}, 
110         { ID_TE,                "Texture",      IDTYPE_FLAGS_ISLINKABLE}, 
111         { ID_TXT,               "Text",         IDTYPE_FLAGS_ISLINKABLE}, 
112         { ID_VF,                "VFont",        IDTYPE_FLAGS_ISLINKABLE}, 
113         { ID_WO,                "World",        IDTYPE_FLAGS_ISLINKABLE}, 
114         { ID_WV,                "Wave",         0}, 
115 };
116 static int nidtypes= sizeof(idtypes)/sizeof(idtypes[0]);
117
118 static IDType *idtype_from_name(char *str) 
119 {
120         int i= nidtypes;
121         
122         while (i--)
123                 if (BLI_streq(str, idtypes[i].name))
124                         return &idtypes[i];
125         
126         return NULL;
127 }
128 static IDType *idtype_from_code(int code) 
129 {
130         int i= nidtypes;
131         
132         while (i--)
133                 if (code==idtypes[i].code)
134                         return &idtypes[i];
135         
136         return NULL;
137 }
138
139 static int bheadcode_is_idcode(int code) 
140 {
141         return idtype_from_code(code)?1:0;
142 }
143
144 static int idcode_is_linkable(int code) {
145         IDType *idt= idtype_from_code(code);
146         return idt?(idt->flags&IDTYPE_FLAGS_ISLINKABLE):0;
147 }
148
149 char *BLO_idcode_to_name(int code) 
150 {
151         IDType *idt= idtype_from_code(code);
152         
153         return idt?idt->name:NULL;
154 }
155
156 int BLO_idcode_from_name(char *name) 
157 {
158         IDType *idt= idtype_from_name(name);
159         
160         return idt?idt->code:0;
161 }
162         
163         /* Access routines used by filesel. */
164          
165 BlendHandle *BLO_blendhandle_from_file(char *file) 
166 {
167         return (BlendHandle*) blo_openblenderfile(file);
168 }
169
170 void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) 
171 {
172         FileData *fd= (FileData*) bh;
173         BHead *bhead;
174
175         fprintf(fp, "[\n");
176         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
177                 if (bhead->code==ENDB)
178                         break;
179                 else {
180                         short *sp= fd->filesdna->structs[bhead->SDNAnr];
181                         char *name= fd->filesdna->types[ sp[0] ];
182                         char buf[4];
183                         
184                         buf[0]= (bhead->code>>24)&0xFF;
185                         buf[1]= (bhead->code>>16)&0xFF;
186                         buf[2]= (bhead->code>>8)&0xFF;
187                         buf[3]= (bhead->code>>0)&0xFF;
188                         
189                         buf[0]= buf[0]?buf[0]:' ';
190                         buf[1]= buf[1]?buf[1]:' ';
191                         buf[2]= buf[2]?buf[2]:' ';
192                         buf[3]= buf[3]?buf[3]:' ';
193                         
194                         fprintf(fp, "['%.4s', '%s', %d, %d], \n", buf, name, bhead->nr, bhead->len+sizeof(BHead));
195                 }
196         }
197         fprintf(fp, "]\n");
198 }
199
200 LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype) 
201 {
202         FileData *fd= (FileData*) bh;
203         LinkNode *names= NULL;
204         BHead *bhead;
205
206         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
207                 if (bhead->code==ofblocktype) {
208                         ID *id= (ID*) (bhead+1);
209                         
210                         BLI_linklist_prepend(&names, strdup(id->name+2));
211                 } else if (bhead->code==ENDB)
212                         break;
213         }
214         
215         return names;
216 }
217
218 LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) 
219 {
220         FileData *fd= (FileData*) bh;
221         GHash *gathered= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
222         LinkNode *names= NULL;
223         BHead *bhead;
224         
225         for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
226                 if (bhead->code==ENDB) {
227                         break;
228                 } else if (bheadcode_is_idcode(bhead->code)) {
229                         if (idcode_is_linkable(bhead->code)) {
230                                 char *str= BLO_idcode_to_name(bhead->code);
231                                 
232                                 if (!BLI_ghash_haskey(gathered, str)) {
233                                         BLI_linklist_prepend(&names, strdup(str));
234                                         BLI_ghash_insert(gathered, str, NULL);
235                                 }
236                         }
237                 }
238         }
239         
240         BLI_ghash_free(gathered, NULL, NULL);
241         
242         return names;
243 }               
244
245 void BLO_blendhandle_close(BlendHandle *bh) {
246         FileData *fd= (FileData*) bh;
247         
248         blo_freefiledata(fd);
249 }
250
251         /**********/
252
253 BlendFileData *BLO_read_from_file(char *file, BlendReadError *error_r) 
254 {
255         BlendFileData *bfd = NULL;
256         FileData *fd;
257                 
258         fd = blo_openblenderfile(file);
259         if (fd) {
260                 bfd= blo_read_file_internal(fd, error_r);
261                 if (bfd) {
262                         bfd->type= BLENFILETYPE_BLEND;
263                         strcpy(bfd->main->name, file);
264                 }
265                 blo_freefiledata(fd);                   
266         }
267
268         return bfd;     
269 }
270
271 BlendFileData *BLO_read_from_memory(void *mem, int memsize, BlendReadError *error_r) 
272 {
273         BlendFileData *bfd = NULL;
274         FileData *fd;
275                 
276         fd = blo_openblendermemory(mem, memsize);
277         if (fd) {
278                 bfd= blo_read_file_internal(fd, error_r);
279                 if (bfd) {
280                         bfd->type= BLENFILETYPE_BLEND;
281                         strcpy(bfd->main->name, "");
282                 }
283                 blo_freefiledata(fd);                   
284         }
285
286         return bfd;     
287 }
288
289 BlendFileData *BLO_read_from_memfile(MemFile *memfile, BlendReadError *error_r) 
290 {
291         BlendFileData *bfd = NULL;
292         FileData *fd;
293                 
294         fd = blo_openblendermemfile(memfile);
295         if (fd) {
296                 bfd= blo_read_file_internal(fd, error_r);
297                 if (bfd) {
298                         bfd->type= BLENFILETYPE_BLEND;
299                         strcpy(bfd->main->name, "");
300                 }
301                 blo_freefiledata(fd);                   
302         }
303
304         return bfd;     
305 }
306
307 void BLO_blendfiledata_free(BlendFileData *bfd)
308 {
309         if (bfd->main) {
310                 free_main(bfd->main);
311         }
312         
313         if (bfd->user) {
314                 MEM_freeN(bfd->user);
315         }
316
317         MEM_freeN(bfd);
318 }
319
320 char *BLO_bre_as_string(BlendReadError error) 
321 {
322         switch (error) {
323         case BRE_NONE:
324                 return "No error";
325         
326         case BRE_UNABLE_TO_OPEN:
327                 return "Unable to open";
328         case BRE_UNABLE_TO_READ:
329                 return "Unable to read";
330                 
331         case BRE_OUT_OF_MEMORY:
332                 return "Out of memory";
333         case BRE_INTERNAL_ERROR:
334                 return "<internal error>";
335
336         case BRE_NOT_A_BLEND:
337                 return "File is not a Blender file";
338         case BRE_NOT_A_PUBFILE:
339                 return "File is not a compressed, locked or signed Blender file";
340         case BRE_INCOMPLETE:
341                 return "File incomplete";
342         case BRE_CORRUPT:
343                 return "File corrupt";
344
345         case BRE_TOO_NEW:
346                 return "File needs newer Blender version, please upgrade";
347         case BRE_NOT_ALLOWED:
348                 return "File is locked";
349                                                 
350         case BRE_NO_SCREEN:
351                 return "File has no screen";
352         case BRE_NO_SCENE:
353                 return "File has no scene";
354                 
355         default:
356         case BRE_INVALID:
357                 return "<invalid read error>";
358         }
359 }