Subpanels for node group sockets #108565

Closed
Lukas Tönne wants to merge 84 commits from LukasTonne/blender:socket_subpanels into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
Member

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.

image

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 instead UI_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. A custom_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 and MOD_nodes_child_panel_instances_match_data which should be replaced at some point.

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. ![image](/attachments/fa71e038-768f-4d7b-b78c-50b94897597d) 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 instead `UI_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. A `custom_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` and `MOD_nodes_child_panel_instances_match_data` which should be replaced at some point.
Lukas Tönne added 17 commits 2023-06-03 12:42:54 +02:00
bb181d782d Fix stale data reads in event handlers from child panels.
panel->activedata needs to be freed for instanced panels, which now
includes child panels.
8a6fe67a49 Avoid infinite update loops caused by syncing of flags.
Modifiers store "expansion" flags in addition to the panels' own
open/closed states. This is so panel state is persistent when editors
are switched, which destroys and recreates the panels.

The expansion flags are applied to panels twice: An initial update
after creating a panel makes sure the flag matches panel state, a
general update happens in `UI_panels_end` to update existing panels.

The syncing function for panel state was assuming that instancing would
only happen for top-level panels. Now that child panels can also use
instancing the flag index to sync needs to be computed from the child's
position in the list. It's important that the index for gettings and
setting the panel state is correct, otherwise a wrong panel is used and
the expected update does not happen. That can lead to infinite drawing
updates because the expected change never happens and the syncing
function keeps tagging the region for redraw.
Hans Goudey added this to the Nodes & Physics project 2023-06-03 17:02:04 +02:00
Hans Goudey added the
Interest
Geometry Nodes
Interest
Render & Cycles
labels 2023-06-03 17:02:15 +02:00
Hans Goudey added this to the 4.0 milestone 2023-06-03 17:02:20 +02:00
Lukas Tönne added 1 commit 2023-06-05 11:58:48 +02:00
ef822f0f2d Remove unnecessary child panel index offset.
`panel_set_expansion_from_list_data` is only called for the root panels
which have a `get_list_data_expand_flag` callback. Modifier child panels
do no have this callback, so we don't need to take their offset in the
parent flags array into account.
Lukas Tönne added 1 commit 2023-06-05 14:07:29 +02:00
2ba9f75703 Return a simple bit data array for expand flags.
Using a BitIterator makes the flag lookups simpler.
Lukas Tönne added 1 commit 2023-06-05 14:08:23 +02:00
Lukas Tönne added 1 commit 2023-06-05 14:23:56 +02:00
Lukas Tönne added 1 commit 2023-06-06 10:44:05 +02:00
Lukas Tönne added 6 commits 2023-06-06 11:57:22 +02:00
26a0e7359a Return a simple bit data array for expand flags.
Using a BitIterator makes the flag lookups simpler.
909430f5dc Category declarations in node trees for organizing modifier UI.
Adds an optional list of "categories" to node trees. Each socket can be
assigned a category. Sub-panels will be created in the future for these
categories (TODO).

Sockets of the same category will remain together even when adding,
removing, or moving sockets or categories, renaming, etc.
A socket can be moved up or down within a category but each category
remains a contiguous block. Actual tree views may be created later.
Author
Member

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.

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.
Lukas Tönne added 2 commits 2023-06-06 12:24:58 +02:00
Lukas Tönne added 3 commits 2023-06-06 17:18:04 +02:00
73a45e94e3 Added a `category_id` identifier for stable Panel<->category relations.
Instead of just an index, we now use the category_id to specify the
category of a socket as well as associating a panel with a category.
This has two consequences:
1. No need to remap indices after adding/removing/moving a category.
    Flip side is that finding the category of a socket now requires a
    linear search. In future this could be more efficient using a map,
    but that is a separate task.
2. Now the panel open/closed state bits are associated with a stable
    identifier, so panels will retain their state when moving.
c7ab5dc068 Added a `category_id` identifier for stable Panel<->category relations.
Instead of just an index, we now use the category_id to specify the
category of a socket as well as associating a panel with a category.
This has two consequences:
1. No need to remap indices after adding/removing/moving a category.
    Flip side is that finding the category of a socket now requires a
    linear search. In future this could be more efficient using a map,
    but that is a separate task.
2. Now the panel open/closed state bits are associated with a stable
    identifier, so panels will retain their state when moving.
Lukas Tönne added 1 commit 2023-06-06 18:26:29 +02:00

@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.

@LukasStockner worked on the same functionality in [D16644](https://archive.blender.org/developer/D16633), 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.
Lukas Tönne added 22 commits 2023-06-12 12:44:25 +02:00
ab0d8761d2 Use array of pointers for node panels instead plain array.
This has the advantage that pointers to panel declarations remain valid
after most panel API functions. This is important for python scripting
where a panel is referenced by pointer internally.
f9003d386b Renamed bNodeSocketPanel to just bNodePanel.
While sockets will be the first thing to populate such panels there can
be other things in future that go into them.
Lukas Tönne added 1 commit 2023-06-15 12:17:49 +02:00
Lukas Tönne added 1 commit 2023-08-30 12:20:30 +02:00
Lukas Tönne added 1 commit 2023-09-13 14:13:52 +02:00
Lukas Tönne added 1 commit 2023-09-13 14:26:59 +02:00
Lukas Tönne added 1 commit 2023-09-13 16:32:35 +02:00
48c9f13bd0 Removed the new modifier callbacks for child panels.
These are only used by the nodes modifier, it makes more sense to have
a MOD_nodes api function for this.
Lukas Tönne added 1 commit 2023-09-14 12:55:38 +02:00
Lukas Tönne added 2 commits 2023-09-14 14:17:51 +02:00
Lukas Tönne added 1 commit 2023-09-14 15:41:09 +02:00
Lukas Tönne added 1 commit 2023-09-14 16:15:28 +02:00
Member

What 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.

What 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.
Author
Member

For the purpose of modifier node panels i added a modifier_subpanel_register_ex function that allows overriding the default poll callback and flags. The poll callback still only gets the panel type info (like a classmethod).

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 supplementary custom_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:

  1. Create once and then poll for visibility (works well for classic single-instance panels)
  2. Generate ("draw") panels in UI layout as needed, necessary for instanced panels but clashes with approach 1
For the purpose of modifier node panels i added a `modifier_subpanel_register_ex` function that allows overriding the default `poll` callback and flags. The poll callback still only gets the panel type info (like a `classmethod`). 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 supplementary `custom_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: 1. Create once and then poll for visibility (works well for classic single-instance panels) 2. Generate ("draw") panels in UI layout as needed, necessary for instanced panels but clashes with approach 1
Lukas Tönne added 2 commits 2023-09-26 10:08:18 +02:00
Lukas Tönne changed title from WIP: Subpanels for node group sockets to Subpanels for node group sockets 2023-09-26 10:22:22 +02:00
Lukas Tönne requested review from Jacques Lucke 2023-09-26 10:22:33 +02:00
Lukas Tönne requested review from Hans Goudey 2023-09-26 10:22:42 +02:00
Author
Member

