This implements the ability to have file exporters added and configured on Collections.
Exporting is reachable from several locations:
- Individually on each exporter configuration: The `Export` button in each panel header
- For all exporters on the collection: The `Export All` button in the main panel interface
- For all exporters on all collections in the scene: The `File`->`Export All Collections` button
Visibility of which collections currently have exporters configured is done by ways of an icon added to the Collection row in the Outliner.
Adding multiple exporters for the same file type is permitted. The user is free to setup several exports of the same format but with different file locations or settings etc.
Notes:
Only USD and Wavefront OBJ are enabled for the initial commit. Additional formats, including those implemented in Python will be added as separate commits after this.
Ref #115690
Pull Request: https://projects.blender.org/blender/blender/pulls/116646
Instead of only referencing an existing one. This will be used for
collection exporter and presets, to make sure the operator instance
stays alive long enough for the preset to be able to be applied.
Pull Request: https://projects.blender.org/blender/blender/pulls/120034
Previously retrieving a collection from the context like "selected_ids"
would give a linked list of allocated items. Now it returns a vector of
RNA pointers. Though the number of items is typically fairly small,
using contiguous memory and avoiding many small allocations are
typical performance improvements that could still be beneficial
when there are many items. Iteration also becomes much simpler.
Pull Request: https://projects.blender.org/blender/blender/pulls/119939
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
Add more flexibility to tooltip images by adding the ability to specify
if (one of two) checkerboards are added, border, premultiplied
blending, or recoloring.
Pull Request: https://projects.blender.org/blender/blender/pulls/119437
"Own" (the adjective) cannot be used on its own. It should be combined
with something like "its own", "our own", "her own", or "the object's own".
It also isn't used separately to mean something like "separate".
Also, "its own" is correct instead of "it's own" which is a misues of the verb.
Over the last couple years (!) UI buttons have moved to derived classes,
meaning we don't need to use the same "a1" and "a2" variables to store
different information. At this point, that information is set specifically
by internal UI code, or functions like `UI_but_*_set`.
These values are only set to their default 0 values now (or -1 in some
non-meaningful cases). This commit removes the values from buttons
and removes the remaining a1 and a2 arguments from the UI API.
Previously these used a special "menu func" that used an argument value
passed through each menu button's a2 value. This was more complex than
necessary given the existence of generic button callbacks.
So use std::function in these remaining cases, and remove the now-unused
`butm_func` and `butm_func_arg` values in the uiBlock.
Remove uses for `uiDefButS`. -1 was passed as a2 still in a few
places, but that was most likely just because of copy & paste,
it doesn't look like that's actually used anywhere.
The main simplification is using return values rather than return
arguments, and the additional semantic clarity from std::optional.
Also use `fmt` for formatting and use lambdas instead of macros
as helpers in a few modal keymap formatting functions.
Similar commits:
- a1792e98a4
- f04bc75f8c
- 6abf43cef5
- 7ca4dcac5a
Pull Request: https://projects.blender.org/blender/blender/pulls/117785
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.
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
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
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.
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
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
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.
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.
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.
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