Commit Graph

60 Commits

Author SHA1 Message Date
Hans Goudey
266230dd88 Refactor: UI: Pass StringRef to more button definition functions
Similar to 9c3aa8b824. This time there is one null argument
that has to be changed. It was simple to just move the logic to that one
caller.
2024-02-01 14:40:40 -05:00
Hans Goudey
5155feeeb8 Cleanup: UI: Remove a1 and a2 unused arguments from uiDefButF function
These were removed in previous commits like e6f0b60c2e.
2024-02-01 13:09:09 -05:00
Hans Goudey
809499a3d0 Refactor: UI: Use derived struct for number slider buttons
Similar to d204830107. This is the last real use of
the a1 and a2 arguments for many button definition functions.
2024-02-01 13:08:50 -05:00
Hans Goudey
9c3aa8b824 Cleanup: Use StringRef arguments for some UI button functions
The benefits are O(1) access to the string size, clearer ownership,
and easily accessible utility functions. For now, only change functions
where the string is clearly non-null. It's not clear in what cases some
other functions recieve null strings.
2024-01-31 17:16:25 -05:00
Hans Goudey
e89b4927e4 Cleanup: UI: Remove unused button creation functions 2024-01-31 13:45:26 -05:00
Hans Goudey
f04bc75f8c Cleanup: Use std::string for some RNA function return values
This significantly simplifies memory management, mostly by avoiding
the need to free the memory manually. It may also improve performance,
since std::string has an inline buffer that can prevent heap
allocations and it stores the size.

Pull Request: https://projects.blender.org/blender/blender/pulls/117695
2024-01-31 17:08:09 +01:00
Jacques Lucke
f358843108 UI: simplify layout panels C++ API
This simplifies the C++ API for making layout panels. Now it is also more similar to the Python API.
`uiLayoutPanel` is like `layout.panel` and `uiLayoutPanelProp` is like `layout.panel_prop`.

Both, `uiLayoutPanel` and `uiLayoutPanelProp`, now exist in two variants. One that takes a label
parameter and one that does not. If the label is passed in, only the panel body layout is returned.
Otherwise, the header and body are returned for more customization.

Pull Request: https://projects.blender.org/blender/blender/pulls/117670
2024-01-30 17:44:56 +01:00
Hans Goudey
13d280b8d8 Cleanup: Rename function to ensure button operator properties
For some reason the "get" function actually allocates the button's
operator properties container. This may or may not make sense to
do, but while it happens, the function name might as well make
that clear.
2024-01-29 16:33:12 -05:00
Harley Acheson
28366f624f UI: Operator Confirm Dialog Changes
Removal of "confirm" operator callback for confirmation customization,
in favor of new method that shares existing operator dialog code and
allows python configuration.

Pull Request: https://projects.blender.org/blender/blender/pulls/117564
2024-01-29 18:52:18 +01:00
Hans Goudey
1bb358f423 Fix: Tooltip memory leak
Use std::string for custom tooltip function return value.
2024-01-26 14:39:05 -05:00
Jesse Yurkovich
ddd06eeb8f UI: Add ability to configure the header row of layout panels
There are many instances where customizing the header row is desired so
return both the header row layout and the main body layout.

For consistency and correctness, the arrow symbol and the is_open check
are always performed so callers only need to perform layout tasks.

The C++ side now receives a `PanelLayout` structure containing both:
```cpp
PanelLayout panel_layout = uiLayoutPanelWithHeader( ... );
uiItemL(panel_layout.header, ... );
if (panel_layout.body) {
    ...
}
```

And the Python side receives a tuple:
```python
header, body = layout.panel( ... )
header.label(...)
if body:
    ...
```

