In 13fac109 the node panels got support for individual option button
callbacks, but these were not included in the node editor side bar.
Only the older top-level buttons are drawn there.
The panel structure is currently not accessible in python since it is
part of the `NodeDeclaration` system. To draw node input sockets and
buttons in the correct panel order as they appear on the node, a new
template function `uiTemplateNodeInputs` has been added. This iterates
over declared panels and their contents in the appropriate order and
draws the buttons before sockets in the same panel.
Pull Request: https://projects.blender.org/blender/blender/pulls/116936
This adds a Python API for layout panels that have been introduced in #113584.
Two new methods on `UILayout` are added:
* `.panel(idname, text="...", default_closed=False) -> Optional[UILayout]`
* `.panel_prop(owner, prop_name, text="...") -> Optional[UILayout]`
Both create a panel and return `None` if the panel is collapsed. The difference lies
in how the open-close-state is stored. The first method internally manages the
open-close-state based on the provided identifier. The second one allows for
providing a boolean property that stores whether the panel is open. This is useful
when creating a dynamic of panels and when it is difficult to create a unique idname.
For the `.panel(...)` method, a new internal map on `Panel` is created which keeps
track of all the panel states based on the idname. Currently, there is no mechanism
for freeing any elements once they have been added to the map. This is unlikely to
cause a problem anytime soon, but we might need some kind of garbage collection
in the future.
```python
import bpy
from bpy.props import BoolProperty
class LayoutDemoPanel(bpy.types.Panel):
bl_label = "Layout Panel Demo"
bl_idname = "SCENE_PT_layout_panel"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
scene = context.scene
layout.label(text="Before")
if panel := layout.panel("my_panel_id", text="Hello World", default_closed=False):
panel.label(text="Success")
if panel := layout.panel_prop(scene, "show_demo_panel", text="My Panel"):
panel.prop(scene, "frame_start")
panel.prop(scene, "frame_end")
layout.label(text="After")
bpy.utils.register_class(LayoutDemoPanel)
bpy.types.Scene.show_demo_panel = BoolProperty(default=False)
```
Pull Request: https://projects.blender.org/blender/blender/pulls/116949
Make it possible to nest bone collections. The data structure on the
armature is still a flat array. It is organised as follows:
- Sibling collections (i.e. ones with the same parent) are stored
sequentially in the array.
- Each bone collection keep track of the number of children, and the
index of the first child.
- Root collections (i.e. ones without parent) are stored as the first
elements in the array.
- The number of root collections is stored on the Armature.
This commit also contains the following:
- Replaced the flat UIList of bone collections with a tree view.
- Updated the M/Shift+M operators (move/assign to collection) to work
with hierarchical bone collections.
- Updated RNA interface to expose only root collections at
`armature.collections`. All collections are available on
`armature.collections.all`, and children at `bonecollection.children`.
- Library override support. Only new roots + their subtrees can be added
via overrides.
See https://projects.blender.org/blender/blender/issues/115934
Co-authored with @nathanvegdahl and @nrupsis.
Pull Request: https://projects.blender.org/blender/blender/pulls/115945
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 initial use case for this are panels in the geometry nodes modifier. This patch provides
a better solution compared to what was attempted in #108565.
### 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 negligible. Therefor, a much simpler solution
is possible: the open/close state can be stored in the modifier directly. This is actually
how it was implemented before 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 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 (not included)
Adding a Python API is fairly straight forward. 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.
```
Pull Request: https://projects.blender.org/blender/blender/pulls/113584
Improvements to the drawing of shadows, used with blocks, menus, nodes,
etc. Improvements to shape, especially at the top corner or at extremes
of widget roundness. Allows transparent objects to have shadows. This
is a nice refactor that removes a lot of code.
Pull Request: https://projects.blender.org/blender/blender/pulls/111794
This new member gives access to the current active panel category (i.e.
tab) if supported, and allows to set its value to another defined
category.
While typically add-ons should not force a tab to be the active one,
there are cases where this is a valid and necessary behavior, e.g. in
'Blender App' where an app can add some new tab to the UI and require
them to be active.
Note that there is a ctach here: typically at start time these panel
categories are unknown (enum is empty), since they are validated by
drawing code. So setting them usually needs to be done after initial
startup and drawing of the UI...
Pull Request: https://projects.blender.org/blender/blender/pulls/114070
Calling this state "active" has been confusing for a long time for a number of reasons:
- It's not clear that this is essentially a mouse hover state.
- Easy to confuse with "select" state (`UI_SELECT`), both terms are vague.
- Buttons can be "inactive" (`UI_BUT_INACTIVE`) which is totally related to this "active" state.
- Button handling can consider a button as active that doesn't have this flag set (e.g. during text input).
- Active and selected are well established terms in Blender, but they mean a different thing there.
See #112160.
Pull Request: https://projects.blender.org/blender/blender/pulls/114113
The `blender-v4.0-release` branch would not build because some parts of grease pencil v3 were still exposed when experimental features are disabled.
This is hiding the relevant parts behind `#ifdef WITH_GREASE_PENCIL_V3` to make sure they are only built when the experimental features is enabled.
Pull Request: https://projects.blender.org/blender/blender/pulls/112953
Draw the background of the asset shelf header fully transparent, with an opaque
background with rounded corners behind sections containing buttons. This
reduces the visual space consumed by the asset shelf, and makes the header
follow a tabbed folder metaphor better. Also, this works much better with our
click-through feature, where transparent parts of regions without buttons are
passed through the region under it (we might want to consider unifying code
here a bit).
The edge to drag for region resizing respects the transparent sections.
When there is little space between sections, the sections get merged so that
there are no small gaps in the bar.
Part of #107881.
----
Note that the core of this is implemented in a generic way, so this can be
reused for other regions.
Pull Request: https://projects.blender.org/blender/blender/pulls/112241
It was already called that way in the UI, since it's referring to a
behavior, not a type. Update the code to match that. Note that this is
a BPY compatibility breaking change for 4.0.
This change makes it so the list interface in the properties panels looks
closer to things like shape keys, vertex groups and so on: there are two
buttons to add selected objects to the collection and remove active item
from the collection, as well as the "extra" drop down menu.
The add operator adds selected objects to the light linking collection
using the Include policy. For the light linking it means that the objects
are added as receivers that receive the light, and for the shadow linking
it means that objects are added as blockers which cast shadow from the
light.
The communication of the active list element is done via context property
similar to how it was done before. The difference is that these properties
are set on a parent of the list layout, which makes it so they are inherited
by the layout hierarchy needed to place the Remove button.
Pull Request: https://projects.blender.org/blender/blender/pulls/112713
With 9d0907560a, button tooltips would now often display the label even though
it's already visible in the button itself.
This fix brings back the old logic for displaying the label, but it's still
possible to override the label via the callback introduced in the earlier
commit.
Comments are updated/added here to make the behavior more clear.
Pull Request: https://projects.blender.org/blender/blender/pulls/110469
This adds an optional uiBut callback that allows creating a tooltip
line-by-line with specified style and color in any order. It also
allows adding images as well to create very informative tooltips.
Pull Request: https://projects.blender.org/blender/blender/pulls/105905
Changes the `asset_poll()` and `draw_context_menu()` methods for asset
shelves to use the `AssetRepresentation` type, instead of `AssetHandle`.
The latter should be removed, so it's better to avoid using it in the
asset shelf BPY to avoid future compatibility breakage. This is possible
now with d421ebac5e.
The previous limit of 63 bytes for the panel name was an issue for
languages where characters use multiple bytes. The UI would show panel
names truncated that had reasonably long/short names.
It's easy to support dynamically sized strings here, so do that instead
of using fixed size buffers.
Fixes#111927.
Pull Request: https://projects.blender.org/blender/blender/pulls/111979
The basic idea is very simple. Whenever a supported menu is open, one can just
start typing and this opens a search that contains all the (nested) menu entries.
The main downside is that this collides with accelerator keys. Those are the
underlined characters in each menu. For now, we just enable this new searching
behavior in a few selected menus: Node Add Menu, View3D Add Menu and
Modifier Add Menu.
This new functionality can be enabled for a menu by setting
`bl_options = {'SEARCH_ON_KEY_PRESS'}` to true in the menu type.
The status bar shows `Type to search...` when a menu is opened that supports search.
Pull Request: https://projects.blender.org/blender/blender/pulls/110855
When estimating widget sizes, ui_text_icon_width_ex() assumes that all
items are using the "widget" text style, which is incorrect for labels.
This PR uses widget_label style for uiItemL_ and the label portion of
ui_item_with_label.
Pull Request: https://projects.blender.org/blender/blender/pulls/111908
Generally the context store is owned by `uiBlock`. Other pointers
to the store (in `bContext` and other operator data) shouldn't change
it, so those variables are now const. One exception is the pointer in
`uiLayout`, but that has a clearly short lifetime, so that's okay.
Part 3/3 of #109135, #110272
Switch to new node group interfaces and deprecate old DNA and API.
This completes support for panels in node drawing and in node group
interface declarations in particular.
The new node group interface DNA and RNA code has been added in parts
1 and 2 (#110885, #110952) but has not be enabled yet. This commit
completes the integration by
* enabling the new RNA API
* using the new API in UI
* read/write new interfaces from blend files
* add versioning for backward compatibility
* add forward-compatible writing code to reconstruct old interfaces
All places accessing node group interface declarations should now be
using the new API. A runtime cache has been added that allows simple
linear access to socket inputs and outputs even when a panel hierarchy
is used.
Old DNA has been deprecated and should only be accessed for versioning
(inputs/outputs renamed to inputs_legacy/outputs_legacy to catch
errors). Versioning code ensures both backward and forward
compatibility of existing files.
The API for old interfaces is removed. The new API is very similar but
is defined on the `ntree.interface` instead of the `ntree` directly.
Breaking change notifications and detailed instructions for migrating
will be added.
A python test has been added for the node group API functions. This
includes new functionality such as creating panels and moving items
between different levels.
This patch does not yet contain panel representations in the modifier
UI. This has been tested in a separate branch and will be added with a
later PR (#108565).
Pull Request: https://projects.blender.org/blender/blender/pulls/111348