Add Chromium-only Blender WebEngine parity work
This commit is contained in:
275
blender-5.2.0/scripts/modules/rna_prop_ui.py
Normal file
275
blender-5.2.0/scripts/modules/rna_prop_ui.py
Normal file
@@ -0,0 +1,275 @@
|
||||
# SPDX-FileCopyrightText: 2009-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
|
||||
from mathutils import Vector
|
||||
from bpy.types import bpy_prop_array
|
||||
from idprop.types import IDPropertyArray, IDPropertyGroup
|
||||
|
||||
ARRAY_TYPES = (list, tuple, IDPropertyArray, Vector, bpy_prop_array)
|
||||
|
||||
# Maximum length of an array property for which a multi-line
|
||||
# edit field will be displayed in the Custom Properties panel.
|
||||
MAX_DISPLAY_ROWS = 8
|
||||
|
||||
|
||||
def rna_idprop_quote_path(prop):
|
||||
return "[\"{:s}\"]".format(bpy.utils.escape_identifier(prop))
|
||||
|
||||
|
||||
def rna_idprop_ui_prop_update(item, prop):
|
||||
prop_path = rna_idprop_quote_path(prop)
|
||||
prop_rna = item.path_resolve(prop_path, False)
|
||||
if isinstance(prop_rna, bpy.types.bpy_prop):
|
||||
prop_rna.update()
|
||||
|
||||
|
||||
def rna_idprop_ui_prop_clear(item, prop):
|
||||
ui_data = item.id_properties_ui(prop)
|
||||
ui_data.clear()
|
||||
|
||||
|
||||
def rna_idprop_context_value(context, context_member, property_type):
|
||||
space = context.space_data
|
||||
|
||||
if space is None or isinstance(space, bpy.types.SpaceProperties):
|
||||
pin_id = space.pin_id
|
||||
else:
|
||||
pin_id = None
|
||||
|
||||
if pin_id and isinstance(pin_id, property_type):
|
||||
rna_item = pin_id
|
||||
context_member = "space_data.pin_id"
|
||||
else:
|
||||
rna_item = context.path_resolve(context_member)
|
||||
|
||||
return rna_item, context_member
|
||||
|
||||
|
||||
def rna_idprop_has_properties(rna_item):
|
||||
keys = rna_item.keys()
|
||||
return bool(keys)
|
||||
|
||||
|
||||
def rna_idprop_value_to_python(value):
|
||||
if isinstance(value, IDPropertyArray):
|
||||
return value.to_list()
|
||||
elif isinstance(value, IDPropertyGroup):
|
||||
return value.to_dict()
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def rna_idprop_value_item_type(value):
|
||||
is_array = isinstance(value, ARRAY_TYPES) and len(value) > 0
|
||||
item_value = value[0] if is_array else value
|
||||
return type(item_value), is_array
|
||||
|
||||
|
||||
def rna_idprop_ui_prop_default_set(item, prop, value):
|
||||
# NOTE: the internal check to know if a property supports UI is not exposed.
|
||||
# Use an exception here and assert this isn't catching unrelated errors.
|
||||
try:
|
||||
ui_data = item.id_properties_ui(prop)
|
||||
except TypeError as ex:
|
||||
assert ex.args and ("does not support UI data" in ex.args[0])
|
||||
return
|
||||
ui_data.update(default=value)
|
||||
|
||||
|
||||
def rna_idprop_ui_create(
|
||||
item, prop, *, default,
|
||||
min=0, max=1,
|
||||
soft_min=None, soft_max=None,
|
||||
description=None,
|
||||
overridable=False,
|
||||
subtype=None,
|
||||
step=None,
|
||||
precision=None,
|
||||
id_type='OBJECT',
|
||||
items=None,
|
||||
):
|
||||
"""Create and initialize a custom property with limits, defaults and other settings."""
|
||||
|
||||
# Assign the value
|
||||
item[prop] = default
|
||||
|
||||
rna_idprop_ui_prop_update(item, prop)
|
||||
ui_data = item.id_properties_ui(prop)
|
||||
proptype, _ = rna_idprop_value_item_type(default)
|
||||
|
||||
if soft_min is None:
|
||||
soft_min = min
|
||||
if soft_max is None:
|
||||
soft_max = max
|
||||
|
||||
if (proptype is bool) or (proptype is str):
|
||||
ui_data.update(
|
||||
description=description,
|
||||
default=default,
|
||||
)
|
||||
elif proptype is type(None) or issubclass(proptype, bpy.types.ID):
|
||||
ui_data.update(
|
||||
description=description,
|
||||
id_type=id_type,
|
||||
)
|
||||
elif proptype is float:
|
||||
if step is None:
|
||||
step = 0.1
|
||||
if precision is None:
|
||||
precision = 3
|
||||
|
||||
ui_data.update(
|
||||
subtype=subtype,
|
||||
min=min,
|
||||
max=max,
|
||||
soft_min=soft_min,
|
||||
soft_max=soft_max,
|
||||
step=step,
|
||||
precision=precision,
|
||||
description=description,
|
||||
default=default,
|
||||
)
|
||||
elif proptype is int:
|
||||
if step is None:
|
||||
step = 1
|
||||
|
||||
if items is None:
|
||||
ui_data.update(
|
||||
subtype=subtype,
|
||||
min=min,
|
||||
max=max,
|
||||
soft_min=soft_min,
|
||||
soft_max=soft_max,
|
||||
step=step,
|
||||
description=description,
|
||||
default=default,
|
||||
)
|
||||
else:
|
||||
ui_data.update(
|
||||
subtype=subtype,
|
||||
description=description,
|
||||
default=default,
|
||||
items=items,
|
||||
)
|
||||
else:
|
||||
raise TypeError("Unexpected value type")
|
||||
|
||||
prop_path = rna_idprop_quote_path(prop)
|
||||
|
||||
item.property_overridable_library_set(prop_path, overridable)
|
||||
|
||||
|
||||
def draw(layout, context, context_member, property_type, *, use_edit=True):
|
||||
rna_item, context_member = rna_idprop_context_value(context, context_member, property_type)
|
||||
# poll should really get this...
|
||||
if not rna_item:
|
||||
return
|
||||
|
||||
if rna_item.id_data.library is not None:
|
||||
use_edit = False
|
||||
is_lib_override = rna_item.id_data.override_library and rna_item.id_data.override_library.reference
|
||||
|
||||
assert isinstance(rna_item, property_type)
|
||||
|
||||
items = list(rna_item.items())
|
||||
items.sort()
|
||||
|
||||
# TODO: Allow/support adding new custom props to overrides.
|
||||
if use_edit and not is_lib_override:
|
||||
row = layout.row()
|
||||
props = row.operator("wm.properties_add", text="New", icon='ADD')
|
||||
props.data_path = context_member
|
||||
del row
|
||||
layout.separator()
|
||||
|
||||
show_developer_ui = context.preferences.view.show_developer_ui
|
||||
rna_properties = {prop.identifier for prop in rna_item.bl_rna.properties if prop.is_runtime} if items else None
|
||||
|
||||
layout.use_property_decorate = False
|
||||
|
||||
for key, value in items:
|
||||
is_rna = (key in rna_properties)
|
||||
|
||||
# Only show API defined properties to developers.
|
||||
if is_rna and not show_developer_ui:
|
||||
continue
|
||||
|
||||
to_dict = getattr(value, "to_dict", None)
|
||||
to_list = getattr(value, "to_list", None)
|
||||
is_datablock = value is None or isinstance(value, bpy.types.ID)
|
||||
|
||||
if to_dict:
|
||||
value = to_dict()
|
||||
elif to_list:
|
||||
value = to_list()
|
||||
|
||||
split = layout.split(factor=0.4, align=True)
|
||||
label_row = split.row()
|
||||
label_row.alignment = 'RIGHT'
|
||||
label_row.label(text=key, translate=False)
|
||||
|
||||
value_row = split.row(align=True)
|
||||
value_column = value_row.column(align=True)
|
||||
|
||||
is_long_array = to_list and len(value) >= MAX_DISPLAY_ROWS
|
||||
|
||||
if is_rna:
|
||||
value_column.prop(rna_item, key, text="")
|
||||
elif to_dict or is_long_array:
|
||||
props = value_column.operator("wm.properties_edit_value", text="Edit Value")
|
||||
props.data_path = context_member
|
||||
props.property_name = key
|
||||
elif is_datablock:
|
||||
value_column.template_ID(rna_item, rna_idprop_quote_path(key), text="")
|
||||
else:
|
||||
value_column.prop(rna_item, rna_idprop_quote_path(key), text="")
|
||||
|
||||
operator_row = value_row.row(align=True)
|
||||
operator_row.alignment = 'RIGHT'
|
||||
|
||||
# Do not allow editing of overridden properties (we cannot use a poll function
|
||||
# of the operators here since they have no access to the specific property).
|
||||
operator_row.enabled = not (is_lib_override and key in rna_item.id_data.override_library.reference)
|
||||
|
||||
if use_edit:
|
||||
if is_rna:
|
||||
operator_row.label(text="API Defined")
|
||||
elif is_lib_override:
|
||||
operator_row.active = False
|
||||
operator_row.label(text="", icon='DECORATE_LIBRARY_OVERRIDE')
|
||||
else:
|
||||
props = operator_row.operator("wm.properties_edit", text="", icon='PREFERENCES', emboss=False)
|
||||
props.data_path = context_member
|
||||
props.property_name = key
|
||||
props = operator_row.operator("wm.properties_remove", text="", icon='X', emboss=False)
|
||||
props.data_path = context_member
|
||||
props.property_name = key
|
||||
|
||||
|
||||
class PropertyPanel:
|
||||
"""
|
||||
The subclass should have its own poll function
|
||||
and the variable '_context_path' MUST be set.
|
||||
"""
|
||||
bl_label = "Custom Properties"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_order = 1000 # Order panel after all others
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
rna_item, _context_member = rna_idprop_context_value(context, cls._context_path, cls._property_type)
|
||||
return bool(rna_item)
|
||||
|
||||
"""
|
||||
def draw_header(self, context):
|
||||
rna_item, context_member = rna_idprop_context_value(context, self._context_path, self._property_type)
|
||||
tot = len(rna_item.keys())
|
||||
if tot:
|
||||
self.layout().label(text="{:d}:".format(tot))
|
||||
"""
|
||||
|
||||
def draw(self, context):
|
||||
draw(self.layout, context, self._context_path, self._property_type)
|
||||
Reference in New Issue
Block a user