Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_tree.c
| Show First 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | else if (space_outliner->runtime->treehash) { | ||||
| BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash); | BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void check_persistent( | static void check_persistent( | ||||
| SpaceOutliner *space_outliner, TreeElement *te, ID *id, short type, short nr) | SpaceOutliner *space_outliner, TreeElement *te, ID *id, short type, short nr) | ||||
| { | { | ||||
| TreeStoreElem *tselem; | |||||
| if (space_outliner->treestore == NULL) { | if (space_outliner->treestore == NULL) { | ||||
| /* if treestore was not created in readfile.c, create it here */ | /* if treestore was not created in readfile.c, create it here */ | ||||
| space_outliner->treestore = BLI_mempool_create( | space_outliner->treestore = BLI_mempool_create( | ||||
| sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); | sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); | ||||
| } | } | ||||
| if (space_outliner->runtime->treehash == NULL) { | if (space_outliner->runtime->treehash == NULL) { | ||||
| space_outliner->runtime->treehash = BKE_outliner_treehash_create_from_treestore( | space_outliner->runtime->treehash = BKE_outliner_treehash_create_from_treestore( | ||||
| space_outliner->treestore); | space_outliner->treestore); | ||||
| } | } | ||||
| /* find any unused tree element in treestore and mark it as used | /* find any unused tree element in treestore and mark it as used | ||||
| * (note that there may be multiple unused elements in case of linked objects) */ | * (note that there may be multiple unused elements in case of linked objects) */ | ||||
| tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id); | TreeStoreElem *tselem = BKE_outliner_treehash_lookup_unused( | ||||
| space_outliner->runtime->treehash, type, nr, id); | |||||
| if (tselem) { | if (tselem) { | ||||
| te->store_elem = tselem; | te->store_elem = tselem; | ||||
| tselem->used = 1; | tselem->used = 1; | ||||
| return; | return; | ||||
| } | } | ||||
| /* add 1 element to treestore */ | /* add 1 element to treestore */ | ||||
| tselem = BLI_mempool_alloc(space_outliner->treestore); | tselem = BLI_mempool_alloc(space_outliner->treestore); | ||||
| tselem->type = type; | tselem->type = type; | ||||
| tselem->nr = type ? nr : 0; | tselem->nr = type ? nr : 0; | ||||
| tselem->id = id; | tselem->id = id; | ||||
| tselem->used = 0; | tselem->used = 0; | ||||
| tselem->flag = TSE_CLOSED; | tselem->flag = TSE_CLOSED; | ||||
| te->store_elem = tselem; | te->store_elem = tselem; | ||||
| BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); | BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); | ||||
| } | } | ||||
| /* ********************************************************* */ | /* ********************************************************* */ | ||||
| /* Tree Management */ | /* Tree Management */ | ||||
| void outliner_free_tree(ListBase *tree) | void outliner_free_tree(ListBase *tree) | ||||
| { | { | ||||
| for (TreeElement *element = tree->first, *element_next; element; element = element_next) { | LISTBASE_FOREACH_MUTABLE (TreeElement *, element, tree) { | ||||
| element_next = element->next; | |||||
| outliner_free_tree_element(element, tree); | outliner_free_tree_element(element, tree); | ||||
| } | } | ||||
| } | } | ||||
| void outliner_cleanup_tree(SpaceOutliner *space_outliner) | void outliner_cleanup_tree(SpaceOutliner *space_outliner) | ||||
| { | { | ||||
| outliner_free_tree(&space_outliner->tree); | outliner_free_tree(&space_outliner->tree); | ||||
| outliner_storage_cleanup(space_outliner); | outliner_storage_cleanup(space_outliner); | ||||
| ▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | static void outliner_add_bone(SpaceOutliner *space_outliner, | ||||
| int *a) | int *a) | ||||
| { | { | ||||
| TreeElement *te = outliner_add_element(space_outliner, lb, id, parent, TSE_BONE, *a); | TreeElement *te = outliner_add_element(space_outliner, lb, id, parent, TSE_BONE, *a); | ||||
| (*a)++; | (*a)++; | ||||
| te->name = curBone->name; | te->name = curBone->name; | ||||
| te->directdata = curBone; | te->directdata = curBone; | ||||
| for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) { | LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) { | ||||
| outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, a); | outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a); | ||||
| } | } | ||||
| } | } | ||||
| static bool outliner_animdata_test(AnimData *adt) | static bool outliner_animdata_test(AnimData *adt) | ||||
| { | { | ||||
| if (adt) { | if (adt) { | ||||
| return (adt->action || adt->drivers.first || adt->nla_tracks.first); | return (adt->action || adt->drivers.first || adt->nla_tracks.first); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static void outliner_add_object_contents(SpaceOutliner *space_outliner, | ||||
| if (ob->proxy && !ID_IS_LINKED(ob)) { | if (ob->proxy && !ID_IS_LINKED(ob)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, ob->proxy, te, TSE_PROXY, 0); | outliner_add_element(space_outliner, &te->subtree, ob->proxy, te, TSE_PROXY, 0); | ||||
| } | } | ||||
| outliner_add_element(space_outliner, &te->subtree, ob->data, te, 0, 0); | outliner_add_element(space_outliner, &te->subtree, ob->data, te, 0, 0); | ||||
| if (ob->pose) { | if (ob->pose) { | ||||
| bArmature *arm = ob->data; | bArmature *arm = ob->data; | ||||
| bPoseChannel *pchan; | |||||
| TreeElement *tenla = outliner_add_element( | TreeElement *tenla = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_POSE_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_POSE_BASE, 0); | ||||
| tenla->name = IFACE_("Pose"); | tenla->name = IFACE_("Pose"); | ||||
| /* channels undefined in editmode, but we want the 'tenla' pose icon itself */ | /* channels undefined in editmode, but we want the 'tenla' pose icon itself */ | ||||
| if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) { | if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) { | ||||
| TreeElement *ten; | int const_index = 1000; /* ensure unique id for bone constraints */ | ||||
| int a = 0, const_index = 1000; /* ensure unique id for bone constraints */ | int a; | ||||
| LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, a) { | |||||
| for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) { | TreeElement *ten = outliner_add_element( | ||||
| ten = outliner_add_element( | |||||
| space_outliner, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a); | space_outliner, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a); | ||||
| ten->name = pchan->name; | ten->name = pchan->name; | ||||
| ten->directdata = pchan; | ten->directdata = pchan; | ||||
| pchan->temp = (void *)ten; | pchan->temp = (void *)ten; | ||||
| if (pchan->constraints.first) { | if (!BLI_listbase_is_empty(&pchan->constraints)) { | ||||
| /* Object *target; */ | /* Object *target; */ | ||||
| bConstraint *con; | |||||
| TreeElement *ten1; | |||||
| TreeElement *tenla1 = outliner_add_element( | TreeElement *tenla1 = outliner_add_element( | ||||
| space_outliner, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0); | space_outliner, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0); | ||||
| tenla1->name = IFACE_("Constraints"); | |||||
| /* char *str; */ | /* char *str; */ | ||||
| tenla1->name = IFACE_("Constraints"); | LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { | ||||
| for (con = pchan->constraints.first; con; con = con->next, const_index++) { | TreeElement *ten1 = outliner_add_element( | ||||
| ten1 = outliner_add_element( | |||||
| space_outliner, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index); | space_outliner, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index); | ||||
| #if 0 /* disabled as it needs to be reworked for recoded constraints system */ | #if 0 /* disabled as it needs to be reworked for recoded constraints system */ | ||||
| target = get_constraint_target(con, &str); | target = get_constraint_target(con, &str); | ||||
| if (str && str[0]) { | if (str && str[0]) { | ||||
| ten1->name = str; | ten1->name = str; | ||||
| } | } | ||||
| else if (target) { | else if (target) { | ||||
| ten1->name = target->id.name + 2; | ten1->name = target->id.name + 2; | ||||
| } | } | ||||
| else { | else { | ||||
| ten1->name = con->name; | ten1->name = con->name; | ||||
| } | } | ||||
| #endif | #endif | ||||
| ten1->name = con->name; | ten1->name = con->name; | ||||
| ten1->directdata = con; | ten1->directdata = con; | ||||
| /* possible add all other types links? */ | /* possible add all other types links? */ | ||||
| } | } | ||||
| const_index++; | |||||
| } | } | ||||
| } | } | ||||
| /* make hierarchy */ | /* make hierarchy */ | ||||
| ten = tenla->subtree.first; | TreeElement *ten = tenla->subtree.first; | ||||
| while (ten) { | while (ten) { | ||||
| TreeElement *nten = ten->next, *par; | TreeElement *nten = ten->next, *par; | ||||
| tselem = TREESTORE(ten); | tselem = TREESTORE(ten); | ||||
| if (tselem->type == TSE_POSE_CHANNEL) { | if (tselem->type == TSE_POSE_CHANNEL) { | ||||
| pchan = (bPoseChannel *)ten->directdata; | bPoseChannel *pchan = (bPoseChannel *)ten->directdata; | ||||
| if (pchan->parent) { | if (pchan->parent) { | ||||
| BLI_remlink(&tenla->subtree, ten); | BLI_remlink(&tenla->subtree, ten); | ||||
| par = (TreeElement *)pchan->parent->temp; | par = (TreeElement *)pchan->parent->temp; | ||||
| BLI_addtail(&par->subtree, ten); | BLI_addtail(&par->subtree, ten); | ||||
| ten->parent = par; | ten->parent = par; | ||||
| } | } | ||||
| } | } | ||||
| ten = nten; | ten = nten; | ||||
| } | } | ||||
| } | } | ||||
| /* Pose Groups */ | /* Pose Groups */ | ||||
| if (ob->pose->agroups.first) { | if (!BLI_listbase_is_empty(&ob->pose->agroups)) { | ||||
| bActionGroup *agrp; | |||||
| TreeElement *ten_bonegrp = outliner_add_element( | TreeElement *ten_bonegrp = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0); | ||||
| int a = 0; | |||||
| ten_bonegrp->name = IFACE_("Bone Groups"); | ten_bonegrp->name = IFACE_("Bone Groups"); | ||||
| for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) { | |||||
| TreeElement *ten; | int index; | ||||
| ten = outliner_add_element( | LISTBASE_FOREACH_INDEX (bActionGroup *, agrp, &ob->pose->agroups, index) { | ||||
| space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a); | TreeElement *ten = outliner_add_element( | ||||
| space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, index); | |||||
| ten->name = agrp->name; | ten->name = agrp->name; | ||||
| ten->directdata = agrp; | ten->directdata = agrp; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| for (int a = 0; a < ob->totcol; a++) { | for (int a = 0; a < ob->totcol; a++) { | ||||
| outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a); | outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a); | ||||
| } | } | ||||
| if (ob->constraints.first) { | if (!BLI_listbase_is_empty(&ob->constraints)) { | ||||
| /* Object *target; */ | |||||
| bConstraint *con; | |||||
| TreeElement *ten; | |||||
| TreeElement *tenla = outliner_add_element( | TreeElement *tenla = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0); | ||||
| /* char *str; */ | |||||
| int a; | |||||
| tenla->name = IFACE_("Constraints"); | tenla->name = IFACE_("Constraints"); | ||||
| for (con = ob->constraints.first, a = 0; con; con = con->next, a++) { | |||||
| ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a); | int index; | ||||
| LISTBASE_FOREACH_INDEX (bConstraint *, con, &ob->constraints, index) { | |||||
| TreeElement *ten = outliner_add_element( | |||||
| space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, index); | |||||
| #if 0 /* disabled due to constraints system targets recode... code here needs review */ | #if 0 /* disabled due to constraints system targets recode... code here needs review */ | ||||
| target = get_constraint_target(con, &str); | target = get_constraint_target(con, &str); | ||||
| if (str && str[0]) { | if (str && str[0]) { | ||||
| ten->name = str; | ten->name = str; | ||||
| } | } | ||||
| else if (target) { | else if (target) { | ||||
| ten->name = target->id.name + 2; | ten->name = target->id.name + 2; | ||||
| } | } | ||||
| else { | else { | ||||
| ten->name = con->name; | ten->name = con->name; | ||||
| } | } | ||||
| #endif | #endif | ||||
| ten->name = con->name; | ten->name = con->name; | ||||
| ten->directdata = con; | ten->directdata = con; | ||||
| /* possible add all other types links? */ | /* possible add all other types links? */ | ||||
| } | } | ||||
| } | } | ||||
| if (ob->modifiers.first) { | if (!BLI_listbase_is_empty(&ob->modifiers)) { | ||||
| ModifierData *md; | |||||
| TreeElement *ten_mod = outliner_add_element( | TreeElement *ten_mod = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); | ||||
| int index; | |||||
| ten_mod->name = IFACE_("Modifiers"); | ten_mod->name = IFACE_("Modifiers"); | ||||
| for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) { | |||||
| int index; | |||||
| LISTBASE_FOREACH_INDEX (ModifierData *, md, &ob->modifiers, index) { | |||||
| TreeElement *ten = outliner_add_element( | TreeElement *ten = outliner_add_element( | ||||
| space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); | space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); | ||||
| ten->name = md->name; | ten->name = md->name; | ||||
| ten->directdata = md; | ten->directdata = md; | ||||
| if (md->type == eModifierType_Lattice) { | if (md->type == eModifierType_Lattice) { | ||||
| outliner_add_element(space_outliner, | outliner_add_element(space_outliner, | ||||
| &ten->subtree, | &ten->subtree, | ||||
| Show All 36 Lines | LISTBASE_FOREACH_INDEX (ModifierData *, md, &ob->modifiers, index) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Grease Pencil modifiers. */ | /* Grease Pencil modifiers. */ | ||||
| if (!BLI_listbase_is_empty(&ob->greasepencil_modifiers)) { | if (!BLI_listbase_is_empty(&ob->greasepencil_modifiers)) { | ||||
| TreeElement *ten_mod = outliner_add_element( | TreeElement *ten_mod = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); | ||||
| ten_mod->name = IFACE_("Modifiers"); | ten_mod->name = IFACE_("Modifiers"); | ||||
| int index; | int index; | ||||
| LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) { | LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) { | ||||
| TreeElement *ten = outliner_add_element( | TreeElement *ten = outliner_add_element( | ||||
| space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); | space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); | ||||
| ten->name = md->name; | ten->name = md->name; | ||||
| ten->directdata = md; | ten->directdata = md; | ||||
| if (md->type == eGpencilModifierType_Armature) { | if (md->type == eGpencilModifierType_Armature) { | ||||
| Show All 22 Lines | LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Grease Pencil effects. */ | /* Grease Pencil effects. */ | ||||
| if (!BLI_listbase_is_empty(&ob->shader_fx)) { | if (!BLI_listbase_is_empty(&ob->shader_fx)) { | ||||
| TreeElement *ten_fx = outliner_add_element( | TreeElement *ten_fx = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_GPENCIL_EFFECT_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_GPENCIL_EFFECT_BASE, 0); | ||||
| ten_fx->name = IFACE_("Effects"); | ten_fx->name = IFACE_("Effects"); | ||||
| int index; | int index; | ||||
| LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &ob->shader_fx, index) { | LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &ob->shader_fx, index) { | ||||
| TreeElement *ten = outliner_add_element( | TreeElement *ten = outliner_add_element( | ||||
| space_outliner, &ten_fx->subtree, ob, ten_fx, TSE_GPENCIL_EFFECT, index); | space_outliner, &ten_fx->subtree, ob, ten_fx, TSE_GPENCIL_EFFECT, index); | ||||
| ten->name = fx->name; | ten->name = fx->name; | ||||
| ten->directdata = fx; | ten->directdata = fx; | ||||
| if (fx->type == eShaderFxType_Swirl) { | if (fx->type == eShaderFxType_Swirl) { | ||||
| outliner_add_element(space_outliner, | outliner_add_element(space_outliner, | ||||
| &ten->subtree, | &ten->subtree, | ||||
| ((SwirlShaderFxData *)fx)->object, | ((SwirlShaderFxData *)fx)->object, | ||||
| ten, | ten, | ||||
| TSE_LINKED_OB, | TSE_LINKED_OB, | ||||
| 0); | 0); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* vertex groups */ | /* vertex groups */ | ||||
| if (ob->defbase.first) { | if (!BLI_listbase_is_empty(&ob->defbase)) { | ||||
| bDeformGroup *defgroup; | |||||
| TreeElement *ten; | |||||
| TreeElement *tenla = outliner_add_element( | TreeElement *tenla = outliner_add_element( | ||||
| space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); | space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); | ||||
| int a; | |||||
| tenla->name = IFACE_("Vertex Groups"); | tenla->name = IFACE_("Vertex Groups"); | ||||
| for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) { | |||||
| ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a); | int index; | ||||
| LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) { | |||||
| TreeElement *ten = outliner_add_element( | |||||
| space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); | |||||
| ten->name = defgroup->name; | ten->name = defgroup->name; | ||||
| ten->directdata = defgroup; | ten->directdata = defgroup; | ||||
| } | } | ||||
| } | } | ||||
| /* duplicated group */ | /* duplicated group */ | ||||
| if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) { | if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, ob->instance_collection, te, 0, 0); | outliner_add_element(space_outliner, &te->subtree, ob->instance_collection, te, 0, 0); | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | case ID_SCE: { | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_OB: { | case ID_OB: { | ||||
| outliner_add_object_contents(space_outliner, te, tselem, (Object *)id); | outliner_add_object_contents(space_outliner, te, tselem, (Object *)id); | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_ME: { | case ID_ME: { | ||||
| Mesh *me = (Mesh *)id; | Mesh *me = (Mesh *)id; | ||||
| int a; | |||||
| if (outliner_animdata_test(me->adt)) { | if (outliner_animdata_test(me->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0); | outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0); | ||||
| for (a = 0; a < me->totcol; a++) { | for (int a = 0; a < me->totcol; a++) { | ||||
| outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a); | outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a); | ||||
| } | } | ||||
| /* could do tfaces with image links, but the images are not grouped nicely. | /* could do tfaces with image links, but the images are not grouped nicely. | ||||
| * would require going over all tfaces, sort images in use. etc... */ | * would require going over all tfaces, sort images in use. etc... */ | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_CU: { | case ID_CU: { | ||||
| Curve *cu = (Curve *)id; | Curve *cu = (Curve *)id; | ||||
| int a; | |||||
| if (outliner_animdata_test(cu->adt)) { | if (outliner_animdata_test(cu->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, cu, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, cu, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| for (a = 0; a < cu->totcol; a++) { | for (int a = 0; a < cu->totcol; a++) { | ||||
| outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a); | outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_MB: { | case ID_MB: { | ||||
| MetaBall *mb = (MetaBall *)id; | MetaBall *mb = (MetaBall *)id; | ||||
| int a; | |||||
| if (outliner_animdata_test(mb->adt)) { | if (outliner_animdata_test(mb->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, mb, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, mb, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| for (a = 0; a < mb->totcol; a++) { | for (int a = 0; a < mb->totcol; a++) { | ||||
| outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a); | outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_MA: { | case ID_MA: { | ||||
| Material *ma = (Material *)id; | Material *ma = (Material *)id; | ||||
| if (outliner_animdata_test(ma->adt)) { | if (outliner_animdata_test(ma->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, ma, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, ma, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_TE: { | case ID_TE: { | ||||
| Tex *tex = (Tex *)id; | Tex *tex = (Tex *)id; | ||||
| if (outliner_animdata_test(tex->adt)) { | if (outliner_animdata_test(tex->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| outliner_add_element(space_outliner, &te->subtree, tex->ima, te, 0, 0); | outliner_add_element(space_outliner, &te->subtree, tex->ima, te, 0, 0); | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_CA: { | case ID_CA: { | ||||
| Camera *ca = (Camera *)id; | Camera *ca = (Camera *)id; | ||||
| if (outliner_animdata_test(ca->adt)) { | if (outliner_animdata_test(ca->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, ca, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, ca, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_CF: { | case ID_CF: { | ||||
| CacheFile *cache_file = (CacheFile *)id; | CacheFile *cache_file = (CacheFile *)id; | ||||
| if (outliner_animdata_test(cache_file->adt)) { | if (outliner_animdata_test(cache_file->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_LA: { | case ID_LA: { | ||||
| Light *la = (Light *)id; | Light *la = (Light *)id; | ||||
| if (outliner_animdata_test(la->adt)) { | if (outliner_animdata_test(la->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, la, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, la, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_SPK: { | case ID_SPK: { | ||||
| Speaker *spk = (Speaker *)id; | Speaker *spk = (Speaker *)id; | ||||
| if (outliner_animdata_test(spk->adt)) { | if (outliner_animdata_test(spk->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, spk, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, spk, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_LP: { | case ID_LP: { | ||||
| LightProbe *prb = (LightProbe *)id; | LightProbe *prb = (LightProbe *)id; | ||||
| if (outliner_animdata_test(prb->adt)) { | if (outliner_animdata_test(prb->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, prb, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, prb, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_WO: { | case ID_WO: { | ||||
| World *wrld = (World *)id; | World *wrld = (World *)id; | ||||
| if (outliner_animdata_test(wrld->adt)) { | if (outliner_animdata_test(wrld->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, wrld, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, wrld, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_KE: { | case ID_KE: { | ||||
| Key *key = (Key *)id; | Key *key = (Key *)id; | ||||
| if (outliner_animdata_test(key->adt)) { | if (outliner_animdata_test(key->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, key, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, key, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_AC: { | case ID_AC: { | ||||
| /* XXX do we want to be exposing the F-Curves here? */ | /* XXX do we want to be exposing the F-Curves here? */ | ||||
| /* bAction *act = (bAction *)id; */ | /* bAction *act = (bAction *)id; */ | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_AR: { | case ID_AR: { | ||||
| bArmature *arm = (bArmature *)id; | bArmature *arm = (bArmature *)id; | ||||
| int a = 0; | |||||
| if (outliner_animdata_test(arm->adt)) { | if (outliner_animdata_test(arm->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| if (arm->edbo) { | if (arm->edbo) { | ||||
| EditBone *ebone; | int a = 0; | ||||
| TreeElement *ten; | LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm->edbo, a) { | ||||
| TreeElement *ten = outliner_add_element( | |||||
| for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) { | space_outliner, &te->subtree, id, te, TSE_EBONE, a); | ||||
| ten = outliner_add_element(space_outliner, &te->subtree, id, te, TSE_EBONE, a); | |||||
| ten->directdata = ebone; | ten->directdata = ebone; | ||||
| ten->name = ebone->name; | ten->name = ebone->name; | ||||
| ebone->temp.p = ten; | ebone->temp.p = ten; | ||||
| } | } | ||||
| /* make hierarchy */ | /* make hierarchy */ | ||||
| ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; | TreeElement *ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; | ||||
| while (ten) { | while (ten) { | ||||
| TreeElement *nten = ten->next, *par; | TreeElement *nten = ten->next, *par; | ||||
| ebone = (EditBone *)ten->directdata; | EditBone *ebone = (EditBone *)ten->directdata; | ||||
| if (ebone->parent) { | if (ebone->parent) { | ||||
| BLI_remlink(&te->subtree, ten); | BLI_remlink(&te->subtree, ten); | ||||
| par = ebone->parent->temp.p; | par = ebone->parent->temp.p; | ||||
| BLI_addtail(&par->subtree, ten); | BLI_addtail(&par->subtree, ten); | ||||
| ten->parent = par; | ten->parent = par; | ||||
| } | } | ||||
| ten = nten; | ten = nten; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* do not extend Armature when we have posemode */ | /* do not extend Armature when we have posemode */ | ||||
| tselem = TREESTORE(te->parent); | tselem = TREESTORE(te->parent); | ||||
| if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) { | if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) { | ||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| else { | else { | ||||
| Bone *curBone; | int a = 0; | ||||
| for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) { | LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { | ||||
| outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, &a); | outliner_add_bone(space_outliner, &te->subtree, id, bone, te, &a); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_LS: { | case ID_LS: { | ||||
| FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; | FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; | ||||
| int a; | |||||
| if (outliner_animdata_test(linestyle->adt)) { | if (outliner_animdata_test(linestyle->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| for (a = 0; a < MAX_MTEX; a++) { | for (int a = 0; a < MAX_MTEX; a++) { | ||||
| if (linestyle->mtex[a]) { | if (linestyle->mtex[a]) { | ||||
| outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a); | outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a); | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_GD: { | case ID_GD: { | ||||
| bGPdata *gpd = (bGPdata *)id; | bGPdata *gpd = (bGPdata *)id; | ||||
| bGPDlayer *gpl; | |||||
| int a = 0; | |||||
| if (outliner_animdata_test(gpd->adt)) { | if (outliner_animdata_test(gpd->adt)) { | ||||
| outliner_add_element(space_outliner, &te->subtree, gpd, te, TSE_ANIM_DATA, 0); | outliner_add_element(space_outliner, &te->subtree, gpd, te, TSE_ANIM_DATA, 0); | ||||
| } | } | ||||
| /* TODO: base element for layers? */ | /* TODO: base element for layers? */ | ||||
| for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) { | int index = 0; | ||||
| outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, a); | LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd->layers) { | ||||
| a++; | outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, index); | ||||
| index++; | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_GR: { | case ID_GR: { | ||||
| /* Don't expand for instances, creates too many elements. */ | /* Don't expand for instances, creates too many elements. */ | ||||
| if (!(te->parent && te->parent->idcode == ID_OB)) { | if (!(te->parent && te->parent->idcode == ID_OB)) { | ||||
| Collection *collection = (Collection *)id; | Collection *collection = (Collection *)id; | ||||
| outliner_add_collection_recursive(space_outliner, collection, te); | outliner_add_collection_recursive(space_outliner, collection, te); | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| TreeElement *outliner_add_element(SpaceOutliner *space_outliner, | TreeElement *outliner_add_element(SpaceOutliner *space_outliner, | ||||
| ListBase *lb, | ListBase *lb, | ||||
| void *idv, | void *idv, | ||||
| TreeElement *parent, | TreeElement *parent, | ||||
| short type, | short type, | ||||
| short index) | short index) | ||||
| { | { | ||||
| TreeElement *te; | |||||
| TreeStoreElem *tselem; | |||||
| ID *id = idv; | ID *id = idv; | ||||
| if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { | if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { | ||||
| id = ((PointerRNA *)idv)->owner_id; | id = ((PointerRNA *)idv)->owner_id; | ||||
| if (!id) { | if (!id) { | ||||
| id = ((PointerRNA *)idv)->data; | id = ((PointerRNA *)idv)->data; | ||||
| } | } | ||||
| } | } | ||||
| Show All 10 Lines | else if (id == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (type == 0) { | if (type == 0) { | ||||
| /* Zero type means real ID, ensure we do not get non-outliner ID types here... */ | /* Zero type means real ID, ensure we do not get non-outliner ID types here... */ | ||||
| BLI_assert(TREESTORE_ID_TYPE(id)); | BLI_assert(TREESTORE_ID_TYPE(id)); | ||||
| } | } | ||||
| te = MEM_callocN(sizeof(TreeElement), "tree elem"); | TreeElement *te = MEM_callocN(sizeof(TreeElement), __func__); | ||||
| /* add to the visual tree */ | /* add to the visual tree */ | ||||
| BLI_addtail(lb, te); | BLI_addtail(lb, te); | ||||
| /* add to the storage */ | /* add to the storage */ | ||||
| check_persistent(space_outliner, te, id, type, index); | check_persistent(space_outliner, te, id, type, index); | ||||
| tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| /* if we are searching for something expand to see child elements */ | /* if we are searching for something expand to see child elements */ | ||||
| if (SEARCHING_OUTLINER(space_outliner)) { | if (SEARCHING_OUTLINER(space_outliner)) { | ||||
| tselem->flag |= TSE_CHILDSEARCH; | tselem->flag |= TSE_CHILDSEARCH; | ||||
| } | } | ||||
| te->parent = parent; | te->parent = parent; | ||||
| te->index = index; /* For data arrays. */ | te->index = index; /* For data arrays. */ | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | TreeElement *outliner_add_element(SpaceOutliner *space_outliner, | ||||
| else if (type == TSE_GP_LAYER) { | else if (type == TSE_GP_LAYER) { | ||||
| bGPDlayer *gpl = (bGPDlayer *)idv; | bGPDlayer *gpl = (bGPDlayer *)idv; | ||||
| te->name = gpl->info; | te->name = gpl->info; | ||||
| te->directdata = gpl; | te->directdata = gpl; | ||||
| } | } | ||||
| else if (type == TSE_SEQUENCE) { | else if (type == TSE_SEQUENCE) { | ||||
| Sequence *seq = (Sequence *)idv; | Sequence *seq = (Sequence *)idv; | ||||
| Sequence *p; | |||||
| /* | /* | ||||
| * The idcode is a little hack, but the outliner | * The idcode is a little hack, but the outliner | ||||
| * only check te->idcode if te->type is equal to zero, | * only check te->idcode if te->type is equal to zero, | ||||
| * so this is "safe". | * so this is "safe". | ||||
| */ | */ | ||||
| te->idcode = seq->type; | te->idcode = seq->type; | ||||
| te->directdata = seq; | te->directdata = seq; | ||||
| te->name = seq->name + 2; | te->name = seq->name + 2; | ||||
| if (!(seq->type & SEQ_TYPE_EFFECT)) { | if (!(seq->type & SEQ_TYPE_EFFECT)) { | ||||
| /* | /* | ||||
| * This work like the sequence. | * This work like the sequence. | ||||
| * If the sequence have a name (not default name) | * If the sequence have a name (not default name) | ||||
| * show it, in other case put the filename. | * show it, in other case put the filename. | ||||
| */ | */ | ||||
| if (seq->type == SEQ_TYPE_META) { | if (seq->type == SEQ_TYPE_META) { | ||||
| p = seq->seqbase.first; | LISTBASE_FOREACH (Sequence *, p, &seq->seqbase) { | ||||
| while (p) { | |||||
| outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); | outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); | ||||
| p = p->next; | |||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| outliner_add_element( | outliner_add_element( | ||||
| space_outliner, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index); | space_outliner, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 11 Lines | TreeElement *outliner_add_element(SpaceOutliner *space_outliner, | ||||
| else if (type == TSE_SEQUENCE_DUP) { | else if (type == TSE_SEQUENCE_DUP) { | ||||
| Sequence *seq = (Sequence *)idv; | Sequence *seq = (Sequence *)idv; | ||||
| te->idcode = seq->type; | te->idcode = seq->type; | ||||
| te->directdata = seq; | te->directdata = seq; | ||||
| te->name = seq->strip->stripdata->name; | te->name = seq->strip->stripdata->name; | ||||
| } | } | ||||
| else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { | else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { | ||||
| PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv; | PointerRNA *ptr = (PointerRNA *)idv; | ||||
| PropertyRNA *prop, *iterprop; | |||||
| PropertyType proptype; | |||||
| /* Don't display arrays larger, weak but index is stored as a short, | /* Don't display arrays larger, weak but index is stored as a short, | ||||
| * also the outliner isn't intended for editing such large data-sets. */ | * also the outliner isn't intended for editing such large data-sets. */ | ||||
| BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!") | BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!") | ||||
| const int tot_limit = SHRT_MAX; | const int tot_limit = SHRT_MAX; | ||||
| int a, tot; | |||||
| /* we do lazy build, for speed and to avoid infinite recursion */ | /* we do lazy build, for speed and to avoid infinite recursion */ | ||||
| if (ptr->data == NULL) { | if (ptr->data == NULL) { | ||||
| te->name = IFACE_("(empty)"); | te->name = IFACE_("(empty)"); | ||||
| } | } | ||||
| else if (type == TSE_RNA_STRUCT) { | else if (type == TSE_RNA_STRUCT) { | ||||
| /* struct */ | /* struct */ | ||||
| te->name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); | te->name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); | ||||
| if (te->name) { | if (te->name) { | ||||
| te->flag |= TE_FREE_NAME; | te->flag |= TE_FREE_NAME; | ||||
| } | } | ||||
| else { | else { | ||||
| te->name = RNA_struct_ui_name(ptr->type); | te->name = RNA_struct_ui_name(ptr->type); | ||||
| } | } | ||||
| /* If searching don't expand RNA entries */ | /* If searching don't expand RNA entries */ | ||||
| if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", te->name) == 0) { | if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", te->name) == 0) { | ||||
| tselem->flag &= ~TSE_CHILDSEARCH; | tselem->flag &= ~TSE_CHILDSEARCH; | ||||
| } | } | ||||
| iterprop = RNA_struct_iterator_property(ptr->type); | PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); | ||||
| tot = RNA_property_collection_length(ptr, iterprop); | int tot = RNA_property_collection_length(ptr, iterprop); | ||||
| CLAMP_MAX(tot, tot_limit); | CLAMP_MAX(tot, tot_limit); | ||||
| /* auto open these cases */ | /* auto open these cases */ | ||||
| if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER) { | if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER) { | ||||
| if (!tselem->used) { | if (!tselem->used) { | ||||
| tselem->flag &= ~TSE_CLOSED; | tselem->flag &= ~TSE_CLOSED; | ||||
| } | } | ||||
| } | } | ||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | if (TSELEM_OPEN(tselem, space_outliner)) { | ||||
| for (a = 0; a < tot; a++) { | for (int a = 0; a < tot; a++) { | ||||
| PointerRNA propptr; | |||||
| RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr); | RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr); | ||||
| if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) { | if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) { | ||||
| outliner_add_element( | outliner_add_element( | ||||
| space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a); | space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (tot) { | else if (tot) { | ||||
| te->flag |= TE_LAZY_CLOSED; | te->flag |= TE_LAZY_CLOSED; | ||||
| } | } | ||||
| te->rnaptr = *ptr; | te->rnaptr = *ptr; | ||||
| } | } | ||||
| else if (type == TSE_RNA_PROPERTY) { | else if (type == TSE_RNA_PROPERTY) { | ||||
| /* property */ | /* property */ | ||||
| iterprop = RNA_struct_iterator_property(ptr->type); | PointerRNA propptr; | ||||
| PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); | |||||
| RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); | RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); | ||||
| prop = propptr.data; | PropertyRNA *prop = propptr.data; | ||||
| proptype = RNA_property_type(prop); | PropertyType proptype = RNA_property_type(prop); | ||||
| te->name = RNA_property_ui_name(prop); | te->name = RNA_property_ui_name(prop); | ||||
| te->directdata = prop; | te->directdata = prop; | ||||
| te->rnaptr = *ptr; | te->rnaptr = *ptr; | ||||
| /* If searching don't expand RNA entries */ | /* If searching don't expand RNA entries */ | ||||
| if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", te->name) == 0) { | if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", te->name) == 0) { | ||||
| tselem->flag &= ~TSE_CHILDSEARCH; | tselem->flag &= ~TSE_CHILDSEARCH; | ||||
| } | } | ||||
| if (proptype == PROP_POINTER) { | if (proptype == PROP_POINTER) { | ||||
| pptr = RNA_property_pointer_get(ptr, prop); | PointerRNA pptr = RNA_property_pointer_get(ptr, prop); | ||||
| if (pptr.data) { | if (pptr.data) { | ||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | if (TSELEM_OPEN(tselem, space_outliner)) { | ||||
| outliner_add_element( | outliner_add_element( | ||||
| space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, -1); | space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, -1); | ||||
| } | } | ||||
| else { | else { | ||||
| te->flag |= TE_LAZY_CLOSED; | te->flag |= TE_LAZY_CLOSED; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (proptype == PROP_COLLECTION) { | else if (proptype == PROP_COLLECTION) { | ||||
| tot = RNA_property_collection_length(ptr, prop); | int tot = RNA_property_collection_length(ptr, prop); | ||||
| CLAMP_MAX(tot, tot_limit); | CLAMP_MAX(tot, tot_limit); | ||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | if (TSELEM_OPEN(tselem, space_outliner)) { | ||||
| for (a = 0; a < tot; a++) { | for (int a = 0; a < tot; a++) { | ||||
| PointerRNA pptr; | |||||
| RNA_property_collection_lookup_int(ptr, prop, a, &pptr); | RNA_property_collection_lookup_int(ptr, prop, a, &pptr); | ||||
| outliner_add_element( | outliner_add_element( | ||||
| space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a); | space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a); | ||||
| } | } | ||||
| } | } | ||||
| else if (tot) { | else if (tot) { | ||||
| te->flag |= TE_LAZY_CLOSED; | te->flag |= TE_LAZY_CLOSED; | ||||
| } | } | ||||
| } | } | ||||
| else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { | else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { | ||||
| tot = RNA_property_array_length(ptr, prop); | int tot = RNA_property_array_length(ptr, prop); | ||||
| CLAMP_MAX(tot, tot_limit); | CLAMP_MAX(tot, tot_limit); | ||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | if (TSELEM_OPEN(tselem, space_outliner)) { | ||||
| for (a = 0; a < tot; a++) { | for (int a = 0; a < tot; a++) { | ||||
| outliner_add_element( | outliner_add_element( | ||||
| space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a); | space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a); | ||||
| } | } | ||||
| } | } | ||||
| else if (tot) { | else if (tot) { | ||||
| te->flag |= TE_LAZY_CLOSED; | te->flag |= TE_LAZY_CLOSED; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (type == TSE_RNA_ARRAY_ELEM) { | else if (type == TSE_RNA_ARRAY_ELEM) { | ||||
| char c; | PropertyRNA *prop = parent->directdata; | ||||
| prop = parent->directdata; | |||||
| te->directdata = prop; | te->directdata = prop; | ||||
| te->rnaptr = *ptr; | te->rnaptr = *ptr; | ||||
| te->index = index; | te->index = index; | ||||
| c = RNA_property_array_item_char(prop, index); | char c = RNA_property_array_item_char(prop, index); | ||||
| te->name = MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName"); | te->name = MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName"); | ||||
| if (c) { | if (c) { | ||||
| sprintf((char *)te->name, " %c", c); | sprintf((char *)te->name, " %c", c); | ||||
| } | } | ||||
| else { | else { | ||||
| sprintf((char *)te->name, " %d", index + 1); | sprintf((char *)te->name, " %d", index + 1); | ||||
| } | } | ||||
| te->flag |= TE_FREE_NAME; | te->flag |= TE_FREE_NAME; | ||||
| } | } | ||||
| } | } | ||||
| else if (type == TSE_KEYMAP) { | else if (type == TSE_KEYMAP) { | ||||
| wmKeyMap *km = (wmKeyMap *)idv; | wmKeyMap *km = (wmKeyMap *)idv; | ||||
| wmKeyMapItem *kmi; | |||||
| char opname[OP_MAX_TYPENAME]; | char opname[OP_MAX_TYPENAME]; | ||||
| te->directdata = idv; | te->directdata = idv; | ||||
| te->name = km->idname; | te->name = km->idname; | ||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | if (TSELEM_OPEN(tselem, space_outliner)) { | ||||
| int a = 0; | int a; | ||||
| LISTBASE_FOREACH_INDEX (wmKeyMapItem *, kmi, &km->items, a) { | |||||
| for (kmi = km->items.first; kmi; kmi = kmi->next, a++) { | |||||
| const char *key = WM_key_event_string(kmi->type, false); | const char *key = WM_key_event_string(kmi->type, false); | ||||
| if (key[0]) { | if (key[0]) { | ||||
| wmOperatorType *ot = NULL; | wmOperatorType *ot = NULL; | ||||
| if (kmi->propvalue) { | if (kmi->propvalue) { | ||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
| /* ======================================================= */ | /* ======================================================= */ | ||||
| /* Generic Tree Building helpers - order these are called is top to bottom */ | /* Generic Tree Building helpers - order these are called is top to bottom */ | ||||
| /* Hierarchy --------------------------------------------- */ | /* Hierarchy --------------------------------------------- */ | ||||
| /* make sure elements are correctly nested */ | /* make sure elements are correctly nested */ | ||||
| void outliner_make_object_parent_hierarchy(ListBase *lb) | void outliner_make_object_parent_hierarchy(ListBase *lb) | ||||
| { | { | ||||
| TreeElement *te, *ten, *tep; | |||||
| TreeStoreElem *tselem; | |||||
| /* build hierarchy */ | /* build hierarchy */ | ||||
| /* XXX also, set extents here... */ | /* XXX also, set extents here... */ | ||||
| te = lb->first; | TreeElement *te = lb->first; | ||||
| while (te) { | while (te) { | ||||
| ten = te->next; | TreeElement *ten = te->next; | ||||
| tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| if (tselem->type == 0 && te->idcode == ID_OB) { | if (tselem->type == 0 && te->idcode == ID_OB) { | ||||
| Object *ob = (Object *)tselem->id; | Object *ob = (Object *)tselem->id; | ||||
| if (ob->parent && ob->parent->id.newid) { | if (ob->parent && ob->parent->id.newid) { | ||||
| BLI_remlink(lb, te); | BLI_remlink(lb, te); | ||||
| tep = (TreeElement *)ob->parent->id.newid; | TreeElement *tep = (TreeElement *)ob->parent->id.newid; | ||||
| BLI_addtail(&tep->subtree, te); | BLI_addtail(&tep->subtree, te); | ||||
| te->parent = tep; | te->parent = tep; | ||||
| } | } | ||||
| } | } | ||||
| te = ten; | te = ten; | ||||
| } | } | ||||
| } | } | ||||
| /* Sorting ------------------------------------------------------ */ | /* Sorting ------------------------------------------------------ */ | ||||
| typedef struct tTreeSort { | typedef struct tTreeSort { | ||||
| TreeElement *te; | TreeElement *te; | ||||
| ID *id; | ID *id; | ||||
| const char *name; | const char *name; | ||||
| short idcode; | short idcode; | ||||
| } tTreeSort; | } tTreeSort; | ||||
| /* alphabetical comparator, trying to put objects first */ | /* alphabetical comparator, trying to put objects first */ | ||||
| static int treesort_alpha_ob(const void *v1, const void *v2) | static int treesort_alpha_ob(const void *v1, const void *v2) | ||||
| { | { | ||||
| const tTreeSort *x1 = v1, *x2 = v2; | const tTreeSort *x1 = v1, *x2 = v2; | ||||
| int comp; | |||||
| /* first put objects last (hierarchy) */ | /* first put objects last (hierarchy) */ | ||||
| comp = (x1->idcode == ID_OB); | int comp = (x1->idcode == ID_OB); | ||||
| if (x2->idcode == ID_OB) { | if (x2->idcode == ID_OB) { | ||||
| comp += 2; | comp += 2; | ||||
| } | } | ||||
| if (comp == 1) { | if (comp == 1) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| if (comp == 2) { | if (comp == 2) { | ||||
| Show All 32 Lines | static int treesort_child_not_in_collection(const void *v1, const void *v2) | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* alphabetical comparator */ | /* alphabetical comparator */ | ||||
| static int treesort_alpha(const void *v1, const void *v2) | static int treesort_alpha(const void *v1, const void *v2) | ||||
| { | { | ||||
| const tTreeSort *x1 = v1, *x2 = v2; | const tTreeSort *x1 = v1, *x2 = v2; | ||||
| int comp; | |||||
| comp = BLI_strcasecmp_natural(x1->name, x2->name); | int comp = BLI_strcasecmp_natural(x1->name, x2->name); | ||||
| if (comp > 0) { | if (comp > 0) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| if (comp < 0) { | if (comp < 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| Show All 38 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| /* sort happens on each subtree individual */ | /* sort happens on each subtree individual */ | ||||
| static void outliner_sort(ListBase *lb) | static void outliner_sort(ListBase *lb) | ||||
| { | { | ||||
| TreeElement *te; | TreeElement *te = lb->last; | ||||
| TreeStoreElem *tselem; | |||||
| te = lb->last; | |||||
| if (te == NULL) { | if (te == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| /* sorting rules; only object lists, ID lists, or deformgroups */ | /* sorting rules; only object lists, ID lists, or deformgroups */ | ||||
| if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || | if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || | ||||
| (tselem->type == 0 && te->idcode == ID_OB)) { | (tselem->type == 0 && te->idcode == ID_OB)) { | ||||
| int totelem = BLI_listbase_count(lb); | int totelem = BLI_listbase_count(lb); | ||||
| if (totelem > 1) { | if (totelem > 1) { | ||||
| tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array"); | tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array"); | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | static void outliner_sort(ListBase *lb) | ||||
| LISTBASE_FOREACH (TreeElement *, te_iter, lb) { | LISTBASE_FOREACH (TreeElement *, te_iter, lb) { | ||||
| outliner_sort(&te_iter->subtree); | outliner_sort(&te_iter->subtree); | ||||
| } | } | ||||
| } | } | ||||
| static void outliner_collections_children_sort(ListBase *lb) | static void outliner_collections_children_sort(ListBase *lb) | ||||
| { | { | ||||
| TreeElement *te; | TreeElement *te = lb->last; | ||||
| TreeStoreElem *tselem; | |||||
| te = lb->last; | |||||
| if (te == NULL) { | if (te == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| /* Sorting rules: only object lists. */ | /* Sorting rules: only object lists. */ | ||||
| if (tselem->type == 0 && te->idcode == ID_OB) { | if (tselem->type == 0 && te->idcode == ID_OB) { | ||||
| int totelem = BLI_listbase_count(lb); | int totelem = BLI_listbase_count(lb); | ||||
| if (totelem > 1) { | if (totelem > 1) { | ||||
| tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array"); | tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array"); | ||||
| tTreeSort *tp = tear; | tTreeSort *tp = tear; | ||||
| ▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
| * Basically we keep going up and down the outliner tree from that point forward, until we find | * Basically we keep going up and down the outliner tree from that point forward, until we find | ||||
| * what we are looking for. If we are past the visible range and we can't find a valid element | * what we are looking for. If we are past the visible range and we can't find a valid element | ||||
| * we return NULL. | * we return NULL. | ||||
| */ | */ | ||||
| static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner *space_outliner, | static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner *space_outliner, | ||||
| const float view_co, | const float view_co, | ||||
| const float view_co_limit) | const float view_co_limit) | ||||
| { | { | ||||
| TreeElement *te, *te_sub; | TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); | ||||
| te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); | |||||
| bool (*callback_test)(TreeElement *); | bool (*callback_test)(TreeElement *); | ||||
| if ((space_outliner->outlinevis == SO_VIEW_LAYER) && | if ((space_outliner->outlinevis == SO_VIEW_LAYER) && | ||||
| (space_outliner->filter & SO_FILTER_NO_COLLECTION)) { | (space_outliner->filter & SO_FILTER_NO_COLLECTION)) { | ||||
| callback_test = test_object_callback; | callback_test = test_object_callback; | ||||
| } | } | ||||
| else { | else { | ||||
| callback_test = test_collection_callback; | callback_test = test_collection_callback; | ||||
| } | } | ||||
| while (te != NULL) { | while (te != NULL) { | ||||
| te_sub = outliner_find_first_desired_element_at_y_recursive( | TreeElement *te_sub = outliner_find_first_desired_element_at_y_recursive( | ||||
| space_outliner, te, view_co_limit, callback_test); | space_outliner, te, view_co_limit, callback_test); | ||||
| if (te_sub != NULL) { | if (te_sub != NULL) { | ||||
| /* Skip the element if it was not visible to start with. */ | /* Skip the element if it was not visible to start with. */ | ||||
| if (te->ys + UI_UNIT_Y > view_co_limit) { | if (te->ys + UI_UNIT_Y > view_co_limit) { | ||||
| return te_sub; | return te_sub; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| Show All 25 Lines | |||||
| * Finds the top-most collection visible in the outliner and populates the | * Finds the top-most collection visible in the outliner and populates the | ||||
| * #OutlinerTreeElementFocus struct to retrieve this element later to make sure it is in the same | * #OutlinerTreeElementFocus struct to retrieve this element later to make sure it is in the same | ||||
| * original position as before filtering. | * original position as before filtering. | ||||
| */ | */ | ||||
| static void outliner_store_scrolling_position(SpaceOutliner *space_outliner, | static void outliner_store_scrolling_position(SpaceOutliner *space_outliner, | ||||
| ARegion *region, | ARegion *region, | ||||
| OutlinerTreeElementFocus *focus) | OutlinerTreeElementFocus *focus) | ||||
| { | { | ||||
| TreeElement *te; | |||||
| float limit = region->v2d.cur.ymin; | float limit = region->v2d.cur.ymin; | ||||
| outliner_set_coordinates(region, space_outliner); | outliner_set_coordinates(region, space_outliner); | ||||
| te = outliner_find_first_desired_element_at_y(space_outliner, region->v2d.cur.ymax, limit); | TreeElement *te = outliner_find_first_desired_element_at_y( | ||||
| space_outliner, region->v2d.cur.ymax, limit); | |||||
| if (te != NULL) { | if (te != NULL) { | ||||
| focus->tselem = TREESTORE(te); | focus->tselem = TREESTORE(te); | ||||
| focus->ys = te->ys; | focus->ys = te->ys; | ||||
| } | } | ||||
| else { | else { | ||||
| focus->tselem = NULL; | focus->tselem = NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 348 Lines • Show Last 20 Lines | |||||