make links now allows groups - this means you can make objects have matching groups...
authorCampbell Barton <ideasman42@gmail.com>
Wed, 18 Jul 2012 09:45:50 +0000 (09:45 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 18 Jul 2012 09:45:50 +0000 (09:45 +0000)
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/object.c
source/blender/editors/object/object_group.c
source/blender/editors/object/object_relations.c

index b8ba309..3aa7148 100644 (file)
@@ -177,6 +177,8 @@ typedef enum eObjectSet {
 } eObjectSet;
 
 struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
+struct LinkNode *BKE_object_groups(struct Object *ob);
+void             BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
 
 #ifdef __cplusplus
 }
index a3145dd..048560f 100644 (file)
@@ -3156,7 +3156,7 @@ static void obrel_list_add(LinkNode **links, Object *ob)
  * If OB_SET_VISIBLE or OB_SET_SELECTED are collected, 
  * then also add related objects according to the given includeFilters.
  */
-struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
 {
        LinkNode *links = NULL;
 
@@ -3235,3 +3235,32 @@ struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet
 
        return links;
 }
+
+/**
+ * return all groups this object is apart of, caller must free.
+ */
+struct LinkNode *BKE_object_groups(Object *ob)
+{
+       LinkNode *group_linknode = NULL;
+       Group *group = NULL;
+       while ((group = find_group(ob, group))) {
+               BLI_linklist_prepend(&group_linknode, group);
+       }
+
+       return group_linknode;
+}
+
+void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+{
+       Group *group = NULL;
+
+       BLI_assert(base->object == object);
+
+       if (scene && base == NULL) {
+               base = BKE_scene_base_find(scene, object);
+       }
+
+       while ((group = find_group(base->object, group))) {
+               rem_from_group(group, object, scene, base);
+       }
+}
index 3b9d54d..e86a62f 100644 (file)
@@ -44,6 +44,7 @@
 #include "BKE_group.h"
 #include "BKE_main.h"
 #include "BKE_report.h"
+#include "BKE_object.h"
 
 #include "ED_screen.h"
 #include "ED_object.h"
@@ -113,7 +114,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        int group_object_index = RNA_enum_get(op->ptr, "group");
-       int cycle = FALSE;
+       int is_cycle = FALSE;
 
        if (ob) {
                Group *group = group_object_active_find_index(ob, group_object_index);
@@ -127,7 +128,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
                                        add_to_group(group, base->object, scene, base);
                                }
                                else {
-                                       cycle = TRUE;
+                                       is_cycle = TRUE;
                                }
                        }
                        CTX_DATA_END;
@@ -139,8 +140,9 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
                }
        }
 
-       if (cycle)
+       if (is_cycle) {
                BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+       }
 
        return OPERATOR_CANCELLED;
 }
@@ -220,13 +222,10 @@ static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
-       Group *group = NULL;
 
        CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
        {
-               group = NULL;
-               while ((group = find_group(base->object, group)))
-                       rem_from_group(group, base->object, scene, base);
+               BKE_object_groups_clear(scene, base, base->object);
        }
        CTX_DATA_END;
 
index 860ff24..d25e418 100644 (file)
@@ -50,6 +50,7 @@
 
 #include "BLI_math.h"
 #include "BLI_listbase.h"
+#include "BLI_linklist.h"
 #include "BLI_string.h"
 #include "BLI_utildefines.h"
 
@@ -64,6 +65,7 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
+#include "BKE_group.h"
 #include "BKE_fcurve.h"
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
@@ -1277,14 +1279,15 @@ enum {
        MAKE_LINKS_OBDATA = 1,
        MAKE_LINKS_MATERIALS,
        MAKE_LINKS_ANIMDATA,
+       MAKE_LINKS_GROUP,
        MAKE_LINKS_DUPLIGROUP,
        MAKE_LINKS_MODIFIERS
 };
 
 /* Return 1 if make link data is allow, zero otherwise */