Examples of breaking cases:

  • Moving a panel up or down uses the old open/closed state at that position: expand_flag is index-based, panel identifiers are ignored. After moving "Panel BBB" above "Panel AAA" the states are swapped:

Screenshot_20230926_112736

Screenshot_20230926_112958

  • Only up to 15 panels per modifier have correct open/close behavior due to the limited short bit field for expand_flag (bit 0 is used for the modifier panel itself). The remaining panels will use the same state as panel 15 (demo file):
Examples of breaking cases: - Moving a panel up or down uses the old open/closed state at that position: `expand_flag` is index-based, panel identifiers are ignored. After moving "Panel BBB" above "Panel AAA" the states are swapped: <table> <tr> <td> ![Screenshot_20230926_112736](/attachments/d3781284-d294-42c6-98db-294d5d18830e) </td> <td> ![Screenshot_20230926_112958](/attachments/d4c70ef7-109d-4aec-bfa7-fe20cd975bb1) </td> </tr> </table> - Only up to 15 panels per modifier have correct open/close behavior due to the limited `short` bit field for `expand_flag` (bit 0 is used for the modifier panel itself). The remaining panels will use the same state as panel 15 ([demo file](/attachments/60dc9675-8ef6-4a57-883f-4df87a4dde8d)): <video src="/attachments/7d66dca1-992d-4c8a-a506-7f738066e663" title="2023-09-26 11-41-01.mp4" controls></video>
Hans Goudey requested changes 2023-09-26 14:12:02 +02:00
Hans Goudey left a comment
Member

