Implement a native method to swap between different node and zone types. This implementation repurposes the existing menu definitions as base classes, from which both an "Add" and a "Swap" version would be generated from. This allows both menus to have the same layout, but use their own operators for handling the different node/zone types. In this PR, support for all node editors has been implemented. Invoking the menu is currently bound to `Shift + S`, same as the old implementation in Node Wrangler. Since "Swap" is implemented as a regular menu, features that menus already have such as type-to-search and adding to Quick Favorites don't require any extra caveats to consider. Resolves #133452 Pull Request: https://projects.blender.org/blender/blender/pulls/143997
1001 lines
35 KiB
C++
1001 lines
35 KiB
C++
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
#include <optional>
|
|
|
|
#include "BLI_math_vector_types.hh"
|
|
#include "BLI_string_ref.hh"
|
|
#include "BLI_utility_mixins.hh"
|
|
#include "BLI_vector.hh"
|
|
|
|
#include "UI_interface_icons.hh" /* `eAlertIcon` */
|
|
#include "UI_interface_types.hh"
|
|
|
|
struct bContext;
|
|
struct bContextStore;
|
|
struct EnumPropertyItem;
|
|
struct IDProperty;
|
|
struct uiBlock;
|
|
struct uiBut;
|
|
struct uiLayoutRoot;
|
|
struct uiList;
|
|
struct uiStyle;
|
|
struct MenuType;
|
|
struct PanelType;
|
|
struct Panel;
|
|
struct PointerRNA;
|
|
struct PropertyRNA;
|
|
struct StructRNA;
|
|
struct wmOperatorType;
|
|
|
|
/* Layout
|
|
*
|
|
* More automated layout of buttons. Has three levels:
|
|
* - Layout: contains a number templates, within a bounded width or height.
|
|
* - Template: predefined layouts for buttons with a number of slots, each
|
|
* slot can contain multiple items.
|
|
* - Item: item to put in a template slot, being either an RNA property,
|
|
* operator, label or menu. Also regular buttons can be used when setting
|
|
* uiBlockCurLayout. */
|
|
|
|
namespace blender::ui {
|
|
enum class ItemType : int8_t;
|
|
enum class ItemInternalFlag : uint8_t;
|
|
enum class EmbossType : uint8_t;
|
|
enum class LayoutAlign : int8_t;
|
|
enum class ButProgressType : int8_t;
|
|
enum class LayoutDirection : int8_t;
|
|
|
|
struct ItemInternal;
|
|
struct LayoutInternal;
|
|
} // namespace blender::ui
|
|
|
|
namespace blender::wm {
|
|
enum class OpCallContext : int8_t;
|
|
}
|
|
|
|
struct PanelLayout {
|
|
uiLayout *header;
|
|
uiLayout *body;
|
|
};
|
|
|
|
struct uiItem {
|
|
|
|
uiItem(blender::ui::ItemType type);
|
|
uiItem(const uiItem &) = default;
|
|
virtual ~uiItem() = default;
|
|
|
|
[[nodiscard]] bool fixed_size() const;
|
|
void fixed_size_set(bool fixed_size);
|
|
|
|
[[nodiscard]] blender::ui::ItemType type() const;
|
|
|
|
protected:
|
|
blender::ui::ItemInternalFlag flag_ = {};
|
|
blender::ui::ItemType type_ = {};
|
|
|
|
friend struct blender::ui::ItemInternal;
|
|
};
|
|
|
|
enum eUI_Item_Flag : uint16_t;
|
|
|
|
enum class LayoutSeparatorType : int8_t {
|
|
Auto,
|
|
Space,
|
|
Line,
|
|
};
|
|
|
|
enum class NodeAssetMenuOperatorType : int8_t {
|
|
Add,
|
|
Swap,
|
|
};
|
|
|
|
/**
|
|
* NOTE: `uiLayout` properties should be considered private outside `interface_layout.cc`,
|
|
* incoming refactors would remove public access and add public read/write function methods.
|
|
* Meanwhile keep using `uiLayout*` functions to read/write this properties.
|
|
*/
|
|
struct uiLayout : public uiItem, blender::NonCopyable, blender::NonMovable {
|
|
// protected:
|
|
|
|
int x_ = 0, y_ = 0, w_ = 0, h_ = 0;
|
|
short space_ = 0;
|
|
|
|
protected:
|
|
uiLayoutRoot *root_ = nullptr;
|
|
bContextStore *context_ = nullptr;
|
|
uiLayout *parent_ = nullptr;
|
|
std::string heading_;
|
|
|
|
blender::Vector<uiItem *> items_;
|
|
|
|
/** Sub layout to add child items, if not the layout itself. */
|
|
uiLayout *child_items_layout_ = nullptr;
|
|
|
|
float scale_[2] = {0.0f, 0.0f};
|
|
bool align_ = false;
|
|
bool active_ = false;
|
|
bool active_default_ = false;
|
|
bool activate_init_ = false;
|
|
bool enabled_ = false;
|
|
bool redalert_ = false;
|
|
/** For layouts inside grid-flow, they and their items shall never have a fixed maximal size. */
|
|
bool variable_size_ = false;
|
|
blender::ui::LayoutAlign alignment_ = {};
|
|
blender::ui::EmbossType emboss_ = {};
|
|
/** for fixed width or height to avoid UI size changes */
|
|
float units_[2] = {0.0f, 0.0f};
|
|
/** Is copied to uiButs created in this layout. */
|
|
float search_weight_ = 0.0f;
|
|
|
|
public:
|
|
uiLayout(blender::ui::ItemType type, uiLayoutRoot *root);
|
|
|
|
[[nodiscard]] bool active() const;
|
|
/**
|
|
* Sets the active state of the layout and its items.
|
|
* When false the layout and its buttons are grayed out, user can still interact with them but
|
|
* generally they will not have an active use.
|
|
*/
|
|
void active_set(bool active);
|
|
|
|
[[nodiscard]] bool active_default() const;
|
|
/**
|
|
* When set to true the next operator button added in the layout will be highlighted as default
|
|
* action when pressing return, in popup dialogs this overrides default confirmation buttons.
|
|
*/
|
|
void active_default_set(bool active_default);
|
|
|
|
[[nodiscard]] bool activate_init() const;
|
|
/**
|
|
* When set to true, the next button added in the layout will be activated on first display.
|
|
* Only for popups dialogs and only the first button in the popup with this flag will be
|
|
* activated.
|
|
*/
|
|
void activate_init_set(bool activate_init);
|
|
|
|
[[nodiscard]] blender::ui::LayoutAlign alignment() const;
|
|
void alignment_set(blender::ui::LayoutAlign alignment);
|
|
|
|
[[nodiscard]] uiBlock *block() const;
|
|
|
|
void context_copy(const bContextStore *context);
|
|
|
|
[[nodiscard]] const PointerRNA *context_ptr_get(const blender::StringRef name,
|
|
const StructRNA *type) const;
|
|
void context_ptr_set(blender::StringRef name, const PointerRNA *ptr);
|
|
|
|
[[nodiscard]] std::optional<blender::StringRefNull> context_string_get(
|
|
const blender::StringRef name) const;
|
|
void context_string_set(blender::StringRef name, blender::StringRef value);
|
|
|
|
[[nodiscard]] std::optional<int64_t> context_int_get(const blender::StringRef name) const;
|
|
void context_int_set(blender::StringRef name, int64_t value);
|
|
|
|
/** Only for convenience. */
|
|
void context_set_from_but(const uiBut *but);
|
|
|
|
[[nodiscard]] bContextStore *context_store() const;
|
|
|
|
[[nodiscard]] bool enabled() const;
|
|
/**
|
|
* Sets the enabled state of the layout and its items.
|
|
* When false the layout and its buttons are grayed out, user can't interaction with them, only
|
|
* buttons tooltips are available on hovering.
|
|
*/
|
|
void enabled_set(bool enabled);
|
|
|
|
[[nodiscard]] blender::ui::EmbossType emboss() const;
|
|
void emboss_set(blender::ui::EmbossType emboss);
|
|
|
|
[[nodiscard]] blender::ui::LayoutDirection local_direction() const;
|
|
|
|
[[nodiscard]] blender::wm::OpCallContext operator_context() const;
|
|
/** Sets the default call context for new operator buttons added in any #root_ sub-layout. */
|
|
void operator_context_set(blender::wm::OpCallContext opcontext);
|
|
|
|
[[nodiscard]] bool red_alert() const;
|
|
/**
|
|
* When set to true new items added in the layout are highlighted with the error state
|
|
* color #TH_REDALERT.
|
|
*/
|
|
void red_alert_set(bool red_alert);
|
|
|
|
[[nodiscard]] Panel *root_panel() const;
|
|
|
|
[[nodiscard]] float scale_x() const;
|
|
void scale_x_set(float scale);
|
|
|
|
[[nodiscard]] float scale_y() const;
|
|
void scale_y_set(float scale);
|
|
|
|
[[nodiscard]] float search_weight() const;
|
|
void search_weight_set(float weight);
|
|
|
|
[[nodiscard]] float ui_units_x() const;
|
|
/** Sets a fixed width size for this layout. */
|
|
void ui_units_x_set(float width);
|
|
|
|
[[nodiscard]] float ui_units_y() const;
|
|
/** Sets a fixed height size for this layout. */
|
|
void ui_units_y_set(float height);
|
|
|
|
[[nodiscard]] bool use_property_split() const;
|
|
/**
|
|
* Sets when to split property's label into a separate button when adding new property buttons.
|
|
*/
|
|
void use_property_split_set(bool value);
|
|
|
|
[[nodiscard]] bool use_property_decorate() const;
|
|
/**
|
|
* Sets when to add an extra button to insert keyframes next to new property buttons added in the
|
|
* layout.
|
|
*/
|
|
void use_property_decorate_set(bool is_sep);
|
|
|
|
[[nodiscard]] int width() const;
|
|
|
|
/** Sub-layout items. */
|
|
|
|
uiLayout &absolute(bool align);
|
|
uiBlock *absolute_block();
|
|
|
|
/**
|
|
* Add a new box sub-layout, items placed in this sub-layout are added vertically one under
|
|
* each other in a column and are surrounded by a box.
|
|
*/
|
|
uiLayout &box();
|
|
/**
|
|
* Add a new column sub-layout, items placed in this sub-layout are added vertically one under
|
|
* each other in a column.
|
|
*/
|
|
uiLayout &column(bool align);
|
|
/**
|
|
* Add a new column sub-layout, items placed in this sub-layout are added vertically one under
|
|
* each other in a column.
|
|
* \param heading: Heading label to set to the first child element added in the sub-layout
|
|
* through #uiLayout::prop. When property split is used, this heading label is set in the split
|
|
* label column when there is no label defined.
|
|
*/
|
|
uiLayout &column(bool align, blender::StringRef heading);
|
|
|
|
/**
|
|
* Add a new row sub-layout, items placed in this sub-layout are added horizontally next to each
|
|
* other in row.
|
|
*/
|
|
uiLayout &row(bool align);
|
|
/**
|
|
* Add a new row sub-layout, items placed in this sub-layout are added horizontally next to each
|
|
* other in row.
|
|
* \param heading: Heading label to set to the first child element added in the sub-layout
|
|
* through #uiLayout::prop. When property split is used, this heading label is set in the split
|
|
* label column when there is no label defined.
|
|
*/
|
|
uiLayout &row(bool align, blender::StringRef heading);
|
|
|
|
/**
|
|
* Add a new column flow sub-layout, items placed in this sub-layout would be evenly distributed
|
|
* in columns.
|
|
* \param number: the number of columns in which items are distributed.
|
|
*/
|
|
uiLayout &column_flow(int number, bool align);
|
|
/**
|
|
* Add a new grid flow sub-layout, items placed in this sub-layout would be distributed in a
|
|
* grid.
|
|
* \param row_major: When true items are distributed by rows, otherwise items are distributed by
|
|
* columns.
|
|
* \param columns_len: When positive is the fixed number of columns to show, when 0 its automatic
|
|
* defined, when negative its an automatic stepped number of columns/rows to show (e.g. when \a
|
|
* row_major is true -3 will automatically show (1,2,3,6,9,...) columns, or when \a row_major is
|
|
* false -3 will automatically show (3,6,9,...) rows).
|
|
* \param even_columns: All columns will have the same width.
|
|
* \param even_rows: All rows will have the same height.
|
|
*/
|
|
uiLayout &grid_flow(
|
|
bool row_major, int columns_len, bool even_columns, bool even_rows, bool align);
|
|
|
|
/** Add a new list box sub-layout. */
|
|
uiLayout &list_box(uiList *ui_list, PointerRNA *actptr, PropertyRNA *actprop);
|
|
|
|
/**
|
|
* Add a pie menu layout, buttons are arranged around a center.
|
|
* Only one pie menu per layout root can be added, if it's already initialized it will be
|
|
* returned instead of adding a new one.
|
|
*/
|
|
uiLayout &menu_pie();
|
|
|
|
/** Add a new overlap sub-layout. */
|
|
uiLayout &overlap();
|
|
|
|
/**
|
|
* Create a "layout panel" which is a panel that is defined as part of the `uiLayout`. This
|
|
* allows creating expandable sections which can also be nested.
|
|
*
|
|
* The open-state of the panel is defined by an RNA property which is passed in as a pointer +
|
|
* property name pair. This gives the caller flexibility to decide who should own the open-state.
|
|
*
|
|
* \param C: The context is necessary because sometimes the panel may be forced to be open by the
|
|
* context even of the open-property is `false`. This can happen with e.g. property search.
|
|
* \param layout: The `uiLayout` that should contain the sub-panel.
|
|
* Only layouts that span the full width of the region are supported for now.
|
|
* \param open_prop_owner: Data that contains the open-property.
|
|
* \param open_prop_name: Name of the open-property in `open_prop_owner`.
|
|
*
|
|
* \return A #PanelLayout containing layouts for both the header row and the panel body. If the
|
|
* panel is closed and should not be drawn, the body layout will be NULL.
|
|
*/
|
|
PanelLayout panel_prop(const bContext *C,
|
|
PointerRNA *open_prop_owner,
|
|
blender::StringRefNull open_prop_name);
|
|
/**
|
|
* Variant of #panel_prop that automatically creates the header row with the
|
|
* given label and only returns the body layout.
|
|
*
|
|
* \param label: Text that's shown in the panel header. It should already be translated.
|
|
*
|
|
* \return NULL if the panel is closed and should not be drawn, otherwise the layout where the
|
|
* sub-panel should be inserted into.
|
|
*/
|
|
uiLayout *panel_prop(const bContext *C,
|
|
PointerRNA *open_prop_owner,
|
|
blender::StringRefNull open_prop_name,
|
|
blender::StringRef label);
|
|
PanelLayout panel_prop_with_bool_header(const bContext *C,
|
|
PointerRNA *open_prop_owner,
|
|
blender::StringRefNull open_prop_name,
|
|
PointerRNA *bool_prop_owner,
|
|
blender::StringRefNull bool_prop_name,
|
|
std::optional<blender::StringRef> label);
|
|
/**
|
|
* Variant of #panel_prop that automatically stores the open-close-state in the root
|
|
* panel. When a dynamic number of panels is required, it's recommended to use #panel_prop
|
|
* instead of passing in generated id names.
|
|
*
|
|
* \param idname: String that identifies the open-close-state in the root panel.
|
|
*/
|
|
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed);
|
|
|
|
/**
|
|
* Variant of #panel that automatically creates the header row with the given label and
|
|
* only returns the body layout.
|
|
*
|
|
* \param label: Text that's shown in the panel header. It should already be translated.
|
|
*
|
|
* \return NULL if the panel is closed and should not be drawn, otherwise the layout where the
|
|
* sub-panel should be inserted into.
|
|
*/
|
|
uiLayout *panel(const bContext *C,
|
|
blender::StringRef idname,
|
|
bool default_closed,
|
|
blender::StringRef label);
|
|
|
|
/**
|
|
* Add a new split sub-layout, items placed in this sub-layout are added horizontally next to
|
|
* each other in row, but width is splitted between the first item and remaining items.
|
|
* \param percentage: Width percent to split.
|
|
*/
|
|
uiLayout &split(float percentage, bool align);
|
|
|
|
/** Items. */
|
|
|
|
/**
|
|
* Insert a decorator item for a button with the same property as \a prop.
|
|
* To force inserting a blank dummy element, nullptr can be passed for \a or and \a prop.
|
|
*/
|
|
void decorator(PointerRNA *ptr, PropertyRNA *prop, int index);
|
|
/**
|
|
* Insert a decorator item for a button with the same property as \a prop.
|
|
* To force inserting a blank dummy element, nullptr can be passed for \a ptr or `std::nullopt`
|
|
* for \a propname.
|
|
*/
|
|
void decorator(PointerRNA *ptr, std::optional<blender::StringRefNull> propname, int index);
|
|
|
|
/** Adds a label item that will display text and/or icon in the layout. */
|
|
void label(blender::StringRef name, int icon);
|
|
|
|
/**
|
|
* Adds a menu item, which is a button that when active will display a menu.
|
|
* If menu fails to poll with `WM_menutype_poll` it will not be added into the layout.
|
|
*/
|
|
void menu(MenuType *mt, std::optional<blender::StringRef> name, int icon);
|
|
/**
|
|
* Adds a menu item, which is a button that when active will display a menu.
|
|
* If menu fails to poll with `WM_menutype_poll` it will not be added into the layout.
|
|
*/
|
|
void menu(blender::StringRef menuname, std::optional<blender::StringRef> name, int icon);
|
|
|
|
/** Adds the menu content into this layout. */
|
|
void menu_contents(blender::StringRef menuname);
|
|
|
|
/**
|
|
* Adds a menu item, which is a button that when active will display a menu.
|
|
* \param name: Label to show in the menu button.
|
|
* \param func: Function that generates the menu layout.
|
|
* \param arg: Pointer to data used as last argument in \a func.
|
|
*/
|
|
void menu_fn(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *arg);
|
|
/**
|
|
* Adds a menu item, which is a button that when active will display a menu.
|
|
* \param name: Label to show in the menu button.
|
|
* \param func: Function that generates the menu layout.
|
|
* \param argN: Pointer to data used as last argument in \a func, it will be
|
|
* freed with the menu button.
|
|
*/
|
|
void menu_fn_argN_free(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *argN);
|
|
/**
|
|
* Adds a operator item, places a button in the layout to call the operator.
|
|
* \param ot: Operator to add.
|
|
* \param name: Text to show in the layout.
|
|
* \param context: Operator call context for #WM_operator_name_call.
|
|
* \returns Operator pointer to write properties.
|
|
*/
|
|
PointerRNA op(wmOperatorType *ot,
|
|
std::optional<blender::StringRef> name,
|
|
int icon,
|
|
blender::wm::OpCallContext context,
|
|
eUI_Item_Flag flag);
|
|
|
|
/**
|
|
* Adds a operator item, places a button in the layout to call the operator.
|
|
* \param ot: Operator to add.
|
|
* \param name: Text to show in the layout.
|
|
* \returns Operator pointer to write properties.
|
|
*/
|
|
PointerRNA op(wmOperatorType *ot, std::optional<blender::StringRef> name, int icon);
|
|
|
|
/**
|
|
* Adds a operator item, places a button in the layout to call the operator.
|
|
* \param opname: Operator id name.
|
|
* \param name: Text to show in the layout.
|
|
* \returns Operator pointer to write properties, might be #PointerRNA_NULL if operator does not
|
|
* exists.
|
|
*/
|
|
PointerRNA op(blender::StringRefNull opname, std::optional<blender::StringRef> name, int icon);
|
|
|
|
/**
|
|
* Adds a operator item, places a button in the layout to call the operator.
|
|
* \param opname: Operator id name.
|
|
* \param name: Text to show in the layout.
|
|
* \param context: Operator call context for #WM_operator_name_call.
|
|
* \returns Operator pointer to write properties, might be #PointerRNA_NULL if operator does not
|
|
* exists.
|
|
*/
|
|
PointerRNA op(blender::StringRefNull opname,
|
|
std::optional<blender::StringRef> name,
|
|
int icon,
|
|
blender::wm::OpCallContext context,
|
|
eUI_Item_Flag flag);
|
|
/**
|
|
* Expands and sets each enum property value as an operator button.
|
|
* \param propname: Name of the operator's enum property.
|
|
* \param properties: Extra operator properties values to set.
|
|
* \param active: an optional item to highlight.
|
|
*/
|
|
void op_enum(blender::StringRefNull opname,
|
|
blender::StringRefNull propname,
|
|
IDProperty *properties,
|
|
blender::wm::OpCallContext context,
|
|
eUI_Item_Flag flag,
|
|
const int active = -1);
|
|
|
|
/**
|
|
* Expands and sets each enum property value as an operator button.
|
|
* \param propname: Name of the operator's enum property.
|
|
*/
|
|
void op_enum(blender::StringRefNull opname, blender::StringRefNull propname);
|
|
/**
|
|
* Expands and sets each enum property value as an operator button.
|
|
* \param prop: Operator's enum property.
|
|
* \param properties: Extra operator properties values to set.
|
|
* \param item_array: Precalculated item array, could be a subset of the enum property values.
|
|
* \param active: an optional item to highlight.
|
|
*/
|
|
void op_enum_items(wmOperatorType *ot,
|
|
const PointerRNA &ptr,
|
|
PropertyRNA *prop,
|
|
IDProperty *properties,
|
|
blender::wm::OpCallContext context,
|
|
eUI_Item_Flag flag,
|
|
const EnumPropertyItem *item_array,
|
|
int totitem,
|
|
int active = -1);
|
|
|
|
/**
|
|
* Adds a #op_enum menu.
|
|
* \returns Operator pointer to write extra properties to set when menu buttons are
|
|
* displayed, might be #PointerRNA_NULL if operator does not exist.
|
|
*/
|
|
PointerRNA op_menu_enum(const bContext *C,
|
|
wmOperatorType *ot,
|
|
blender::StringRefNull propname,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
/**
|
|
* Adds a #op_enum menu.
|
|
* \returns Operator pointer to write extra properties to set when menu buttons are
|
|
* displayed, might be #PointerRNA_NULL if operator does not exist.
|
|
*/
|
|
PointerRNA op_menu_enum(const bContext *C,
|
|
blender::StringRefNull opname,
|
|
blender::StringRefNull propname,
|
|
blender::StringRefNull name,
|
|
int icon);
|
|
/**
|
|
* Adds a operator item, places a button in the layout to call the operator, if the button is
|
|
* held down, a menu will be displayed instead.
|
|
* \param ot: Operator to add.
|
|
* \param name: Text to show in the layout.
|
|
* \param context: Operator call context for #WM_operator_name_call.
|
|
* \param menu_id: menu to show on held down.
|
|
* \returns Operator pointer to write properties, might be #PointerRNA_NULL if operator does not
|
|
* exists.
|
|
*/
|
|
PointerRNA op_menu_hold(wmOperatorType *ot,
|
|
std::optional<blender::StringRef> name,
|
|
int icon,
|
|
blender::wm::OpCallContext context,
|
|
eUI_Item_Flag flag,
|
|
const char *menu_id);
|
|
|
|
void progress_indicator(const char *text,
|
|
float factor,
|
|
blender::ui::ButProgressType progress_type);
|
|
|
|
/**
|
|
* Adds a RNA property item, and exposes it into the layout.
|
|
* \param ptr: RNA pointer to the struct owner of \a prop.
|
|
* \param prop: The property in \a ptr to add.
|
|
* \param index: When \a prop is a array property, indicates what entry to expose through the
|
|
* layout, #RNA_NO_INDEX (-1) means all.
|
|
*/
|
|
void prop(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
int index,
|
|
int value,
|
|
eUI_Item_Flag flag,
|
|
std::optional<blender::StringRef> name_opt,
|
|
int icon,
|
|
std::optional<blender::StringRef> placeholder = std::nullopt);
|
|
/** Adds a RNA property item, and exposes it into the layout. */
|
|
void prop(PointerRNA *ptr,
|
|
blender::StringRefNull propname,
|
|
eUI_Item_Flag flag,
|
|
std::optional<blender::StringRef> name,
|
|
int icon);
|
|
|
|
void popover(const bContext *C,
|
|
PanelType *pt,
|
|
std::optional<blender::StringRef> name_opt,
|
|
int icon);
|
|
void popover(const bContext *C,
|
|
blender::StringRef panel_type,
|
|
std::optional<blender::StringRef> name_opt,
|
|
int icon);
|
|
void popover_group(
|
|
bContext *C, int space_id, int region_id, const char *context, const char *category);
|
|
|
|
/**
|
|
* Add a enum property value item. This button acts like a radio button that are used to chose
|
|
* a single enum value from a set of the enum property value items.
|
|
*/
|
|
void prop_enum(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
int value,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
/**
|
|
* Add a enum property value item. This button acts like a radio button that are used to chose
|
|
* a single enum value from a set of the enum property value items.
|
|
*/
|
|
void prop_enum(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
const char *value,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
/**
|
|
* Add a enum property value item. This button acts like a radio button that are used to chose
|
|
* a single enum value from a set of the enum property value items.
|
|
*/
|
|
void prop_enum(PointerRNA *ptr,
|
|
blender::StringRefNull propname,
|
|
const char *value,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
|
|
/** Add a enum property item, and exposes its value throw a radio button menu. */
|
|
void prop_menu_enum(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
|
|
/** Expands enum property value items as tabs buttons. */
|
|
void prop_tabs_enum(bContext *C,
|
|
PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
PointerRNA *ptr_highlight,
|
|
PropertyRNA *prop_highlight,
|
|
bool icon_only);
|
|
|
|
/** Expands enum property value items as radio buttons. */
|
|
void props_enum(PointerRNA *ptr, blender::StringRefNull propname);
|
|
|
|
/**
|
|
* Adds a RNA enum/pointer/string/ property item, and exposes it into the layout. Button input
|
|
* would suggest values from the search property collection.
|
|
* \param searchprop: Collection property in \a searchptr from where to take input values.
|
|
* \param results_are_suggestions: Allow inputs that not match any suggested value.
|
|
*/
|
|
void prop_search(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
PointerRNA *searchptr,
|
|
PropertyRNA *searchprop,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon,
|
|
bool results_are_suggestions);
|
|
/**
|
|
* Adds a RNA enum/pointer/string/ property item, and exposes it into the layout. Button input
|
|
* would suggest values from the search property collection, input must match a suggested value.
|
|
* \param searchprop: Collection property in \a searchptr from where to take input values.
|
|
*/
|
|
void prop_search(PointerRNA *ptr,
|
|
blender::StringRefNull propname,
|
|
PointerRNA *searchptr,
|
|
blender::StringRefNull searchpropname,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon);
|
|
|
|
/**
|
|
* Adds a RNA property item, and sets a custom popover to expose its value.
|
|
*/
|
|
void prop_with_popover(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
int index,
|
|
int value,
|
|
eUI_Item_Flag flag,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon,
|
|
const char *panel_type);
|
|
|
|
/**
|
|
* Adds a RNA property item, and sets a custom menu to expose its value.
|
|
*/
|
|
void prop_with_menu(PointerRNA *ptr,
|
|
PropertyRNA *prop,
|
|
int index,
|
|
int value,
|
|
eUI_Item_Flag flag,
|
|
std::optional<blender::StringRefNull> name,
|
|
int icon,
|
|
const char *menu_type);
|
|
|
|
/** Simple button executing \a func on click. */
|
|
uiBut *button(blender::StringRef name,
|
|
int icon,
|
|
std::function<void(bContext &)> func,
|
|
std::optional<blender::StringRef> tooltip = std::nullopt);
|
|
|
|
/** Adds a separator item, that adds empty space between items. */
|
|
void separator(float factor = 1.0f, LayoutSeparatorType type = LayoutSeparatorType::Auto);
|
|
|
|
/** Adds a spacer item that inserts empty horizontal space between other items in the layout. */
|
|
void separator_spacer();
|
|
|
|
friend struct blender::ui::LayoutInternal;
|
|
|
|
[[nodiscard]] uiLayoutRoot *root() const;
|
|
[[nodiscard]] const bContextStore *context() const;
|
|
[[nodiscard]] uiLayout *parent() const;
|
|
[[nodiscard]] blender::StringRef heading() const;
|
|
void heading_reset();
|
|
[[nodiscard]] blender::Span<uiItem *> items() const;
|
|
[[nodiscard]] bool align() const;
|
|
[[nodiscard]] bool variable_size() const;
|
|
[[nodiscard]] blender::ui::EmbossType emboss_or_undefined() const;
|
|
|
|
protected:
|
|
void estimate();
|
|
virtual void estimate_impl();
|
|
};
|
|
|
|
inline bool uiLayout::active() const
|
|
{
|
|
return active_;
|
|
}
|
|
inline void uiLayout::active_set(bool active)
|
|
{
|
|
active_ = active;
|
|
}
|
|
|
|
inline bool uiLayout::active_default() const
|
|
{
|
|
return active_default_;
|
|
}
|
|
inline void uiLayout::active_default_set(bool active_default)
|
|
{
|
|
active_default_ = active_default;
|
|
}
|
|
|
|
inline bool uiLayout::activate_init() const
|
|
{
|
|
return activate_init_;
|
|
}
|
|
inline void uiLayout::activate_init_set(bool activate_init)
|
|
{
|
|
activate_init_ = activate_init;
|
|
}
|
|
|
|
inline blender::ui::LayoutAlign uiLayout::alignment() const
|
|
{
|
|
return alignment_;
|
|
}
|
|
|
|
inline void uiLayout::alignment_set(blender::ui::LayoutAlign alignment)
|
|
{
|
|
alignment_ = alignment;
|
|
}
|
|
|
|
inline bContextStore *uiLayout::context_store() const
|
|
{
|
|
return context_;
|
|
}
|
|
|
|
inline bool uiLayout::enabled() const
|
|
{
|
|
return enabled_;
|
|
}
|
|
inline void uiLayout::enabled_set(bool enabled)
|
|
{
|
|
enabled_ = enabled;
|
|
}
|
|
|
|
inline bool uiLayout::red_alert() const
|
|
{
|
|
return redalert_;
|
|
}
|
|
inline void uiLayout::red_alert_set(bool red_alert)
|
|
{
|
|
redalert_ = red_alert;
|
|
}
|
|
|
|
inline float uiLayout::search_weight() const
|
|
{
|
|
return search_weight_;
|
|
}
|
|
inline void uiLayout::search_weight_set(float weight)
|
|
{
|
|
search_weight_ = weight;
|
|
}
|
|
|
|
inline float uiLayout::scale_x() const
|
|
{
|
|
return scale_[0];
|
|
};
|
|
inline void uiLayout::scale_x_set(float scale)
|
|
{
|
|
scale_[0] = scale;
|
|
};
|
|
|
|
inline float uiLayout::scale_y() const
|
|
{
|
|
return scale_[1];
|
|
};
|
|
inline void uiLayout::scale_y_set(float scale)
|
|
{
|
|
scale_[1] = scale;
|
|
};
|
|
|
|
inline float uiLayout::ui_units_x() const
|
|
{
|
|
return units_[0];
|
|
};
|
|
inline void uiLayout::ui_units_x_set(float width)
|
|
{
|
|
units_[0] = width;
|
|
};
|
|
|
|
inline float uiLayout::ui_units_y() const
|
|
{
|
|
return units_[1];
|
|
};
|
|
inline void uiLayout::ui_units_y_set(float height)
|
|
{
|
|
units_[1] = height;
|
|
};
|
|
|
|
inline int uiLayout::width() const
|
|
{
|
|
return this->w_;
|
|
}
|
|
|
|
namespace blender::ui {
|
|
enum class LayoutDirection : int8_t {
|
|
Horizontal = 0,
|
|
Vertical = 1,
|
|
};
|
|
|
|
enum class LayoutType : int8_t {
|
|
Panel = 0,
|
|
Header = 1,
|
|
Menu = 2,
|
|
Toolbar = 3,
|
|
PieMenu = 4,
|
|
VerticalBar = 5,
|
|
};
|
|
|
|
enum class LayoutAlign : int8_t {
|
|
Expand = 0,
|
|
Left = 1,
|
|
Center = 2,
|
|
Right = 3,
|
|
};
|
|
enum class ButProgressType : int8_t {
|
|
Bar = 0,
|
|
Ring = 1,
|
|
};
|
|
|
|
uiLayout &block_layout(uiBlock *block,
|
|
LayoutDirection direction,
|
|
LayoutType type,
|
|
int x,
|
|
int y,
|
|
int size,
|
|
int em,
|
|
int padding,
|
|
const uiStyle *style);
|
|
int2 block_layout_resolve(uiBlock *block);
|
|
|
|
void block_layout_set_current(uiBlock *block, uiLayout *layout);
|
|
bool block_layout_needs_resolving(const uiBlock *block);
|
|
/**
|
|
* Used for property search when the layout process needs to be cancelled in order to avoid
|
|
* computing the locations for buttons, but the layout items created while adding the buttons
|
|
* must still be freed.
|
|
*/
|
|
void block_layout_free(uiBlock *block);
|
|
|
|
} // namespace blender::ui
|
|
|
|
enum eUI_Item_Flag : uint16_t {
|
|
/* UI_ITEM_O_RETURN_PROPS = 1 << 0, */ /* UNUSED */
|
|
UI_ITEM_R_EXPAND = 1 << 1,
|
|
UI_ITEM_R_SLIDER = 1 << 2,
|
|
/**
|
|
* Use for booleans, causes the button to draw with an outline (emboss),
|
|
* instead of text with a checkbox.
|
|
* This is implied when toggle buttons have an icon
|
|
* unless #UI_ITEM_R_ICON_NEVER flag is set.
|
|
*/
|
|
UI_ITEM_R_TOGGLE = 1 << 3,
|
|
/**
|
|
* Don't attempt to use an icon when the icon is set to #ICON_NONE.
|
|
*
|
|
* Use for booleans, causes the buttons to always show as a checkbox
|
|
* even when there is an icon (which would normally show the button as a toggle).
|
|
*/
|
|
UI_ITEM_R_ICON_NEVER = 1 << 4,
|
|
UI_ITEM_R_ICON_ONLY = 1 << 5,
|
|
UI_ITEM_R_EVENT = 1 << 6,
|
|
UI_ITEM_R_FULL_EVENT = 1 << 7,
|
|
UI_ITEM_R_NO_BG = 1 << 8,
|
|
UI_ITEM_R_IMMEDIATE = 1 << 9,
|
|
UI_ITEM_O_DEPRESS = 1 << 10,
|
|
UI_ITEM_R_COMPACT = 1 << 11,
|
|
UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
|
|
/** Don't add a real decorator item, just blank space. */
|
|
UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13,
|
|
/* Even create the property split layout if there's no name to show there. */
|
|
UI_ITEM_R_SPLIT_EMPTY_NAME = 1 << 14,
|
|
/**
|
|
* Only for text buttons (for now): Force the button as active in a semi-modal state (capturing
|
|
* text input while leaving the remaining UI interactive).
|
|
*/
|
|
UI_ITEM_R_TEXT_BUT_FORCE_SEMI_MODAL_ACTIVE = 1 << 15,
|
|
};
|
|
ENUM_OPERATORS(eUI_Item_Flag, UI_ITEM_R_TEXT_BUT_FORCE_SEMI_MODAL_ACTIVE)
|
|
#define UI_ITEM_NONE eUI_Item_Flag(0)
|
|
|
|
/**
|
|
* Apply property search behavior, setting panel flags and deactivating buttons that don't match.
|
|
*
|
|
* \note Must not be run after #UI_block_layout_resolve.
|
|
*/
|
|
bool UI_block_apply_search_filter(uiBlock *block, const char *search_filter);
|
|
|
|
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
|
|
|
|
/**
|
|
* Set tooltip function for all buttons in the layout.
|
|
* func, arg and free_arg are passed on to UI_but_func_tooltip_set, so their meaning is the same.
|
|
*
|
|
* \param func: The callback function that gets called to get tooltip content
|
|
* \param arg: An optional opaque pointer that gets passed to func
|
|
* \param free_arg: An optional callback for freeing arg (can be set to e.g. MEM_freeN)
|
|
* \param copy_arg: An optional callback for duplicating arg in case UI_but_func_tooltip_set
|
|
* is being called on multiple buttons (can be set to e.g. MEM_dupallocN). If set to NULL, arg will
|
|
* be passed as-is to all buttons.
|
|
*/
|
|
void uiLayoutSetTooltipFunc(uiLayout *layout,
|
|
uiButToolTipFunc func,
|
|
void *arg,
|
|
uiCopyArgFunc copy_arg,
|
|
uiFreeArgFunc free_arg);
|
|
|
|
/**
|
|
* Same as above but should be used when building a fully custom tooltip instead of just
|
|
* generating a description.
|
|
*/
|
|
void uiLayoutSetTooltipCustomFunc(uiLayout *layout,
|
|
uiButToolTipCustomFunc func,
|
|
void *arg,
|
|
uiCopyArgFunc copy_arg,
|
|
uiFreeArgFunc free_arg);
|
|
|
|
void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout);
|
|
|
|
/**
|
|
* Used for popup panels only.
|
|
*/
|
|
void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout);
|
|
|
|
int uiLayoutListItemPaddingWidth();
|
|
void uiLayoutListItemAddPadding(uiLayout *layout);
|
|
|
|
/* Layout create functions. */
|
|
|
|
bool uiLayoutEndsWithPanelHeader(const uiLayout &layout);
|
|
|
|
struct uiPropertySplitWrapper {
|
|
uiLayout *label_column;
|
|
uiLayout *property_row;
|
|
/**
|
|
* Column for decorators. Note that this may be null, see #uiItemPropertySplitWrapperCreate().
|
|
*/
|
|
uiLayout *decorate_column;
|
|
};
|
|
|
|
/**
|
|
* Normally, we handle the split layout in #uiLayout::prop(), but there are other cases where the
|
|
* logic is needed. Ideally, #uiLayout::prop() could just call this, but it currently has too many
|
|
* special needs.
|
|
*
|
|
* The returned #uiPropertySplitWrapper.decorator_column may be null when decorators are disabled
|
|
* (#uiLayoutGetPropDecorate() returns false).
|
|
*/
|
|
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout);
|
|
|
|
uiBut *uiItemL_ex(
|
|
uiLayout *layout, blender::StringRef name, int icon, bool highlight, bool redalert);
|
|
/**
|
|
* Helper to add a label using a property split layout if needed. After calling this the
|
|
* active layout will be the one to place the labeled items in. An additional layout may be
|
|
* returned to place decorator buttons in.
|
|
*
|
|
* \return the layout to place decorators in, if #UI_ITEM_PROP_SEP is enabled. Otherwise null.
|
|
*/
|
|
uiLayout *uiItemL_respect_property_split(uiLayout *layout, blender::StringRef text, int icon);
|
|
/**
|
|
* Label icon for dragging.
|
|
*/
|
|
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, blender::StringRef name, int icon);
|
|
|
|
/* Only for testing, inspecting layouts. */
|
|
/**
|
|
* Evaluate layout items as a Python dictionary.
|
|
*/
|
|
const char *UI_layout_introspect(uiLayout *layout);
|
|
|
|
/**
|
|
* Helpers to add a big icon and create a split layout for alert popups.
|
|
* Returns the layout to place further items into the alert box.
|
|
*/
|
|
uiLayout *uiItemsAlertBox(uiBlock *block,
|
|
const uiStyle *style,
|
|
const int dialog_width,
|
|
const eAlertIcon icon,
|
|
const int icon_size);
|
|
uiLayout *uiItemsAlertBox(uiBlock *block, const int size, const eAlertIcon icon);
|