Make Links (Ctrl+L) back
authorCampbell Barton <ideasman42@gmail.com>
Wed, 4 Nov 2009 10:25:57 +0000 (10:25 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 4 Nov 2009 10:25:57 +0000 (10:25 +0000)
- split into 2 operators: object.make_links_data() & object.make_links_scene since they are quite different.
- added reusable functions RNA_group_itemf & RNA_scene_itemf which can be used for any operator that takes ID data (easy to add more types Mesh, Text etc)
- DummyRNA_NULL_items for dynamic items so each operator need not define its own empty enum.

release/scripts/ui/space_view3d.py
source/blender/editors/object/object_add.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/intern/rna_access.c
source/blender/windowmanager/intern/wm_operators.c

index 33e2df11f8edf4ec369775465beba45ee33ffd2a..ba6f1c4740d768c71acd43a28c15f050bdd9a893 100644 (file)
@@ -479,8 +479,10 @@ class VIEW3D_MT_object(bpy.types.Menu):
         layout.item_booleanO("object.duplicate", "linked", True, text="Duplicate Linked")
         layout.itemO("object.delete", text="Delete...")
         layout.itemO("object.proxy_make", text="Make Proxy...")
+        layout.itemM("VIEW3D_MT_make_links", text="Make Links...")
         layout.item_menu_enumO("object.make_local", "type", text="Make Local...")
         layout.itemM("VIEW3D_MT_make_single_user")
+        layout.itemM("VIEW3D_MT_make_links")
 
         layout.itemS()
 
@@ -604,6 +606,18 @@ class VIEW3D_MT_make_single_user(bpy.types.Menu):
         props = layout.itemO("object.make_single_user", properties=True, text="Animation")
         props.animation = True
 
+
+class VIEW3D_MT_make_links(bpy.types.Menu):
+    bl_label = "Make Links"
+
+    def draw(self, context):
+        layout = self.layout
+        
+        layout.item_menu_enumO("object.make_links_scene", "type", text="Objects to Scene...")
+
+        layout.items_enumO("object.make_links_data", property="type") # inline
+
+
 # ********** Vertex paint menu **********
 
 
@@ -1600,6 +1614,7 @@ bpy.types.register(VIEW3D_MT_object_group)
 bpy.types.register(VIEW3D_MT_object_constraints)
 bpy.types.register(VIEW3D_MT_object_showhide)
 bpy.types.register(VIEW3D_MT_make_single_user)
+bpy.types.register(VIEW3D_MT_make_links)
 
 
 bpy.types.register(VIEW3D_MT_sculpt) # Sculpt Menu
index e1c23123b8493f053371caa5c89b0807581e77be..63bb3f87480a5bfb990b77d49d21bdf793450282 100644 (file)
@@ -678,31 +678,8 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
        ED_object_add_generic_props(ot, FALSE);
 }
 
-/* add dupligroup */
-static EnumPropertyItem *add_dupligroup_itemf(bContext *C, PointerRNA *ptr, int *free)
-{
-       EnumPropertyItem *item= NULL, item_tmp;
-       int totitem= 0;
-       int i= 0;
-       Group *group;
-
-       memset(&item_tmp, 0, sizeof(item_tmp));
-
-       for(group= CTX_data_main(C)->group.first; group; group= group->id.next) {
-               item_tmp.identifier= item_tmp.name= group->id.name+2;
-               item_tmp.value= i++;
-               RNA_enum_item_add(&item, &totitem, &item_tmp);
-       }
-
-       RNA_enum_item_end(&item, &totitem);
-       *free= 1;
-
-       return item;
-}
-
 static int group_instance_add_exec(bContext *C, wmOperator *op)
 {
-       /* XXX, using an enum for library lookups is a bit dodgy */
        Group *group= BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "type"));
 
        int view_align, enter_editmode;
