Adds support for saving some view state persistently and uses this to keep the
height of a tree-view, even as the region containing it is hidden, or the file
re-loaded.
Fixes#129058.
Basically the design is to have state stored in the region, so it can be saved
to files. Views types (tree-view, grid-view, etc) can decide themselves if they
have state to be preserved, and what state that is. If a view wants to preserve
state, it's stored in a list inside the region, identified by the view's idname.
Limitation is that multiple instances of the same view would share these bits of
state, in practice I don't think that's ever an issue.
More state can be added to be preserved as needed. Since different kinds of
views may require different state, I was thinking we could add ID properties to
`uiViewState` even, making it much more dynamic.
Pull Request: https://projects.blender.org/blender/blender/pulls/130292
We already have the `description` property on panels but are currently not
displaying it when hovering over a panel header. With this patch, the
descriptions will be shown in group nodes as well as the geometry nodes
modifier.
I had to do two lower level changes for layout panels because it didn't work
with tooltips properly.
* Tooltips make the label in the panel header interactive, but clicking to
open/close the panel should still work.
* The tooltip should disappear when clicking on the header. This is consistent
with tooltips in other places.
Pull Request: https://projects.blender.org/blender/blender/pulls/127852
Mainly changes some UI-internal structs allocation, and the Panel
runtime custom data storage.
These changes from C-style alloc/free to C++ new/delete are a step
towards making PointerRNA non-trivial (part of #122431).
Pull Request: https://projects.blender.org/blender/blender/pulls/126698
This PR removes the "Widget Label" text style, found in Preferences /
Themes / Text Style. This results in both labels and the text found in
input boxes sharing settings. This results in a slight loss of
customization but it isn't that useful to have these things separate
and results in code complication and errors.
Pull Request: https://projects.blender.org/blender/blender/pulls/122898
In `ui_popup_block_position` popup blocks are scaled with the owner
button region scale which wasn't being done for layout panel bounds.
This applies the scale applied to the popup block to layout panels
bodies and headers.
Also when calculating layout-panels headers and bodies the offset
`layout_panel_y_offset` is applied in place, this because this value
can also be affected by this scale.
This solves the original issue described in #122411 and reverts the
regression #123807.
Ref !123980
When a popover includes panels, the calculation of whether the mouse
is over the panel header does not take into consideration local 2D
scaling. Therefore the hit area is in the wrong location if scaled.
Pull Request: https://projects.blender.org/blender/blender/pulls/122696
User feedback has been that the pinned modifier looks broken because
there is no feedback in the UI showing that it's pinned (related to the
recently reported #121620). It's also inconvenient to disable the pinning
if it's required to move the modifier up (before another modifier that
controls normals for example). Now the "Pin" icon is displayed here,
and clicking on it turns off the pinning.
Also, change the property name from "Stick to Last" to "Pin to Last".
"Stick" is a weird word in the UI, it sounds uncommon and strangely
physical. "Pin" is more associated with this concept.
---

Pull Request: https://projects.blender.org/blender/blender/pulls/122444
These were added/exposed in aa03646a74.
There's no need to expose them in the public UI API, and they don't seem
like functions that should be used outside of the UI internals.
Based on the design in #120230.
* Replaces the `Shade Smooth by Angle` operator with `Shade Auto Smooth`
in the object context menu menu.
* The new operator automatically adds and removes the modifier instead
of being a destructive operation.
* The `Shade Smooth` and `Shade Flat` operators now remove the
`Smooth by Angle` modifier automatically.
* Add a pin option to modifiers, which limits dragging and keeps the
modifier after newly added modifiers in the list.
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/121494
Enables operators that uses `WM_operator_props_dialog_popup`
or `redo` popup to use layout panels.
Other popups would likely also support layout panels, only
they need to set its dummy panel with `UI_popup_dummy_panel_set`.
Popups don't normally use `Panel`, but that's the type that stores the
layout panel states. Therefore, to use layout panels in a popup, one
currently needs to create a dummy panel whose purpose is to store the
layout panel states for as long as the popup is open.
Alternatively, we could potentially also store the layout panel states
somewhere else in the future for popups, but that might be a more involved
change for now.
See #119519 for an example script that uses layout panels in a popup.
Pull Request: https://projects.blender.org/blender/blender/pulls/119519
The `FILE_PT_operator` panel used in the file browser does not correctly
allow the new UI layout panels to be drawn correctly.
The layout panels depend on drawing the background so that different
colors can denote each panel section. In the case of `FILE_PT_operator`,
this background drawing is skipped entirely leading to a situation where
there's no panel delineation at all.
Forcing the background to be drawn leads to a second problem where
the "typical" panel colors are not used in this part of the file
browser. We need to match the surrounding area otherwise a much
lighter shade of gray will be used and look out of place.
The fix is to extend the processing for PANEL_TYPE_NO_HEADER to account
for both of the above situations.
Pull Request: https://projects.blender.org/blender/blender/pulls/118231
For icons that represent collapsible and collapsed content we use a
variety of icons: chevrons and closed triangles of varying
proportions. This PR makes everything use a chevron for consistency.
Pull Request: https://projects.blender.org/blender/blender/pulls/116240
The term `PIL` stands for "platform independent library." It exists since the `Initial Revision`
commit from 2002. Nowadays, we generally just use the `BLI` (blenlib) prefix for such code
and the `PIL` prefix feels more confusing then useful. Therefore, this patch renames the
`PIL` to `BLI`.
Pull Request: https://projects.blender.org/blender/blender/pulls/117325
Previously, panels without headers were always skipped in the code
that opens and closes panels because they could not be closed.
Now they can contain layout panels that can be closed even if the root
panel can not be closed.
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
Along with the 4.1 libraries upgrade, we are bumping the clang-format
version from 8-12 to 17. This affects quite a few files.
If not already the case, you may consider pointing your IDE to the
clang-format binary bundled with the Blender precompiled libraries.
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
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
When clicking or dragging a Panel's drag handle, a PANEL_STATE_DRAG
state transition is followed immediately by a PANEL_STATE_ANIMATE
transition. Both transitions start a timer.
Unfortunately, a subtle change introduced in
f3ab698951 meant the first timer would no
longer be destroyed before starting the second one.
The fix is to just reuse the timer if it's already present so that a
second one is not created in the first place.
Pull Request: https://projects.blender.org/blender/blender/pulls/113711
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
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944