UI: preset popover buttons in panel headers.
Moves the preset into a menu for the panel header, so it can be changed without opening the panel and takes up less space. Two remaining issues: * For long lists the add new preset button can be scrolled off screen. * We should support showing the name of the chosen preset in the panel header, but the current preset system does not support detecting which preset is used. Differential Revision: https://developer.blender.org/D3366
This commit is contained in:
parent
1664ccb675
commit
7a10cfe7fe
|
@ -18,6 +18,7 @@
|
|||
|
||||
import bpy
|
||||
from bpy_extras.node_utils import find_node_input, find_output_node
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from bpy.types import (
|
||||
Panel,
|
||||
|
@ -26,20 +27,20 @@ from bpy.types import (
|
|||
)
|
||||
|
||||
|
||||
class CYCLES_MT_sampling_presets(Menu):
|
||||
class CYCLES_MT_sampling_presets(PresetMenu):
|
||||
bl_label = "Sampling Presets"
|
||||
preset_subdir = "cycles/sampling"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "render.cycles_sampling_preset_add"
|
||||
COMPAT_ENGINES = {'CYCLES'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class CYCLES_MT_integrator_presets(Menu):
|
||||
class CYCLES_MT_integrator_presets(PresetMenu):
|
||||
bl_label = "Integrator Presets"
|
||||
preset_subdir = "cycles/integrator"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "render.cycles_integrator_preset_add"
|
||||
COMPAT_ENGINES = {'CYCLES'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class CyclesButtonsPanel:
|
||||
|
@ -144,6 +145,9 @@ class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
|
|||
bl_label = "Sampling"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CYCLES_MT_sampling_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = False
|
||||
|
@ -151,11 +155,6 @@ class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
|
|||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
|
||||
row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
|
||||
row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
layout.prop(cscene, "progressive")
|
||||
|
@ -315,17 +314,11 @@ class CYCLES_RENDER_PT_light_paths(CyclesButtonsPanel, Panel):
|
|||
bl_label = "Light Paths"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CYCLES_MT_integrator_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
|
||||
row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
|
||||
row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
|
||||
pass
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel):
|
||||
|
|
|
@ -31910,6 +31910,15 @@
|
|||
id="radialGradient16215"
|
||||
xlink:href="#linearGradient18134"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient27277-1-8"
|
||||
id="linearGradient18811"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="4.1933641"
|
||||
y1="199.12067"
|
||||
x2="17.16466"
|
||||
y2="211.01585" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
|
@ -92657,6 +92666,61 @@
|
|||
y="75.5" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(461.71013,377.29483)"
|
||||
style="display:inline;enable-background:new"
|
||||
id="ICON_SOLO_OFF-7">
|
||||
<rect
|
||||
y="198.9792"
|
||||
x="4.9506397"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect23018-5-4-5"
|
||||
style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(0.94058502,0,0,0.94058502,0.9128606,12.74924)"
|
||||
id="g56716-3" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(461.99301,376.87052)"
|
||||
style="display:inline;enable-background:new"
|
||||
id="ICON_SOLO_OFF-1">
|
||||
<rect
|
||||
y="198.9792"
|
||||
x="4.9506397"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect23018-5-4-2"
|
||||
style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(0.94058502,0,0,0.94058502,0.9128606,12.74924)"
|
||||
id="g56716-7">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:url(#linearGradient18811);fill-opacity:1.0;stroke:#000000;stroke-width:0.96882826;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.80000001"
|
||||
id="path15855-0"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="13.700194"
|
||||
sodipodi:cy="207.20645"
|
||||
sodipodi:r1="7.1873641"
|
||||
sodipodi:r2="3.3158474"
|
||||
sodipodi:arg1="0.94697287"
|
||||
sodipodi:arg2="1.5618338"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 17.898641,213.04008 -4.168729,-2.51791 -4.280439,2.47993 1.106473,-4.74277 -3.6812884,-3.3046 4.8525664,-0.41328 2.005278,-4.52229 1.892578,4.48735 4.920618,0.50967 -3.682889,3.18662 z"
|
||||
inkscape:transform-center-x="-0.010954063"
|
||||
inkscape:transform-center-y="-0.74285516"
|
||||
transform="matrix(1.0972098,0,0,1.0975406,-2.0923019,-19.740595)" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1.06316817;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.51147538"
|
||||
d="m 12.931855,202.51514 -1.201334,2.70994 c -0.137665,0.32193 -0.454082,0.55986 -0.800889,0.60222 l -2.9032248,0.26765 2.2358168,1.97391 c 0.261321,0.2395 0.380487,0.62447 0.300333,0.97022 l -0.667408,2.81032"
|
||||
id="path15869-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
|
|
Before Width: | Height: | Size: 4.4 MiB After Width: | Height: | Size: 4.4 MiB |
Binary file not shown.
Binary file not shown.
|
@ -856,7 +856,8 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
|
|||
|
||||
def path_menu(self, searchpaths, operator, *,
|
||||
props_default=None, prop_filepath="filepath",
|
||||
filter_ext=None, filter_path=None, display_name=None):
|
||||
filter_ext=None, filter_path=None, display_name=None,
|
||||
add_operator=None):
|
||||
"""
|
||||
Populate a menu from a list of paths.
|
||||
|
||||
|
@ -902,12 +903,16 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
|
|||
|
||||
files.sort()
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
||||
for f, filepath in files:
|
||||
# Intentionally pass the full path to 'display_name' callback,
|
||||
# since the callback may want to use part a directory in the name.
|
||||
props = layout.operator(
|
||||
row = col.row(align=True)
|
||||
name = display_name(filepath) if display_name else bpy.path.display_name(f)
|
||||
props = row.operator(
|
||||
operator,
|
||||
text=display_name(filepath) if display_name else bpy.path.display_name(f),
|
||||
text=name,
|
||||
translate=False,
|
||||
)
|
||||
|
||||
|
@ -919,6 +924,25 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
|
|||
if operator == "script.execute_preset":
|
||||
props.menu_idname = self.bl_idname
|
||||
|
||||
if add_operator:
|
||||
props = row.operator(add_operator, text="", icon='ZOOMOUT')
|
||||
props.name = name
|
||||
props.remove_name = True
|
||||
|
||||
if add_operator:
|
||||
wm = bpy.data.window_managers[0]
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
|
||||
sub = row.row()
|
||||
sub.emboss = 'NORMAL'
|
||||
sub.prop(wm, "preset_name", text="")
|
||||
|
||||
props = row.operator(add_operator, text="", icon='ZOOMIN')
|
||||
props.name = wm.preset_name
|
||||
|
||||
|
||||
def draw_preset(self, context):
|
||||
"""
|
||||
Define these on the subclass:
|
||||
|
@ -926,16 +950,19 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
|
|||
- preset_subdir (string)
|
||||
|
||||
Optionally:
|
||||
- preset_add_operator (string)
|
||||
- preset_extensions (set of strings)
|
||||
- preset_operator_defaults (dict of keyword args)
|
||||
"""
|
||||
import bpy
|
||||
ext_valid = getattr(self, "preset_extensions", {".py", ".xml"})
|
||||
props_default = getattr(self, "preset_operator_defaults", None)
|
||||
add_operator = getattr(self, "preset_add_operator", None)
|
||||
self.path_menu(bpy.utils.preset_paths(self.preset_subdir),
|
||||
self.preset_operator,
|
||||
props_default=props_default,
|
||||
filter_ext=lambda ext: ext.lower() in ext_valid)
|
||||
filter_ext=lambda ext: ext.lower() in ext_valid,
|
||||
add_operator=add_operator)
|
||||
|
||||
@classmethod
|
||||
def draw_collapsible(cls, context, layout):
|
||||
|
|
|
@ -19,9 +19,15 @@
|
|||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.types import Menu, Operator
|
||||
from bpy.types import Menu, Operator, Panel, WindowManager
|
||||
from bpy.props import StringProperty, BoolProperty
|
||||
|
||||
# For preset popover menu
|
||||
WindowManager.preset_name = StringProperty(
|
||||
name="Preset Name",
|
||||
description="Name for new preset",
|
||||
default="New Preset"
|
||||
)
|
||||
|
||||
class AddPresetBase:
|
||||
"""Base preset class, only for subclassing
|
||||
|
@ -40,6 +46,10 @@ class AddPresetBase:
|
|||
maxlen=64,
|
||||
options={'SKIP_SAVE'},
|
||||
)
|
||||
remove_name = BoolProperty(
|
||||
default=False,
|
||||
options={'HIDDEN', 'SKIP_SAVE'},
|
||||
)
|
||||
remove_active = BoolProperty(
|
||||
default=False,
|
||||
options={'HIDDEN', 'SKIP_SAVE'},
|
||||
|
@ -48,6 +58,7 @@ class AddPresetBase:
|
|||
# needed for mix-ins
|
||||
order = [
|
||||
"name",
|
||||
"remove_name",
|
||||
"remove_active",
|
||||
]
|
||||
|
||||
|
@ -85,11 +96,17 @@ class AddPresetBase:
|
|||
else:
|
||||
ext = ".py"
|
||||
|
||||
if not self.remove_active:
|
||||
name = self.name.strip()
|
||||
name = self.name.strip()
|
||||
if not (self.remove_name or self.remove_active):
|
||||
|
||||
if not name:
|
||||
return {'FINISHED'}
|
||||
|
||||
# Reset preset name
|
||||
wm = bpy.data.window_managers[0]
|
||||
if name == wm.preset_name:
|
||||
wm.preset_name = 'New Preset'
|
||||
|
||||
filename = self.as_filename(name)
|
||||
|
||||
target_path = os.path.join("presets", self.preset_subdir)
|
||||
|
@ -155,15 +172,16 @@ class AddPresetBase:
|
|||
preset_menu_class.bl_label = bpy.path.display_name(filename)
|
||||
|
||||
else:
|
||||
preset_active = preset_menu_class.bl_label
|
||||
if self.remove_active:
|
||||
name = preset_menu_class.bl_label
|
||||
|
||||
# fairly sloppy but convenient.
|
||||
filepath = bpy.utils.preset_find(preset_active,
|
||||
filepath = bpy.utils.preset_find(name,
|
||||
self.preset_subdir,
|
||||
ext=ext)
|
||||
|
||||
if not filepath:
|
||||
filepath = bpy.utils.preset_find(preset_active,
|
||||
filepath = bpy.utils.preset_find(name,
|
||||
self.preset_subdir,
|
||||
display_name=True,
|
||||
ext=ext)
|
||||
|
@ -194,7 +212,7 @@ class AddPresetBase:
|
|||
self.name = self.as_filename(self.name.strip())
|
||||
|
||||
def invoke(self, context, event):
|
||||
if not self.remove_active:
|
||||
if not (self.remove_active or self.remove_name):
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
else:
|
||||
|
@ -241,6 +259,40 @@ class ExecutePreset(Operator):
|
|||
return {'FINISHED'}
|
||||
|
||||
|
||||
class PresetMenu(Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'HEADER'
|
||||
bl_label = "Presets"
|
||||
path_menu = Menu.path_menu
|
||||
|
||||
@classmethod
|
||||
def draw_panel_header(cls, layout):
|
||||
layout.emboss = 'NONE'
|
||||
layout.popover(cls.bl_space_type,
|
||||
cls.bl_region_type,
|
||||
cls.__name__,
|
||||
icon='PRESET',
|
||||
text='')
|
||||
|
||||
@classmethod
|
||||
def draw_menu(cls, layout, text=None):
|
||||
if text == None:
|
||||
text = cls.bl_label
|
||||
|
||||
layout.popover(cls.bl_space_type,
|
||||
cls.bl_region_type,
|
||||
cls.__name__,
|
||||
icon='PRESET',
|
||||
text=text)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.emboss = 'PULLDOWN_MENU'
|
||||
layout.operator_context = 'EXEC_DEFAULT'
|
||||
|
||||
Menu.draw_preset(self, context)
|
||||
|
||||
|
||||
class AddPresetRender(AddPresetBase, Operator):
|
||||
"""Add or remove a Render Preset"""
|
||||
bl_idname = "render.preset_add"
|
||||
|
@ -385,35 +437,6 @@ class AddPresetHairDynamics(AddPresetBase, Operator):
|
|||
]
|
||||
|
||||
|
||||
class AddPresetSunSky(AddPresetBase, Operator):
|
||||
"""Add or remove a Sky & Atmosphere Preset"""
|
||||
bl_idname = "lamp.sunsky_preset_add"
|
||||
bl_label = "Add Sunsky Preset"
|
||||
preset_menu = "LAMP_MT_sunsky_presets"
|
||||
|
||||
preset_defines = [
|
||||
"sky = bpy.context.lamp.sky"
|
||||
]
|
||||
|
||||
preset_values = [
|
||||
"sky.atmosphere_extinction",
|
||||
"sky.atmosphere_inscattering",
|
||||
"sky.atmosphere_turbidity",
|
||||
"sky.backscattered_light",
|
||||
"sky.horizon_brightness",
|
||||
"sky.spread",
|
||||
"sky.sun_brightness",
|
||||
"sky.sun_intensity",
|
||||
"sky.sun_size",
|
||||
"sky.sky_blend",
|
||||
"sky.sky_blend_type",
|
||||
"sky.sky_color_space",
|
||||
"sky.sky_exposure",
|
||||
]
|
||||
|
||||
preset_subdir = "sunsky"
|
||||
|
||||
|
||||
class AddPresetInteraction(AddPresetBase, Operator):
|
||||
"""Add or remove an Application Interaction Preset"""
|
||||
bl_idname = "wm.interaction_preset_add"
|
||||
|
@ -665,7 +688,6 @@ classes = (
|
|||
AddPresetOperator,
|
||||
AddPresetRender,
|
||||
AddPresetSafeAreas,
|
||||
AddPresetSunSky,
|
||||
AddPresetTrackingCamera,
|
||||
AddPresetTrackingSettings,
|
||||
AddPresetTrackingTrackColor,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
import bpy
|
||||
from bpy.types import Panel, Menu
|
||||
from rna_prop_ui import PropertyPanel
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
|
||||
class CameraButtonsPanel:
|
||||
|
@ -33,20 +34,20 @@ class CameraButtonsPanel:
|
|||
return context.camera and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
|
||||
class CAMERA_MT_presets(Menu):
|
||||
class CAMERA_MT_presets(PresetMenu):
|
||||
bl_label = "Camera Presets"
|
||||
preset_subdir = "camera"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "camera.preset_add"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class SAFE_AREAS_MT_presets(Menu):
|
||||
class SAFE_AREAS_MT_presets(PresetMenu):
|
||||
bl_label = "Camera Presets"
|
||||
preset_subdir = "safe_areas"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "safe_areas.preset_add"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
|
||||
|
@ -185,17 +186,14 @@ class DATA_PT_camera(CameraButtonsPanel, Panel):
|
|||
bl_label = "Camera"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CAMERA_MT_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
cam = context.camera
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
row.menu("CAMERA_MT_presets", text=bpy.types.CAMERA_MT_presets.bl_label)
|
||||
row.operator("camera.preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("camera.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
|
@ -410,6 +408,9 @@ class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
|
|||
|
||||
self.layout.prop(cam, "show_safe_areas", text="")
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
SAFE_AREAS_MT_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
safe_data = context.scene.safe_areas
|
||||
|
@ -430,13 +431,6 @@ def draw_display_safe_settings(layout, safe_data, settings):
|
|||
|
||||
layout.use_property_split = True
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("SAFE_AREAS_MT_presets", text=bpy.types.SAFE_AREAS_MT_presets.bl_label)
|
||||
row.operator("safe_areas.preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("safe_areas.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
layout.separator()
|
||||
|
||||
col = layout.column()
|
||||
col.active = show_safe_areas
|
||||
|
||||
|
|
|
@ -22,14 +22,6 @@ from bpy.types import Menu, Panel
|
|||
from rna_prop_ui import PropertyPanel
|
||||
|
||||
|
||||
class LAMP_MT_sunsky_presets(Menu):
|
||||
bl_label = "Sun & Sky Presets"
|
||||
preset_subdir = "sunsky"
|
||||
preset_operator = "script.execute_preset"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class DataButtonsPanel:
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
|
@ -352,7 +344,6 @@ class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, Panel):
|
|||
|
||||
|
||||
classes = (
|
||||
LAMP_MT_sunsky_presets,
|
||||
DATA_PT_context_lamp,
|
||||
DATA_PT_preview,
|
||||
DATA_PT_lamp,
|
||||
|
|
|
@ -21,6 +21,7 @@ import bpy
|
|||
from bpy.types import Panel, Menu
|
||||
from rna_prop_ui import PropertyPanel
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from .properties_physics_common import (
|
||||
point_cache_ui,
|
||||
|
@ -82,12 +83,12 @@ class PARTICLE_MT_specials(Menu):
|
|||
layout.operator("particle.duplicate_particle_system")
|
||||
|
||||
|
||||
class PARTICLE_MT_hair_dynamics_presets(Menu):
|
||||
class PARTICLE_MT_hair_dynamics_presets(PresetMenu):
|
||||
bl_label = "Hair Dynamics Presets"
|
||||
preset_subdir = "hair_dynamics"
|
||||
preset_operator = "script.execute_preset"
|
||||
preset_add_operator = "particle.hair_dynamics_preset_add"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class ParticleButtonsPanel:
|
||||
|
@ -340,6 +341,16 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
|
|||
psys = context.particle_system
|
||||
self.layout.prop(psys, "use_hair_dynamics", text="")
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
psys = context.particle_system
|
||||
|
||||
if not psys.cloth:
|
||||
return
|
||||
|
||||
layout = self.layout
|
||||
layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
|
||||
PARTICLE_MT_hair_dynamics_presets.draw_panel_header(layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
@ -355,11 +366,6 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
|
|||
|
||||
layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("PARTICLE_MT_hair_dynamics_presets", text=bpy.types.PARTICLE_MT_hair_dynamics_presets.bl_label)
|
||||
row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Menu, Panel
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from .properties_physics_common import (
|
||||
point_cache_ui,
|
||||
|
@ -30,11 +31,11 @@ def cloth_panel_enabled(md):
|
|||
return md.point_cache.is_baked is False
|
||||
|
||||
|
||||
class CLOTH_MT_presets(Menu):
|
||||
class CLOTH_MT_presets(PresetMenu):
|
||||
bl_label = "Cloth Presets"
|
||||
preset_subdir = "cloth"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "cloth.preset_add"
|
||||
|
||||
|
||||
class PhysicButtonsPanel:
|
||||
|
@ -52,6 +53,9 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
|
|||
bl_label = "Cloth"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CLOTH_MT_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
|
@ -63,16 +67,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
|
|||
|
||||
split = layout.split(percentage=0.25)
|
||||
|
||||
col = split.column()
|
||||
|
||||
split.label(text="Presets:")
|
||||
sub = split.row(align=True)
|
||||
sub.menu("CLOTH_MT_presets", text=bpy.types.CLOTH_MT_presets.bl_label)
|
||||
sub.operator("cloth.preset_add", text="", icon='ZOOMIN')
|
||||
sub.operator("cloth.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
split = layout.split(percentage=0.25)
|
||||
|
||||
split.label(text="Quality:")
|
||||
split.prop(cloth, "quality", text="Steps")
|
||||
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
import bpy
|
||||
from bpy.types import Panel, Menu
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
|
||||
class FLUID_MT_presets(Menu):
|
||||
class FLUID_MT_presets(PresetMenu):
|
||||
bl_label = "Fluid Presets"
|
||||
preset_subdir = "fluid"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "fluid.preset_add"
|
||||
|
||||
|
||||
class PhysicButtonsPanel:
|
||||
|
@ -240,11 +241,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
|
|||
col.prop(fluid, "simulation_scale", text="Meters")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Viscosity Presets:")
|
||||
sub = col.row(align=True)
|
||||
sub.menu("FLUID_MT_presets", text=bpy.types.FLUID_MT_presets.bl_label)
|
||||
sub.operator("fluid.preset_add", text="", icon='ZOOMIN')
|
||||
sub.operator("fluid.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
FLUID_MT_presets.draw_menu(col, text="Viscosity Presets")
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.prop(fluid, "viscosity_base", text="Base")
|
||||
|
|
|
@ -20,20 +20,20 @@
|
|||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
|
||||
class RENDER_MT_presets(Menu):
|
||||
class RENDER_MT_presets(PresetMenu):
|
||||
bl_label = "Render Presets"
|
||||
preset_subdir = "render"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "render.preset_add"
|
||||
|
||||
|
||||
class RENDER_MT_ffmpeg_presets(Menu):
|
||||
class RENDER_MT_ffmpeg_presets(PresetMenu):
|
||||
bl_label = "FFMPEG Presets"
|
||||
preset_subdir = "ffmpeg"
|
||||
preset_operator = "script.python_file_run"
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class RENDER_MT_framerate_presets(Menu):
|
||||
|
@ -83,6 +83,9 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
|
|||
_frame_rate_args_prev = None
|
||||
_preset_class = None
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
RENDER_MT_presets.draw_panel_header(self.layout)
|
||||
|
||||
@staticmethod
|
||||
def _draw_framerate_label(*args):
|
||||
# avoids re-creating text string each draw
|
||||
|
@ -131,11 +134,6 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
|
|||
scene = context.scene
|
||||
rd = scene.render
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("RENDER_MT_presets", text=bpy.types.RENDER_MT_presets.bl_label)
|
||||
row.operator("render.preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("render.preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(rd, "resolution_x", text="Resolution X")
|
||||
col.prop(rd, "resolution_y", text="Y")
|
||||
|
@ -297,6 +295,9 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
|
|||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
RENDER_MT_ffmpeg_presets.draw_panel_header(self.layout)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
rd = context.scene.render
|
||||
|
@ -308,8 +309,6 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
|
|||
rd = context.scene.render
|
||||
ffmpeg = rd.ffmpeg
|
||||
|
||||
layout.menu("RENDER_MT_ffmpeg_presets", text="Presets")
|
||||
|
||||
split = layout.split()
|
||||
split.prop(rd.ffmpeg, "format")
|
||||
split.prop(ffmpeg, "use_autosplit")
|
||||
|
|
|
@ -25,6 +25,7 @@ from bpy.types import (
|
|||
)
|
||||
|
||||
from rna_prop_ui import PropertyPanel
|
||||
from bl_operators.presets import PresetMenu
|
||||
|
||||
from .properties_physics_common import (
|
||||
point_cache_ui,
|
||||
|
@ -32,12 +33,12 @@ from .properties_physics_common import (
|
|||
)
|
||||
|
||||
|
||||
class SCENE_MT_units_length_presets(Menu):
|
||||
class SCENE_MT_units_length_presets(PresetMenu):
|
||||
"""Unit of measure for properties that use length values"""
|
||||
bl_label = "Unit Presets"
|
||||
preset_subdir = "units_length"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "scene.units_length_preset_add"
|
||||
|
||||
|
||||
class SCENE_UL_keying_set_paths(UIList):
|
||||
|
@ -81,16 +82,14 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
|
|||
bl_label = "Units"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
SCENE_MT_units_length_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
unit = context.scene.unit_settings
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.menu("SCENE_MT_units_length_presets", text=SCENE_MT_units_length_presets.bl_label)
|
||||
row.operator("scene.units_length_preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("scene.units_length_preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import bpy
|
||||
from bpy.types import Panel, Header, Menu, UIList
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
|
@ -277,6 +278,9 @@ class CLIP_PT_tracking_settings(CLIP_PT_tracking_panel, Panel):
|
|||
bl_label = "Tracking Settings"
|
||||
bl_category = "Track"
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CLIP_MT_tracking_settings_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
sc = context.space_data
|
||||
|
@ -285,14 +289,6 @@ class CLIP_PT_tracking_settings(CLIP_PT_tracking_panel, Panel):
|
|||
layout = self.layout
|
||||
col = layout.column()
|
||||
|
||||
row = col.row(align=True)
|
||||
label = CLIP_MT_tracking_settings_presets.bl_label
|
||||
row.menu('CLIP_MT_tracking_settings_presets', text=label)
|
||||
row.operator("clip.tracking_settings_preset_add",
|
||||
text="", icon='ZOOMIN')
|
||||
row.operator("clip.tracking_settings_preset_add",
|
||||
text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
row = col.row(align=True)
|
||||
row.prop(settings, "use_default_red_channel",
|
||||
text="R", toggle=True)
|
||||
|
@ -625,12 +621,8 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
|
|||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
label = bpy.types.CLIP_MT_track_color_presets.bl_label
|
||||
row.menu('CLIP_MT_track_color_presets', text=label)
|
||||
CLIP_MT_track_color_presets.draw_menu(row, 'Color Presets')
|
||||
row.menu('CLIP_MT_track_color_specials', text="", icon='DOWNARROW_HLT')
|
||||
row.operator("clip.track_color_preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("clip.track_color_preset_add",
|
||||
text="", icon='ZOOMOUT').remove_active = True
|
||||
|
||||
row = layout.row()
|
||||
row.prop(act_track, "use_custom_color")
|
||||
|
@ -720,19 +712,15 @@ class CLIP_PT_tracking_camera(Panel):
|
|||
|
||||
return False
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
CLIP_MT_camera_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
sc = context.space_data
|
||||
clip = sc.clip
|
||||
|
||||
row = layout.row(align=True)
|
||||
label = bpy.types.CLIP_MT_camera_presets.bl_label
|
||||
row.menu('CLIP_MT_camera_presets', text=label)
|
||||
row.operator("clip.camera_preset_add", text="", icon='ZOOMIN')
|
||||
row.operator("clip.camera_preset_add", text="",
|
||||
icon='ZOOMOUT').remove_active = True
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Sensor:")
|
||||
col.prop(clip.tracking.camera, "sensor_width", text="Width")
|
||||
|
@ -1431,28 +1419,28 @@ class CLIP_MT_tracking_specials(Menu):
|
|||
text="Unlock Tracks").action = 'UNLOCK'
|
||||
|
||||
|
||||
class CLIP_MT_camera_presets(Menu):
|
||||
class CLIP_MT_camera_presets(PresetMenu):
|
||||
"""Predefined tracking camera intrinsics"""
|
||||
bl_label = "Camera Presets"
|
||||
preset_subdir = "tracking_camera"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "clip.camera_preset_add"
|
||||
|
||||
|
||||
class CLIP_MT_track_color_presets(Menu):
|
||||
class CLIP_MT_track_color_presets(PresetMenu):
|
||||
"""Predefined track color"""
|
||||
bl_label = "Color Presets"
|
||||
preset_subdir = "tracking_track_color"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "clip.track_color_preset_add"
|
||||
|
||||
|
||||
class CLIP_MT_tracking_settings_presets(Menu):
|
||||
class CLIP_MT_tracking_settings_presets(PresetMenu):
|
||||
"""Predefined tracking settings"""
|
||||
bl_label = "Tracking Presets"
|
||||
preset_subdir = "tracking_settings"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "clip.tracking_settings_preset_add"
|
||||
|
||||
|
||||
class CLIP_MT_track_color_specials(Menu):
|
||||
|
|
|
@ -21,6 +21,7 @@ import bpy
|
|||
import nodeitems_utils
|
||||
from bpy.types import Header, Menu, Panel
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bl_operators.presets import PresetMenu
|
||||
from .properties_grease_pencil_common import (
|
||||
GreasePencilDrawingToolsPanel,
|
||||
GreasePencilStrokeEditPanel,
|
||||
|
@ -289,12 +290,12 @@ class NODE_MT_node(Menu):
|
|||
layout.operator("node.read_fullsamplelayers")
|
||||
|
||||
|
||||
class NODE_MT_node_color_presets(Menu):
|
||||
class NODE_MT_node_color_presets(PresetMenu):
|
||||
"""Predefined node color"""
|
||||
bl_label = "Color Presets"
|
||||
preset_subdir = "node_color"
|
||||
preset_operator = "script.execute_preset"
|
||||
draw = Menu.draw_preset
|
||||
preset_add_operator = "node.node_color_preset_add"
|
||||
|
||||
|
||||
class NODE_MT_node_color_specials(Menu):
|
||||
|
@ -373,6 +374,9 @@ class NODE_PT_active_node_color(Panel):
|
|||
node = context.active_node
|
||||
self.layout.prop(node, "use_custom_color", text="")
|
||||
|
||||
def draw_header_preset(self, context):
|
||||
NODE_MT_node_color_presets.draw_panel_header(self.layout)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
node = context.active_node
|
||||
|
@ -380,13 +384,8 @@ class NODE_PT_active_node_color(Panel):
|
|||
layout.enabled = node.use_custom_color
|
||||
|
||||
row = layout.row()
|
||||
col = row.column()
|
||||
col.menu("NODE_MT_node_color_presets")
|
||||
col.prop(node, "color", text="")
|
||||
col = row.column(align=True)
|
||||
col.operator("node.node_color_preset_add", text="", icon='ZOOMIN').remove_active = False
|
||||
col.operator("node.node_color_preset_add", text="", icon='ZOOMOUT').remove_active = True
|
||||
col.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
|
||||
row.prop(node, "color", text="")
|
||||
row.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
|
||||
|
||||
|
||||
class NODE_PT_active_node_properties(Panel):
|
||||
|
|
|
@ -216,6 +216,8 @@ typedef struct PanelType {
|
|||
int (*poll)(const struct bContext *C, struct PanelType *pt);
|
||||
/* draw header (optional) */
|
||||
void (*draw_header)(const struct bContext *C, struct Panel *pa);
|
||||
/* draw header preset (optional) */
|
||||
void (*draw_header_preset)(const struct bContext *C, struct Panel *pa);
|
||||
/* draw entirely, view changes should be handled here */
|
||||
void (*draw)(const struct bContext *C, struct Panel *pa);
|
||||
|
||||
|
|
|
@ -113,9 +113,7 @@ DEF_ICON(FILE_TICK)
|
|||
DEF_ICON(QUIT)
|
||||
DEF_ICON(URL)
|
||||
DEF_ICON(RECOVER_LAST)
|
||||
#ifndef DEF_ICON_BLANK_SKIP
|
||||
DEF_ICON(BLANK038)
|
||||
#endif
|
||||
DEF_ICON(PRESET)
|
||||
DEF_ICON(FULLSCREEN_ENTER)
|
||||
DEF_ICON(FULLSCREEN_EXIT)
|
||||
DEF_ICON(BLANK1) // Not actually blank - this is used all over the place
|
||||
|
|
|
@ -168,11 +168,17 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
|
|||
block->my = handle->prev_my;
|
||||
}
|
||||
|
||||
/* Prefer popover from header to be positioned into the editor. */
|
||||
if (!slideout) {
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
|
||||
if (ar && ar->panels.first) {
|
||||
/* For regions with panels, prefer to open to top so we can
|
||||
* see the values of the buttons below changing. */
|
||||
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
|
||||
}
|
||||
else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
|
||||
/* Prefer popover from header to be positioned into the editor. */
|
||||
if (ar && ar->regiontype == RGN_TYPE_HEADER) {
|
||||
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
|
||||
}
|
||||
|
|
|
@ -1861,6 +1861,21 @@ static void ed_panel_draw(const bContext *C,
|
|||
/* bad fixed values */
|
||||
int xco, yco, h = 0;
|
||||
|
||||
if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
|
||||
/* for preset menu */
|
||||
panel->layout = UI_block_layout(
|
||||
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
|
||||
0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
|
||||
|
||||
pt->draw_header_preset(C, panel);
|
||||
|
||||
int headerend = w - UI_UNIT_X;
|
||||
|
||||
UI_block_layout_resolve(block, &xco, &yco);
|
||||
UI_block_translate(block, headerend - xco, 0);
|
||||
panel->layout = NULL;
|
||||
}
|
||||
|
||||
if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
|
||||
int labelx, labely;
|
||||
UI_panel_label_offset(block, &labelx, &labely);
|
||||
|
|
|
@ -166,6 +166,24 @@ static void panel_draw_header(const bContext *C, Panel *pnl)
|
|||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static void panel_draw_header_preset(const bContext *C, Panel *pnl)
|
||||
{
|
||||
extern FunctionRNA rna_Panel_draw_header_preset_func;
|
||||
|
||||
PointerRNA ptr;
|
||||
ParameterList list;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->ext.srna, pnl, &ptr);
|
||||
func = &rna_Panel_draw_header_preset_func;
|
||||
|
||||
RNA_parameter_list_create(&list, &ptr, func);
|
||||
RNA_parameter_set_lookup(&list, "context", &C);
|
||||
pnl->type->ext.call((bContext *)C, &ptr, func, &list);
|
||||
|
||||
RNA_parameter_list_free(&list);
|
||||
}
|
||||
|
||||
static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
|
||||
{
|
||||
ARegionType *art;
|
||||
|
@ -199,7 +217,7 @@ static StructRNA *rna_Panel_register(
|
|||
PanelType *pt, *parent = NULL, dummypt = {NULL};
|
||||
Panel dummypanel = {NULL};
|
||||
PointerRNA dummyptr;
|
||||
int have_function[3];
|
||||
int have_function[4];
|
||||
|
||||
/* setup dummy panel & panel type to store static properties in */
|
||||
dummypanel.type = &dummypt;
|
||||
|
@ -267,6 +285,7 @@ static StructRNA *rna_Panel_register(
|
|||
pt->poll = (have_function[0]) ? panel_poll : NULL;
|
||||
pt->draw = (have_function[1]) ? panel_draw : NULL;
|
||||
pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
|
||||
pt->draw_header_preset = (have_function[3]) ? panel_draw_header_preset : NULL;
|
||||
|
||||
/* XXX use "no header" flag for some ordering of panels until we have real panel ordering */
|
||||
if (pt->flag & PNL_NO_HEADER) {
|
||||
|
@ -1058,6 +1077,12 @@ static void rna_def_panel(BlenderRNA *brna)
|
|||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "draw_header_preset", NULL);
|
||||
RNA_def_function_ui_description(func, "Draw UI elements for presets in the panel's header");
|
||||
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
|
||||
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "UILayout");
|
||||
RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI");
|
||||
|
|
Loading…
Reference in New Issue