I think you could change the two new MOD_nodes_ functions into panel type callbacks. That would fix the MOD_nodes include in the interface code.

I think you could change the two new `MOD_nodes_` functions into panel type callbacks. That would fix the `MOD_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);
Member

using uiListPanelMatchesDataFunc = bool (*)(...);

`using uiListPanelMatchesDataFunc = bool (*)(...);`
LukasTonne marked this conversation as resolved
@ -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,
Member

struct is unnecessary in C++ headers

`struct` is unnecessary in C++ headers
LukasTonne marked this conversation as resolved
@ -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
Member

I think the XXX and the commented code could be removed.

I think the XXX and the commented code could be removed.
LukasTonne marked this conversation as resolved
@ -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);
Member

Unnecessary whitespace changes

Unnecessary whitespace changes
LukasTonne marked this conversation as resolved
@ -1639,0 +1706,4 @@
static bool child_panel_poll(const bContext *C, PanelType * /*panel_type*/)
{
/* Always hidden, panel is drawn explicitly. */
// return false;
Member

Remove commented code, or remove the other code since I think this poll is pointless?

Remove commented code, or remove the other code since I think this poll is pointless?
LukasTonne marked this conversation as resolved
@ -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
Member

Unnecessary line wrapping changes here and below

Unnecessary line wrapping changes here and below
LukasTonne marked this conversation as resolved
Lukas Tönne added 1 commit 2023-09-26 15:55:12 +02:00
b288c2ccae Use panel type callbacks of the parent for child panel generation.
This avoids adding a dependency on MOD_nodes to the interface code.
Author
Member

I think you could change the two new MOD_nodes_ functions into panel type callbacks

Thanks @HooglyBoogly this works beautifully, no more dependency on modifiers.

> I think you could change the two new MOD_nodes_ functions into panel type callbacks Thanks @HooglyBoogly this works beautifully, no more dependency on modifiers.
Lukas Tönne added 6 commits 2023-09-26 16:11:22 +02:00
Lukas Tönne added 1 commit 2023-09-26 16:18:52 +02:00
Lukas Tönne added 1 commit 2023-09-26 16:19:56 +02:00
Lukas Tönne requested review from Hans Goudey 2023-09-26 16:21:07 +02:00
Hans Goudey requested changes 2023-09-26 17:02:04 +02:00
Hans Goudey left a comment
Member
  • There is a flicker in the modifier tab of the property editor when I add a new panel to a node group. Looks like the panels are all drawn expanded for one instant.
- [ ] There is a flicker in the modifier tab of the property editor when I add a new panel to a node group. Looks like the panels are all drawn expanded for one instant.
@ -38,8 +38,12 @@ struct Main;
struct Mesh;
struct ModifierData;
struct Object;
struct Panel;
Member

Unnecessary forward declarations?

Unnecessary forward declarations?
LukasTonne marked this conversation as resolved
@ -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)
Member

Unused function?

Unused function?
Author
Member

Looks like it, don't remember why i added this.

Looks like it, don't remember why i added this.
LukasTonne marked this conversation as resolved
@ -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];
Member

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.

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.
LukasTonne marked this conversation as resolved
@ -1506,17 +1580,9 @@ static void panel_draw(const bContext *C, Panel *panel)
nullptr);
}
Member

Adding this in here should resolve the formatting (it's already done for the root panel):

  uiLayoutSetPropSep(layout, true);
  /* Decorators are added manually for supported properties because the
   * attribute/value toggle requires a manually built layout anyway. */
  uiLayoutSetPropDecorate(layout, false);
Adding this in here should resolve the formatting (it's already done for the root panel): ``` uiLayoutSetPropSep(layout, true); /* Decorators are added manually for supported properties because the * attribute/value toggle requires a manually built layout anyway. */ uiLayoutSetPropDecorate(layout, false); ```
LukasTonne marked this conversation as resolved
@ -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,
Member

Would be fine to avoid adding this function by just setting the two values afterwards. Either way though.

Would be fine to avoid adding this function by just setting the two values afterwards. Either way though.
LukasTonne marked this conversation as resolved
Author
Member

There is a flicker in the modifier tab of the property editor when I add a new panel to a node group. Looks like the panels are all drawn expanded for one instant.

I suspect this is a general panel bug. The PNL_CLOSED flag is ultimately responsible for how the panel is drawn (through UI_panel_is_closed). In UI_panel_begin this gets copied from the panel type (default value), then in UI_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.

> There is a flicker in the modifier tab of the property editor when I add a new panel to a node group. Looks like the panels are all drawn expanded for one instant. I suspect this is a general panel bug. The `PNL_CLOSED` flag is ultimately responsible for how the panel is drawn (through `UI_panel_is_closed`). In `UI_panel_begin` this gets copied from the panel type (default value), then in `UI_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.
Member

