UI: add support for uiLayout based panels #113584

Merged
Jacques Lucke merged 51 commits from JacquesLucke/blender:layout-panels into main 2023-12-22 17:58:06 +01:00
Member

This adds support for so called "layout panels" which are panels that are created as part of uiLayout. The goal is to make it easier to have expandable sections as part of a UI.

The reason I'm working on this is to find a better solution to what was attempted in #108565.

image

Problems with Existing Approaches

Currently, there are two ways to create these expandable sections:

  • One can define a new Panel type for each expandable section and use the parent_id to make this a subpanel of another panel. This has a few problems:
    • uiLayout drawing code is more scattered, because one can't just use a single function that creates the layout for an entire panel including its subpanels.
    • It does not work so well for dynamic amounts of panels (e.g. like what we need for the geometry nodes modifier to organize the inputs).
    • Typically, Blender uses a immediate-ui approach, but subpanels break that currently and need extra handling.
    • The order of panels is not very explicit.
    • One can't interleave subpanels and other ui elements, subpanels always come at the end of the parent panel.
  • Custom solution using existing uiLayout. This is done in the material properties. It also has a few problems:
    • Custom solutions tend to work slightly different in different places. So the UI is less unified.
    • Can't drag open/close multiple panels.
    • The background color for subpanels does not change.

Solution

A possible solution to all of these problems is to add support for panels to uiLayout directly:

/* Add elements before subpanel. */
if (uiLayout *panel_layout = uiLayoutPanel(layout, ...)) {
  /* Add elements in subpanel, but only of the panel is open. */
}
/* Add elements after subpanel. */

Integrating subpanels with uiLayout has some benefits:

  • Subpanels are treated like any other sub-layout and don't have unnecessary boilerplate.
  • It becomes trivial to have a dynamic number of potentially nested subpanels.
  • Resolves all mentioned problems of custom subpanel solutions.

Open/Close State

The most tricky thing is to decide where to store the open/close state. Ideally, it should be stored in the region because then the same layout panel can be opened and closed in every region independently. Unfortunately, storing the state in the region is fairly complex in some cases.

For example, for modifier subpanels the region would have to store an open/close state for each panel in each modifier in each object. So a map with object pointer + modifier id + panel id as key would be required. Obviously, this map could become quite big. Also storing that many ID pointers in UI data is not great and we don't even have stable modifier ids yet. There also isn't an obvious way for how to clear unused elements from the map which could become necessary when it becomes big.

In practice, it's rare that the same modifier list is shown in two editors. So the benefit of storing the open/close state in the region is negilible. Therefor, a much simpler solution is possible: the open/close state can be stored in the modifier directly. This is actually how it's implemented right now already (see ui_expand_flag).

The implementation of layout panels in this patch is agnostic to how the open/close state is stored exactly, as long as it can be referenced as a boolean rna property. This allows us to store the state the state in the modifier directly but also allows us to store the state in the region for other layout panels in the future. We could consider adding an API that makes it easy to store the state in the region for cases where the key is simpler. For example: uiLayoutPanel(layout, TIP_("Mesh Settings"), PanelRegionKey("mesh_settings")).

Python API

Adding a Python API is fairly straight forward with the current design. However, it is not included in this patch so that we can mature the internal API a bit more if necessary, before addon developers start to depend on it. It would probably work like so:

if panel := layout.panel("Mesh Settings", ...):
    # Add layout elements in the panel if it's open.