-static int allow_make_links_data(int ev, Object *ob, Object *obt)
+static int allow_make_links_data(const int type, Object *ob, Object *obt)
 {
-       switch (ev) {
+       switch (type) {
                case MAKE_LINKS_OBDATA:
                        if (ob->type == obt->type && ob->type != OB_EMPTY)
                                return 1;
@@ -1297,6 +1300,7 @@ static int allow_make_links_data(int ev, Object *ob, Object *obt)
                        }
                        break;
                case MAKE_LINKS_ANIMDATA:
+               case MAKE_LINKS_GROUP:
                case MAKE_LINKS_DUPLIGROUP:
                        return 1;
                case MAKE_LINKS_MODIFIERS:
@@ -1310,52 +1314,81 @@ static int allow_make_links_data(int ev, Object *ob, Object *obt)
 static int make_links_data_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
-       int event = RNA_enum_get(op->ptr, "type");
-       Object *ob;
+       Scene *scene = CTX_data_scene(C);
+       const int type = RNA_enum_get(op->ptr, "type");
+       Object *ob_src;
        ID *id;
        int a;
 
-       ob = ED_object_active_context(C);
+       /* group */
+       LinkNode *ob_groups = NULL;
+       int is_cycle = FALSE;
+
+       ob_src = ED_object_active_context(C);
+
+       /* avoid searching all groups in source object each time */
+       if (type == MAKE_LINKS_GROUP) {
+               ob_groups = BKE_object_groups(ob_src);
+       }
 
-       CTX_DATA_BEGIN (C, Object *, obt, selected_editable_objects)
+       CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
        {
-               if (ob != obt) {
-                       if (allow_make_links_data(event, ob, obt)) {
-                               switch (event) {
+               Object *ob_dst = base_dst->object;
+
+               if (ob_src != ob_dst) {
+                       if (allow_make_links_data(type, ob_src, ob_dst)) {
+                               switch (type) {
                                        case MAKE_LINKS_OBDATA: /* obdata */
-                                               id = obt->data;
+                                               id = ob_dst->data;
                                                id->us--;
 
-                                               id = ob->data;
+                                               id = ob_src->data;
                                                id_us_plus(id);
-                                               obt->data = id;
+                                               ob_dst->data = id;
 
                                                /* if amount of material indices changed: */
-                                               test_object_materials(obt->data);
+                                               test_object_materials(ob_dst->data);
 
-                                               obt->recalc |= OB_RECALC_DATA;
+                                               ob_dst->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 */
+                                               for (a = 0; a < ob_src->totcol; a++) {
+                                                       Material *ma = give_current_material(ob_src, a + 1);
+                                                       assign_material(ob_dst, ma, a + 1); /* also works with ma==NULL */
                                                }
                                                break;
                                        case MAKE_LINKS_ANIMDATA:
-                                               BKE_copy_animdata_id((ID *)obt, (ID *)ob, FALSE);
-                                               BKE_copy_animdata_id((ID *)obt->data, (ID *)ob->data, FALSE);
+                                               BKE_copy_animdata_id((ID *)ob_dst, (ID *)ob_src, FALSE);
+                                               BKE_copy_animdata_id((ID *)ob_dst->data, (ID *)ob_src->data, FALSE);
                                                break;
+                                       case MAKE_LINKS_GROUP:
+                                       {
+                                               LinkNode *group_node;
+
+                                               /* first clear groups */
+                                               BKE_object_groups_clear(scene, base_dst, ob_dst);
+
+                                               /* now add in the groups from the link nodes */
+                                               for (group_node = ob_groups; group_node; group_node = group_node->next) {
+                                                       if (ob_dst->dup_group != group_node->link) {
+                                                               add_to_group(group_node->link, ob_dst, scene, base_dst);
+                                                       }
+                                                       else {
+                                                               is_cycle = TRUE;
+                                                       }
+                                               }
+                                       }
                                        case MAKE_LINKS_DUPLIGROUP:
-                                               obt->dup_group = ob->dup_group;
-                                               if (obt->dup_group) {
-                                                       id_lib_extern(&obt->dup_group->id);
-                                                       obt->transflag |= OB_DUPLIGROUP;
+                                               ob_dst->dup_group = ob_src->dup_group;
+                                               if (ob_dst->dup_group) {
+                                                       id_lib_extern(&ob_dst->dup_group->id);
+                                                       ob_dst->transflag |= OB_DUPLIGROUP;
                                                }
                                                break;
                                        case MAKE_LINKS_MODIFIERS:
-                                               BKE_object_link_modifiers(obt, ob);
-                                               obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+                                               BKE_object_link_modifiers(ob_dst, ob_src);
+                                               ob_dst->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
                                                break;
                                }
                        }
@@ -1363,7 +1396,17 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
 
-       DAG_scene_sort(bmain, CTX_data_scene(C));
+       if (type == MAKE_LINKS_GROUP) {
+               if (ob_groups) {
+                       BLI_linklist_free(ob_groups, NULL);
+               }
+
+               if (is_cycle) {
+                       BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+               }
+       }
+
+       DAG_scene_sort(bmain, scene);
        
        DAG_ids_flush_update(bmain, 0);
        WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
@@ -1400,6 +1443,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
                {MAKE_LINKS_OBDATA,     "OBDATA", 0, "Object Data", ""},
                {MAKE_LINKS_MATERIALS,  "MATERIAL", 0, "Materials", ""},
                {MAKE_LINKS_ANIMDATA,   "ANIMATION", 0, "Animation Data", ""},
+               {MAKE_LINKS_GROUP,      "GROUPS", 0, "Group", ""},
                {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""},
                {MAKE_LINKS_MODIFIERS,  "MODIFIERS", 0, "Modifiers", ""},
                {0, NULL, 0, NULL, NULL}};