Initial revision
[blender.git] / source / blender / blenkernel / intern / group.c
1 /*  group.c   sept 2000
2  *  - cleaned up mar-01 nzc 
3  * 
4  * 
5  *  ton roosendaal
6  * $Id$
7  *
8  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version. The Blender
14  * Foundation also sells licenses for use in proprietary software under
15  * the Blender License.  See http://www.blender.org/BL/ for information
16  * about this.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
28  * All rights reserved.
29  *
30  * The Original Code is: all of this file.
31  *
32  * Contributor(s): none yet.
33  *
34  * ***** END GPL/BL DUAL LICENSE BLOCK *****
35  */
36
37 #include <stdio.h>
38 #include <string.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_ID.h"
43 #include "DNA_group_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_ipo_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BKE_global.h"
49 #include "BKE_main.h"
50
51 #include "BKE_library.h"
52 #include "BKE_group.h"
53 #include "BKE_object.h"
54 #include "BKE_ipo.h"
55
56 void free_object_key(ObjectKey *ok)
57 {
58         if(ok->ipo) ok->ipo->id.us--;
59         
60         MEM_freeN(ok);
61 }
62
63 void free_group_object(GroupObject *go)
64 {
65         ObjectKey *ok;
66         
67         while(go->okey.first) {
68                 ok= go->okey.first;
69                 BLI_remlink(&go->okey, ok);
70                 free_object_key(ok);
71         }
72         MEM_freeN(go);
73 }
74
75
76 void free_group(Group *group)
77 {
78         /* don't free group itself */
79         GroupObject *go;
80         
81         BLI_freelistN(&group->gkey);
82         
83         while(group->gobject.first) {
84                 go= group->gobject.first;
85                 BLI_remlink(&group->gobject, go);
86                 free_group_object(go);
87         }
88         
89 }
90
91 Group *add_group()
92 {
93         Group *group;
94         
95         group = alloc_libblock(&G.main->group, ID_GR, "Group");
96         return group;
97 }
98
99 /* assumes 'ok' is unitialized */
100 void object_to_obkey(Object *ob, ObjectKey *ok)
101 {
102         ok->partype= ob->partype;
103         ok->par1= ob->par1;
104         ok->par2= ob->par2;
105         ok->par3= ob->par3;
106         
107         ok->parent= ob->parent;
108         ok->track= ob->track;
109         
110         ok->ipo= copy_ipo(ob->ipo);
111         
112         memcpy(ok->loc, ob->loc, 7*3*sizeof(float));
113         memcpy(ok->quat, ob->quat, 2*4*sizeof(float));
114         memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float));
115         
116         ok->lay= ob->lay;
117         ok->transflag= ob->transflag;
118         ok->trackflag= ob->transflag;
119         ok->upflag= ob->upflag;
120         ok->sf= ob->sf;
121         ok->ctime= ob->ctime;
122
123         
124 }
125
126 void obkey_to_object(ObjectKey *ok, Object *ob)
127 {
128         ob->partype= ok->partype;
129         ob->par1= ok->par1;
130         ob->par2= ok->par2;
131         ob->par3= ok->par3;
132         
133         ob->parent= ok->parent;
134         ob->track= ok->track;
135         
136         /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */
137         if(ob->ipo) {
138                 free_libblock_us(&G.main->ipo, ob->ipo);
139         }
140         ob->ipo= copy_ipo(ok->ipo);
141         
142         memcpy(ob->loc, ok->loc, 7*3*sizeof(float));
143         memcpy(ob->quat, ok->quat, 2*4*sizeof(float));
144         memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float));
145         
146         ob->lay= ok->lay;
147         ob->transflag= ok->transflag;
148         ob->trackflag= ok->transflag;
149         ob->upflag= ok->upflag;
150         ob->sf= ok->sf;
151         ob->ctime= ok->ctime;
152 }
153
154 /* current ob position */
155 void add_object_key(GroupObject *go, GroupKey *gk)
156 {
157         ObjectKey *ok;
158         
159         /* check if there already is a key */
160         ok= go->okey.first;
161         while(ok) {
162                 if(ok->gkey == gk) break;
163                 ok= ok->next;
164         }
165         
166         if(ok) {
167                 BLI_remlink(&go->okey, ok);
168                 free_object_key(ok);
169         }
170         ok= MEM_mallocN(sizeof(ObjectKey), "objectkey");
171         ok->gkey= gk;
172         
173         object_to_obkey(go->ob, ok);
174         
175         BLI_addtail(&go->okey, ok);
176         
177 }
178
179 /* external */
180 void add_to_group(Group *group, Object *ob)
181 {
182         GroupObject *go;
183         GroupKey *gk;
184         
185         /* check if the object has been added already */
186         go= group->gobject.first;
187         while(go) {
188                 if(go->ob==ob) return;
189                 go= go->next;
190         }
191         
192         go= MEM_callocN(sizeof(GroupObject), "groupobject");
193         BLI_addtail( &group->gobject, go);
194         
195         go->ob= ob;
196         
197         /* keys? */
198         gk= group->gkey.first;
199         while(gk) {
200                 add_object_key(go, gk);
201                 gk= gk->next;
202         }
203 }
204
205 void rem_from_group(Group *group, Object *ob)
206 {
207         GroupObject *go, *gon;
208         ObjectKey *ok;
209         
210         go= group->gobject.first;
211         while(go) {
212                 gon= go->next;
213                 if(go->ob==ob) {
214                         BLI_remlink(&group->gobject, go);
215                         free_group_object(go);
216                 }
217                 else {
218                         ok= go->okey.first;
219                         while(ok) {
220                                 if(ok->parent==ob) ok->parent= NULL;
221                                 if(ok->track==ob) ok->track= NULL;
222                                 ok= ok->next;
223                         }
224                 }
225                 go= gon;
226         }
227 }
228
229 void add_group_key(Group *group)
230 {
231         GroupObject *go;
232         GroupKey *gk;   
233         int nr=10;
234         extern char colname_array[][20]; /* material.c */
235
236         gk= group->gkey.first;
237         while(gk) {
238                 nr++;
239                 gk= gk->next;
240         }
241
242         gk= MEM_callocN(sizeof(GroupKey), "groupkey");
243         BLI_addtail(&group->gkey, gk);
244         strcpy(gk->name, colname_array[ nr % 120 ]);
245         
246         go= group->gobject.first;
247         while(go) {
248                 add_object_key(go, gk);
249                 go= go->next;
250         }
251         
252         group->active= gk;
253 }
254
255 void set_object_key(Object *ob, ObjectKey *ok)
256 {
257         obkey_to_object(ok, ob);        
258 }
259
260 void set_group_key(Group *group)
261 {
262         /* sets active */
263         GroupObject *go;
264         ObjectKey *ok;
265         
266         if(group->active==NULL) return;
267         
268         go= group->gobject.first;
269         while(go) {
270                 ok= go->okey.first;
271                 while(ok) {
272                         if(ok->gkey==group->active) {
273                                 set_object_key(go->ob, ok);
274                                 break;
275                         }
276                         ok= ok->next;
277                 }
278                 go= go->next;
279         }
280         
281 }
282
283 Group *find_group(Object *ob)
284 {
285         Group *group= G.main->group.first;
286         GroupObject *go;
287         
288         while(group) {
289
290                 go= group->gobject.first;
291                 while(go) {
292                         if(go->ob==ob) return group;
293                         go= go->next;
294                 }
295                 group= group->id.next;
296         }
297         return NULL;
298 }
299
300 void set_group_key_name(Group *group, char *name)
301 {
302         GroupKey *gk;
303         
304         if(group==NULL) return;
305         
306         gk= group->gkey.first;
307         while(gk) {
308                 if(strcmp(name, gk->name)==0) break;
309                 gk= gk->next;
310         }
311         
312         if(gk) {
313                 group->active= gk;
314                 set_group_key(group);
315         }
316 }
317
318 void set_group_key_frame(Group *group, float frame)
319 {
320         GroupObject *go;
321         
322         if(group==NULL) return;
323
324         go= group->gobject.first;
325         while(go) {
326                 where_is_object_time(go->ob, frame);
327                 go= go->next;
328         }
329 }