Subpanels for node group sockets #108565
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#108565
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "LukasTonne/blender:socket_subpanels"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Node groups support adding panels to nodes. This patch recreates the node panel structure in the modifier properties for geometry ndoes using the conventional UI panel system.
Closes #108897
Implementation Details
Most UI panels are generated by type, i.e. one instance of the panel type is created by default. But panels can also be instanced (
PANEL_TYPE_INSTANCED
flag). Instanced panels do not have a default instance, and insteadUI_panel_add_instanced
must be called to generate instances. Modifier panels are instanced panels, because there can be an arbitrary number of the same modifier type (including zero).Child panels were designed to not be instanced, but they use the same data structures and it's only a hidden assumption in code. Now child panels need to support instancing, because each socket category will be represented by the same panel type on top of the "parent" modifier panel.
The "Output Attributes" and "Internal Dependencies" subpanels of the nodes modifier were not instanced (there is only one of each per modifier panel). But because the order of type-based and instanced panels is fixed, these two panels would now always render in front of node panels. These panels are now instanced as well to have control over the panel order.
Adding a panel instance sets the panel open/closed state to match the expand flag from the modifier. Mapping panels to the respective flag index in the expand flags is based purely on depth-first iteration order.
Panels have their own open/closed state (
PNL_CLOSED
), but panels are destroyed and recreated with UI changes (e.g. switching workspace). For this reason a more persistent storage of "expand flags" was added (PanelType::get_list_data_expand_flag
). The implementation depends on panel type, for modifiers this is a set of up to 16 flags (ModifierData::ui_expand_flag
). This means modifiers only support up to 15 child panel states in addition to the root panel state. This worked for fixed limited child panel numbers, but we will need more than this, and preferably an arbitrary number instead of adding a hidden technical limit.Open/Closed state for child panels will get mixed up when adding, removing, or moving categories. The panels for categories will have a different index in their parent's list, while the flag indices are not updated accordingly.
The socket_category panels need to know which category they are displaying. The only way to communicate such info to panels atm is their
custom_data_ptr
pointer, which is already used for the modifier pointer in modifier panels. Acustom_data_int
field in panels has been added to store this extra information (the panel uid).Panels are rendered outside of the UI layout system. This means there is no direct callback for modifiers to generate or validate panels. The panel system directly calls
MOD_nodes_add_child_panel_instances
andMOD_nodes_child_panel_instances_match_data
which should be replaced at some point.These two PRs implement part of the feature for easier independent review:
Category declaration in node trees and sockets for grouping sockets #108649
More flexible callback for persistent panel expand flags #108648
Both of them are included here, this branch adds modifier sub-panels as a UI for socket categories.
category_id
identifier for stable Panel<->category relations. 73a45e94e3category_id
identifier for stable Panel<->category relations. c7ab5dc068@LukasStockner worked on the same functionality in D16644, though starting with panels inside nodes rather than the properties editor.
There is some design discussion in that differential that would be good if you could read it.
INSTANCED_PANEL_UNIQUE_STR_LEN
was renamed to..._SIZE
. de67d6ef8bWhat do you think about how this approach relates to adding poll functions to the subpanels that can depend on the the panel's custom data pointer? For example, I'm currently looking into moving the particles panels into the modifier stack as part of #111538 and that sort of polling is probably necessary for moving the particle panels to modifier subpanels. I'm curious if you think these two things are related.
For the purpose of modifier node panels i added a
modifier_subpanel_register_ex
function that allows overriding the defaultpoll
callback and flags. The poll callback still only gets the panel type info (like aclassmethod
).When it comes to the
custom_data
pointer: This system is already too limited for identifying panels in a node group layout, because the data pointer is only the modifier. I had to add a supplementarycustom_data_int
to store the panel identifier, it's a crutch.I don't currently need to hide/unhide the node panels. If any of the node group interface data changes it will trigger a redraw, which makes the panel system run a comparison (
MOD_nodes_child_panel_instances_match_data
) and regenerate panels if needed. So if a panel becomes "hidden" i can simply not generate it. This is redundant with the poll method, which is rather useless for instanced panels. It's a weird mix of two paradigms:WIP: Subpanels for node group socketsto Subpanels for node group socketsExamples of breaking cases:
expand_flag
is index-based, panel identifiers are ignored. After moving "Panel BBB" above "Panel AAA" the states are swapped:short
bit field forexpand_flag
(bit 0 is used for the modifier panel itself). The remaining panels will use the same state as panel 15 (demo file):I think you could change the two new
MOD_nodes_
functions into panel type callbacks. That would fix theMOD_nodes
include in the interface code.@ -2013,6 +2013,20 @@ bool UI_panel_list_matches_data(ARegion *region,
ListBase *data,
uiListPanelIDFromDataFunc panel_idname_func);
typedef bool (*uiListPanelMatchesDataFunc)(void *data_link, const struct Panel *panel);
using uiListPanelMatchesDataFunc = bool (*)(...);
@ -2206,6 +2220,9 @@ void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout);
* Used for popup panels only.
*/
void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout);
void UI_paneltype_draw_with_header(struct bContext *C,
struct
is unnecessary in C++ headers@ -299,0 +304,4 @@
panel_activate_state(C, child, PANEL_STATE_EXIT);
}
// XXX child panel's customdata is expected(!) to be shared with parent and free'd by the
I think the XXX and the commented code could be removed.
@ -481,6 +543,7 @@ static void panel_set_expansion_from_list_data(const bContext *C, Panel *panel)
{
BLI_assert(panel->type != nullptr);
BLI_assert(panel->type->flag & PANEL_TYPE_INSTANCED);
Unnecessary whitespace changes
@ -1639,0 +1706,4 @@
static bool child_panel_poll(const bContext *C, PanelType * /*panel_type*/)
{
/* Always hidden, panel is drawn explicitly. */
// return false;
Remove commented code, or remove the other code since I think this poll is pointless?
@ -1669,3 +1886,2 @@
* properties are automatically converted to boolean sockets where applicable as well.
* However, boolean properties will crash old versions of Blender, so convert them to integer
* properties for writing. The actual value is stored in the same variable for both types */
* However, boolean properties will crash old versions of Blender, so convert them to
Unnecessary line wrapping changes here and below
Thanks @HooglyBoogly this works beautifully, no more dependency on modifiers.
@ -38,8 +38,12 @@ struct Main;
struct Mesh;
struct ModifierData;
struct Object;
struct Panel;
Unnecessary forward declarations?
@ -6029,6 +6032,19 @@ void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout)
}
}
void UI_paneltype_draw_with_header(bContext *C, PanelType *pt, uiLayout *layout)
Unused function?
Looks like it, don't remember why i added this.
@ -137,0 +140,4 @@
* and then use the custom_data_ptr (with an internal pointer back to modifier).
* It's really limiting here to have to put so much context data into a single pointer.
*/
int custom_data_int[2];
I guess this could just be a single integer now. I think it's best to remove the "XXX" for now and just describe the situation as it is.
@ -1506,17 +1580,9 @@ static void panel_draw(const bContext *C, Panel *panel)
nullptr);
}
Adding this in here should resolve the formatting (it's already done for the root panel):
@ -59,0 +63,4 @@
* \note To create the panel type's #PanelType.idname,
* it appends the \a name argument to the \a parent's `idname`.
*/
PanelType *modifier_subpanel_register_ex(ARegionType *region_type,
Would be fine to avoid adding this function by just setting the two values afterwards. Either way though.
I suspect this is a general panel bug. The
PNL_CLOSED
flag is ultimately responsible for how the panel is drawn (throughUI_panel_is_closed
). InUI_panel_begin
this gets copied from the panel type (default value), then inUI_panel_add_instanced
it's copied from the "expand flags".UI_panels_end
also copies from the expand flags, but only for the active panel.In short: i have no idea how what is happening and i don't want to know, but i'll try setting the default value to match.
EDIT: nope, that doesn't help. Not sure if this is worth fixing.
Thanks for investigating. I can look into that bug during Bcon3.
I found an issue that looks to me like it's not a known issue yet:
Nice find!
(Initial guess: panel identifiers get copied along with the modifier and only the last found panel is used)
Would it be possible to disconnect the collapsing/expanding of subpanels from making a modifier the active one? For collapsing the modifier itself this is already disconnected and to me it feels like this should be the same here, since generally interacting with the modifier interface for tweaking values etc. that should just work on modifiers that aren't active. Making a modifier active should stay a conscious decision.
One last issue that I could find from user end:
For nodes you are already handling not showing a panel if it would be empty, for the modifier that's not yet the case. Currently I can see 3 different ways you might end up with an empty panel in the modifier.
Hide in Modifier
This patch won't make it into 4.0, too many risky changes still needed for the panel system in general.
ad7a5abb2d
Was implemented by Jacques, closing.
Pull request closed