```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="Basic Panels")

        header, panel = layout.panel("my_panel_id", default_closed=True)
        header.label(text="Hello World")
        if panel:
            panel.label(text="Success")

        header, panel = layout.panel_prop(scene, "show_demo_panel")
        header.label(text="My Panel")
        if panel:
            panel.prop(scene, "frame_start")
            panel.prop(scene, "frame_end")

        layout.label(text="Customized headers")

        # Add a checkbox to the Panel header. text must be None for this panel
        header, panel = layout.panel("my_panel_id-2", default_closed=True)
        header.prop(scene, "use_checkmark", text="") # text must be empty for the checkbox
        header.label(text="Checkmark at beginning")
        if panel:
            panel.label(text="Success")

        header, panel = layout.panel("my_panel_id-3", default_closed=True)
        header.label(text="Buttons at the end")
        header.operator("mesh.primitive_cube_add", text="", icon='EXPORT')
        header.operator("mesh.primitive_cube_add", text="", icon='X')
        if panel:
            panel.label(text="Success")

        header, panel = layout.panel("my_panel_id-4", default_closed=True)
        header.prop(scene, "use_checkmark2", text="")
        header.label(text="Both")
        header.operator("mesh.primitive_cube_add", text="", icon='EXPORT')
        header.operator("mesh.primitive_cube_add", text="", icon='X')
        if panel:
            panel.label(text="Success")

bpy.utils.register_class(LayoutDemoPanel)
bpy.types.Scene.show_demo_panel = BoolProperty(default=False)
bpy.types.Scene.use_checkmark = BoolProperty(default=False)
bpy.types.Scene.use_checkmark2 = BoolProperty(default=False)
```

Pull Request: https://projects.blender.org/blender/blender/pulls/117248
2024-01-26 10:11:22 +01:00
Brecht Van Lommel
487adcb992 Fix: build error when not using unity build 2024-01-19 20:12:45 +01:00
Hans Goudey
7ca4dcac5a Cleanup: Use std::string for UI drop box tooltip return type
And use fmt for formatting strings.
2024-01-19 12:08:48 -05:00
Hans Goudey
6abf43cef5 Cleanup: Use std::string to store and pass tooltip text
Store temporrary tooltip text as `std::string` instead of
manually allocated C strings. Use `fmt` to format instead
of our own formatting utilities that return an allocated C
string.
2024-01-19 09:27:56 -05:00
Hans Goudey
90c4e2e6ec Cleanup: Replace UI button "string info" function
Instead of a single function with variadic arguments, a special enum
type containing which string to request, and a special struct to
contain the request and the result, just use separate functions for
each request, and return a std::string by value. Also change the enum
item string access to just give access to the enum item itself and add
const in a few places as necessary.

The callers of the API function get much clearer this way, and it's
much easier to see which information is used to create certain tooltip
strings.
2024-01-19 09:27:56 -05:00
Hans Goudey
f929fb5d77 Cleanup: Store uiBlock name as std::string
And change some adjacent code to benefit from the simplicity
and constant time access to the length of the string.
2024-01-18 16:13:00 -05:00
Campbell Barton
b8a340e630 UI: always return shortcuts from UI_but_string_info_get on request
Change the behavior of UI_but_string_info_get to fill in shortcuts
when requested.

Previously shortcuts were ignored for menus, because showing shortcuts
in tool-tips which are already displayed in the menu isn't needed.

Move this logic to tool-tip creation so other the shortcuts may be
accessed in other contexts.
2024-01-18 10:52:58 +11:00
Lukas Tönne
53e34dba80 Fix #115727: Draw panel buttons in the node editor side bar
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
2024-01-16 13:37:57 +01:00
Campbell Barton
a294a9083e UI: don't show property shortcuts in menus
Operator shortcuts aren't shown in this case,
use the same logic for properties.
2024-01-16 14:09:37 +11:00
Jacques Lucke
8896446f7e Python: add Python API for layout panels
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
2024-01-11 19:08:45 +01:00
Campbell Barton
617f7b76df Cleanup: comment block formatting 2024-01-08 11:31:43 +11:00
Campbell Barton
0ba83fde1f Cleanup: spelling in comments 2024-01-08 11:24:37 +11:00
Hans Goudey
53e2dcadec Cleanup: Remove unnecessary C default argument macro 2024-01-04 15:42:54 -05:00
Hans Goudey
d6cfd7d1f4 Cleanup: Remove unnecessary keywords from C++ headers
- Remove unnecessary `struct`
- Use `using` instead of `typedef`
- Remove `void` from `(void)` as function arguments
2024-01-04 15:07:48 -05:00
Sybren A. Stüvel
129fb2eab8 Anim: make bone collections hierarchical
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
2023-12-28 18:14:55 +01:00
Jacques Lucke
f824476bd5 UI: add support for uiLayout based panels
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
2023-12-22 17:57:57 +01:00
Campbell Barton
15db0cb446 Cleanup: use style for doxygen comment blocks 2023-11-30 14:15:11 +11:00
Leon Schittek
0335b6a3b7 UI: Improve menu dropshadow
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
2023-11-24 22:50:20 +01:00
Hans Goudey
0c1bb82fc4 Cleanup: Remove unnecessary struct and typedef keywords from C++ headers 2023-11-14 09:51:41 +01:00
Bastien Montagne
f84b0a4dd2 UI/Py API: Add active_panel_category to RNA Region struct.
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
2023-10-31 18:10:28 +01:00
Julian Eisel
72a8851a95 UI Code Quality: Rename UI_ACTIVE button flag to UI_HOVER
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
2023-10-25 18:36:27 +02:00
Harley Acheson
cb9832f9b1 UI: Allow Tooltip Padding In Any Order
Allow padding anywhere within a tooltip, not just before the current
field, by adding a new field type of UI_TIP_STYLE_SPACER.

