Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_tree.c
| Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_world_types.h" | #include "DNA_world_types.h" | ||||
| #include "DNA_sequence_types.h" | #include "DNA_sequence_types.h" | ||||
| #include "DNA_speaker_types.h" | #include "DNA_speaker_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_linestyle_types.h" | #include "DNA_linestyle_types.h" | ||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_listbase.h" | |||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_mempool.h" | #include "BLI_mempool.h" | ||||
| #include "BLI_fnmatch.h" | #include "BLI_fnmatch.h" | ||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_fcurve.h" | #include "BKE_fcurve.h" | ||||
| #include "BKE_idcode.h" | #include "BKE_idcode.h" | ||||
| ▲ Show 20 Lines • Show All 1,413 Lines • ▼ Show 20 Lines | if (tselem->type == 0 && te->idcode == ID_OB) { | ||||
| BLI_addtail(&tep->subtree, te); | BLI_addtail(&tep->subtree, te); | ||||
| te->parent = tep; | te->parent = tep; | ||||
| } | } | ||||
| } | } | ||||
| te = ten; | te = ten; | ||||
| } | } | ||||
| } | } | ||||
| static void outliner_make_object_parent_hierarchy_recursive(SpaceOutliner *soops, | |||||
| GHash *parent_children_hash, | |||||
| TreeElement *te_parent, | |||||
| ListBase *tree_to_remove_objects_from) | |||||
| { | |||||
| if (tree_to_remove_objects_from == NULL) { | |||||
| tree_to_remove_objects_from = &te_parent->subtree; | |||||
| } | |||||
| /* Build hierarchy. */ | |||||
| for (TreeElement *te = te_parent->subtree.first; te; te = te->next) { | |||||
| TreeStoreElem *tselem = TREESTORE(te); | |||||
| if (tselem->type == TSE_LAYER_COLLECTION) { | |||||
| outliner_make_object_parent_hierarchy_recursive(soops, parent_children_hash, te, NULL); | |||||
| } | |||||
| else if (tselem->type == 0 && te->idcode == ID_OB) { | |||||
| Object *ob = (Object *)tselem->id; | |||||
| ListBase *children = BLI_ghash_lookup(parent_children_hash, ob); | |||||
| if (children) { | |||||
| TreeElement *te_last_element_in_object_tree = te->subtree.last; | |||||
| for (LinkData *link = children->first; link; link = link->next) { | |||||
| Object *child = link->data; | |||||
| TreeElement *te_child = NULL; | |||||
| /* Check if the child is in the layer collection / tree. */ | |||||
| for (TreeElement *te_iter = tree_to_remove_objects_from->first; te_iter; | |||||
| te_iter = te_iter->next) { | |||||
| TreeStoreElem *tselem_iter = TREESTORE(te_iter); | |||||
| if ((tselem_iter->type == 0 && te_iter->idcode == ID_OB) && | |||||
| (tselem_iter->id == &child->id)) { | |||||
| te_child = te_iter; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (te_child) { | |||||
| BLI_remlink(tree_to_remove_objects_from, te_child); | |||||
| /* We group the children that are in the collection before the ones that are not. | |||||
| * This way we can try to draw them in a different style altogether. | |||||
| * We also have to respect the original order of the elements in case alphabetical | |||||
| * sorting is not enabled. This keep object data and modifiers before its children. */ | |||||
| BLI_insertlinkafter(&te->subtree, te_last_element_in_object_tree, te_child); | |||||
| te_child->parent = te; | |||||
| continue; | |||||
| } | |||||
| /* If not see if it is already nested under its parent. | |||||
| * This happens depending on the order of the evaluation. */ | |||||
| for (TreeElement *te_iter = te->subtree.first; te_iter; te_iter = te_iter->next) { | |||||
| TreeStoreElem *tselem_iter = TREESTORE(te_iter); | |||||
| if ((tselem_iter->type == 0 && te_iter->idcode == ID_OB) && | |||||
| (tselem_iter->id == &child->id)) { | |||||
| te_child = te_iter; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (te_child == NULL) { | |||||
| te_child = outliner_add_element(soops, &te->subtree, child, te, 0, 0); | |||||
| outliner_free_tree(&te_child->subtree); | |||||
| te_child->flag |= TE_CHILD_NOT_IN_COLLECTION; | |||||
| } | |||||
| } | |||||
| outliner_make_object_parent_hierarchy_recursive( | |||||
| soops, parent_children_hash, te, tree_to_remove_objects_from); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| static void outliner_build_parent_children_tree_create(Main *bmain, GHash *parent_children_hash) | |||||
| { | |||||
| ListBase *children = NULL; | |||||
| for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { | |||||
| if (!ob->parent) { | |||||
| continue; | |||||
| } | |||||
| children = BLI_ghash_lookup(parent_children_hash, ob->parent); | |||||
| if (children == NULL) { | |||||
| children = MEM_callocN(sizeof(ListBase), __func__); | |||||
| BLI_ghash_insert(parent_children_hash, ob->parent, children); | |||||
| } | |||||
| BLI_addtail(children, BLI_genericNodeN(ob)); | |||||
| } | |||||
| } | |||||
| static void outliner_build_parent_children_tree_free(Main *bmain, GHash *parent_children_hash) | |||||
| { | |||||
| for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { | |||||
| ListBase *children = BLI_ghash_lookup(parent_children_hash, ob); | |||||
| if (children) { | |||||
| BLI_freelistN(children); | |||||
| MEM_freeN(children); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* 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; | ||||
| Show All 12 Lines | static int treesort_alpha_ob(const void *v1, const void *v2) | ||||
| if (comp == 1) { | if (comp == 1) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| else if (comp == 2) { | else if (comp == 2) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (comp == 3) { | else if (comp == 3) { | ||||
| /* Among objects first come the ones in the collection, followed by the ones not on it. | |||||
| * This way we can have the dashed lines in a separate style connecting the former. */ | |||||
| if ((x1->te->flag & TE_CHILD_NOT_IN_COLLECTION) != | |||||
| (x2->te->flag & TE_CHILD_NOT_IN_COLLECTION)) { | |||||
| return (x1->te->flag & TE_CHILD_NOT_IN_COLLECTION) ? 1 : -1; | |||||
| } | |||||
| comp = strcmp(x1->name, x2->name); | comp = strcmp(x1->name, x2->name); | ||||
| if (comp > 0) { | if (comp > 0) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| else if (comp < 0) { | else if (comp < 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 670 Lines • ▼ Show 20 Lines | else if (soops->outlinevis == SO_VIEW_LAYER) { | ||||
| else { | else { | ||||
| /* Show collections in the view layer. */ | /* Show collections in the view layer. */ | ||||
| ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0); | ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0); | ||||
| ten->name = IFACE_("Scene Collection"); | ten->name = IFACE_("Scene Collection"); | ||||
| TREESTORE(ten)->flag &= ~TSE_CLOSED; | TREESTORE(ten)->flag &= ~TSE_CLOSED; | ||||
| bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT); | bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT); | ||||
| outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects); | outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects); | ||||
| if ((soops->filter & SO_FILTER_NO_CHILDREN) == 0) { | |||||
| GHash *parent_children_hash = BLI_ghash_new( | |||||
| BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); | |||||
| outliner_build_parent_children_tree_create(mainvar, parent_children_hash); | |||||
| outliner_make_object_parent_hierarchy_recursive(soops, parent_children_hash, ten, NULL); | |||||
| outliner_build_parent_children_tree_free(mainvar, parent_children_hash); | |||||
| BLI_ghash_free(parent_children_hash, NULL, NULL); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) { | if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) { | ||||
| outliner_sort(&soops->tree); | outliner_sort(&soops->tree); | ||||
| } | } | ||||
| outliner_filter_tree(soops, view_layer); | outliner_filter_tree(soops, view_layer); | ||||
| outliner_restore_scrolling_position(soops, ar, &focus); | outliner_restore_scrolling_position(soops, ar, &focus); | ||||
| BKE_main_id_clear_newpoins(mainvar); | BKE_main_id_clear_newpoins(mainvar); | ||||
| } | } | ||||