This adds support for so called "layout panels" which are panels that are created as part of `uiLayout`. The goal is to make it easier to have expandable sections as part of a UI. The reason I'm working on this is to find a better solution to what was attempted in #108565. ![image](/attachments/29eaedb0-5263-4630-9931-f0097d1a28c2) ### Problems with Existing Approaches Currently, there are two ways to create these expandable sections: * One can define a new `Panel` type for each expandable section and use the `parent_id` to make this a subpanel of another panel. This has a few problems: * `uiLayout` drawing code is more scattered, because one can't just use a single function that creates the layout for an entire panel including its subpanels. * It does not work so well for dynamic amounts of panels (e.g. like what we need for the geometry nodes modifier to organize the inputs). * Typically, Blender uses a immediate-ui approach, but subpanels break that currently and need extra handling. * The order of panels is not very explicit. * One can't interleave subpanels and other ui elements, subpanels always come at the end of the parent panel. * Custom solution using existing `uiLayout`. This is done in the material properties. It also has a few problems: * Custom solutions tend to work slightly different in different places. So the UI is less unified. * Can't drag open/close multiple panels. * The background color for subpanels does not change. ### Solution A possible solution to all of these problems is to add support for panels to `uiLayout` directly: ```cpp /* Add elements before subpanel. */ if (uiLayout *panel_layout = uiLayoutPanel(layout, ...)) { /* Add elements in subpanel, but only of the panel is open. */ } /* Add elements after subpanel. */ ``` Integrating subpanels with `uiLayout` has some benefits: * Subpanels are treated like any other sub-layout and don't have unnecessary boilerplate. * It becomes trivial to have a dynamic number of potentially nested subpanels. * Resolves all mentioned problems of custom subpanel solutions. ### Open/Close State The most tricky thing is to decide where to store the open/close state. Ideally, it should be stored in the `region` because then the same layout panel can be opened and closed in every region independently. Unfortunately, storing the state in the region is fairly complex in some cases. For example, for modifier subpanels the region would have to store an open/close state for each panel in each modifier in each object. So a map with `object pointer + modifier id + panel id` as key would be required. Obviously, this map could become quite big. Also storing that many ID pointers in UI data is not great and we don't even have stable modifier ids yet. There also isn't an obvious way for how to clear unused elements from the map which could become necessary when it becomes big. In practice, it's rare that the same modifier list is shown in two editors. So the benefit of storing the open/close state in the region is negilible. Therefor, a much simpler solution is possible: the open/close state can be stored in the modifier directly. This is actually how it's implemented right now already (see `ui_expand_flag`). The implementation of layout panels in this patch is *agnostic* to how the open/close state is stored exactly, as long as it can be referenced as a boolean rna property. This allows us to store the state the state in the modifier directly but also allows us to store the state in the region for other layout panels in the future. We could consider adding an API that makes it easy to store the state in the region for cases where the key is simpler. For example: `uiLayoutPanel(layout, TIP_("Mesh Settings"), PanelRegionKey("mesh_settings"))`. ### Python API Adding a Python API is fairly straight forward with the current design. However, it is **not** included in this patch so that we can mature the internal API a bit more if necessary, before addon developers start to depend on it. It would probably work like so: ```python if panel := layout.panel("Mesh Settings", ...): # Add layout elements in the panel if it's open. ```
Jacques Lucke added 16 commits 2023-10-12 12:12:09 +02:00
Jacques Lucke changed title from WIP: UI: UILayout based subpanels to WIP: UI: uiLayout based subpanels 2023-10-12 12:12:31 +02:00
Jacques Lucke requested review from Campbell Barton 2023-10-12 12:51:27 +02:00
Jacques Lucke requested review from Julian Eisel 2023-10-12 12:51:27 +02:00
Jacques Lucke requested review from Hans Goudey 2023-10-12 12:51:27 +02:00
Hans Goudey reviewed 2023-10-13 15:42:43 +02:00
Hans Goudey left a comment
Member

The overall approach looks pretty nice, especially at the API level. Two points:

  • Make sure property search still reads the buttons inside of the panels when they're closed
  • Would be nice to have an overview of how this works in the description, and how this could enable interleaved subpanels and top-level buttons. That's one part I can't imagine on my own yet

Other than that I didn't do an in depth look at the code.

The overall approach looks pretty nice, especially at the API level. Two points: - Make sure property search still reads the buttons inside of the panels when they're closed - Would be nice to have an overview of how this works in the description, and how this could enable interleaved subpanels and top-level buttons. That's one part I can't imagine on my own yet Other than that I didn't do an in depth look at the code.
Jacques Lucke added 2 commits 2023-10-13 16:27:36 +02:00
Author
Member

Make sure property search still reads the buttons inside of the panels when they're closed

Fixed that part.