@@ -728,9 +705,6 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
 void OBJECT_OT_group_instance_add(wmOperatorType *ot)
 {
        PropertyRNA *prop;
-       static EnumPropertyItem prop_group_dummy_types[] = {
-               {0, NULL, 0, NULL, NULL}
-       };
 
        /* identifiers */
        ot->name= "Add Group Instance";
@@ -746,8 +720,8 @@ void OBJECT_OT_group_instance_add(wmOperatorType *ot)
        ot->flag= 0;
 
        /* properties */
-       prop= RNA_def_enum(ot->srna, "type", prop_group_dummy_types, 0, "Type", "");
-       RNA_def_enum_funcs(prop, add_dupligroup_itemf);
+       prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", "");
+       RNA_def_enum_funcs(prop, RNA_group_itemf);
        ED_object_add_generic_props(ot, FALSE);
 }
 
index ebc36dddb33721124e5bbdcf19adae1320845dd5..8f27f0fbae4b59ff81b149711671856f30bf38bd 100644 (file)
@@ -60,6 +60,8 @@ void OBJECT_OT_slow_parent_set(struct wmOperatorType *ot);
 void OBJECT_OT_slow_parent_clear(struct wmOperatorType *ot);
 void OBJECT_OT_make_local(struct wmOperatorType *ot);
 void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
+void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
+void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
 void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
 
 /* object_edit.c */
index ab35320cc7448c2f7dab275893ccb379ae970b34..ccb6e8cdea31d730999526e2e3f5feb4d967372d 100644 (file)
@@ -92,6 +92,8 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_slow_parent_clear);
        WM_operatortype_append(OBJECT_OT_make_local);
        WM_operatortype_append(OBJECT_OT_make_single_user);
+       WM_operatortype_append(OBJECT_OT_make_links_scene);
+       WM_operatortype_append(OBJECT_OT_make_links_data);
        WM_operatortype_append(OBJECT_OT_move_to_layer);
 
        WM_operatortype_append(OBJECT_OT_select_inverse);
@@ -290,6 +292,9 @@ void ED_keymap_object(wmKeyConfig *keyconf)
 
        kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", UKEY, KM_PRESS, 0, 0);
        RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_make_single_user");
+    
+       kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", LKEY, KM_PRESS, KM_CTRL, 0);
+       RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_make_links");
 
        WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move_linked", DKEY, KM_PRESS, KM_ALT, 0);
index 6849cefbbd9bb6dab00e939bc8a175d48d99ddf1..cbd1e1be8d575eed7b1d4b3e5e26a1c351a07d74 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)
@@ -1132,97 +1130,77 @@ void link_to_scene(unsigned short nr)
 #endif
 }
 
+static int make_links_scene_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene_to= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "type"));
+
+       if(scene_to==NULL) {
+               BKE_report(op->reports, RPT_ERROR, "Scene not found");
+               return OPERATOR_CANCELLED;
+       }
+
+       if(scene_to == CTX_data_scene(C)) {
+               BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene");
+               return OPERATOR_CANCELLED;
+       }
+
+       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( &(scene_to->base), nbase);
+                       id_us_plus((ID *)base->object);
+               }
+       }
+       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,
+};
 