Thanks for investigating. I can look into that bug during Bcon3.

Thanks for investigating. I can look into that bug during Bcon3.
Lukas Tönne added 4 commits 2023-09-26 18:26:13 +02:00
Member

I found an issue that looks to me like it's not a known issue yet:

I found an issue that looks to me like it's not a known issue yet: <video src="/attachments/986a3bdd-cdd9-41e4-b04e-42832f40c6fe" title="bugs_modifier_panels_invisible-2023-09-26_18.26.09.mp4" controls></video>
Author
Member

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)

> 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)
Member

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.

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.
Lukas Tönne added 1 commit 2023-09-26 18:50:24 +02:00
Member

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.

  • there are truly no sockets in that panel
  • all sockets in the panel are checked to Hide in Modifier
  • all sockets in the panel are not currently exposable in the modifier UI e.g. Geometry socket
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. - there are truly no sockets in that panel - all sockets in the panel are checked to `Hide in Modifier` - all sockets in the panel are not currently exposable in the modifier UI e.g. Geometry socket
Author
Member

This patch won't make it into 4.0, too many risky changes still needed for the panel system in general.

This patch won't make it into 4.0, too many risky changes still needed for the panel system in general.
Lukas Tönne modified the milestone from 4.0 to 4.1 2023-09-27 11:33:37 +02:00
Lukas Tönne added 1 commit 2023-09-27 11:48:05 +02:00
82259645a1 Fix panel drawing when using multiple modifiers.
The child panels were using the same UI block for each instance of the
modifier, because the identifiers were not unique.

Passing the parent panel optionally allows generating a more unique
string for blocks. Note that this will still fail when nesting more than
two levels of instanced child panels, but that's not a case which exists
at this time. A future fix can address this more thoroughly.
Lukas Tönne added 1 commit 2023-09-27 11:55:05 +02:00
Member
ad7a5abb2da15563bfd61c455421b82b5c400f75
Hans Goudey closed this pull request 2024-03-14 17:39:06 +01:00
Author
Member

Was implemented by Jacques, closing.

Was implemented by Jacques, closing.

Pull request closed

Sign in to join this conversation.
No reviewers
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
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
EEVEE & Viewport
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
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
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
EEVEE & Viewport
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
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
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 Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#108565
No description provided.