Page MenuHome

Support RNA properties initializing operator properties
Needs ReviewPublic

Authored by Campbell Barton (campbellbarton) on Sep 16 2022, 8:40 AM.

Details

Summary

Supports RNA properties initializing settings for operators.

When activating the file browser to change a property, there was no way to control the settings which the file browser would use.

Resolve this by adding PropertyRNA.operator_invoke which operators may call when editing properties.
Currently file browsing is the most obvious use-case but it could be used for other kinds of properties in the future (so the property could control how the eye-dropper is used for e.g.).

This introduces user visible changes:

  • Browsing font paths in the user preferences enables the font filter.
  • Browsing the render output path shows +/- buttons (to increment/decrement the file name).

Now "check_existing" is available for all file browser operators, defaulting to ON for FILE_SAFE, allowing any call to the browse operator to optionally check for output.

Exposing this to the Python API (via bpy.props is a remaining TODO).


Notes:

  • This is an alternative to both D13937 & D15968.
  • The naming operator_invoke could be changed to be less generic (as it's a fairly spesific action).
  • There are some unused arguments to the PropertyRNA.operator_invoke(..), these will be needed when Python supports defining the callback.

Possible Solutions

Add File Browser Specific RNA Properties

The property it's self could store settings such as.

  • Is the path input or output (which could control "check_existing").
  • The filter flag (to filter on images, fonts, textures etc).

The main down side of this is we would end up adding properties which are spesific to the file browser into RNA, adding API duplication for something that is only used in a few places.

Add File Browser Specific Property API

We could UILayout.prop_filepath(..) however it has some draw-backs.

  • The prop_filepath may end up having to take many file-paramaters (duplicating the filter options for e.g. for different file types).
  • Something which is logically part of the property is being stored in UI layout (meaning automatic layouts won't have useful file browser settings).
Add an Operator Invoke Callback (this patch)

This allows the property to set any operator settings that seem useful, as shown in this patch "check_existing" and "filter_font" happen to be useful for render output and font selection.

It has the advantage of not duplicating operator settings into the RNAProperty or the UILayout methods.

A down side of this is that the operator needs to be checked by the properties invoke function, which is a trade-off made to avoid duplicating those settings into other parts of the API.

Diff Detail

Repository
rB Blender
Branch
UI-OPERATOR-INVOKE (branched from master)
Build Status
Buildable 23797
Build 23797: arc lint + arc unit

Event Timeline

Campbell Barton (campbellbarton) requested review of this revision.Sep 16 2022, 8:40 AM
Campbell Barton (campbellbarton) created this revision.

Fix error referencing wrong ptr.

@Campbell Barton (campbellbarton) can you update the patch to also include this option for the File Output node in the compositor? (see D15968)

  • File output node now shows +/- buttons.

To me this seems like some kind of circular dependency. I would expect operators to be aware of properties, not the other way around.

I would rather expect properties to have information about which type of file path they are. To me that's not even really file browser specific, although it would be the immediate use case. There could be other uses to distinguish path types, for example image paths can have UDIM tokens, maybe we will add support for tokens in render/cache output paths, some path support // and others don't, etc. The UI and scripts could potentially make use of that information beyond just known operators.

The challenge with adding this information into the properties is how to do that in a way that doesn't expose too much of the file selector internals.

Support for relative paths / use as output / use as input ... are generic hints (which RNA might reasonably know about).

Things we might want to set in the file selector that don't fit so well in RNA are filter types (font, blender, collada, btx ~ 20+ types) and extensions to show, e.g. filter_glob="*.jpg;*.jpeg". These seem more like details of the file selector that are being exposed in RNA.

Adding spesific fields into RNA properties for these settings seems too much like storing FileSelectParams in RNA.

Possible solutions to this could be...

  • Define a key:value store for RNA properties (it could be used to store hints that operators could inspect). This avoids disruptive RNA changes when having there is the need to specify details about a property.
  • We could optionally allocate a hints structure where each type/sub-type could store additional hints about it's use. This avoids having to add sub-types to adjust behavior, although it would mean some work exposing these hints to Python whenever new ones are added. Although this has the overhead of needing some work exposing each setting to the Python API whenever it's added and may duplicate flags/ID's used elsewhere.

Edit, this doesn't have to be all or nothing, we could have some extended hints for file paths (supporting relative, input/output.. etc). as well as a way to communicate information to the file browser (which could work differently if we don't want to make that part of the RNA string API).

Copying & replying to the existing discussion from D13937:

I agree that using the property type is an issue. An RNA property callback that has to know the possible operators and operator properties it can act on sounds... I don't know... not great either? :)

I'd rather have a UILayout.prop_filepath(..., browse="buttons.font_browse") then, where the operator just calls the file browser with the necessary properties set, all as normal.

@Julian Eisel (Severin) agree it's a down-side, although any kind of coupling between the RNA-property and the file browser has a similar problem.

Some reasons we didn't opt to use the UI API for to solve this problem (IIRC):

  • We would have to hand-pick properties users might want to set for the file selector and send them through to UILayout.prop_filepath(..). If some properties are missing it seems like an arbitrary limitation, and if most are exposed this would be adding a function with the majority of the file-selection-parameters - which is most likely needed if properties are to control filtering, checking for existing files ... etc.

Note that my suggestion is not to let the prop_filepath() take the file browser options. You'd just pass it the path property and an operator name, the operator sets up and spawns the file browser. Just like it's done for normal file browsing operations that are not tied to RNA properties.

We could however let prop_filepath() return the operator properties, which sounds quite simple & powerful.

  • It also has the down side that the UI is declaring something which is logically part of the property, where automatic layouts (uiDefAutoButsRNA for e.g.) won't load the file browser with expected settings.

I don't think there is a current case where this would be an issue. For example File Browser and undo/redo don't work well together, I don't think spawning File Browsers from a redo panel would work even.
If there ever is such a case, it's not a big problem to create the layout manually.

  • Initializing operator properties is more generic & flexible, as it's not limited to the file browser. Any kind of operator that manipulates a property could use this and we don't have to add new UILayout.prop_* functions for each case.

It may be more generic and flexible in this way, but it's much more limited in others. The the behavior has to be hardcoded into RNA, that's not great flexibility.
Custom path properties would not be addressed by this solution at all (ie still not support opening file browser with specific settings). Unless we expose this callback to RNA, which would make this (IMO) not-great solution part of the public API even.

I'm not sure what other use cases there would be for operators that manipulate properties, where this solution is better than a more dedicated solution.


Thinking more high level: Any file browser settings are UI for me, and spawning a file browser operation with all its settings should be managed by the UI. In this case we want specific settings based on a specific RNA path, so the UI should get the necessary info out of RNA and spawn a file browser with it. I agree with @Brecht Van Lommel (brecht) that the proposed solution adds too much of a cyclic dependency.

I'd also agree that it makes sense to have file type information defined in the RNA property. That seems like the solution closest to what I described above. We can start with just storing basic path/file type information. Overlap with the file browser properties is not a big deal for me, RNA contains plenty of other UI information too.

-> So I'd still favor either a UILayout.prop_filepath(), or expanding path properties with path/file information in RNA. The latter also address the uiDefAutoButsRNA() "issue" (which I'm not convinced is an issue really).

Personally I'd be fine with either:

  • Custom operators for browsing fonts, render outputs, .. along with custom UI code to use them.
  • Adding filetypes natively supported by the filebrowser to RNA.

Indeed you don't automatically get the right file browser when exposing some types of file paths, but I would rather just not try to solve that problem if we have to couple RNA properties to operators like this.

Personally I'd be fine with either:

  • Custom operators for browsing fonts, render outputs, .. along with custom UI code to use them.
  • Adding filetypes natively supported by the filebrowser to RNA.

These aren't mutually exclusive things, right? We can store some basic information like the file type in the RNA property, and for cases where that's not enough, support custom browsing operators.

None of these would be difficult to add.