-void make_links(bContext *C, wmOperator *op, Scene *scene, View3D *v3d, short event)
+static int make_links_data_exec(bContext *C, wmOperator *op)
 {
-       Object *ob, *obt;
-       Base *base, *nbase, *sbase;
-       Scene *sce = NULL;
+       int event = RNA_int_get(op->ptr, "type");
+       Object *ob;
        ID *id;
        int a;
-       short nr=0;
-       char *strp;
 
-       if(!(ob=OBACT)) return;
+       ob= CTX_data_active_object(C);
 
-       if(event==1) {
-               IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
-               
-               if(nr == -2) {
-                       MEM_freeN(strp);
+       CTX_DATA_BEGIN(C, Object*, obt, selected_editable_objects) {
+               if(ob != obt) {
+                       switch(event) {
+                       case MAKE_LINKS_OBDATA: /* obdata */
+                               id= obt->data;
+                               id->us--;
 
-// 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;
-               }
-       }
+                               id= ob->data;
+                               id_us_plus(id);
+                               obt->data= id;
 
-       /* All non group linking */
-       for(base= FIRSTBASE; base; base= base->next) {
-               if(event==1 || base != BASACT) {
-                       
-                       obt= base->object;
+                               /* if amount of material indices changed: */
+                               test_object_materials(obt->data);
 
-                       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");
-                                       *nbase= *base;
-                                       BLI_addhead( &(sce->base), nbase);
-                                       id_us_plus((ID *)base->object);
+                               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 */
                                }
-                       }
-                       if(TESTBASELIB(v3d, base)) {
-                               if(event==2 || event==5) {  /* obdata */
-                                       if(ob->type==obt->type) {
-                                               
-                                                       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;
-                                               }
-                                       }
-                               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;
@@ -1231,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
+                               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;
                                }
-                               else if(event==6) {
-                                       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;
-                                       }
-                               }
-                               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 */
-                                       }
-                               }
+                               break;
                        }
                }
        }
-       
-       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)
index ca44e3405f62223e4aab25d73f96b79b83178434..318178d15220325d833a161bd02ae7fd562bf1e5 100644 (file)
@@ -31,6 +31,8 @@
 
 extern EnumPropertyItem id_type_items[];
 
+/* use in cases where only dynamic types are used */
+extern EnumPropertyItem DummyRNA_NULL_items[];
 
 extern EnumPropertyItem object_mode_items[];
 
@@ -69,6 +71,11 @@ struct bContext;
 struct PointerRNA;
 EnumPropertyItem *rna_TransformOrientation_itemf(struct bContext *C, struct PointerRNA *ptr, int *free);
 
+/* Generic functions, return an enum from library data, index is the position
+ * in the linked list can add more for different types as needed */
+EnumPropertyItem *RNA_group_itemf(struct bContext *C, struct PointerRNA *ptr, int *free);
+EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, int *free);
+
 #endif /* RNA_ENUM_TYPES */
 
 
index f0aaceec4aa28882dd0a1af25fd45bd9a8a29452..93e83492efad0c6d484358f7afb669e25bebbabb 100644 (file)
@@ -734,6 +734,11 @@ StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
        return &RNA_UnknownType;
 }
 
+/* Reuse for dynamic types  */
+EnumPropertyItem DummyRNA_NULL_items[] = {
+       {0, NULL, 0, NULL, NULL}
+};
+
 void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free)
 {
        EnumPropertyRNA *eprop= (EnumPropertyRNA*)rna_ensure_property(prop);
index 743a4ceebe858be48cd3454cc0a825aeef1205cf..db09619046e3423d2315c302150e7588e3c55c13 100644 (file)
@@ -2446,3 +2446,33 @@ void wm_window_keymap(wmKeyConfig *keyconf)
        RNA_string_set(km->ptr, "value", "DOPESHEET_EDITOR");
 }
 
+/* Generic itemf's for operators that take library args */
+static EnumPropertyItem *rna_id_itemf(bContext *C, PointerRNA *ptr, int *free, ID *id)
+{
+       EnumPropertyItem *item= NULL, item_tmp;
+       int totitem= 0;
+       int i= 0;
+
+       memset(&item_tmp, 0, sizeof(item_tmp));
+
+       for( ; id; id= id->next) {
+               item_tmp.identifier= item_tmp.name= id->name+2;
+               item_tmp.value= i++;
+               RNA_enum_item_add(&item, &totitem, &item_tmp);
+       }
+
+       RNA_enum_item_end(&item, &totitem);
+       *free= 1;
+
+       return item;
+}
+
+/* can add more */
+EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       rna_id_itemf(C, ptr, free, (ID *)CTX_data_main(C)->group.first);
+}
+EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       rna_id_itemf(C, ptr, free, (ID *)CTX_data_main(C)->scene.first);
+}