Would be nice to have an overview of how this works in the description, and how this could enable interleaved subpanels and top-level buttons. That's one part I can't imagine on my own yet

Don't really want to make the specifics of the current implementation part of the discussion yet, before it's not clear that we want to be able to create subpanels like this in the first place. Nested subpanels and interleaved top-level buttons actually "just work". Not that it looks super great currently.

image

> Make sure property search still reads the buttons inside of the panels when they're closed Fixed that part. > Would be nice to have an overview of how this works in the description, and how this could enable interleaved subpanels and top-level buttons. That's one part I can't imagine on my own yet Don't really want to make the specifics of the current implementation part of the discussion yet, before it's not clear that we want to be able to create subpanels like this in the first place. Nested subpanels and interleaved top-level buttons actually "just work". Not that it looks super great currently. ![image](/attachments/b9f87bb4-faf1-470a-9824-088deedb4ce0)

Checked over the patch & tested functionality.
Overall I think this is nice functionality to be able to declare expandable sections inline, but this exposes some awkwardness in the API which don't have clear solutions AFAICS.

Notes:

The uiLayoutPanel are likely to be used by add-ons, script authors are likely to favor them over PanelType sub-panels if they're less hassle to add (may be OK, but something to be aware of).

In some cases it will seem strange that UI show-state is shared between all regions - not in the case of modifiers, but if script authors might share this state in situations users wouldn't expect it (toolbar/properties for e.g.).

