Fix #112588: Hide node panels when all sockets are hidden
The panel state gets a new flag to indicate if content is visible. This gets updated in the visibility pass during node drawing. Pull Request: https://projects.blender.org/blender/blender/pulls/113003
This commit is contained in:
@@ -915,4 +915,9 @@ inline bool bNodePanelState::is_parent_collapsed() const
|
||||
return flag & NODE_PANEL_PARENT_COLLAPSED;
|
||||
}
|
||||
|
||||
inline bool bNodePanelState::has_visible_content() const
|
||||
{
|
||||
return flag & NODE_PANEL_CONTENT_VISIBLE;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -631,8 +631,10 @@ struct VisibilityUpdateState {
|
||||
/* Recursive function to determine visibility of items before drawing. */
|
||||
static void node_update_panel_items_visibility_recursive(int num_items,
|
||||
const bool is_parent_collapsed,
|
||||
bNodePanelState &parent_state,
|
||||
VisibilityUpdateState &state)
|
||||
{
|
||||
parent_state.flag &= ~NODE_PANEL_CONTENT_VISIBLE;
|
||||
while (state.item_iter != state.item_end) {
|
||||
/* Stop after adding the expected number of items.
|
||||
* Root panel consumes all remaining items (num_items == -1). */
|
||||
@@ -651,14 +653,24 @@ static void node_update_panel_items_visibility_recursive(int num_items,
|
||||
const bool is_collapsed = is_parent_collapsed || item.state->is_collapsed();
|
||||
|
||||
node_update_panel_items_visibility_recursive(
|
||||
item.panel_decl->num_child_decls, is_collapsed, state);
|
||||
item.panel_decl->num_child_decls, is_collapsed, *item.state, state);
|
||||
if (item.state->flag & NODE_PANEL_CONTENT_VISIBLE) {
|
||||
/* If child panel is visible so is the parent panel. */
|
||||
parent_state.flag |= NODE_PANEL_CONTENT_VISIBLE;
|
||||
}
|
||||
}
|
||||
else if (item.is_valid_socket()) {
|
||||
if (item.input) {
|
||||
SET_FLAG_FROM_TEST(item.input->flag, is_parent_collapsed, SOCK_PANEL_COLLAPSED);
|
||||
if (item.input->is_visible()) {
|
||||
parent_state.flag |= NODE_PANEL_CONTENT_VISIBLE;
|
||||
}
|
||||
}
|
||||
if (item.output) {
|
||||
SET_FLAG_FROM_TEST(item.output->flag, is_parent_collapsed, SOCK_PANEL_COLLAPSED);
|
||||
if (item.output->is_visible()) {
|
||||
parent_state.flag |= NODE_PANEL_CONTENT_VISIBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -719,36 +731,41 @@ static void add_panel_items_recursive(const bContext &C,
|
||||
C, ntree, node, node.typeinfo->draw_buttons, block, locy);
|
||||
}
|
||||
|
||||
if (!is_parent_collapsed) {
|
||||
locy -= NODE_DY;
|
||||
state.is_first = false;
|
||||
}
|
||||
/* Panel visible if any content is visible. */
|
||||
if (item.state->has_visible_content()) {
|
||||
if (!is_parent_collapsed) {
|
||||
locy -= NODE_DY;
|
||||
state.is_first = false;
|
||||
}
|
||||
|
||||
/* New top panel is collapsed if self or parent is collapsed. */
|
||||
const bool is_collapsed = is_parent_collapsed || item.state->is_collapsed();
|
||||
/* New top panel is collapsed if self or parent is collapsed. */
|
||||
const bool is_collapsed = is_parent_collapsed || item.state->is_collapsed();
|
||||
|
||||
/* Round the socket location to stop it from jiggling. */
|
||||
item.runtime->location_y = round(locy + NODE_DYS);
|
||||
if (!is_collapsed) {
|
||||
locy -= NODE_ITEM_SPACING_Y / 2; /* Space at bottom of panel header. */
|
||||
}
|
||||
item.runtime->max_content_y = item.runtime->min_content_y = round(locy);
|
||||
if (!is_collapsed) {
|
||||
locy -= NODE_ITEM_SPACING_Y; /* Space at top of panel contents. */
|
||||
node_update_basis_buttons(C, ntree, node, item.panel_decl->draw_buttons, block, locy);
|
||||
}
|
||||
/* Round the socket location to stop it from jiggling. */
|
||||
item.runtime->location_y = round(locy + NODE_DYS);
|
||||
if (is_collapsed) {
|
||||
item.runtime->max_content_y = item.runtime->min_content_y = round(locy);
|
||||
}
|
||||
else {
|
||||
locy -= NODE_ITEM_SPACING_Y / 2; /* Space at bottom of panel header. */
|
||||
item.runtime->max_content_y = item.runtime->min_content_y = round(locy);
|
||||
locy -= NODE_ITEM_SPACING_Y; /* Space at top of panel contents. */
|
||||
|
||||
add_panel_items_recursive(C,
|
||||
ntree,
|
||||
node,
|
||||
block,
|
||||
locx,
|
||||
locy,
|
||||
item.panel_decl->num_child_decls,
|
||||
is_collapsed,
|
||||
item.panel_decl->name.c_str(),
|
||||
item.runtime,
|
||||
state);
|
||||
node_update_basis_buttons(C, ntree, node, item.panel_decl->draw_buttons, block, locy);
|
||||
}
|
||||
|
||||
add_panel_items_recursive(C,
|
||||
ntree,
|
||||
node,
|
||||
block,
|
||||
locx,
|
||||
locy,
|
||||
item.panel_decl->num_child_decls,
|
||||
is_collapsed,
|
||||
item.panel_decl->name.c_str(),
|
||||
item.runtime,
|
||||
state);
|
||||
}
|
||||
}
|
||||
else if (item.is_valid_socket()) {
|
||||
if (item.input) {
|
||||
@@ -804,7 +821,7 @@ static void add_panel_items_recursive(const bContext &C,
|
||||
}
|
||||
locy -= NODE_ITEM_SPACING_Y / 2; /* Space at top of next panel header. */
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* Advanced drawing with panels and arbitrary input/output ordering. */
|
||||
static void node_update_basis_from_declaration(
|
||||
@@ -819,7 +836,9 @@ static void node_update_basis_from_declaration(
|
||||
|
||||
/* Update item visibility flags first. */
|
||||
VisibilityUpdateState visibility_state(item_data);
|
||||
node_update_panel_items_visibility_recursive(-1, false, visibility_state);
|
||||
/* Dummy state item to write into, unused. */
|
||||
bNodePanelState root_panel_state;
|
||||
node_update_panel_items_visibility_recursive(-1, false, root_panel_state, visibility_state);
|
||||
|
||||
/* Space at the top. */
|
||||
locy -= NODE_DYS / 2;
|
||||
@@ -2015,10 +2034,11 @@ static void node_draw_panels_background(const bNode &node, uiBlock &block)
|
||||
const bke::bNodePanelRuntime &runtime = node.runtime->panels[panel_i];
|
||||
|
||||
/* Don't draw hidden or collapsed panels. */
|
||||
const bool is_visible = !(state.is_collapsed() || state.is_parent_collapsed());
|
||||
is_last_panel_visible = is_visible;
|
||||
const bool is_background_visible = state.has_visible_content() &&
|
||||
!(state.is_collapsed() || state.is_parent_collapsed());
|
||||
is_last_panel_visible = is_background_visible;
|
||||
last_panel_content_y = runtime.max_content_y;
|
||||
if (!is_visible) {
|
||||
if (!is_background_visible) {
|
||||
++panel_i;
|
||||
continue;
|
||||
}
|
||||
@@ -2068,7 +2088,8 @@ static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block
|
||||
|
||||
const bNodePanelState &state = node.panel_states()[panel_i];
|
||||
/* Don't draw hidden panels. */
|
||||
if (state.is_parent_collapsed()) {
|
||||
const bool is_header_visible = state.has_visible_content() && !state.is_parent_collapsed();
|
||||
if (!is_header_visible) {
|
||||
++panel_i;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -315,6 +315,8 @@ typedef enum eNodePanelFlag {
|
||||
NODE_PANEL_COLLAPSED = (1 << 0),
|
||||
/* The parent panel is collapsed. */
|
||||
NODE_PANEL_PARENT_COLLAPSED = (1 << 1),
|
||||
/* The panel has visible content. */
|
||||
NODE_PANEL_CONTENT_VISIBLE = (1 << 2),
|
||||
} eNodePanelFlag;
|
||||
|
||||
typedef struct bNodePanelState {
|
||||
@@ -327,6 +329,7 @@ typedef struct bNodePanelState {
|
||||
#ifdef __cplusplus
|
||||
bool is_collapsed() const;
|
||||
bool is_parent_collapsed() const;
|
||||
bool has_visible_content() const;
|
||||
#endif
|
||||
} bNodePanelState;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user