(On Hold) Rework Properties UI Editor #159

Open
Demeter Dzadik wants to merge 10 commits from new-props-ux into master

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 108 additions and 49 deletions
Showing only changes of commit e322ab8588 - Show all commits

View File

@ -1522,11 +1522,13 @@ class CloudRig_UIElement(PropertyGroup):
# Supported Types: Label, Row, Property(bool), Operator # Supported Types: Label, Row, Property(bool), Operator
name="Icon", name="Icon",
description="Icon", description="Icon",
default='CHECKBOX_HLT',
) )
icon_false: StringProperty( icon_false: StringProperty(
# Supported Types: Property(bool) # Supported Types: Property(bool)
name="Icon False", name="Icon False",
description="Icon to display when this boolean property is False", description="Icon to display when this boolean property is False",
default='CHECKBOX_DEHLT',
) )
prop_owner_path: StringProperty( prop_owner_path: StringProperty(
@ -1546,7 +1548,7 @@ class CloudRig_UIElement(PropertyGroup):
def update_prop_name(self, context): def update_prop_name(self, context):
if self.is_custom_prop: if self.is_custom_prop:
self.display_name = self.prop_name.replace("_", " ").title() self.display_name = self.prop_name.replace("_", " ").title()
elif self.prop_name == 'is_visible': elif self.prop_name == 'is_visible' and self.prop_owner:
self.display_name = self.prop_owner.name self.display_name = self.prop_owner.name
prop_name: StringProperty( prop_name: StringProperty(
@ -1668,16 +1670,17 @@ class CloudRig_UIElement(PropertyGroup):
# Property is a Datablock Pointer. # Property is a Datablock Pointer.
layout.prop(self.prop_owner, bracketed_prop_name, text=display_name) layout.prop(self.prop_owner, bracketed_prop_name, text=display_name)
elif value_type in {int, float, bool}: elif value_type in {int, float, bool}:
texts = [t.strip() for t in self.texts.split(",")]
if ( if (
self.texts texts
and not is_array and not is_array
and len(self.texts) - 1 >= int(prop_value) >= 0 and len(texts) - 1 >= int(prop_value) >= 0
): ):
text = self.texts[int(prop_value)].strip() text = texts[int(prop_value)]
if text: if text:
display_name += ": " + text display_name += ": " + text
if value_type == bool: if value_type == bool:
icon = self.icon if prop_value else self.icon_flase icon = self.icon if prop_value else self.icon_false
layout.prop( layout.prop(
self.prop_owner, self.prop_owner,
bracketed_prop_name, bracketed_prop_name,
@ -1743,7 +1746,7 @@ class CLOUDRIG_PT_custom_ui(CLOUDRIG_PT_base):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.use_property_split = True layout.use_property_split = False
layout.use_property_decorate = False layout.use_property_decorate = False
layout = layout.column(align=True) layout = layout.column(align=True)

View File

@ -10,14 +10,25 @@ from bpy.props import (
PointerProperty, PointerProperty,
) )
from rna_prop_ui import rna_idprop_value_item_type from rna_prop_ui import rna_idprop_value_item_type
import bpy import bpy, json
def draw_ui_editing(context, layout, ui_element, operator): def draw_ui_editing(context, layout, ui_element, operator):
rig = find_cloudrig(context)
layout.prop(operator, 'element_type', expand=True) layout.prop(operator, 'element_type', expand=True)
draw_parent_picking(context, layout, ui_element, operator)
if operator.element_type == 'PROPERTY':
draw_prop_editing(context, layout, ui_element, operator)
if operator.element_type == 'OPERATOR':
draw_op_editing(context, layout, ui_element, operator)
# debug
# layout.prop(ui_element, 'prop_owner_path')
# layout.prop(ui_element, 'is_custom_prop')
def draw_parent_picking(context, layout, ui_element, operator):
parent_row = layout.row() parent_row = layout.row()
if operator.create_new_ui: if operator.create_new_ui:
parent_row.prop(operator, 'new_panel_name') parent_row.prop(operator, 'new_panel_name')
@ -30,12 +41,14 @@ def draw_ui_editing(context, layout, ui_element, operator):
if context.scene.cloudrig_ui_parent_selector: if context.scene.cloudrig_ui_parent_selector:
parent_row.prop(operator, 'create_new_ui', text="", icon='ADD') parent_row.prop(operator, 'create_new_ui', text="", icon='ADD')
if operator.element_type == 'PROPERTY': def draw_prop_editing(context, layout, ui_element, operator):
layout.prop(operator, 'prop_owner_type', expand=True) rig = find_cloudrig(context)
owner_row = layout.row()
if operator.prop_owner_type == 'BONE': if operator.prop_owner_type == 'BONE':
layout.prop_search(operator, 'prop_bone', rig.pose, 'bones') owner_row.prop_search(operator, 'prop_bone', rig.pose, 'bones')
elif operator.prop_owner_type == 'COLLECTION': elif operator.prop_owner_type == 'COLLECTION':
layout.prop_search( owner_row.prop_search(
operator, operator,
'prop_coll', 'prop_coll',
rig.data, rig.data,
@ -43,7 +56,15 @@ def draw_ui_editing(context, layout, ui_element, operator):
icon='OUTLINER_COLLECTION', icon='OUTLINER_COLLECTION',
) )
elif operator.prop_owner_type == 'DATA_PATH': elif operator.prop_owner_type == 'DATA_PATH':
layout.prop(operator, 'prop_data_path', icon='RNA') owner_row.prop(operator, 'prop_data_path', icon='RNA')
owner_row.prop(operator, 'prop_owner_type', expand=True, text="")
if not ui_element.prop_owner:
return
if operator.prop_owner_type == 'COLLECTION' and not operator.prop_coll:
return
if operator.prop_owner_type == 'BONE' and not operator.prop_bone:
return
if context.scene.cloudrig_ui_prop_selector: if context.scene.cloudrig_ui_prop_selector:
layout.prop_search( layout.prop_search(
@ -52,14 +73,27 @@ def draw_ui_editing(context, layout, ui_element, operator):
else: else:
layout.prop(ui_element, 'prop_name') layout.prop(ui_element, 'prop_name')
if operator.element_type == 'OPERATOR': if not ui_element.prop_name:
draw_op_editing(context, layout, ui_element, operator) return
layout.prop(ui_element, 'display_name') layout.prop(ui_element, 'display_name')
# debug value_type, is_array = rna_idprop_value_item_type(ui_element.prop_value)
# layout.prop(ui_element, 'prop_owner_path') if not is_array:
# layout.prop(ui_element, 'is_custom_prop') if value_type in {bool, int}:
layout.prop(ui_element, 'texts')
if value_type == bool:
icons = UILayout.bl_rna.functions["prop"].parameters["icon"]
layout.prop_search(
ui_element, 'icon', icons, 'enum_items', icon=ui_element.icon
)
layout.prop_search(
ui_element,
'icon_false',
icons,
'enum_items',
icon=ui_element.icon_false,
)
def draw_op_editing(context, layout, ui_element, operator): def draw_op_editing(context, layout, ui_element, operator):
@ -85,6 +119,8 @@ def draw_op_editing(context, layout, ui_element, operator):
ui_element, 'icon', icons, 'enum_items', icon=ui_element.icon ui_element, 'icon', icons, 'enum_items', icon=ui_element.icon
) )
layout.prop(ui_element, 'display_name')
def update_parent_selector(context): def update_parent_selector(context):
context.scene.cloudrig_ui_parent_selector.clear() context.scene.cloudrig_ui_parent_selector.clear()
@ -139,20 +175,31 @@ class UIElementAddMixin:
self.parent_element self.parent_element
].index ].index
parent_element: StringProperty(name="Parent Element", update=update_parent_element) parent_element: StringProperty(
name="Parent Element",
description="Optional. UI element that this new one should be a part of",
update=update_parent_element,
)
def update_prop_bone(self, context): def update_prop_bone(self, context):
ui_element = get_new_ui_element(context) ui_element = get_new_ui_element(context)
if self.prop_bone:
ui_element.prop_owner_path = f'pose.bones["{self.prop_bone}"]' ui_element.prop_owner_path = f'pose.bones["{self.prop_bone}"]'
update_property_selector(self, context) update_property_selector(self, context)
if ui_element.prop_name not in ui_element.prop_owner:
ui_element.prop_name = ""
prop_bone: StringProperty(name="Bone Name", update=update_prop_bone) prop_bone: StringProperty(name="Bone Name", update=update_prop_bone)
def update_prop_coll(self, context): def update_prop_coll(self, context):
ui_element = get_new_ui_element(context) ui_element = get_new_ui_element(context)
ui_element.display_name = self.prop_coll if self.prop_coll:
ui_element.prop_owner_path = f'data.collections_all["{self.prop_coll}"]' ui_element.prop_owner_path = f'data.collections_all["{self.prop_coll}"]'
update_property_selector(self, context) update_property_selector(self, context)
ui_element.prop_name = 'is_visible'
ui_element.display_name = self.prop_coll
ui_element.icon = 'HIDE_OFF'
ui_element.icon_false = 'HIDE_ON'
prop_coll: StringProperty(name="Bone Collection", update=update_prop_coll) prop_coll: StringProperty(name="Bone Collection", update=update_prop_coll)
@ -166,9 +213,6 @@ class UIElementAddMixin:
def update_prop_owner_type(self, context): def update_prop_owner_type(self, context):
ui_element = get_new_ui_element(context) ui_element = get_new_ui_element(context)
if self.prop_owner_type == 'COLLECTION': if self.prop_owner_type == 'COLLECTION':
ui_element.prop_name = 'is_visible'
ui_element.icon = 'HIDE_OFF'
ui_element.icon_false = 'HIDE_ON'
self.prop_coll = self.prop_coll self.prop_coll = self.prop_coll
if self.prop_owner_type == 'BONE': if self.prop_owner_type == 'BONE':
self.prop_bone = self.prop_bone self.prop_bone = self.prop_bone
@ -202,13 +246,25 @@ class UIElementAddMixin:
name="Element Type", name="Element Type",
items=[ items=[
('PROPERTY', 'Property', "Property"), ('PROPERTY', 'Property', "Property"),
('OPERATOR', 'Operator', "Operator") ('OPERATOR', 'Operator', "Operator"),
] ],
)
create_new_ui: BoolProperty(
name="Create Containers",
description="Instead of placing this UI element in an existing panel, label, and row, create new ones",
)
new_panel_name: StringProperty(
name="Panel Name",
description="Optional. Elements parented to this panel can be hidden by collapsing the panel",
)
new_label_name: StringProperty(
name="Label Name",
description="Optional. Elements parented to this label will be displayed below it",
)
new_row_name: StringProperty(
name="Row Name",
description="Optional. Elements parented to this row will be displayed side-by-side",
) )
create_new_ui: BoolProperty(name="Create Containers", description="Instead of placing this UI element in an existing panel, label, and row, create new ones")
new_panel_name: StringProperty(name="Panel Name", description="Optional. Elements parented to this panel can be hidden by collapsing the panel")
new_label_name: StringProperty(name="Label Name", description="Optional. Elements parented to this label will be displayed below it")
new_row_name: StringProperty(name="Row Name", description="Optional. Elements parented to this row will be displayed side-by-side")
use_batch_add: BoolProperty( use_batch_add: BoolProperty(
name="Batch Add", name="Batch Add",