Pull Request: https://projects.blender.org/blender/blender/pulls/112487
2023-10-13 22:34:43 +02:00
Harley Acheson
3c4f84e0fc UI: Input Placeholders
Optional inline hint describing the expected value of an input field.

Pull Request: #112104
2023-10-12 11:44:08 -07:00
Campbell Barton
b8ad624006 Cleanup: use doxygen doc-strings, spelling in comments 2023-10-12 09:26:53 +11:00
Harley Acheson
d6a6c3e1fc UI: Highlight Selected Item in View3D Mode Menu
Allow the View3D "Mode" menu to highlight the currently-selected mode.

Pull Request: https://projects.blender.org/blender/blender/pulls/112058
2023-10-11 19:27:02 +02:00
Harley Acheson
aa88d9a8e3 Revert "UI: Input Placeholders"
This reverts commit b0515e34f9.
Unintentionally added to 4.0
2023-10-11 08:01:24 -07:00
Harley Acheson
b0515e34f9 UI: Input Placeholders
Optional inline hint describing the expected value of an input field.

Pull Request: https://projects.blender.org/blender/blender/pulls/112104
2023-10-11 00:47:13 +02:00
Falk David
4f617bc728 Fix: Expose GPv3 RNA only in experimental
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
2023-09-27 15:46:18 +02:00
Campbell Barton
b4d3bd134b Cleanup: quiet ASAN warning with invalid value for eButGradientType
-1 was assigned to eButGradientType which isn't a valid value,
add UI_GRAD_NONE to resolve this.
2023-09-27 14:28:47 +10:00
Julian Eisel
73460903fa Asset Shelf: Transparent asset shelf header with background for buttons
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
2023-09-26 17:12:37 +02:00
Julian Eisel
ca2a8be15f Assets: Rename "Import Type" to "Import Method" in code/BPY
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.
2023-09-26 16:48:47 +02:00
Hans Goudey
0cb01332f1 Cleanup: Consistency between asset-extended menu UI templates
Define the UI template in the namespace of its own module, and
consistently use references and const in those UI template functions.
2023-09-25 21:58:30 -04:00
Sergey Sharybin
015bc7ca4d Light linking: Make list interface look more similar to other places
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
2023-09-22 17:44:25 +02:00
Julian Eisel
8b610723b6 Fix tooltip showing button label redundantly (regression)
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
2023-09-21 14:49:53 +02:00
Campbell Barton
e39940e255 Fix error from 106d2bb312
Swapped width/height for the image size.
2023-09-17 11:32:41 +10:00
Campbell Barton
106d2bb312 Cleanup: document ownership for uiTooltipField, add function attributes
- Document ownership.
- Make some arguments const.
- Use function style casts.
- Make width/height into a size[2].
2023-09-17 09:05:40 +10:00
Campbell Barton
c75a304b51 Cleanup: use lowercase ui prefix for enum, rename Color -> ColorID
Follow current conventions for types e.g. uiFontStyle, uiBlock etc.
Also rename UiTooltipColor to uiTooltipColorID since this isn't
storing the color.
2023-09-17 09:05:40 +10:00
Campbell Barton
7eae806dda Cleanup: format, spelling 2023-09-17 09:05:40 +10:00
Harley Acheson
6453b00f44 UI: Custom Tooltips with Optional Images
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
2023-09-15 21:06:30 +02:00
Julian Eisel
728d47f3e4 Asset shelf: Use asset representation for asset shelf BPY methods
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.
2023-09-15 16:17:44 +02:00