It would be good if the shown state could be stored automatically without define RNA elsewhere because it adds more boiler plate and may cause unexpected shared state if Python developers are forced to store these values on the Scene or WindowManager (in situations where they can't attach ID properties).

The use of unique RNA properties per sub-panel seems like it could be an issue in the future.
If this was limited to modifiers it's not so bad, but add-ons are going to have to define their own properties in situations that are likely to get messy (script authors might add bpy.types.WindowManager.show_my_exporter_1, show_my_exporter_2 ... etc) if they wish to use these in a file selector for example... with multiple add-ons I think this is likely to get out of hand, having to define many properties for UI elements.

This could be handled by supporting an unique-name, passed to for each sub-panel ({addon}.{name} by convention for e.g.), then the Panel could store this data. A down side of this is the potential for garbage to accumulate, although in practice I don't think it's likely to be a problem and we could support clearing unused ID's if needed.

We could consider supporting both (RNA properties and ID's in the Panel), although this also feels a bit weak & worth avoiding if possible.


Regarding naming, these should be clearly differentiated from Panel/PanelType panels. Terms such as anonymous, pseudo, collapsible... could be used.

Checked over the patch & tested functionality. Overall I think this is nice functionality to be able to declare expandable sections inline, but this exposes some awkwardness in the API which don't have clear solutions AFAICS. Notes: The `uiLayoutPanel` are likely to be used by add-ons, script authors are likely to favor them over `PanelType` sub-panels if they're less hassle to add (may be OK, but something to be aware of). In some cases it will seem strange that UI show-state is shared between all regions - not in the case of modifiers, but if script authors might share this state in situations users wouldn't expect it (toolbar/properties for e.g.). It would be good if the shown state could be stored automatically without define RNA elsewhere because it adds more boiler plate and may cause unexpected shared state if Python developers are forced to store these values on the Scene or WindowManager (in situations where they can't attach ID properties). The use of unique RNA properties per sub-panel seems like it could be an issue in the future. If this was limited to modifiers it's not so bad, but add-ons are going to have to define their own properties in situations that are likely to get messy (script authors might add `bpy.types.WindowManager.show_my_exporter_1`, `show_my_exporter_2` ... etc) if they wish to use these in a file selector for example... with multiple add-ons I think this is likely to get out of hand, having to define many properties for UI elements. This could be handled by supporting an unique-name, passed to for each sub-panel (`{addon}.{name}` by convention for e.g.), then the `Panel` could store this data. A down side of this is the potential for garbage to accumulate, although in practice I don't think it's likely to be a problem and we could support clearing unused ID's if needed. We could consider supporting both (RNA properties and ID's in the `Panel`), although this also feels a bit weak & worth avoiding if possible. ---- Regarding naming, these should be clearly differentiated from `Panel/PanelType` panels. Terms such as `anonymous`, `pseudo`, `collapsible`... could be used.
Jacques Lucke added 3 commits 2023-11-17 22:23:03 +01:00
Author
Member

Thanks for the feedback.

I think the term "collapsible" is ok, or just "section". Using "anonymous" or "pseudo" feels wrong to me.

I tried to use string identifiers for the sections now. I agree that it would be nice to store the open-state per region and not in rna properties in the modifier. Unfortunately, I ran into a issue with instanced panels which is that they are constantly being freed and added again whenever something changes. I couldn't find a way to keep the open-state around after adding a new modifier for example. Seems like this will require proper identifiers for instanced panels, which also implies that we'll need identifiers for modifiers, constraints, etc.
This might be good anyway. We rely on the modifier name as identifier in a few places where it would be nice to have a more stable identifier instead.

Thanks for the feedback. I think the term "collapsible" is ok, or just "section". Using "anonymous" or "pseudo" feels wrong to me. I tried to use string identifiers for the sections now. I agree that it would be nice to store the open-state per region and not in rna properties in the modifier. Unfortunately, I ran into a issue with instanced panels which is that they are constantly being freed and added again whenever something changes. I couldn't find a way to keep the open-state around after adding a new modifier for example. Seems like this will require proper identifiers for instanced panels, which also implies that we'll need identifiers for modifiers, constraints, etc. This might be good anyway. We rely on the modifier name as identifier in a few places where it would be nice to have a more stable identifier instead.
Author
Member

Quick summary for myself and others:

Currently, whether a modifier (sub)panel is open is stored in the modifier itself. This works okayish, but has the problem that the open-close-status is shared between multiple property editors, which is generally unexpected for panels. Would be good to know if that behavior is ok for you (ideally not just for modifiers, but also constraints, fcurve modifiers, and maybe even all subpanels).
An alternative could be to store the open-close-status in each area/editor independently. This is more similar to most panels. Unfortunately, it requires us to uniquely identify a panel within an editor and it's not entirely clear how that identifier should be build. There are different options for the identifier:

  • [modifier_name][panel_id]: Has the problem that the open-close-status is shared between different objects with the same modifiers. Also, it would be lost when the modifier name changes.
  • [modifier_id][panel_id]: Fixes the problem that renaming the modifier opens/closes panels, but the open-close-status might still be linked between different objects, because modifier ids wouldn't be globally unique (we don't even have them at all yet).
  • [object_name][modifier_id][panel_id]: Now the open-close-state is not shared between objects anymore, but renaming the object would break things.
  • [object_pointer][modifier_id][panel_id]: Would not have any of the mentioned issues, but now the identifier can't just be a simple string anymore, which makes things more difficult when we want to expose the functionality to create subpanels to the Python API. More generally, a single ID pointer might not be enough in all cases, but it could be good enough for now.
Quick summary for myself and others: Currently, whether a modifier (sub)panel is open is stored in the modifier itself. This works okayish, but has the problem that the open-close-status is shared between multiple property editors, which is generally unexpected for panels. Would be good to know if that behavior is ok for you (ideally not just for modifiers, but also constraints, fcurve modifiers, and maybe even all subpanels). An alternative could be to store the open-close-status in each area/editor independently. This is more similar to most panels. Unfortunately, it requires us to uniquely identify a panel within an editor and it's not entirely clear how that identifier should be build. There are different options for the identifier: * `[modifier_name][panel_id]`: Has the problem that the open-close-status is shared between different objects with the same modifiers. Also, it would be lost when the modifier name changes. * `[modifier_id][panel_id]`: Fixes the problem that renaming the modifier opens/closes panels, but the open-close-status might still be linked between different objects, because modifier ids wouldn't be globally unique (we don't even have them at all yet). * `[object_name][modifier_id][panel_id]`: Now the open-close-state is not shared between objects anymore, but renaming the object would break things. * `[object_pointer][modifier_id][panel_id]`: Would not have any of the mentioned issues, but now the identifier can't just be a simple string anymore, which makes things more difficult when we want to expose the functionality to create subpanels to the Python API. More generally, a single ID pointer might not be enough in all cases, but it could be good enough for now.
Member

Just to add my input to the conversation:

What I would consider 'correct' behavior is indeed if the collapse state of each panel is separate per editor.
However, I personally don't really see any realistic use-case for two editors with the same context and different panel states. Of course, this might change in the future. Other editors like 3D viewport or outliner have several display or filter options that provide different value despite the context being the same, but for the properties panels, as they really just give an overview over all properties of the context I personally don't see the same benefit.

Just to add my input to the conversation: What I would consider 'correct' behavior is indeed if the collapse state of each panel is separate per editor. However, I personally don't really see any realistic use-case for two editors with the same context and different panel states. Of course, this might change in the future. Other editors like 3D viewport or outliner have several display or filter options that provide different value despite the context being the same, but for the properties panels, as they really just give an overview over all properties of the context I personally don't see the same benefit.
Author
Member

I'll change this patch as follows:

  • Use the term "layout panel". There are arguments for using a new term, but the existing term "panel" describes what it is too well already and another term would always be explained using the the term "panel". The existing panels could be called "region panels" in conversations.
  • Move the storage of the layout panel visibility back to the modifier. The perfect solution of storing the id pointers + modifier id + panel id keys in every region is a bit too far away, comes with new problems (huge number of keys in files with many objects in many regions), does not provide a significant benefit for users in practice and is also the existing behavior for modifier panels (so no regression).
  • Remove functionality from the Python API for now (mainly because the API is not fully defined).

The goal here is to reduce the scope of this patch so that we can get panels in the geometry nodes modifier in 4.1 which has high priority without getting in the way of opening up this functionality to the API later on.

I'll change this patch as follows: * Use the term "layout panel". There are arguments for using a new term, but the existing term "panel" describes what it is too well already and another term would always be explained using the the term "panel". The existing panels could be called "region panels" in conversations. * Move the storage of the layout panel visibility back to the modifier. The perfect solution of storing the `id pointers + modifier id + panel id` keys in every region is a bit too far away, comes with new problems (huge number of keys in files with many objects in many regions), does not provide a significant benefit for users in practice and is also the existing behavior for modifier panels (so no regression). * Remove functionality from the Python API for now (mainly because the API is not fully defined). The goal here is to reduce the scope of this patch so that we can get panels in the geometry nodes modifier in 4.1 which has high priority without getting in the way of opening up this functionality to the API later on.
Jacques Lucke added 1 commit 2023-12-05 15:55:43 +01:00
Jacques Lucke added 14 commits 2023-12-12 12:18:20 +01:00
Jacques Lucke added 1 commit 2023-12-12 12:51:45 +01:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
028785a916
cleanup
Jacques Lucke changed title from WIP: UI: uiLayout based subpanels to UI: add support for uiLayout based panels 2023-12-12 12:55:27 +01:00
Author
Member

@blender-bot build

@blender-bot build
Harley Acheson added 1 commit 2023-12-12 20:10:08 +01:00
Hans Goudey requested changes 2023-12-12 20:23:20 +01:00
Hans Goudey left a comment
Member

Looks good. There is a change in the look of the bevel modifier which shouldn't happen here though. Looks like some padding issues and a row/column mismatch maybe.

image

I don't love the way of exposing panel expansion in the modifier RNA, but it's the best option I can think of.

Looks good. There is a change in the look of the bevel modifier which shouldn't happen here though. Looks like some padding issues and a row/column mismatch maybe. ![image](/attachments/bf621e65-b243-40ef-9762-fe1a64d80e88) I don't _love_ the way of exposing panel expansion in the modifier RNA, but it's the best option I can think of.
@ -343,0 +345,4 @@
float start_y;
float end_y;
PointerRNA open_owner_ptr;
std::string open_prop_name;
Member

Don't forget #include <string>

Don't forget `#include <string>`
Harley marked this conversation as resolved
@ -343,0 +354,4 @@
};
/**
* "Layout Panels" are panels which are defined as part of the `uiLayout`. As such they have a
Member

#uiLayout

`#uiLayout`
Harley marked this conversation as resolved
@ -343,0 +357,4 @@
* "Layout Panels" are panels which are defined as part of the `uiLayout`. As such they have a
* specific place in the layout and can not be freely dragged around like top level panels.
*
* This struct gathers information about the layout panels created by layouting code. This is then
Member

layouting -> layout (same below)

`layouting` -> `layout` (same below)
Harley marked this conversation as resolved
@ -2287,0 +2306,4 @@
uiLayout *uiLayoutPanel(const bContext *C,
uiLayout *layout,
const char *name,
PointerRNA *open_prop_owner,
Member

Pass by const reference? And maybe StringRef too? Mostly care about constness though

Pass by const reference? And maybe `StringRef` too? Mostly care about constness though
Author
Member

Note that making it const is not really correct, because the opening and closing of the panel is also done via the poinyer provided here.

Note that making it const is not really correct, because the opening and closing of the panel is also done via the poinyer provided here.
Member

I saw PointerRNA more like the Span vs. MutableSpan situation. It's just a view, and to do it properly we'd need MutablePointerRNA.

I saw `PointerRNA` more like the `Span` vs. `MutableSpan` situation. It's just a view, and to do it properly we'd need `MutablePointerRNA`.
Author
Member

Well, that's true, but doesn't really change the situation here right now imo.

Well, that's true, but doesn't really change the situation here right now imo.
JacquesLucke marked this conversation as resolved
@ -644,6 +644,10 @@ void ui_but_to_pixelrect(rcti *rect,
const ARegion *region,
const uiBlock *block,
const uiBut *but);
void ui_to_pixelrect(const ARegion *region,
Member

Return rcti by value

Return `rcti` by value
JacquesLucke marked this conversation as resolved
Harley Acheson added 1 commit 2023-12-12 21:15:07 +01:00
Jacques Lucke added 6 commits 2023-12-22 15:28:54 +01:00
Jacques Lucke added 1 commit 2023-12-22 15:40:31 +01:00
Jacques Lucke added 1 commit 2023-12-22 15:43:16 +01:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
3ced33a57f
return rcti by value
Author
Member

@blender-bot build

@blender-bot build
Jacques Lucke requested review from Hans Goudey 2023-12-22 15:45:18 +01:00
Hans Goudey approved these changes 2023-12-22 16:05:17 +01:00
Hans Goudey left a comment
Member

image

There's a slightly larger gap below the last subpanel now. It isn't a big deal, and it's a bit subjective, but ideally this wouldn't change spacing at all.

Maybe it would be best not to change existing modifiers in this commit? It seems a bit arbitrary just to change two of them.

![image](/attachments/c2f6cc18-ff80-4900-8d5f-1d5dd36275f7) There's a slightly larger gap below the last subpanel now. It isn't a big deal, and it's a bit subjective, but ideally this wouldn't change spacing at all. Maybe it would be best not to change existing modifiers in this commit? It seems a bit arbitrary just to change two of them.
3.8 KiB
@ -250,0 +255,4 @@
int miter_outer = RNA_enum_get(ptr, "miter_outer");
bool edge_bevel = RNA_enum_get(ptr, "affect") != MOD_BEVEL_AFFECT_VERTICES;
uiItemR(uiLayoutRow(layout, false), ptr, "profile_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
Member

This property isn't supposed to have the label displayed to the left, you'll need to disable property split for this row.

This property isn't supposed to have the label displayed to the left, you'll need to disable property split for this row.
JacquesLucke marked this conversation as resolved
Jacques Lucke added 3 commits 2023-12-22 17:08:26 +01:00
Jacques Lucke added 1 commit 2023-12-22 17:13:14 +01:00
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
2939e39608
remove changes to modifiers
Author
Member

@blender-bot build

@blender-bot build
Jacques Lucke merged commit f824476bd5 into main 2023-12-22 17:58:06 +01:00
Jacques Lucke deleted branch layout-panels 2023-12-22 17:58:09 +01:00
Sign in to join this conversation.
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 project
No Assignees
5 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#113584
No description provided.