diff options
author | Gaia Clary <gaia.clary@machinimatrix.org> | 2012-06-13 01:23:51 +0400 |
---|---|---|
committer | Gaia Clary <gaia.clary@machinimatrix.org> | 2012-06-13 01:23:51 +0400 |
commit | 92d948307549ce1d69ec4e41e42b442360b9bade (patch) | |
tree | 7beceda365db381b424cdaa379a21fdd53ca43c2 | |
parent | aace651e51cfaa725847ef1345418ec6a6e42b6e (diff) |
patch #31794 Added new function BKE_object_relational_superset()
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 20 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 134 |
2 files changed, 154 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 890fc40c284..29979f62d60 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -158,6 +158,26 @@ void BKE_object_relink(struct Object *ob); struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, int use_default); +/* this function returns a superset of the scenes selection based on relationships */ + +typedef enum eObRelationTypes { + OB_REL_NONE = 0, /* just the selection as is */ + OB_REL_PARENT = (1<<0), /* immediate parent */ + OB_REL_PARENT_RECURSIVE = (1<<1), /* parents up to root of selection tree*/ + OB_REL_CHILDREN = (1<<2), /* immediate children */ + OB_REL_CHILDREN_RECURSIVE = (1<<3), /* All children */ + OB_REL_MOD_ARMATURE = (1<<4), /* Armatures related to the selected objects */ + OB_REL_SCENE_CAMERA = (1<<5), /* you might want the scene camera too even if unselected? */ +} eObRelationTypes; + +typedef enum eObjectSet { + OB_SET_SELECTED, /* Selected Objects */ + OB_SET_VISIBLE, /* Visible Objects */ + OB_SET_ALL /* All Objects */ +} eObjectSet; + +struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a01024acfd3..91fd5811911 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -63,6 +63,7 @@ #include "BLI_math.h" #include "BLI_pbvh.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BKE_main.h" #include "BKE_global.h" @@ -3076,3 +3077,136 @@ MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, int use_default) return clip; } + + +/* + * Find an associated Armature object + */ +static Object *obrel_armature_find(Object *ob) +{ + Object *ob_arm = NULL; + + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod = (ModifierData*)ob->modifiers.first; + while (mod) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData*)mod)->object; + } + + mod = mod->next; + } + } + + return ob_arm; +} + +static int obrel_is_recursive_child(Object *ob, Object *child) { + Object *ancestor = child->parent; + while (ancestor) + { + if(ancestor == ob) return TRUE; + ancestor = ancestor->parent; + } + return FALSE; +} + + +static int obrel_list_test(Object *ob) +{ + return ob && !(ob->id.flag & LIB_DOIT); +} + +static void obrel_list_add(LinkNode **links, Object *ob) +{ + BLI_linklist_prepend(links, ob); + ob->id.flag |= LIB_DOIT; +} + +/* + * Iterates over all objects of the given scene. + * Depending on the eObjectSet flag: + * collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects. + * 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 *links = NULL; + + Base *base; + + /* Remove markers from all objects */ + for (base = scene->base.first; base; base = base->next) { + base->object->id.flag &= ~LIB_DOIT; + } + + /* iterate over all selected and visible objects */ + for (base = scene->base.first; base; base = base->next) { + if (objectSet == OB_SET_ALL) { + // as we get all anyways just add it + Object *ob = base->object; + obrel_list_add(&links, ob); + } + else { + if ( (objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) + || (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base)) + ) { + Object *ob = base->object; + + if (obrel_list_test(ob)) + obrel_list_add(&links, ob); + + /* parent relationship */ + if (includeFilter & ( OB_REL_PARENT | OB_REL_PARENT_RECURSIVE )) { + Object *parent = ob->parent; + if (obrel_list_test(parent)) { + + obrel_list_add(&links, parent); + + /* recursive parent relationship */ + if (includeFilter & OB_REL_PARENT_RECURSIVE) { + parent = parent->parent; + while (obrel_list_test(parent)){ + + obrel_list_add(&links, parent); + parent = parent->parent; + } + } + } + } + + /* child relationship */ + if (includeFilter & ( OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE )) { + Base *local_base; + for (local_base = scene->base.first; local_base; local_base = local_base->next) { + if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { + + Object *child = local_base->object; + if (obrel_list_test(child)) { + if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && obrel_is_recursive_child(ob,child)) + || (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob )) { + obrel_list_add(&links, child); + } + } + } + } + } + + + /* include related armatures */ + if (includeFilter & OB_REL_MOD_ARMATURE) { + Object *arm = obrel_armature_find(ob); + if (obrel_list_test(arm)) { + obrel_list_add(&links, arm); + } + } + + } + } + } // end for + + return links; +} |