2.5 - Partial Bugfixes for Parenting Objects to Curves (Ctrl-P)
[blender-staging.git] / source / blender / editors / object / object_relations.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2008 full recode
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_anim_types.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_camera_types.h"
37 #include "DNA_constraint_types.h"
38 #include "DNA_curve_types.h"
39 #include "DNA_group_types.h"
40 #include "DNA_lamp_types.h"
41 #include "DNA_lattice_types.h"
42 #include "DNA_material_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_meta_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_particle_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_view3d_types.h"
49 #include "DNA_world_types.h"
50
51 #include "BLI_arithb.h"
52 #include "BLI_editVert.h"
53 #include "BLI_listbase.h"
54 #include "BLI_string.h"
55
56 #include "BKE_action.h"
57 #include "BKE_animsys.h"
58 #include "BKE_armature.h"
59 #include "BKE_context.h"
60 #include "BKE_constraint.h"
61 #include "BKE_curve.h"
62 #include "BKE_depsgraph.h"
63 #include "BKE_displist.h"
64 #include "BKE_global.h"
65 #include "BKE_lattice.h"
66 #include "BKE_library.h"
67 #include "BKE_main.h"
68 #include "BKE_material.h"
69 #include "BKE_mball.h"
70 #include "BKE_mesh.h"
71 #include "BKE_modifier.h"
72 #include "BKE_object.h"
73 #include "BKE_report.h"
74 #include "BKE_sca.h"
75 #include "BKE_texture.h"
76 #include "BKE_utildefines.h"
77
78 #include "WM_api.h"
79 #include "WM_types.h"
80
81 #include "UI_interface.h"
82 #include "UI_resources.h"
83
84 #include "RNA_access.h"
85 #include "RNA_define.h"
86
87 #include "ED_anim_api.h"
88 #include "ED_armature.h"
89 #include "ED_curve.h"
90 #include "ED_object.h"
91 #include "ED_screen.h"
92
93 #include "object_intern.h"
94
95 /* ************* XXX **************** */
96 static int pupmenu(const char *msg) {return 0;}
97 static int pupmenu_col(const char *msg, int val) {return 0;}
98
99 /*********************** Make Vertex Parent Operator ************************/
100
101 static int vertex_parent_set_poll(bContext *C)
102 {
103         return ED_operator_editmesh(C) || ED_operator_editsurfcurve(C) || ED_operator_editlattice(C);
104 }
105
106 static int vertex_parent_set_exec(bContext *C, wmOperator *op)
107 {
108         Scene *scene= CTX_data_scene(C);
109         Object *obedit= CTX_data_edit_object(C);
110         EditVert *eve;
111         Curve *cu;
112         Nurb *nu;
113         BezTriple *bezt;
114         BPoint *bp;
115         Object *par;
116         int a, v1=0, v2=0, v3=0, v4=0, nr=1;
117         
118         /* we need 1 to 3 selected vertices */
119         
120         if(obedit->type==OB_MESH) {
121                 Mesh *me= obedit->data;
122                 EditMesh *em = BKE_mesh_get_editmesh(me);
123
124                 eve= em->verts.first;
125                 while(eve) {
126                         if(eve->f & 1) {
127                                 if(v1==0) v1= nr;
128                                 else if(v2==0) v2= nr;
129                                 else if(v3==0) v3= nr;
130                                 else if(v4==0) v4= nr;
131                                 else break;
132                         }
133                         nr++;
134                         eve= eve->next;
135                 }
136
137                 BKE_mesh_end_editmesh(me, em);
138         }
139         else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
140                 ListBase *editnurb= curve_get_editcurve(obedit);
141                 
142                 cu= obedit->data;
143
144                 nu= editnurb->first;
145                 while(nu) {
146                         if(nu->type == CU_BEZIER) {
147                                 bezt= nu->bezt;
148                                 a= nu->pntsu;
149                                 while(a--) {
150                                         if(BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
151                                                 if(v1==0) v1= nr;
152                                                 else if(v2==0) v2= nr;
153                                                 else if(v3==0) v3= nr;
154                                                 else if(v4==0) v4= nr;
155                                                 else break;
156                                         }
157                                         nr++;
158                                         bezt++;
159                                 }
160                         }
161                         else {
162                                 bp= nu->bp;
163                                 a= nu->pntsu*nu->pntsv;
164                                 while(a--) {
165                                         if(bp->f1 & SELECT) {
166                                                 if(v1==0) v1= nr;
167                                                 else if(v2==0) v2= nr;
168                                                 else if(v3==0) v3= nr;
169                                                 else if(v4==0) v4= nr;
170                                                 else break;
171                                         }
172                                         nr++;
173                                         bp++;
174                                 }
175                         }
176                         nu= nu->next;
177                 }
178         }
179         else if(obedit->type==OB_LATTICE) {
180                 Lattice *lt= obedit->data;
181                 
182                 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
183                 bp= lt->editlatt->def;
184                 while(a--) {
185                         if(bp->f1 & SELECT) {
186                                 if(v1==0) v1= nr;
187                                 else if(v2==0) v2= nr;
188                                 else if(v3==0) v3= nr;
189                                 else if(v4==0) v4= nr;
190                                 else break;
191                         }
192                         nr++;
193                         bp++;
194                 }
195         }
196         
197         if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
198                 BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
199                 return OPERATOR_CANCELLED;
200         }
201         
202         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
203                 if(ob != obedit) {
204                         ob->recalc |= OB_RECALC;
205                         par= obedit->parent;
206                         
207                         while(par) {
208                                 if(par==ob) break;
209                                 par= par->parent;
210                         }
211                         if(par) {
212                                 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
213                         }
214                         else {
215                                 Object workob;
216                                 
217                                 ob->parent= BASACT->object;
218                                 if(v3) {
219                                         ob->partype= PARVERT3;
220                                         ob->par1= v1-1;
221                                         ob->par2= v2-1;
222                                         ob->par3= v3-1;
223
224                                         /* inverse parent matrix */
225                                         what_does_parent(scene, ob, &workob);
226                                         Mat4Invert(ob->parentinv, workob.obmat);
227                                 }
228                                 else {
229                                         ob->partype= PARVERT1;
230                                         ob->par1= v1-1;
231
232                                         /* inverse parent matrix */
233                                         what_does_parent(scene, ob, &workob);
234                                         Mat4Invert(ob->parentinv, workob.obmat);
235                                 }
236                         }
237                 }
238         }
239         CTX_DATA_END;
240         
241         DAG_scene_sort(scene);
242
243         WM_event_add_notifier(C, NC_OBJECT, NULL);
244
245         return OPERATOR_FINISHED;
246 }
247
248 void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
249 {
250         /* identifiers */
251         ot->name= "Make Vertex Parent";
252         ot->description = "Parent selected objects to the selected vertices.";
253         ot->idname= "OBJECT_OT_vertex_parent_set";
254         
255         /* api callbacks */
256         ot->poll= vertex_parent_set_poll;
257         ot->exec= vertex_parent_set_exec;
258         
259         /* flags */
260         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
261 }
262
263 /********************** Make Proxy Operator *************************/
264
265 /* present menu listing the possible objects within the group to proxify */
266 static void proxy_group_objects_menu (bContext *C, wmOperator *op, Object *ob, Group *group)
267 {
268         uiPopupMenu *pup;
269         uiLayout *layout;
270         GroupObject *go;
271         int len=0;
272         
273         /* check if there are any objects within the group to assign for */
274         for (go= group->gobject.first; go; go= go->next) {
275                 if (go->ob) len++;
276         }
277         if (len==0) return;
278         
279         /* now create the menu to draw */
280         pup= uiPupMenuBegin(C, "Make Proxy For:", 0);
281         layout= uiPupMenuLayout(pup);
282         
283         for (go= group->gobject.first; go; go= go->next) {
284                 if (go->ob) {
285                         PointerRNA props_ptr;
286                         
287                         /* create operator menu item with relevant properties filled in */
288                         props_ptr= uiItemFullO(layout, go->ob->id.name+2, 0, op->idname, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
289                         RNA_string_set(&props_ptr, "object", go->ob->id.name+2);
290                         RNA_string_set(&props_ptr, "group_object", go->ob->id.name+2);
291                 }
292         }
293         
294         /* display the menu, and be done */
295         uiPupMenuEnd(C, pup);
296 }
297
298 /* set the object to proxify */
299 static int make_proxy_invoke (bContext *C, wmOperator *op, wmEvent *evt)
300 {
301         Scene *scene= CTX_data_scene(C);
302         Object *ob= CTX_data_active_object(C);
303         
304         /* sanity checks */
305         if (!scene || scene->id.lib || !ob)
306                 return OPERATOR_CANCELLED;
307                 
308         /* Get object to work on - use a menu if we need to... */
309         if (ob->dup_group && ob->dup_group->id.lib) {
310                 /* gives menu with list of objects in group */
311                 proxy_group_objects_menu(C, op, ob, ob->dup_group);
312         }
313         else if (ob->id.lib) {
314                 uiPopupMenu *pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
315                 uiLayout *layout= uiPupMenuLayout(pup);
316                 PointerRNA props_ptr;
317                 
318                 /* create operator menu item with relevant properties filled in */
319                 props_ptr= uiItemFullO(layout, op->type->name, 0, op->idname, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
320                 RNA_string_set(&props_ptr, "object", ob->id.name+2);
321                 
322                 /* present the menu and be done... */
323                 uiPupMenuEnd(C, pup);
324         }
325         else {
326                 /* error.. cannot continue */
327                 BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
328         }
329         
330         /* this invoke just calls another instance of this operator... */
331         return OPERATOR_CANCELLED;
332 }
333
334 static int make_proxy_exec (bContext *C, wmOperator *op)
335 {
336         Object *ob=NULL, *gob=NULL;
337         Scene *scene= CTX_data_scene(C);
338         char ob_name[21], gob_name[21];
339         
340         /* get object and group object
341          *      - firstly names
342          *      - then pointers from context 
343          */
344         RNA_string_get(op->ptr, "object", ob_name);
345         RNA_string_get(op->ptr, "group_object", gob_name);
346         
347         if (gob_name[0]) {
348                 Group *group;
349                 GroupObject *go;
350                 
351                 /* active object is group object... */
352                 // FIXME: we should get the nominated name instead
353                 gob= CTX_data_active_object(C);
354                 group= gob->dup_group;
355                 
356                 /* find the object to affect */
357                 for (go= group->gobject.first; go; go= go->next) {
358                         if ((go->ob) && strcmp(go->ob->id.name+2, gob_name)==0) {
359                                 ob= go->ob;
360                                 break;
361                         }
362                 }
363         }
364         else {
365                 /* just use the active object for now */
366                 // FIXME: we should get the nominated name instead
367                 ob= CTX_data_active_object(C);
368         }
369         
370         if (ob) {
371                 Object *newob;
372                 Base *newbase, *oldbase= BASACT;
373                 char name[32];
374                 
375                 /* Add new object for the proxy */
376                 newob= add_object(scene, OB_EMPTY);
377                 if (gob)
378                         strcpy(name, gob->id.name+2);
379                 else
380                         strcpy(name, ob->id.name+2);
381                 strcat(name, "_proxy");
382                 rename_id(&newob->id, name);
383                 
384                 /* set layers OK */
385                 newbase= BASACT;        /* add_object sets active... */
386                 newbase->lay= oldbase->lay;
387                 newob->lay= newbase->lay;
388                 
389                 /* remove base, leave user count of object, it gets linked in object_make_proxy */
390                 if (gob==NULL) {
391                         BLI_remlink(&scene->base, oldbase);
392                         MEM_freeN(oldbase);
393                 }
394                 
395                 object_make_proxy(newob, ob, gob);
396                 
397                 /* depsgraph flushes are needed for the new data */
398                 DAG_scene_sort(scene);
399                 DAG_id_flush_update(&newob->id, OB_RECALC);
400                 
401                 WM_event_add_notifier(C, NC_OBJECT, NULL);
402         }
403         else {
404                 BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
405                 return OPERATOR_CANCELLED;
406         }
407         
408         return OPERATOR_FINISHED;
409 }
410
411 void OBJECT_OT_proxy_make (wmOperatorType *ot)
412 {
413         /* identifiers */
414         ot->name= "Make Proxy";
415         ot->idname= "OBJECT_OT_proxy_make";
416         ot->description= "Add empty object to become local replacement data of a library-linked object";
417         
418         /* callbacks */
419         ot->invoke= make_proxy_invoke;
420         ot->exec= make_proxy_exec;
421         ot->poll= ED_operator_object_active;
422         
423         /* flags */
424         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
425         
426         /* properties */
427         RNA_def_string(ot->srna, "object", "", 19, "Proxy Object", "Name of lib-linked/grouped object to make a proxy for.");
428         RNA_def_string(ot->srna, "group_object", "", 19, "Group Object", "Name of group instancer (if applicable).");
429 }
430
431 /********************** Clear Parent Operator ******************* */
432
433 static EnumPropertyItem prop_clear_parent_types[] = {
434         {0, "CLEAR", 0, "Clear Parent", ""},
435         {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
436         {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
437         {0, NULL, 0, NULL, NULL}
438 };
439
440 /* note, poll should check for editable scene */
441 static int parent_clear_exec(bContext *C, wmOperator *op)
442 {
443         int type= RNA_enum_get(op->ptr, "type");
444         
445         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
446
447                 if(type == 0) {
448                         ob->parent= NULL;
449                 }                       
450                 else if(type == 1) {
451                         ob->parent= NULL;
452                         ob->track= NULL;
453                         ED_object_apply_obmat(ob);
454                 }
455                 else if(type == 2)
456                         Mat4One(ob->parentinv);
457
458                 ob->recalc |= OB_RECALC;
459         }
460         CTX_DATA_END;
461         
462         DAG_scene_sort(CTX_data_scene(C));
463         ED_anim_dag_flush_update(C);
464         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
465
466         return OPERATOR_FINISHED;
467 }
468
469 void OBJECT_OT_parent_clear(wmOperatorType *ot)
470 {
471         /* identifiers */
472         ot->name= "Clear Parent";
473         ot->description = "Clear the object's parenting.";
474         ot->idname= "OBJECT_OT_parent_clear";
475         
476         /* api callbacks */
477         ot->invoke= WM_menu_invoke;
478         ot->exec= parent_clear_exec;
479         
480         ot->poll= ED_operator_object_active;
481         
482         /* flags */
483         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
484         
485         RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
486 }
487
488 /* ******************** Make Parent Operator *********************** */
489
490 #define PAR_OBJECT                              0
491 #define PAR_ARMATURE                    1
492 #define PAR_ARMATURE_NAME               2
493 #define PAR_ARMATURE_ENVELOPE   3
494 #define PAR_ARMATURE_AUTO               4
495 #define PAR_BONE                                5
496 #define PAR_CURVE                               6
497 #define PAR_FOLLOW                              7
498 #define PAR_PATH_CONST                  8
499 #define PAR_LATTICE                             9
500 #define PAR_VERTEX                              10
501 #define PAR_TRIA                                11
502
503 static EnumPropertyItem prop_make_parent_types[] = {
504         {PAR_OBJECT, "OBJECT", 0, "Object", ""},
505         {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
506         {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, "   With Empty Groups", ""},
507         {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, "   With Automatic Weights", ""},
508         {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, "   With Envelope Weights", ""},
509         {PAR_BONE, "BONE", 0, "Bone", ""},
510         {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
511         {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
512         {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
513         {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
514         {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
515         {PAR_TRIA, "TRIA", 0, "Triangle", ""},
516         {0, NULL, 0, NULL, NULL}
517 };
518
519 static int test_parent_loop(Object *par, Object *ob)
520 {
521         /* test if 'ob' is a parent somewhere in par's parents */
522         
523         if(par == NULL) return 0;
524         if(ob == par) return 1;
525         
526         return test_parent_loop(par->parent, ob);
527 }
528
529 void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
530 {
531         if(!par || test_parent_loop(par, ob)) {
532                 ob->parent= NULL;
533                 ob->partype= PAROBJECT;
534                 ob->parsubstr[0]= 0;
535                 return;
536         }
537
538         /* this could use some more checks */
539
540         ob->parent= par;
541         ob->partype &= ~PARTYPE;
542         ob->partype |= type;
543         BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
544 }
545
546 static int parent_set_exec(bContext *C, wmOperator *op)
547 {
548         Scene *scene= CTX_data_scene(C);
549         Object *par= CTX_data_active_object(C);
550         bPoseChannel *pchan= NULL;
551         int partype= RNA_enum_get(op->ptr, "type");
552         int pararm= ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
553         
554         par->recalc |= OB_RECALC_OB;
555         
556         /* preconditions */
557         if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
558                 if(par->type!=OB_CURVE)
559                         return OPERATOR_CANCELLED;
560                 else {
561                         Curve *cu= par->data;
562                         
563                         if((cu->flag & CU_PATH)==0) {
564                                 cu->flag |= CU_PATH|CU_FOLLOW;
565                                 makeDispListCurveTypes(scene, par, 0);  /* force creation of path data */
566                         }
567                         else cu->flag |= CU_FOLLOW;
568                         
569                         /* fall back on regular parenting now (for follow only) */
570                         if(partype == PAR_FOLLOW)
571                                 partype= PAR_OBJECT;
572                 }               
573         }
574         else if(partype==PAR_BONE) {
575                 pchan= get_active_posechannel(par);
576                 
577                 if(pchan==NULL) {
578                         BKE_report(op->reports, RPT_ERROR, "No active Bone");
579                         return OPERATOR_CANCELLED;
580                 }
581         }
582         
583         /* context itterator */
584         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
585                 
586                 if(ob!=par) {
587                         
588                         if( test_parent_loop(par, ob) ) {
589                                 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
590                         }
591                         else {
592                                 Object workob;
593                                 
594                                 /* apply transformation of previous parenting */
595                                 ED_object_apply_obmat(ob);
596                                 
597                                 /* set the parent (except for follow-path constraint option) */
598                                 if(partype != PAR_PATH_CONST)
599                                         ob->parent= par;
600                                 
601                                 /* handle types */
602                                 if (pchan)
603                                         strcpy (ob->parsubstr, pchan->name);
604                                 else
605                                         ob->parsubstr[0]= 0;
606                                 
607                                 /* constraint */
608                                 if(partype == PAR_PATH_CONST) {
609                                         bConstraint *con;
610                                         bFollowPathConstraint *data;
611                                         float cmat[4][4], vec[3];
612                                         
613                                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
614                                         strcpy (con->name, "AutoPath");
615                                         
616                                         data = con->data;
617                                         data->tar = par;
618                                         
619                                         add_constraint_to_object(con, ob);
620                                         
621                                         get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
622                                         VecSubf(vec, ob->obmat[3], cmat[3]);
623                                         
624                                         ob->loc[0] = vec[0];
625                                         ob->loc[1] = vec[1];
626                                         ob->loc[2] = vec[2];
627                                 }
628                                 else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) {
629                                         if(partype == PAR_ARMATURE_NAME)
630                                                 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_NAME);
631                                         else if(partype == PAR_ARMATURE_ENVELOPE)
632                                                 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_ENVELOPE);
633                                         else if(partype == PAR_ARMATURE_AUTO)
634                                                 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_AUTO);
635                                         
636                                         /* get corrected inverse */
637                                         ob->partype= PAROBJECT;
638                                         what_does_parent(scene, ob, &workob);
639                                         
640                                         ob->partype= PARSKEL;
641
642                                         Mat4Invert(ob->parentinv, workob.obmat);
643                                 }
644                                 else {
645                                         /* calculate inverse parent matrix */
646                                         what_does_parent(scene, ob, &workob);
647                                         Mat4Invert(ob->parentinv, workob.obmat);
648                                 }
649                                 
650                                 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
651                                 
652                                 if(partype == PAR_PATH_CONST)
653                                         ; /* don't do anything here, since this is not technically "parenting" */
654                                 if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm )
655                                         ob->partype= PARSKEL; /* note, dna define, not operator property */
656                                 else if (partype == PAR_BONE)
657                                         ob->partype= PARBONE; /* note, dna define, not operator property */
658                                 else
659                                         ob->partype= PAROBJECT; /* note, dna define, not operator property */
660                         }
661                 }
662         }
663         CTX_DATA_END;
664         
665         DAG_scene_sort(CTX_data_scene(C));
666         ED_anim_dag_flush_update(C);
667         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
668         
669         return OPERATOR_FINISHED;
670 }
671
672 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
673 {
674         Object *ob= CTX_data_active_object(C);
675         uiPopupMenu *pup= uiPupMenuBegin(C, "Set Parent To", 0);
676         uiLayout *layout= uiPupMenuLayout(pup);
677         
678         uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
679         uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
680         
681         /* ob becomes parent, make the associated menus */
682         if(ob->type==OB_ARMATURE) {
683                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
684                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_NAME);
685                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_ENVELOPE);
686                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_AUTO);
687                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
688         }
689         else if(ob->type==OB_CURVE) {
690                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
691                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
692                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
693         }
694         else if(ob->type == OB_LATTICE) {
695                 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
696         }
697         
698         uiPupMenuEnd(C, pup);
699         
700         return OPERATOR_CANCELLED;
701 }
702
703
704 void OBJECT_OT_parent_set(wmOperatorType *ot)
705 {
706         /* identifiers */
707         ot->name= "Make Parent";
708         ot->description = "Set the object's parenting.";
709         ot->idname= "OBJECT_OT_parent_set";
710         
711         /* api callbacks */
712         ot->invoke= parent_set_invoke;
713         ot->exec= parent_set_exec;
714         
715         ot->poll= ED_operator_object_active;
716         
717         /* flags */
718         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
719         
720         RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
721 }
722
723 /************************ Clear Slow Parent Operator *********************/
724
725 static int object_slow_parent_clear_exec(bContext *C, wmOperator *op)
726 {
727         Scene *scene= CTX_data_scene(C);
728
729         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
730                 if(ob->parent) {
731                         if(ob->partype & PARSLOW) {
732                                 ob->partype -= PARSLOW;
733                                 where_is_object(scene, ob);
734                                 ob->partype |= PARSLOW;
735                                 ob->recalc |= OB_RECALC_OB;
736                         }
737                 }
738         }
739         CTX_DATA_END;
740
741         ED_anim_dag_flush_update(C);    
742         WM_event_add_notifier(C, NC_SCENE, scene);
743         
744         return OPERATOR_FINISHED;
745 }
746
747 void OBJECT_OT_slow_parent_clear(wmOperatorType *ot)
748 {
749         
750         /* identifiers */
751         ot->name= "Clear Slow Parent";
752         ot->description = "Clear the object's slow parent.";
753         ot->idname= "OBJECT_OT_slow_parent_clear";
754         
755         /* api callbacks */
756         ot->invoke= WM_operator_confirm;
757         ot->exec= object_slow_parent_clear_exec;
758         ot->poll= ED_operator_view3d_active;
759         
760         /* flags */
761         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
762 }
763
764 /********************** Make Slow Parent Operator *********************/
765
766 static int object_slow_parent_set_exec(bContext *C, wmOperator *op)
767 {
768         Scene *scene= CTX_data_scene(C);
769
770         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
771                 if(ob->parent)
772                         ob->partype |= PARSLOW;
773
774                 ob->recalc |= OB_RECALC_OB;
775                 
776         }
777         CTX_DATA_END;
778
779         ED_anim_dag_flush_update(C);    
780         WM_event_add_notifier(C, NC_SCENE, scene);
781         
782         return OPERATOR_FINISHED;
783 }
784
785 void OBJECT_OT_slow_parent_set(wmOperatorType *ot)
786 {
787         
788         /* identifiers */
789         ot->name= "Set Slow Parent";
790         ot->description = "Set the object's slow parent.";
791         ot->idname= "OBJECT_OT_slow_parent_set";
792         
793         /* api callbacks */
794         ot->invoke= WM_operator_confirm;
795         ot->exec= object_slow_parent_set_exec;
796         ot->poll= ED_operator_view3d_active;
797         
798         /* flags */
799         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
800 }
801
802 /* ******************** Clear Track Operator ******************* */
803
804 static EnumPropertyItem prop_clear_track_types[] = {
805         {0, "CLEAR", 0, "Clear Track", ""},
806         {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
807         {0, NULL, 0, NULL, NULL}
808 };
809
810 /* note, poll should check for editable scene */
811 static int object_track_clear_exec(bContext *C, wmOperator *op)
812 {
813         int type= RNA_enum_get(op->ptr, "type");
814
815         if(CTX_data_edit_object(C)) {
816                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
817                 return OPERATOR_CANCELLED;
818         }
819         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
820                 ob->track= NULL;
821                 ob->recalc |= OB_RECALC;
822                 
823                 if(type == 1)
824                         ED_object_apply_obmat(ob);
825         }
826         CTX_DATA_END;
827
828         DAG_scene_sort(CTX_data_scene(C));
829         ED_anim_dag_flush_update(C);
830
831         return OPERATOR_FINISHED;
832 }
833
834 void OBJECT_OT_track_clear(wmOperatorType *ot)
835 {
836         /* identifiers */
837         ot->name= "Clear track";
838         ot->description = "Clear tracking constraint or flag from object.";
839         ot->idname= "OBJECT_OT_track_clear";
840         
841         /* api callbacks */
842         ot->invoke= WM_menu_invoke;
843         ot->exec= object_track_clear_exec;
844         
845         ot->poll= ED_operator_scene_editable;
846         
847         /* flags */
848         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
849         
850         RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
851 }
852
853 /************************** Make Track Operator *****************************/
854
855 static EnumPropertyItem prop_make_track_types[] = {
856         {1, "TRACKTO", 0, "TrackTo Constraint", ""},
857         {2, "LOCKTRACK", 0, "LockTrack Constraint", ""},
858         {3, "OLDTRACK", 0, "Old Track", ""},
859         {0, NULL, 0, NULL, NULL}
860 };
861
862 static int track_set_exec(bContext *C, wmOperator *op)
863 {
864         Scene *scene= CTX_data_scene(C);
865         int type= RNA_enum_get(op->ptr, "type");
866                 
867         if(type == 1) {
868                 bConstraint *con;
869                 bTrackToConstraint *data;
870
871                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
872                         if(base!=BASACT) {
873                                 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
874                                 strcpy (con->name, "AutoTrack");
875
876                                 data = con->data;
877                                 data->tar = BASACT->object;
878                                 base->object->recalc |= OB_RECALC;
879                                 
880                                 /* Lamp and Camera track differently by default */
881                                 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
882                                         data->reserved1 = TRACK_nZ;
883                                         data->reserved2 = UP_Y;
884                                 }
885
886                                 add_constraint_to_object(con, base->object);
887                         }
888                 }
889                 CTX_DATA_END;
890         }
891         else if(type == 2) {
892                 bConstraint *con;
893                 bLockTrackConstraint *data;
894
895                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
896                         if(base!=BASACT) {
897                                 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
898                                 strcpy (con->name, "AutoTrack");
899
900                                 data = con->data;
901                                 data->tar = BASACT->object;
902                                 base->object->recalc |= OB_RECALC;
903                                 
904                                 /* Lamp and Camera track differently by default */
905                                 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
906                                         data->trackflag = TRACK_nZ;
907                                         data->lockflag = LOCK_Y;
908                                 }
909
910                                 add_constraint_to_object(con, base->object);
911                         }
912                 }
913                 CTX_DATA_END;
914         }
915         else {
916                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
917                         if(base!=BASACT) {
918                                 base->object->track= BASACT->object;
919                                 base->object->recalc |= OB_RECALC;
920                         }
921                 }
922                 CTX_DATA_END;
923         }
924         DAG_scene_sort(CTX_data_scene(C));
925         ED_anim_dag_flush_update(C);    
926         
927         return OPERATOR_FINISHED;
928 }
929
930 void OBJECT_OT_track_set(wmOperatorType *ot)
931 {
932         /* identifiers */
933         ot->name= "Make Track";
934         ot->description = "Make the object track another object, either by constraint or old way or locked track.";
935         ot->idname= "OBJECT_OT_track_set";
936         
937         /* api callbacks */
938         ot->invoke= WM_menu_invoke;
939         ot->exec= track_set_exec;
940         
941         ot->poll= ED_operator_scene_editable;
942         
943         /* flags */
944         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
945         
946         /* properties */
947         RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
948 }
949
950 /************************** Move to Layer Operator *****************************/
951
952 static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
953 {
954         int values[20], a;
955         unsigned int lay= 0;
956
957         if(!RNA_property_is_set(op->ptr, "layer")) {
958                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
959                         lay |= base->lay;
960                 }
961                 CTX_DATA_END;
962
963                 for(a=0; a<20; a++)
964                         values[a]= (lay & (1<<a));
965                 
966                 RNA_boolean_set_array(op->ptr, "layer", values);
967         }
968         else {
969                 RNA_boolean_get_array(op->ptr, "layer", values);
970
971                 for(a=0; a<20; a++)
972                         if(values[a])
973                                 lay |= (1 << a);
974         }
975
976         return lay;
977 }
978
979 static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event)
980 {
981         move_to_layer_init(C, op);
982         return WM_operator_props_popup(C, op, event);
983 }
984
985 static int move_to_layer_exec(bContext *C, wmOperator *op)
986 {
987         Scene *scene= CTX_data_scene(C);
988         View3D *v3d= CTX_wm_view3d(C);
989         unsigned int lay, local;
990         int islamp= 0;
991         
992         lay= move_to_layer_init(C, op);
993         lay &= 0xFFFFFF;
994
995         if(lay==0) return OPERATOR_CANCELLED;
996         
997         if(v3d && v3d->localview) {
998                 /* now we can move out of localview. */
999                 // XXX if (!okee("Move from localview")) return;
1000                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
1001                         lay= base->lay & ~v3d->lay;
1002                         base->lay= lay;
1003                         base->object->lay= lay;
1004                         base->object->flag &= ~SELECT;
1005                         base->flag &= ~SELECT;
1006                         if(base->object->type==OB_LAMP) islamp= 1;
1007                 }
1008                 CTX_DATA_END;
1009         }
1010         else {
1011                 /* normal non localview operation */
1012                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
1013                         /* upper byte is used for local view */
1014                         local= base->lay & 0xFF000000;  
1015                         base->lay= lay + local;
1016                         base->object->lay= lay;
1017                         if(base->object->type==OB_LAMP) islamp= 1;
1018                 }
1019                 CTX_DATA_END;
1020         }
1021
1022         if(islamp) reshadeall_displist(scene);  /* only frees */
1023         
1024         /* warning, active object may be hidden now */
1025         
1026         WM_event_add_notifier(C, NC_SCENE, scene);
1027         DAG_scene_sort(scene);
1028
1029         return OPERATOR_FINISHED;
1030 }
1031
1032 void OBJECT_OT_move_to_layer(wmOperatorType *ot)
1033 {
1034         /* identifiers */
1035         ot->name= "Move to Layer";
1036         ot->description = "Move the object to different layers.";
1037         ot->idname= "OBJECT_OT_move_to_layer";
1038         
1039         /* api callbacks */
1040         ot->invoke= move_to_layer_invoke;
1041         ot->exec= move_to_layer_exec;
1042         ot->poll= ED_operator_scene_editable;
1043         
1044         /* flags */
1045         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1046         
1047         /* properties */
1048         RNA_def_boolean_layer_member(ot->srna, "layer", 20, NULL, "Layer", "");
1049 }
1050
1051 /************************** Link to Scene Operator *****************************/
1052
1053 void link_to_scene(unsigned short nr)
1054 {
1055 #if 0
1056         Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
1057         Base *base, *nbase;
1058         
1059         if(sce==0) return;
1060         if(sce->id.lib) return;
1061         
1062         for(base= FIRSTBASE; base; base= base->next) {
1063                 if(TESTBASE(v3d, base)) {
1064                         
1065                         nbase= MEM_mallocN( sizeof(Base), "newbase");
1066                         *nbase= *base;
1067                         BLI_addhead( &(sce->base), nbase);
1068                         id_us_plus((ID *)base->object);
1069                 }
1070         }
1071 #endif
1072 }
1073
1074
1075 void make_links(bContext *C, wmOperator *op, Scene *scene, View3D *v3d, short event)
1076 {
1077         Object *ob, *obt;
1078         Base *base, *nbase, *sbase;
1079         Scene *sce = NULL;
1080         ID *id;
1081         int a;
1082         short nr=0;
1083         char *strp;
1084
1085         if(!(ob=OBACT)) return;
1086
1087         if(event==1) {
1088                 IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
1089                 
1090                 if(nr == -2) {
1091                         MEM_freeN(strp);
1092
1093 // XXX                  activate_databrowse((ID *)scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
1094                         
1095                         return;                 
1096                 }
1097                 else {
1098                         event= pupmenu_col(strp, 20);
1099                         MEM_freeN(strp);
1100                 
1101                         if(event<= 0) return;
1102                 
1103                         nr= 1;
1104                         sce= G.main->scene.first;
1105                         while(sce) {
1106                                 if(nr==event) break;
1107                                 nr++;
1108                                 sce= sce->id.next;
1109                         }
1110                         if(sce==scene) {
1111                                 BKE_report(op->reports, RPT_ERROR, "This is the current scene");
1112                                 return;
1113                         }
1114                         if(sce==0 || sce->id.lib) return;
1115                         
1116                         /* remember: is needed below */
1117                         event= 1;
1118                 }
1119         }
1120
1121         /* All non group linking */
1122         for(base= FIRSTBASE; base; base= base->next) {
1123                 if(event==1 || base != BASACT) {
1124                         
1125                         obt= base->object;
1126
1127                         if(TESTBASE(v3d, base)) {
1128                                 
1129                                 if(event==1) {          /* to scene */
1130                                         
1131                                         /* test if already linked */
1132                                         sbase= sce->base.first;
1133                                         while(sbase) {
1134                                                 if(sbase->object==base->object) break;
1135                                                 sbase= sbase->next;
1136                                         }
1137                                         if(sbase) {     /* remove */
1138                                                 continue;
1139                                         }
1140                                         
1141                                         nbase= MEM_mallocN( sizeof(Base), "newbase");
1142                                         *nbase= *base;
1143                                         BLI_addhead( &(sce->base), nbase);
1144                                         id_us_plus((ID *)base->object);
1145                                 }
1146                         }
1147                         if(TESTBASELIB(v3d, base)) {
1148                                 if(event==2 || event==5) {  /* obdata */
1149                                         if(ob->type==obt->type) {
1150                                                 
1151                                                         id= obt->data;
1152                                                         id->us--;
1153                                                         
1154                                                         id= ob->data;
1155                                                         id_us_plus(id);
1156                                                         obt->data= id;
1157                                                         
1158                                                         /* if amount of material indices changed: */
1159                                                         test_object_materials(obt->data);
1160
1161                                                         obt->recalc |= OB_RECALC_DATA;
1162                                                 }
1163                                         }
1164                                 else if(event==4) {  /* ob ipo */
1165 #if 0 // XXX old animation system
1166                                         if(obt->ipo) obt->ipo->id.us--;
1167                                         obt->ipo= ob->ipo;
1168                                         if(obt->ipo) {
1169                                                 id_us_plus((ID *)obt->ipo);
1170                                                 do_ob_ipo(scene, obt);
1171                                         }
1172 #endif // XXX old animation system
1173                                 }
1174                                 else if(event==6) {
1175                                         if(ob->dup_group) ob->dup_group->id.us--;
1176                                         obt->dup_group= ob->dup_group;
1177                                         if(obt->dup_group) {
1178                                                 id_us_plus((ID *)obt->dup_group);
1179                                                 obt->transflag |= OB_DUPLIGROUP;
1180                                         }
1181                                 }
1182                                 else if(event==3) {  /* materials */
1183                                         
1184                                         /* new approach, using functions from kernel */
1185                                         for(a=0; a<ob->totcol; a++) {
1186                                                 Material *ma= give_current_material(ob, a+1);
1187                                                 assign_material(obt, ma, a+1);  /* also works with ma==NULL */
1188                                         }
1189                                 }
1190                         }
1191                 }
1192         }
1193         
1194         ED_anim_dag_flush_update(C);    
1195
1196 }
1197
1198 void make_links_menu(bContext *C, Scene *scene, View3D *v3d)
1199 {
1200         Object *ob;
1201         short event=0;
1202         char str[140];
1203         
1204         if(!(ob=OBACT)) return;
1205         
1206         strcpy(str, "Make Links %t|To Scene...%x1|%l|Object Ipo%x4");
1207         
1208         if(ob->type==OB_MESH)
1209                 strcat(str, "|Mesh Data%x2|Materials%x3");
1210         else if(ob->type==OB_CURVE)
1211                 strcat(str, "|Curve Data%x2|Materials%x3");
1212         else if(ob->type==OB_FONT)
1213                 strcat(str, "|Text Data%x2|Materials%x3");
1214         else if(ob->type==OB_SURF)
1215                 strcat(str, "|Surface Data%x2|Materials%x3");
1216         else if(ob->type==OB_MBALL)
1217                 strcat(str, "|Materials%x3");
1218         else if(ob->type==OB_CAMERA)
1219                 strcat(str, "|Camera Data%x2");
1220         else if(ob->type==OB_LAMP)
1221                 strcat(str, "|Lamp Data%x2");
1222         else if(ob->type==OB_LATTICE)
1223                 strcat(str, "|Lattice Data%x2");
1224         else if(ob->type==OB_ARMATURE)
1225                 strcat(str, "|Armature Data%x2");
1226         
1227         event= pupmenu(str);
1228         
1229         if(event<= 0) return;
1230         
1231         make_links(C, NULL, scene, v3d, event);
1232 }
1233
1234 /**************************** Make Single User ********************************/
1235
1236 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
1237 {
1238         ID_NEW(*obpoin);
1239 }
1240
1241 void single_object_users(Scene *scene, View3D *v3d, int flag)   
1242 {
1243         Base *base;
1244         Object *ob, *obn;
1245         
1246         clear_sca_new_poins();  /* sensor/contr/act */
1247
1248         /* duplicate (must set newid) */
1249         for(base= FIRSTBASE; base; base= base->next) {
1250                 ob= base->object;
1251                 
1252                 if( (base->flag & flag)==flag ) {
1253                         if(ob->id.lib==NULL && ob->id.us>1) {
1254                                 /* base gets copy of object */
1255                                 obn= copy_object(ob);
1256                                 base->object= obn;
1257                                 ob->id.us--;
1258                         }
1259                 }
1260         }
1261         
1262         ID_NEW(scene->camera);
1263         if(v3d) ID_NEW(v3d->camera);
1264         
1265         /* object pointers */
1266         for(base= FIRSTBASE; base; base= base->next) {
1267                 ob= base->object;
1268                 if(ob->id.lib==NULL) {
1269                         relink_constraints(&base->object->constraints);
1270                         if (base->object->pose){
1271                                 bPoseChannel *chan;
1272                                 for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
1273                                         relink_constraints(&chan->constraints);
1274                                 }
1275                         }
1276                         modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL);
1277                         
1278                         ID_NEW(ob->parent);
1279                         ID_NEW(ob->track);
1280                 }
1281         }
1282
1283         set_sca_new_poins();
1284 }
1285
1286 void new_id_matar(Material **matar, int totcol)
1287 {
1288         ID *id;
1289         int a;
1290         
1291         for(a=0; a<totcol; a++) {
1292                 id= (ID *)matar[a];
1293                 if(id && id->lib==0) {
1294                         if(id->newid) {
1295                                 matar[a]= (Material *)id->newid;
1296                                 id_us_plus(id->newid);
1297                                 id->us--;
1298                         }
1299                         else if(id->us>1) {
1300                                 matar[a]= copy_material(matar[a]);
1301                                 id->us--;
1302                                 id->newid= (ID *)matar[a];
1303                         }
1304                 }
1305         }
1306 }
1307
1308 void single_obdata_users(Scene *scene, int flag)
1309 {
1310         Object *ob;
1311         Lamp *la;
1312         Curve *cu;
1313         //Camera *cam;
1314         Base *base;
1315         Mesh *me;
1316         ID *id;
1317         int a;
1318
1319         for(base= FIRSTBASE; base; base= base->next) {
1320                 ob= base->object;
1321                 if(ob->id.lib==NULL && (base->flag & flag)==flag ) {
1322                         id= ob->data;
1323                         
1324                         if(id && id->us>1 && id->lib==0) {
1325                                 ob->recalc= OB_RECALC_DATA;
1326                                 
1327                                 switch(ob->type) {
1328                                 case OB_LAMP:
1329                                         if(id && id->us>1 && id->lib==NULL) {
1330                                                 ob->data= la= copy_lamp(ob->data);
1331                                                 for(a=0; a<MAX_MTEX; a++) {
1332                                                         if(la->mtex[a]) {
1333                                                                 ID_NEW(la->mtex[a]->object);
1334                                                         }
1335                                                 }
1336                                         }
1337                                         break;
1338                                 case OB_CAMERA:
1339                                         ob->data= copy_camera(ob->data);
1340                                         break;
1341                                 case OB_MESH:
1342                                         me= ob->data= copy_mesh(ob->data);
1343                                         //if(me && me->key)
1344                                         //      ipo_idnew(me->key->ipo);        /* drivers */
1345                                         break;
1346                                 case OB_MBALL:
1347                                         ob->data= copy_mball(ob->data);
1348                                         break;
1349                                 case OB_CURVE:
1350                                 case OB_SURF:
1351                                 case OB_FONT:
1352                                         ob->data= cu= copy_curve(ob->data);
1353                                         ID_NEW(cu->bevobj);
1354                                         ID_NEW(cu->taperobj);
1355                                         break;
1356                                 case OB_LATTICE:
1357                                         ob->data= copy_lattice(ob->data);
1358                                         break;
1359                                 case OB_ARMATURE:
1360                                         ob->recalc |= OB_RECALC_DATA;
1361                                         ob->data= copy_armature(ob->data);
1362                                         armature_rebuild_pose(ob, ob->data);
1363                                         break;
1364                                 default:
1365                                         printf("ERROR single_obdata_users: can't copy %s\n", id->name);
1366                                         return;
1367                                 }
1368                                 
1369                                 id->us--;
1370                                 id->newid= ob->data;
1371                                 
1372                         }
1373                         
1374 #if 0 // XXX old animation system
1375                         id= (ID *)ob->action;
1376                         if (id && id->us>1 && id->lib==NULL){
1377                                 if(id->newid){
1378                                         ob->action= (bAction *)id->newid;
1379                                         id_us_plus(id->newid);
1380                                 }
1381                                 else {
1382                                         ob->action= copy_action(ob->action);
1383                                         id->us--;
1384                                         id->newid=(ID *)ob->action;
1385                                 }
1386                         }
1387                         id= (ID *)ob->ipo;
1388                         if(id && id->us>1 && id->lib==NULL) {
1389                                 if(id->newid) {
1390                                         ob->ipo= (Ipo *)id->newid;
1391                                         id_us_plus(id->newid);
1392                                 }
1393                                 else {
1394                                         ob->ipo= copy_ipo(ob->ipo);
1395                                         id->us--;
1396                                         id->newid= (ID *)ob->ipo;
1397                                 }
1398                                 ipo_idnew(ob->ipo);     /* drivers */
1399                         }
1400                         /* other ipos */
1401                         switch(ob->type) {
1402                         case OB_LAMP:
1403                                 la= ob->data;
1404                                 if(la->ipo && la->ipo->id.us>1) {
1405                                         la->ipo->id.us--;
1406                                         la->ipo= copy_ipo(la->ipo);
1407                                         ipo_idnew(la->ipo);     /* drivers */
1408                                 }
1409                                 break;
1410                         case OB_CAMERA:
1411                                 cam= ob->data;
1412                                 if(cam->ipo && cam->ipo->id.us>1) {
1413                                         cam->ipo->id.us--;
1414                                         cam->ipo= copy_ipo(cam->ipo);
1415                                         ipo_idnew(cam->ipo);    /* drivers */
1416                                 }
1417                                 break;
1418                         }
1419 #endif // XXX old animation system
1420                 }
1421         }
1422         
1423         me= G.main->mesh.first;
1424         while(me) {
1425                 ID_NEW(me->texcomesh);
1426                 me= me->id.next;
1427         }
1428 }
1429
1430 void single_ipo_users(Scene *scene, int flag)
1431 {
1432 #if 0 // XXX old animation system
1433         Object *ob;
1434         Base *base;
1435         ID *id;
1436         
1437         for(base= FIRSTBASE; base; base= base->next) {
1438                 ob= base->object;
1439                 if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
1440                         ob->recalc= OB_RECALC_DATA;
1441                         
1442                         id= (ID *)ob->ipo;
1443                         if(id && id->us>1 && id->lib==NULL) {
1444                                 ob->ipo= copy_ipo(ob->ipo);
1445                                 id->us--;
1446                                 ipo_idnew(ob->ipo);     /* drivers */
1447                         }
1448                 }
1449         }
1450 #endif // XXX old animation system
1451 }
1452
1453 void single_mat_users(Scene *scene, int flag)
1454 {
1455         Object *ob;
1456         Base *base;
1457         Material *ma, *man;
1458         Tex *tex;
1459         int a, b;
1460         
1461         for(base= FIRSTBASE; base; base= base->next) {
1462                 ob= base->object;
1463                 if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
1464         
1465                         for(a=1; a<=ob->totcol; a++) {
1466                                 ma= give_current_material(ob, a);
1467                                 if(ma) {
1468                                         /* do not test for LIB_NEW: this functions guaranteed delivers single_users! */
1469                                         
1470                                         if(ma->id.us>1) {
1471                                                 man= copy_material(ma);
1472                                         
1473                                                 man->id.us= 0;
1474                                                 assign_material(ob, man, a);
1475         
1476 #if 0 // XXX old animation system                                               
1477                                                 if(ma->ipo) {
1478                                                         man->ipo= copy_ipo(ma->ipo);
1479                                                         ma->ipo->id.us--;
1480                                                         ipo_idnew(ma->ipo);     /* drivers */
1481                                                 }
1482 #endif // XXX old animation system
1483                                                 
1484                                                 for(b=0; b<MAX_MTEX; b++) {
1485                                                         if(ma->mtex[b] && ma->mtex[b]->tex) {
1486                                                                 tex= ma->mtex[b]->tex;
1487                                                                 if(tex->id.us>1) {
1488                                                                         ma->mtex[b]->tex= copy_texture(tex);
1489                                                                         tex->id.us--;
1490                                                                 }
1491                                                         }
1492                                                 }
1493                                                 
1494                                         }
1495                                 }
1496                         }
1497                 }
1498         }
1499 }
1500
1501 void do_single_tex_user(Tex **from)
1502 {
1503         Tex *tex, *texn;
1504         
1505         tex= *from;
1506         if(tex==0) return;
1507         
1508         if(tex->id.newid) {
1509                 *from= (Tex *)tex->id.newid;
1510                 id_us_plus(tex->id.newid);
1511                 tex->id.us--;
1512         }
1513         else if(tex->id.us>1) {
1514                 texn= copy_texture(tex);
1515                 tex->id.newid= (ID *)texn;
1516                 tex->id.us--;
1517                 *from= texn;
1518         }
1519 }
1520
1521 void single_tex_users_expand()
1522 {
1523         /* only when 'parent' blocks are LIB_NEW */
1524         Main *bmain= G.main;
1525         Material *ma;
1526         Lamp *la;
1527         World *wo;
1528         int b;
1529                 
1530         for(ma= bmain->mat.first; ma; ma=ma->id.next) {
1531                 if(ma->id.flag & LIB_NEW) {
1532                         for(b=0; b<MAX_MTEX; b++) {
1533                                 if(ma->mtex[b] && ma->mtex[b]->tex) {
1534                                         do_single_tex_user( &(ma->mtex[b]->tex) );
1535                                 }
1536                         }
1537                 }
1538         }
1539
1540         for(la= bmain->lamp.first; la; la=la->id.next) {
1541                 if(la->id.flag & LIB_NEW) {
1542                         for(b=0; b<MAX_MTEX; b++) {
1543                                 if(la->mtex[b] && la->mtex[b]->tex) {
1544                                         do_single_tex_user( &(la->mtex[b]->tex) );
1545                                 }
1546                         }
1547                 }
1548         }
1549
1550         for(wo= bmain->world.first; wo; wo=wo->id.next) {
1551                 if(wo->id.flag & LIB_NEW) {
1552                         for(b=0; b<MAX_MTEX; b++) {
1553                                 if(wo->mtex[b] && wo->mtex[b]->tex) {
1554                                         do_single_tex_user( &(wo->mtex[b]->tex) );
1555                                 }
1556                         }
1557                 }
1558         }
1559 }
1560
1561 static void single_mat_users_expand(void)
1562 {
1563         /* only when 'parent' blocks are LIB_NEW */
1564         Main *bmain= G.main;
1565         Object *ob;
1566         Mesh *me;
1567         Curve *cu;
1568         MetaBall *mb;
1569         Material *ma;
1570         int a;
1571         
1572         for(ob=bmain->object.first; ob; ob=ob->id.next)
1573                 if(ob->id.flag & LIB_NEW)
1574                         new_id_matar(ob->mat, ob->totcol);
1575
1576         for(me=bmain->mesh.first; me; me=me->id.next)
1577                 if(me->id.flag & LIB_NEW)
1578                         new_id_matar(me->mat, me->totcol);
1579
1580         for(cu=bmain->curve.first; cu; cu=cu->id.next)
1581                 if(cu->id.flag & LIB_NEW)
1582                         new_id_matar(cu->mat, cu->totcol);
1583
1584         for(mb=bmain->mball.first; mb; mb=mb->id.next)
1585                 if(mb->id.flag & LIB_NEW)
1586                         new_id_matar(mb->mat, mb->totcol);
1587
1588         /* material imats  */
1589         for(ma=bmain->mat.first; ma; ma=ma->id.next)
1590                 if(ma->id.flag & LIB_NEW)
1591                         for(a=0; a<MAX_MTEX; a++)
1592                                 if(ma->mtex[a])
1593                                         ID_NEW(ma->mtex[a]->object);
1594 }
1595
1596 void single_user(Scene *scene, View3D *v3d)
1597 {
1598         int nr;
1599         
1600         if(scene->id.lib) return;
1601
1602         clear_id_newpoins();
1603         
1604         nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex|Ipos");
1605         if(nr>0) {
1606         
1607                 if(nr==1) single_object_users(scene, v3d, 1);
1608         
1609                 else if(nr==2) {
1610                         single_object_users(scene, v3d, 1);
1611                         single_obdata_users(scene, 1);
1612                 }
1613                 else if(nr==3) {
1614                         single_object_users(scene, v3d, 1);
1615                         single_obdata_users(scene, 1);
1616                         single_mat_users(scene, 1); /* also tex */
1617                         
1618                 }
1619                 else if(nr==4) {
1620                         single_mat_users(scene, 1);
1621                 }
1622                 else if(nr==5) {
1623                         single_ipo_users(scene, 1);
1624                 }
1625                 
1626                 
1627                 clear_id_newpoins();
1628
1629         }
1630 }
1631
1632 /* used for copying scenes */
1633 void ED_object_single_users(Scene *scene, int full)
1634 {
1635     single_object_users(scene, NULL, 0);
1636
1637     if(full) {
1638         single_obdata_users(scene, 0);
1639         single_mat_users_expand();
1640         single_tex_users_expand();
1641     }
1642
1643         clear_id_newpoins();
1644 }
1645
1646 /******************************* Make Local ***********************************/
1647
1648 /* helper for below, ma was checked to be not NULL */
1649 static void make_local_makelocalmaterial(Material *ma)
1650 {
1651         AnimData *adt;
1652         int b;
1653         
1654         id_make_local(&ma->id, 0);
1655         
1656         for(b=0; b<MAX_MTEX; b++)
1657                 if(ma->mtex[b] && ma->mtex[b]->tex)
1658                         id_make_local(&ma->mtex[b]->tex->id, 0);
1659         
1660         adt= BKE_animdata_from_id(&ma->id);
1661         if(adt) BKE_animdata_make_local(adt);
1662
1663         /* nodetree? XXX */
1664 }
1665
1666 static int make_local_exec(bContext *C, wmOperator *op)
1667 {
1668         AnimData *adt;
1669         ParticleSystem *psys;
1670         Material *ma, ***matarar;
1671         Lamp *la;
1672         ID *id;
1673         int a, b, mode= RNA_boolean_get(op->ptr, "type");
1674         
1675         if(mode==3) {
1676                 all_local(NULL, 0);     /* NULL is all libs */
1677                 WM_event_add_notifier(C, NC_WINDOW, NULL);
1678                 return OPERATOR_FINISHED;
1679         }
1680
1681         clear_id_newpoins();
1682         
1683         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1684                 if(ob->id.lib)
1685                         id_make_local(&ob->id, 0);
1686         }
1687         CTX_DATA_END;
1688         
1689         /* maybe object pointers */
1690         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1691                 if(ob->id.lib==NULL) {
1692                         ID_NEW(ob->parent);
1693                         ID_NEW(ob->track);
1694                 }
1695         }
1696         CTX_DATA_END;
1697
1698         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1699                 id= ob->data;
1700                         
1701                 if(id && mode>1) {
1702                         id_make_local(id, 0);
1703                         adt= BKE_animdata_from_id(id);
1704                         if(adt) BKE_animdata_make_local(adt);
1705                 }
1706
1707                 for(psys=ob->particlesystem.first; psys; psys=psys->next)
1708                         id_make_local(&psys->part->id, 0);
1709
1710                 adt= BKE_animdata_from_id(&ob->id);
1711                 if(adt) BKE_animdata_make_local(adt);
1712         }
1713         CTX_DATA_END;
1714
1715         if(mode>1) {
1716                 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1717                         if(ob->type==OB_LAMP) {
1718                                 la= ob->data;
1719
1720                                 for(b=0; b<MAX_MTEX; b++)
1721                                         if(la->mtex[b] && la->mtex[b]->tex)
1722                                                 id_make_local(&la->mtex[b]->tex->id, 0);
1723                         }
1724                         else {
1725                                 for(a=0; a<ob->totcol; a++) {
1726                                         ma= ob->mat[a];
1727                                         if(ma)
1728                                                 make_local_makelocalmaterial(ma);
1729                                 }
1730                                 
1731                                 matarar= (Material ***)give_matarar(ob);
1732                                 if(matarar) {
1733                                         for(a=0; a<ob->totcol; a++) {
1734                                                 ma= (*matarar)[a];
1735                                                 if(ma)
1736                                                         make_local_makelocalmaterial(ma);
1737                                         }
1738                                 }
1739                         }
1740                 }
1741                 CTX_DATA_END;
1742         }
1743
1744         WM_event_add_notifier(C, NC_WINDOW, NULL);
1745
1746         return OPERATOR_FINISHED;
1747 }
1748
1749 void OBJECT_OT_make_local(wmOperatorType *ot)
1750 {
1751         static EnumPropertyItem type_items[]= {
1752                 {1, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
1753                 {2, "SELECTED_OBJECTS_DATA", 0, "Selected Objects and Data", ""},
1754                 {3, "ALL", 0, "All", ""},
1755                 {0, NULL, 0, NULL, NULL}};
1756
1757         /* identifiers */
1758         ot->name= "Make Local";
1759         ot->description = "Make library linked datablocks local to this file.";
1760         ot->idname= "OBJECT_OT_make_local";
1761         
1762         /* api callbacks */
1763         ot->invoke= WM_menu_invoke;
1764         ot->exec= make_local_exec;
1765         ot->poll= ED_operator_scene_editable;
1766         
1767         /* flags */
1768         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1769         
1770         /* properties */
1771         RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
1772 }
1773