merge with trunk/2.5 at r24378
[blender-staging.git] / source / blender / editors / object / object_relations.c
index c2550a6b1e8ea752504f9a228efd80f2867c9c42..adbeb196bc858f1bd1422b6ff94068f06f8b065e 100644 (file)
@@ -72,6 +72,7 @@
 #include "BKE_object.h"
 #include "BKE_report.h"
 #include "BKE_sca.h"
+#include "BKE_scene.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 
@@ -83,6 +84,7 @@
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
 #include "ED_anim_api.h"
 #include "ED_armature.h"
 
 #include "object_intern.h"
 
-/* ************* XXX **************** */
-static int pupmenu(const char *msg) {return 0;}
-static int pupmenu_col(const char *msg, int val) {return 0;}
-
 /*********************** Make Vertex Parent Operator ************************/
 
 static int vertex_parent_set_poll(bContext *C)
@@ -638,7 +636,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
                                        what_does_parent(scene, ob, &workob);
                                        
                                        ob->partype= PARSKEL;
-
+                                       
                                        Mat4Invert(ob->parentinv, workob.obmat);
                                }
                                else {
@@ -720,6 +718,59 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
 }
 
+/* ************ Make Parent Without Inverse Operator ******************* */
+
+static int parent_noinv_set_exec(bContext *C, wmOperator *op)
+{
+       Object *par= CTX_data_active_object(C);
+       
+       par->recalc |= OB_RECALC_OB;
+       
+       /* context itterator */
+       CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+               if (ob != par) {
+                       if (test_parent_loop(par, ob)) {
+                               BKE_report(op->reports, RPT_ERROR, "Loop in parents");
+                       }
+                       else {
+                               /* clear inverse matrix and also the object location */
+                               Mat4One(ob->parentinv);
+                               memset(ob->loc, 0, 3*sizeof(float));
+                               
+                               /* set recalc flags */
+                               ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
+                               
+                               /* set parenting type for object - object only... */
+                               ob->parent= par;
+                               ob->partype= PAROBJECT; /* note, dna define, not operator property */
+                       }
+               }
+       }
+       CTX_DATA_END;
+       
+       DAG_scene_sort(CTX_data_scene(C));
+       ED_anim_dag_flush_update(C);
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Make Parent without Inverse";
+       ot->description = "Set the object's parenting without setting the inverse parent correction.";
+       ot->idname= "OBJECT_OT_parent_no_inverse_set";
+       
+       /* api callbacks */
+       ot->invoke= WM_operator_confirm;
+       ot->exec= parent_noinv_set_exec;
+       ot->poll= ED_operator_object_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /************************ Clear Slow Parent Operator *********************/
 
 static int object_slow_parent_clear_exec(bContext *C, wmOperator *op)
@@ -862,28 +913,30 @@ static EnumPropertyItem prop_make_track_types[] = {
 static int track_set_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
+       Object *obact= CTX_data_active_object(C); 
+       
        int type= RNA_enum_get(op->ptr, "type");
                
        if(type == 1) {
                bConstraint *con;
                bTrackToConstraint *data;
 
-               CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
-                       if(base!=BASACT) {
+               CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+                       if(ob!=obact) {
                                con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
                                strcpy (con->name, "AutoTrack");
 
                                data = con->data;
-                               data->tar = BASACT->object;
-                               base->object->recalc |= OB_RECALC;
+                               data->tar = obact;
+                               ob->recalc |= OB_RECALC;
                                
                                /* Lamp and Camera track differently by default */
-                               if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
+                               if (ob->type == OB_LAMP || ob->type == OB_CAMERA) {
                                        data->reserved1 = TRACK_nZ;
                                        data->reserved2 = UP_Y;
                                }
 
-                               add_constraint_to_object(con, base->object);
+                               add_constraint_to_object(con, ob);
                        }
                }
                CTX_DATA_END;
@@ -892,36 +945,36 @@ static int track_set_exec(bContext *C, wmOperator *op)
                bConstraint *con;
                bLockTrackConstraint *data;
 
-               CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
-                       if(base!=BASACT) {
+               CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+                       if(ob!=obact) {
                                con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
                                strcpy (con->name, "AutoTrack");
 
                                data = con->data;
-                               data->tar = BASACT->object;
-                               base->object->recalc |= OB_RECALC;
+                               data->tar = obact;
+                               ob->recalc |= OB_RECALC;
                                
                                /* Lamp and Camera track differently by default */
-                               if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
+                               if (ob->type == OB_LAMP || ob->type == OB_CAMERA) {
                                        data->trackflag = TRACK_nZ;
                                        data->lockflag = LOCK_Y;
                                }
 
-                               add_constraint_to_object(con, base->object);
+                               add_constraint_to_object(con, ob);
                        }
                }
                CTX_DATA_END;
        }
        else {
-               CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
-                       if(base!=BASACT) {
-                               base->object->track= BASACT->object;
-                               base->object->recalc |= OB_RECALC;
+               CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+                       if(ob!=obact) {
+                               ob->track= obact;
+                               ob->recalc |= OB_RECALC;
                        }
                }
                CTX_DATA_END;
        }
-       DAG_scene_sort(CTX_data_scene(C));
+       DAG_scene_sort(scene);
        ED_anim_dag_flush_update(C);    
        
        return OPERATOR_FINISHED;
@@ -1077,97 +1130,77 @@ void link_to_scene(unsigned short nr)
 #endif
 }
 
