forked from bartvdbraak/blender
patch #31794 Added new function BKE_object_relational_superset()
This commit is contained in:
parent
aace651e51
commit
92d9483075
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user