Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c67
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h1
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c119
3 files changed, 176 insertions, 11 deletions
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 9dbea3c5b1b..545e31c8b4a 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -627,6 +627,10 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
}
+ else if ((tselem->type == 0 && te->idcode == ID_OB) &&
+ (te->flag & TE_CHILD_NOT_IN_COLLECTION)) {
+ /* Don't show restrict columns for children that are not directly inside the collection. */
+ }
else if (tselem->type == 0 && te->idcode == ID_OB) {
PointerRNA ptr;
Object *ob = (Object *)tselem->id;
@@ -2074,7 +2078,10 @@ static void outliner_draw_tree_element(bContext *C,
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
- const float alpha_fac = ((te->flag & TE_DISABLED) || draw_grayed_out) ? 0.5f : 1.0f;
+ const float alpha_fac = ((te->flag & TE_DISABLED) || (te->flag & TE_CHILD_NOT_IN_COLLECTION) ||
+ draw_grayed_out) ?
+ 0.5f :
+ 1.0f;
const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
@@ -2338,17 +2345,28 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
bool draw_grayed_out,
int *starty)
{
- TreeElement *te, *te_vertical_line_last = NULL;
- int y1, y2;
+ TreeElement *te, *te_vertical_line_last = NULL, *te_vertical_line_last_dashed = NULL;
+ int y1, y2, y1_dashed, y2_dashed;
if (BLI_listbase_is_empty(lb)) {
return;
}
+ struct {
+ int steps_num;
+ int step_len;
+ int gap_len;
+ } dash = {
+ .steps_num = 4,
+ };
+
+ dash.step_len = UI_UNIT_X / dash.steps_num;
+ dash.gap_len = dash.step_len / 2;
+
const unsigned char grayed_alpha = col[3] / 2;
/* For vertical lines between objects. */
- y1 = y2 = *starty;
+ y1 = y2 = y1_dashed = y2_dashed = *starty;
for (te = lb->first; te; te = te->next) {
bool draw_childs_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING);
TreeStoreElem *tselem = TREESTORE(te);
@@ -2360,16 +2378,31 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
immUniformColor4ubv(col);
}
- /* Horizontal Line? */
- if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) {
- immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
+ if ((te->flag & TE_CHILD_NOT_IN_COLLECTION) == 0) {
+ /* Horizontal Line? */
+ if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) {
+ immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
- /* Vertical Line? */
- if (te->idcode == ID_OB) {
- te_vertical_line_last = te;
- y2 = *starty;
+ /* Vertical Line? */
+ if (te->idcode == ID_OB) {
+ te_vertical_line_last = te;
+ y2 = *starty;
+ }
+ y1_dashed = *starty - UI_UNIT_Y;
}
}
+ else {
+ BLI_assert(te->idcode == ID_OB);
+ /* Horizontal line - dashed. */
+ int start = startx;
+ for (int i = 0; i < dash.steps_num; i++) {
+ immRecti(pos, start, *starty, start + dash.step_len - dash.gap_len, *starty - 1);
+ start += dash.step_len;
+ }
+
+ te_vertical_line_last_dashed = te;
+ y2_dashed = *starty;
+ }
*starty -= UI_UNIT_Y;
@@ -2391,6 +2424,18 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos,
if ((te != NULL) && (te->parent || lb->first != lb->last)) {
immRecti(pos, startx, y1 + UI_UNIT_Y, startx + 1, y2);
}
+
+ /* Children that are not in the collection are always in the end of the subtree.
+ * This way we can draw their own dashed vertical lines. */
+ te = te_vertical_line_last_dashed;
+ if ((te != NULL) && (te->parent || lb->first != lb->last)) {
+ const int steps_num = ((y1_dashed + UI_UNIT_Y) - y2_dashed) / dash.step_len;
+ int start = y1_dashed + UI_UNIT_Y;
+ for (int i = 0; i < steps_num; i++) {
+ immRecti(pos, startx, start, startx + 1, start - dash.step_len + dash.gap_len);
+ start -= dash.step_len;
+ }
+ }
}
static void outliner_draw_hierarchy_lines(SpaceOutliner *soops,
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index d382384076b..d532a1cbbb8 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -130,6 +130,7 @@ enum {
TE_FREE_NAME = (1 << 3),
TE_DISABLED = (1 << 4),
TE_DRAGGING = (1 << 5),
+ TE_CHILD_NOT_IN_COLLECTION = (1 << 6),
};
/* button events */
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 69449f46677..a2f332b0795 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -48,6 +48,7 @@
#include "DNA_linestyle_types.h"
#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_mempool.h"
#include "BLI_fnmatch.h"
@@ -1477,6 +1478,108 @@ static void outliner_make_object_parent_hierarchy(ListBase *lb)
}
}
+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 ------------------------------------------------------ */
typedef struct tTreeSort {
@@ -1505,6 +1608,13 @@ static int treesort_alpha_ob(const void *v1, const void *v2)
return -1;
}
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);
if (comp > 0) {
@@ -2191,6 +2301,15 @@ void outliner_build_tree(
bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
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);
+ }
}
}