Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_draw.c
| Show First 20 Lines • Show All 842 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| typedef struct RestrictProperties { | typedef struct RestrictProperties { | ||||
| bool initialized; | bool initialized; | ||||
| PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render; | PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render; | ||||
| PropertyRNA *base_hide_viewport; | PropertyRNA *base_hide_viewport; | ||||
| PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render; | PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render; | ||||
| PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only, | PropertyRNA *layer_collection_exclude, *layer_collection_holdout, | ||||
| *layer_collection_hide_viewport; | *layer_collection_indirect_only, *layer_collection_hide_viewport; | ||||
| PropertyRNA *modifier_show_viewport, *modifier_show_render; | PropertyRNA *modifier_show_viewport, *modifier_show_render; | ||||
| PropertyRNA *constraint_enable; | PropertyRNA *constraint_enable; | ||||
| PropertyRNA *bone_hide_viewport; | PropertyRNA *bone_hide_viewport; | ||||
| } RestrictProperties; | } RestrictProperties; | ||||
| /* We don't care about the value of the property | /* We don't care about the value of the property | ||||
| * but whether the property should be active or grayed out. */ | * but whether the property should be active or grayed out. */ | ||||
| typedef struct RestrictPropertiesActive { | typedef struct RestrictPropertiesActive { | ||||
| bool object_hide_viewport; | bool object_hide_viewport; | ||||
| bool object_hide_select; | bool object_hide_select; | ||||
| bool object_hide_render; | bool object_hide_render; | ||||
| bool base_hide_viewport; | bool base_hide_viewport; | ||||
| bool collection_hide_viewport; | bool collection_hide_viewport; | ||||
| bool collection_hide_select; | bool collection_hide_select; | ||||
| bool collection_hide_render; | bool collection_hide_render; | ||||
| bool layer_collection_exclude; | |||||
| bool layer_collection_holdout; | bool layer_collection_holdout; | ||||
| bool layer_collection_indirect_only; | bool layer_collection_indirect_only; | ||||
| bool layer_collection_hide_viewport; | bool layer_collection_hide_viewport; | ||||
| bool modifier_show_viewport; | bool modifier_show_viewport; | ||||
| bool modifier_show_render; | bool modifier_show_render; | ||||
| bool constraint_enable; | bool constraint_enable; | ||||
| bool bone_hide_viewport; | bool bone_hide_viewport; | ||||
| } RestrictPropertiesActive; | } RestrictPropertiesActive; | ||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | static bool outliner_restrict_properties_collection_set(Scene *scene, | ||||
| RestrictProperties *props, | RestrictProperties *props, | ||||
| RestrictPropertiesActive *props_active) | RestrictPropertiesActive *props_active) | ||||
| { | { | ||||
| TreeStoreElem *tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : | LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : | ||||
| NULL; | NULL; | ||||
| Collection *collection = outliner_collection_from_tree_element(te); | Collection *collection = outliner_collection_from_tree_element(te); | ||||
| if ((collection->flag & COLLECTION_IS_MASTER) || | if (collection->flag & COLLECTION_IS_MASTER) { | ||||
| (layer_collection && ((layer_collection->flag & LAYER_COLLECTION_EXCLUDE) != 0))) { | |||||
| return false; | return false; | ||||
| } | } | ||||
| /* Create the PointerRNA. */ | /* Create the PointerRNA. */ | ||||
| RNA_id_pointer_create(&collection->id, collection_ptr); | RNA_id_pointer_create(&collection->id, collection_ptr); | ||||
| if (layer_collection != NULL) { | if (layer_collection != NULL) { | ||||
| RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, layer_collection_ptr); | RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, layer_collection_ptr); | ||||
| } | } | ||||
| Show All 23 Lines | if (!props.initialized) { | ||||
| props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport"); | props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport"); | ||||
| props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); | props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); | ||||
| props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); | props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); | ||||
| props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport"); | props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport"); | ||||
| props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, | props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, | ||||
| "hide_viewport"); | "hide_viewport"); | ||||
| props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); | props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); | ||||
| props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render"); | props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render"); | ||||
| props.layer_collection_exclude = RNA_struct_type_find_property(&RNA_LayerCollection, | |||||
| "exclude"); | |||||
| props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection, | props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection, | ||||
| "holdout"); | "holdout"); | ||||
| props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection, | props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection, | ||||
| "indirect_only"); | "indirect_only"); | ||||
| props.layer_collection_hide_viewport = RNA_struct_type_find_property(&RNA_LayerCollection, | props.layer_collection_hide_viewport = RNA_struct_type_find_property(&RNA_LayerCollection, | ||||
| "hide_viewport"); | "hide_viewport"); | ||||
| props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport"); | props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport"); | ||||
| props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render"); | props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render"); | ||||
| props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute"); | props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute"); | ||||
| props.bone_hide_viewport = RNA_struct_type_find_property(&RNA_Bone, "hide"); | props.bone_hide_viewport = RNA_struct_type_find_property(&RNA_Bone, "hide"); | ||||
| props.initialized = true; | props.initialized = true; | ||||
| } | } | ||||
| struct { | struct { | ||||
| int enable; | |||||
| int select; | int select; | ||||
| int hide; | int hide; | ||||
| int viewport; | int viewport; | ||||
| int render; | int render; | ||||
| int indirect_only; | int indirect_only; | ||||
| int holdout; | int holdout; | ||||
| } restrict_offsets = {0}; | } restrict_offsets = {0}; | ||||
| int restrict_column_offset = 0; | int restrict_column_offset = 0; | ||||
| Show All 14 Lines | if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) { | ||||
| restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | ||||
| } | } | ||||
| if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) { | if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) { | ||||
| restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | ||||
| } | } | ||||
| if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) { | if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) { | ||||
| restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | ||||
| } | } | ||||
| if (space_outliner->outlinevis == SO_VIEW_LAYER && | |||||
| space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) { | |||||
| restrict_offsets.enable = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; | |||||
| } | |||||
| BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) == | BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) == | ||||
| outliner_restrict_columns_width(space_outliner)); | outliner_restrict_columns_width(space_outliner)); | ||||
| /* Create buttons. */ | /* Create buttons. */ | ||||
| uiBut *bt; | uiBut *bt; | ||||
| LISTBASE_FOREACH (TreeElement *, te, lb) { | LISTBASE_FOREACH (TreeElement *, te, lb) { | ||||
| TreeStoreElem *tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| ▲ Show 20 Lines • Show All 372 Lines • ▼ Show 20 Lines | if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) { | ||||
| scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active)) { | scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active)) { | ||||
| LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? | LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? | ||||
| te->directdata : | te->directdata : | ||||
| NULL; | NULL; | ||||
| Collection *collection = outliner_collection_from_tree_element(te); | Collection *collection = outliner_collection_from_tree_element(te); | ||||
| if (layer_collection != NULL) { | if (layer_collection != NULL) { | ||||
| if (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) { | |||||
| bt = uiDefIconButR_prop(block, | |||||
| UI_BTYPE_ICON_TOGGLE, | |||||
| 0, | |||||
| 0, | |||||
| (int)(region->v2d.cur.xmax) - restrict_offsets.enable, | |||||
| te->ys, | |||||
| UI_UNIT_X, | |||||
| UI_UNIT_Y, | |||||
| &layer_collection_ptr, | |||||
| props.layer_collection_exclude, | |||||
| -1, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| NULL); | |||||
| UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); | |||||
| } | |||||
| if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) { | if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) { | ||||
| bt = uiDefIconButR_prop(block, | bt = uiDefIconButR_prop(block, | ||||
| UI_BTYPE_ICON_TOGGLE, | UI_BTYPE_ICON_TOGGLE, | ||||
| 0, | 0, | ||||
| 0, | 0, | ||||
| (int)(region->v2d.cur.xmax - restrict_offsets.hide), | (int)(region->v2d.cur.xmax - restrict_offsets.hide), | ||||
| te->ys, | te->ys, | ||||
| UI_UNIT_X, | UI_UNIT_X, | ||||
| ▲ Show 20 Lines • Show All 377 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static void outliner_buttons(const bContext *C, | static void outliner_buttons(const bContext *C, | ||||
| uiBlock *block, | uiBlock *block, | ||||
| ARegion *region, | ARegion *region, | ||||
| const float restrict_column_width, | const float restrict_column_width, | ||||
| TreeElement *te) | TreeElement *te) | ||||
| { | { | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | |||||
| uiBut *bt; | uiBut *bt; | ||||
| TreeStoreElem *tselem; | TreeStoreElem *tselem; | ||||
| int spx, dx, len; | int spx, dx, len; | ||||
| tselem = TREESTORE(te); | tselem = TREESTORE(te); | ||||
| BLI_assert(tselem->flag & TSE_TEXTBUT); | BLI_assert(tselem->flag & TSE_TEXTBUT); | ||||
| /* If we add support to rename Sequence. | /* If we add support to rename Sequence. | ||||
| Show All 9 Lines | static void outliner_buttons(const bContext *C, | ||||
| else if (tselem->id && GS(tselem->id->name) == ID_LI) { | else if (tselem->id && GS(tselem->id->name) == ID_LI) { | ||||
| len = sizeof(((Library *)0)->filepath); | len = sizeof(((Library *)0)->filepath); | ||||
| } | } | ||||
| else { | else { | ||||
| len = MAX_ID_NAME - 2; | len = MAX_ID_NAME - 2; | ||||
| } | } | ||||
| spx = te->xs + 1.8f * UI_UNIT_X; | spx = te->xs + 1.8f * UI_UNIT_X; | ||||
| if ((tselem->type == TSE_LAYER_COLLECTION) && | |||||
| (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE)) { | |||||
| spx += UI_UNIT_X; | |||||
| } | |||||
| dx = region->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X); | dx = region->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X); | ||||
| bt = uiDefBut(block, | bt = uiDefBut(block, | ||||
| UI_BTYPE_TEXT, | UI_BTYPE_TEXT, | ||||
| OL_NAMEBUTTON, | OL_NAMEBUTTON, | ||||
| "", | "", | ||||
| spx, | spx, | ||||
| te->ys, | te->ys, | ||||
| ▲ Show 20 Lines • Show All 478 Lines • ▼ Show 20 Lines | switch (tselem->type) { | ||||
| case TSE_SCENE_COLLECTION_BASE: | case TSE_SCENE_COLLECTION_BASE: | ||||
| case TSE_VIEW_COLLECTION_BASE: { | case TSE_VIEW_COLLECTION_BASE: { | ||||
| Collection *collection = outliner_collection_from_tree_element(te); | Collection *collection = outliner_collection_from_tree_element(te); | ||||
| if (collection && !(collection->flag & COLLECTION_IS_MASTER)) { | if (collection && !(collection->flag & COLLECTION_IS_MASTER)) { | ||||
| data.drag_id = tselem->id; | data.drag_id = tselem->id; | ||||
| data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL; | data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : NULL; | ||||
| } | } | ||||
| data.icon = ICON_GROUP; | data.icon = ICON_OUTLINER_COLLECTION; | ||||
| break; | break; | ||||
| } | } | ||||
| case TSE_GP_LAYER: { | case TSE_GP_LAYER: { | ||||
| data.icon = ICON_OUTLINER_DATA_GP_LAYER; | data.icon = ICON_OUTLINER_DATA_GP_LAYER; | ||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| data.icon = ICON_DOT; | data.icon = ICON_DOT; | ||||
| ▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | else { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return data; | return data; | ||||
| } | } | ||||
| static void tselem_draw_layer_collection_enable_icon( | |||||
| Scene *scene, uiBlock *block, int xmax, float x, float y, TreeElement *te, float alpha) | |||||
| { | |||||
| /* Get RNA property (once for speed). */ | |||||
| static PropertyRNA *exclude_prop = NULL; | |||||
| if (exclude_prop == NULL) { | |||||
| exclude_prop = RNA_struct_type_find_property(&RNA_LayerCollection, "exclude"); | |||||
| } | |||||
| if (x >= xmax) { | |||||
| /* Placement of icons, copied from interface_widgets.c. */ | |||||
| float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; | |||||
| x += 2.0f * aspect; | |||||
| y += 2.0f * aspect; | |||||
| /* restrict column clip... it has been coded by simply overdrawing, | |||||
| * doesn't work for buttons */ | |||||
| uchar color[4]; | |||||
| int icon = RNA_property_ui_icon(exclude_prop); | |||||
| if (UI_icon_get_theme_color(icon, color)) { | |||||
| UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, color, true); | |||||
| } | |||||
| else { | |||||
| UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false); | |||||
| } | |||||
| } | |||||
| else { | |||||
| LayerCollection *layer_collection = te->directdata; | |||||
| PointerRNA layer_collection_ptr; | |||||
| RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr); | |||||
| char emboss = UI_block_emboss_get(block); | |||||
| UI_block_emboss_set(block, UI_EMBOSS_NONE); | |||||
| uiBut *bt = uiDefIconButR_prop(block, | |||||
| UI_BTYPE_ICON_TOGGLE, | |||||
| 0, | |||||
| 0, | |||||
| x, | |||||
| y, | |||||
| UI_UNIT_X, | |||||
| UI_UNIT_Y, | |||||
| &layer_collection_ptr, | |||||
| exclude_prop, | |||||
| -1, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| NULL); | |||||
| UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); | |||||
| UI_block_emboss_set(block, emboss); | |||||
| } | |||||
| } | |||||
| static void tselem_draw_icon(uiBlock *block, | static void tselem_draw_icon(uiBlock *block, | ||||
| int xmax, | int xmax, | ||||
| float x, | float x, | ||||
| float y, | float y, | ||||
| TreeStoreElem *tselem, | TreeStoreElem *tselem, | ||||
| TreeElement *te, | TreeElement *te, | ||||
| float alpha, | float alpha, | ||||
| const bool is_clickable) | const bool is_clickable) | ||||
| { | { | ||||
| TreeElementIcon data = tree_element_get_icon(tselem, te); | TreeElementIcon data = tree_element_get_icon(tselem, te); | ||||
| if (data.icon == 0) { | if (data.icon == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (outliner_is_collection_tree_element(te)) { | |||||
| Collection *collection = outliner_collection_from_tree_element(te); | |||||
| /* placement of icons, copied from interface_widgets.c */ | |||||
| float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; | |||||
| x += 2.0f * aspect; | |||||
| y += 2.0f * aspect; | |||||
| if (collection->color != COLLECTION_COLOR_NONE) { | |||||
| bTheme *btheme = UI_GetTheme(); | |||||
| UI_icon_draw_ex(x, | |||||
| y, | |||||
| data.icon, | |||||
| U.inv_dpi_fac, | |||||
| alpha, | |||||
| 0.0f, | |||||
| btheme->collection_color[collection->color - 1].color, | |||||
| true); | |||||
| } | |||||
| else { | |||||
| UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, NULL, true); | |||||
| } | |||||
| } | |||||
| /* Icon is covered by restrict buttons */ | /* Icon is covered by restrict buttons */ | ||||
| if (!is_clickable || x >= xmax) { | else if (!is_clickable || x >= xmax) { | ||||
| /* Reduce alpha to match icon buttons */ | /* Reduce alpha to match icon buttons */ | ||||
| alpha *= 0.8f; | alpha *= 0.8f; | ||||
| /* placement of icons, copied from interface_widgets.c */ | /* placement of icons, copied from interface_widgets.c */ | ||||
| float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; | float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; | ||||
| x += 2.0f * aspect; | x += 2.0f * aspect; | ||||
| y += 2.0f * aspect; | y += 2.0f * aspect; | ||||
| ▲ Show 20 Lines • Show All 374 Lines • ▼ Show 20 Lines | else if (tselem->type == TSE_GP_LAYER) { | ||||
| if (((bGPDlayer *)te->directdata)->flag & GP_LAYER_ACTIVE) { | if (((bGPDlayer *)te->directdata)->flag & GP_LAYER_ACTIVE) { | ||||
| icon_bgcolor[3] = 0.2f; | icon_bgcolor[3] = 0.2f; | ||||
| active = OL_DRAWSEL_ACTIVE; | active = OL_DRAWSEL_ACTIVE; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| active = tree_element_type_active(C, tvc, space_outliner, te, tselem, OL_SETSEL_NONE, false); | active = tree_element_type_active(C, tvc, space_outliner, te, tselem, OL_SETSEL_NONE, false); | ||||
| /* active collection*/ | /* active collection*/ | ||||
| icon_bgcolor[3] = 0.2f; | |||||
| } | |||||
| /* Checkbox to enable collections. */ | |||||
| if ((tselem->type == TSE_LAYER_COLLECTION) && | |||||
| (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE)) { | |||||
| tselem_draw_layer_collection_enable_icon( | |||||
| tvc->scene, block, xmax, (float)startx + offsx + UI_UNIT_X, (float)*starty, te, 0.8f); | |||||
| offsx += UI_UNIT_X; | |||||
| } | } | ||||
| /* active circle */ | /* active circle */ | ||||
| if (active != OL_DRAWSEL_NONE) { | if (active != OL_DRAWSEL_NONE) { | ||||
| UI_draw_roundbox_corner_set(UI_CNR_ALL); | UI_draw_roundbox_corner_set(UI_CNR_ALL); | ||||
| UI_draw_roundbox_aa(true, | UI_draw_roundbox_aa(true, | ||||
| (float)startx + offsx + UI_UNIT_X, | (float)startx + offsx + UI_UNIT_X, | ||||
| (float)*starty + ufac, | (float)*starty + ufac, | ||||
| ▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | else { | ||||
| LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) { | LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) { | ||||
| outliner_set_coord_tree_element(ten, startx, *starty); | outliner_set_coord_tree_element(ten, startx, *starty); | ||||
| } | } | ||||
| *starty -= UI_UNIT_Y; | *starty -= UI_UNIT_Y; | ||||
| } | } | ||||
| } | } | ||||
| static bool subtree_contains_object(ListBase *lb) | |||||
| { | |||||
| LISTBASE_FOREACH (TreeElement *, te, lb) { | |||||
| TreeStoreElem *tselem = TREESTORE(te); | |||||
| if (tselem->type == 0 && te->idcode == ID_OB) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| static void outliner_draw_hierarchy_lines_recursive(uint pos, | static void outliner_draw_hierarchy_lines_recursive(uint pos, | ||||
| SpaceOutliner *space_outliner, | SpaceOutliner *space_outliner, | ||||
| ListBase *lb, | ListBase *lb, | ||||
| int startx, | int startx, | ||||
| const uchar col[4], | const uchar col[4], | ||||
| bool draw_grayed_out, | bool draw_grayed_out, | ||||
| int *starty) | int *starty) | ||||
| { | { | ||||
| TreeElement *te, *te_vertical_line_last = NULL, *te_vertical_line_last_dashed = NULL; | bTheme *btheme = UI_GetTheme(); | ||||
| int y1, y2, y1_dashed, y2_dashed; | int y = *starty; | ||||
| short color = 0; | |||||
Severin: `color_id` | |||||
| if (BLI_listbase_is_empty(lb)) { | /* Small vertical padding */ | ||||
| return; | const short line_padding = UI_UNIT_Y / 4.0f; | ||||
| } | |||||
| struct { | /* Draw vertical lines between collections */ | ||||
| int steps_num; | bool draw_hierarchy_line; | ||||
| int step_len; | LISTBASE_FOREACH (TreeElement *, te, lb) { | ||||
| int gap_len; | |||||
| } dash = { | |||||
| .steps_num = 4, | |||||
| }; | |||||
| dash.step_len = UI_UNIT_X / dash.steps_num; | |||||
| dash.gap_len = dash.step_len / 2; | |||||
| const uchar grayed_alpha = col[3] / 2; | |||||
| /* For vertical lines between objects. */ | |||||
| y1 = y2 = y1_dashed = y2_dashed = *starty; | |||||
| for (te = lb->first; te; te = te->next) { | |||||
| bool draw_children_grayed_out = draw_grayed_out || (te->flag & TE_DRAGGING); | |||||
| TreeStoreElem *tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| draw_hierarchy_line = false; | |||||
| *starty -= UI_UNIT_Y; | |||||
| if (draw_children_grayed_out) { | /* Only draw hierarchy lines for open collections. */ | ||||
| immUniformColor3ubvAlpha(col, grayed_alpha); | if (TSELEM_OPEN(tselem, space_outliner) && !BLI_listbase_is_empty(&te->subtree)) { | ||||
| } | if (tselem->type == TSE_LAYER_COLLECTION) { | ||||
| else { | draw_hierarchy_line = true; | ||||
| immUniformColor4ubv(col); | |||||
| } | |||||
| if ((te->flag & TE_CHILD_NOT_IN_COLLECTION) == 0) { | Collection *collection = outliner_collection_from_tree_element(te); | ||||
| /* Horizontal Line? */ | color = collection->color; | ||||
| if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE)) { | |||||
| immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - U.pixelsize); | |||||
| /* Vertical Line? */ | y = *starty; | ||||
| if (te->idcode == ID_OB) { | |||||
| te_vertical_line_last = te; | |||||
| y2 = *starty; | |||||
| } | } | ||||
| y1_dashed = *starty - UI_UNIT_Y; | else if (tselem->type == 0 && te->idcode == ID_OB) { | ||||
| } | if (subtree_contains_object(&te->subtree)) { | ||||
| } | draw_hierarchy_line = true; | ||||
| else { | y = *starty; | ||||
| 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 - U.pixelsize); | |||||
| start += dash.step_len; | |||||
| } | } | ||||
| te_vertical_line_last_dashed = te; | |||||
| y2_dashed = *starty; | |||||
| } | } | ||||
| *starty -= UI_UNIT_Y; | outliner_draw_hierarchy_lines_recursive( | ||||
| pos, space_outliner, &te->subtree, startx + UI_UNIT_X, col, draw_grayed_out, starty); | |||||
| if (TSELEM_OPEN(tselem, space_outliner)) { | |||||
| outliner_draw_hierarchy_lines_recursive(pos, | |||||
| space_outliner, | |||||
| &te->subtree, | |||||
| startx + UI_UNIT_X, | |||||
| col, | |||||
| draw_children_grayed_out, | |||||
| starty); | |||||
| } | |||||
| } | } | ||||
| if (draw_grayed_out) { | if (draw_hierarchy_line) { | ||||
| immUniformColor3ubvAlpha(col, grayed_alpha); | if (color != COLLECTION_COLOR_NONE) { | ||||
| immUniformColor4ubv(btheme->collection_color[color - 1].color); | |||||
| } | } | ||||
| else { | else { | ||||
| immUniformColor4ubv(col); | immUniformColor4ubv(col); | ||||
| } | } | ||||
| /* Vertical line. */ | immRecti(pos, startx, y - line_padding, startx + (U.pixelsize * 1), *starty + line_padding); | ||||
| te = te_vertical_line_last; | |||||
| if ((te != NULL) && (te->parent || lb->first != lb->last)) { | |||||
| immRecti(pos, startx, y1 + UI_UNIT_Y, startx + U.pixelsize, 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 + U.pixelsize, start - dash.step_len + dash.gap_len); | |||||
| start -= dash.step_len; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner, | static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner, | ||||
| ListBase *lb, | ListBase *lb, | ||||
| int startx, | int startx, | ||||
| int *starty) | int *starty) | ||||
| ▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | if (restrict_column_width > 0.0f) { | ||||
| int mask_x = BLI_rcti_size_x(®ion->v2d.mask) - (int)restrict_column_width + 1; | int mask_x = BLI_rcti_size_x(®ion->v2d.mask) - (int)restrict_column_width + 1; | ||||
| CLAMP_MIN(mask_x, 0); | CLAMP_MIN(mask_x, 0); | ||||
| GPU_scissor_get(scissor); | GPU_scissor_get(scissor); | ||||
| GPU_scissor(0, 0, mask_x, region->winy); | GPU_scissor(0, 0, mask_x, region->winy); | ||||
| } | } | ||||
| /* Gray hierarchy lines. */ | /* Gray hierarchy lines. */ | ||||
| starty = (int)region->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; | starty = (int)region->v2d.tot.ymax - OL_Y_OFFSET; | ||||
| startx = UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; | startx = UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; | ||||
| outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty); | outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty); | ||||
| /* Items themselves. */ | /* Items themselves. */ | ||||
| starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; | starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET; | ||||
| startx = 0; | startx = 0; | ||||
| LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) { | LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) { | ||||
| outliner_draw_tree_element(C, | outliner_draw_tree_element(C, | ||||
| ▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines | |||||
color_id