-
-void make_links(bContext *C, wmOperator *op, Scene *scene, View3D *v3d, short event)
+static int make_links_scene_exec(bContext *C, wmOperator *op)
 {
-       Object *ob, *obt;
-       Base *base, *nbase, *sbase;
-       Scene *sce = NULL;
-       ID *id;
-       int a;
-       short nr=0;
-       char *strp;
-
-       if(!(ob=OBACT)) return;
+       Scene *scene_to= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "type"));
 
-       if(event==1) {
-               IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
-               
-               if(nr == -2) {
-                       MEM_freeN(strp);
-
-// XXX                 activate_databrowse((ID *)scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
-                       
-                       return;                 
-               }
-               else {
-                       event= pupmenu_col(strp, 20);
-                       MEM_freeN(strp);
-               
-                       if(event<= 0) return;
-               
-                       nr= 1;
-                       sce= G.main->scene.first;
-                       while(sce) {
-                               if(nr==event) break;
-                               nr++;
-                               sce= sce->id.next;
-                       }
-                       if(sce==scene) {
-                               BKE_report(op->reports, RPT_ERROR, "This is the current scene");
-                               return;
-                       }
-                       if(sce==0 || sce->id.lib) return;
-                       
-                       /* remember: is needed below */
-                       event= 1;
-               }
+       if(scene_to==NULL) {
+               BKE_report(op->reports, RPT_ERROR, "Scene not found");
+               return OPERATOR_CANCELLED;
        }
 
-       /* All non group linking */
-       for(base= FIRSTBASE; base; base= base->next) {
-               if(event==1 || base != BASACT) {
-                       
-                       obt= base->object;
+       if(scene_to == CTX_data_scene(C)) {
+               BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene");
+               return OPERATOR_CANCELLED;
+               }
 
-                       if(TESTBASE(v3d, base)) {
-                               
-                               if(event==1) {          /* to scene */
-                                       
-                                       /* test if already linked */
-                                       sbase= sce->base.first;
-                                       while(sbase) {
-                                               if(sbase->object==base->object) break;
-                                               sbase= sbase->next;
-                                       }
-                                       if(sbase) {     /* remove */
-                                               continue;
-                                       }
-                                       
-                                       nbase= MEM_mallocN( sizeof(Base), "newbase");
+       CTX_DATA_BEGIN(C, Base*, base, selected_bases)
+       {
+               if(!object_in_scene(base->object, scene_to)) {
+                       Base *nbase= MEM_mallocN( sizeof(Base), "newbase");
                                        *nbase= *base;
-                                       BLI_addhead( &(sce->base), nbase);
+                       BLI_addhead( &(scene_to->base), nbase);
                                        id_us_plus((ID *)base->object);
                                }
                        }
-                       if(TESTBASELIB(v3d, base)) {
-                               if(event==2 || event==5) {  /* obdata */
-                                       if(ob->type==obt->type) {
-                                               
+       CTX_DATA_END;
+
+       ED_anim_dag_flush_update(C);
+
+       /* one day multiple scenes will be visible, then we should have some update function for them */
+       return OPERATOR_FINISHED;
+}
+
+enum {
+       MAKE_LINKS_OBDATA = 1,
+       MAKE_LINKS_MATERIALS,
+       MAKE_LINKS_ANIMDATA,
+       MAKE_LINKS_DUPLIGROUP,
+};
+
+static int make_links_data_exec(bContext *C, wmOperator *op)
+{
+       int event = RNA_int_get(op->ptr, "type");
+       Object *ob;
+       ID *id;
+       int a;
+
+       ob= CTX_data_active_object(C);
+
+       CTX_DATA_BEGIN(C, Object*, obt, selected_editable_objects) {
+               if(ob != obt) {
+                       switch(event) {
+                       case MAKE_LINKS_OBDATA: /* obdata */
                                                        id= obt->data;
                                                        id->us--;
-                                                       
+
                                                        id= ob->data;
                                                        id_us_plus(id);
                                                        obt->data= id;
-                                                       
+
                                                        /* if amount of material indices changed: */
                                                        test_object_materials(obt->data);
 
                                                        obt->recalc |= OB_RECALC_DATA;
+                               break;
+                       case MAKE_LINKS_MATERIALS:
+                               /* new approach, using functions from kernel */
+                               for(a=0; a<ob->totcol; a++) {
+                                       Material *ma= give_current_material(ob, a+1);
+                                       assign_material(obt, ma, a+1);  /* also works with ma==NULL */
                                                }
-                                       }
-                               else if(event==4) {  /* ob ipo */
+                               break;
+                       case MAKE_LINKS_ANIMDATA:
 #if 0 // XXX old animation system
                                        if(obt->ipo) obt->ipo->id.us--;
                                        obt->ipo= ob->ipo;
@@ -1176,67 +1209,75 @@ void make_links(bContext *C, wmOperator *op, Scene *scene, View3D *v3d, short ev
                                                do_ob_ipo(scene, obt);
                                        }
 #endif // XXX old animation system
-                               }
-                               else if(event==6) {
+                               break;
+                       case MAKE_LINKS_DUPLIGROUP:
                                        if(ob->dup_group) ob->dup_group->id.us--;
                                        obt->dup_group= ob->dup_group;
                                        if(obt->dup_group) {
                                                id_us_plus((ID *)obt->dup_group);
                                                obt->transflag |= OB_DUPLIGROUP;
                                        }
+                               break;
                                }
-                               else if(event==3) {  /* materials */
-                                       
-                                       /* new approach, using functions from kernel */
-                                       for(a=0; a<ob->totcol; a++) {
-                                               Material *ma= give_current_material(ob, a+1);
-                                               assign_material(obt, ma, a+1);  /* also works with ma==NULL */
                                        }
                                }
-                       }
-               }
-       }
-       
-       ED_anim_dag_flush_update(C);    
+       CTX_DATA_END;
 
+       ED_anim_dag_flush_update(C);
+       WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+       return OPERATOR_FINISHED;
 }
 
-void make_links_menu(bContext *C, Scene *scene, View3D *v3d)
+
+void OBJECT_OT_make_links_scene(wmOperatorType *ot)
 {
-       Object *ob;
-       short event=0;
-       char str[140];
-       
-       if(!(ob=OBACT)) return;
-       
-       strcpy(str, "Make Links %t|To Scene...%x1|%l|Object Ipo%x4");
-       
-       if(ob->type==OB_MESH)
-               strcat(str, "|Mesh Data%x2|Materials%x3");
-       else if(ob->type==OB_CURVE)
-               strcat(str, "|Curve Data%x2|Materials%x3");
-       else if(ob->type==OB_FONT)
-               strcat(str, "|Text Data%x2|Materials%x3");
-       else if(ob->type==OB_SURF)
-               strcat(str, "|Surface Data%x2|Materials%x3");
-       else if(ob->type==OB_MBALL)
-               strcat(str, "|Materials%x3");
-       else if(ob->type==OB_CAMERA)
-               strcat(str, "|Camera Data%x2");
-       else if(ob->type==OB_LAMP)
-               strcat(str, "|Lamp Data%x2");
-       else if(ob->type==OB_LATTICE)
-               strcat(str, "|Lattice Data%x2");
-       else if(ob->type==OB_ARMATURE)
-               strcat(str, "|Armature Data%x2");
-       
-       event= pupmenu(str);
-       
-       if(event<= 0) return;
-       
-       make_links(C, NULL, scene, v3d, event);
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name= "Link Objects to Scene";
+       ot->description = "Make linked data local to each object.";
+       ot->idname= "OBJECT_OT_make_links_scene";
+
+       /* api callbacks */
+       ot->exec= make_links_scene_exec;
+       /* better not run the poll check */
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", "");
+       RNA_def_enum_funcs(prop, RNA_scene_itemf);
 }
 
+void OBJECT_OT_make_links_data(wmOperatorType *ot)
+{
+       static EnumPropertyItem make_links_items[]= {
+               {MAKE_LINKS_OBDATA,             "OBDATA", 0, "Object Data", ""},
+               {MAKE_LINKS_MATERIALS,  "MATERIAL", 0, "Materials", ""},
+               {MAKE_LINKS_ANIMDATA,   "ANIMATION", 0, "Animation Data", ""},
+               {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""},
+               {0, NULL, 0, NULL, NULL}};
+
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name= "Link Data";
+       ot->description = "Make links from the active object to other selected objects.";
+       ot->idname= "OBJECT_OT_make_links_data";
+
+       /* api callbacks */
+       ot->exec= make_links_data_exec;
+       ot->poll= ED_operator_scene_editable;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       prop= RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
+}
+
+
 /**************************** Make Single User ********************************/
 
 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)