(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 73 additions and 31 deletions
Showing only changes of commit 0181297bcb - Show all commits

View File

@ -1473,7 +1473,10 @@ class CloudRig_UIElement(PropertyGroup):
return self.rig.cloudrig_ui[self.parent_index] return self.rig.cloudrig_ui[self.parent_index]
@parent.setter @parent.setter
def parent(self, value): def parent(self, value: 'CloudRig_UIElement'):
if not value:
self.parent_index = -1
else:
self.parent_index = value.index self.parent_index = value.index
@property @property
@ -1481,6 +1484,7 @@ class CloudRig_UIElement(PropertyGroup):
for i, elem in enumerate(self.rig.cloudrig_ui): for i, elem in enumerate(self.rig.cloudrig_ui):
if elem == self: if elem == self:
return i return i
return -1
@property @property
def identifier(self): def identifier(self):
@ -1604,7 +1608,7 @@ class CloudRig_UIElement(PropertyGroup):
if not self.should_draw or not layout: if not self.should_draw or not layout:
return return
remove_op_ui = layout parent_layout = remove_op_ui = layout
if self.element_type == 'PANEL': if self.element_type == 'PANEL':
# TODO: Figure out how to allow elements to be drawn in the header. # TODO: Figure out how to allow elements to be drawn in the header.
@ -1612,12 +1616,13 @@ class CloudRig_UIElement(PropertyGroup):
header.label(text=self.display_name) header.label(text=self.display_name)
remove_op_ui = header remove_op_ui = header
if self.element_type == 'LABEL': if self.element_type == 'LABEL':
layout = remove_op_ui = layout.row()
if self.display_name: if self.display_name:
layout.label(text=self.display_name) layout.label(text=self.display_name)
if self.element_type == 'ROW': if self.element_type == 'ROW':
layout = layout.row() layout = remove_op_ui = parent_layout = layout.row()
if self.display_name: # if self.display_name:
layout.label(text=self.display_name) # layout.label(text=self.display_name)
if self.element_type == 'PROPERTY': if self.element_type == 'PROPERTY':
if not self.parent or self.parent.element_type != 'ROW': if not self.parent or self.parent.element_type != 'ROW':
layout = remove_op_ui = layout.row() layout = remove_op_ui = layout.row()
@ -1627,16 +1632,16 @@ class CloudRig_UIElement(PropertyGroup):
if self.element_type == 'OPERATOR': if self.element_type == 'OPERATOR':
self.draw_operator(context, layout) self.draw_operator(context, layout)
if not layout:
return
for child in self.children:
child.draw_ui_element(context, parent_layout)
if self.rig.cloudrig.ui_edit_mode: if self.rig.cloudrig.ui_edit_mode:
remove_op_ui.operator( remove_op_ui.operator(
'object.cloudrig_ui_element_remove', text="", icon='X' 'object.cloudrig_ui_element_remove', text="", icon='X'
).element_index = self.index ).element_index = self.index
if not layout:
return
for child in self.children:
child.draw_ui_element(context, layout)
def draw_property(self, context, layout): def draw_property(self, context, layout):
prop_owner, prop_value = self.prop_owner, self.prop_value prop_owner, prop_value = self.prop_owner, self.prop_value
if not prop_owner: if not prop_owner:
@ -1652,6 +1657,7 @@ class CloudRig_UIElement(PropertyGroup):
text=f"Missing property '{self.prop_name}' of owner '{self.prop_owner_path}'.", text=f"Missing property '{self.prop_name}' of owner '{self.prop_owner_path}'.",
icon='ERROR', icon='ERROR',
) )
return
display_name = self.display_name or self.prop_name display_name = self.display_name or self.prop_name
@ -1739,6 +1745,7 @@ class CLOUDRIG_PT_custom_ui(CLOUDRIG_PT_base):
layout = self.layout layout = self.layout
layout.use_property_split = True layout.use_property_split = True
layout.use_property_decorate = False layout.use_property_decorate = False
layout = layout.column(align=True)
rig = context.active_object # TODO rig = context.active_object # TODO

View File

@ -16,15 +16,21 @@ import bpy
def draw_ui_editing(context, layout, ui_element, operator): def draw_ui_editing(context, layout, ui_element, operator):
rig = find_cloudrig(context) rig = find_cloudrig(context)
layout.prop(ui_element, 'element_type') layout.prop(operator, 'element_type', expand=True)
name_row = layout.row()
if (
ui_element.element_type in {'PANEL', 'LABEL', 'ROW'}
and ui_element.display_name.strip() == ""
):
name_row.alert = True
if ui_element.element_type == 'PROPERTY': parent_row = layout.row()
if operator.create_new_ui:
parent_row.prop(operator, 'new_panel_name')
layout.prop(operator, 'new_label_name')
layout.prop(operator, 'new_row_name')
else:
parent_row.prop_search(
operator, 'parent_element', context.scene, 'cloudrig_ui_parent_selector'
)
if context.scene.cloudrig_ui_parent_selector:
parent_row.prop(operator, 'create_new_ui', text="", icon='ADD')
if operator.element_type == 'PROPERTY':
layout.prop(operator, 'prop_owner_type', expand=True) layout.prop(operator, 'prop_owner_type', expand=True)
if operator.prop_owner_type == 'BONE': if operator.prop_owner_type == 'BONE':
layout.prop_search(operator, 'prop_bone', rig.pose, 'bones') layout.prop_search(operator, 'prop_bone', rig.pose, 'bones')
@ -46,24 +52,15 @@ def draw_ui_editing(context, layout, ui_element, operator):
else: else:
layout.prop(ui_element, 'prop_name') layout.prop(ui_element, 'prop_name')
if ui_element.element_type == 'OPERATOR': if operator.element_type == 'OPERATOR':
draw_op_editing(context, layout, ui_element, operator) draw_op_editing(context, layout, ui_element, operator)
name_row.prop(ui_element, 'display_name') layout.prop(ui_element, 'display_name')
if (
ui_element.element_type in {'PANEL', 'LABEL', 'ROW'}
and ui_element.display_name.strip() == ""
):
return
# debug # debug
# layout.prop(ui_element, 'prop_owner_path') # layout.prop(ui_element, 'prop_owner_path')
# layout.prop(ui_element, 'is_custom_prop') # layout.prop(ui_element, 'is_custom_prop')
layout.prop_search(
operator, 'parent_element', context.scene, 'cloudrig_ui_parent_selector'
)
def draw_op_editing(context, layout, ui_element, operator): def draw_op_editing(context, layout, ui_element, operator):
if operator.use_batch_add: if operator.use_batch_add:
@ -201,6 +198,18 @@ class UIElementAddMixin:
update=update_prop_owner_type, update=update_prop_owner_type,
) )
element_type: EnumProperty(
name="Element Type",
items=[
('PROPERTY', 'Property', "Property"),
('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")
use_batch_add: BoolProperty( use_batch_add: BoolProperty(
name="Batch Add", name="Batch Add",
options={'SKIP_SAVE'}, options={'SKIP_SAVE'},
@ -217,6 +226,8 @@ class UIElementAddMixin:
def invoke(self, context, _event): def invoke(self, context, _event):
update_parent_selector(context) update_parent_selector(context)
if not context.scene.cloudrig_ui_parent_selector:
self.create_new_ui = True
self.ui_element = get_new_ui_element(context) self.ui_element = get_new_ui_element(context)
self.ui_element.reset() self.ui_element.reset()
@ -251,6 +262,25 @@ class CLOUDRIG_OT_ui_element_add(UIElementAddMixin, Operator):
rig = find_cloudrig(context) rig = find_cloudrig(context)
temp_ui_element = get_new_ui_element(context) temp_ui_element = get_new_ui_element(context)
parent = None
if self.create_new_ui:
if self.new_panel_name:
parent = rig.cloudrig_ui.add()
parent.element_type = 'PANEL'
parent.display_name = self.new_panel_name
if self.new_label_name:
label = rig.cloudrig_ui.add()
label.parent = parent
label.element_type = 'LABEL'
label.display_name = self.new_label_name
parent = label
if self.new_row_name:
row = rig.cloudrig_ui.add()
row.parent = parent
row.element_type = 'ROW'
row.display_name = self.new_row_name
parent = row
if ( if (
temp_ui_element.element_type in {'PANEL', 'LABEL', 'ROW'} temp_ui_element.element_type in {'PANEL', 'LABEL', 'ROW'}
and temp_ui_element.display_name.strip() == "" and temp_ui_element.display_name.strip() == ""
@ -265,6 +295,10 @@ class CLOUDRIG_OT_ui_element_add(UIElementAddMixin, Operator):
continue continue
setattr(new_ui_element, prop_name, getattr(temp_ui_element, prop_name)) setattr(new_ui_element, prop_name, getattr(temp_ui_element, prop_name))
if parent:
new_ui_element.parent = parent
new_ui_element.element_type = self.element_type
wipe_parent_selector(context) wipe_parent_selector(context)
del rig['cloudrig_ui_new_element'] del rig['cloudrig_ui_new_element']
@ -316,13 +350,14 @@ class CLOUDRIG_OT_ui_element_remove(Operator):
def remove_element(self, rig, index): def remove_element(self, rig, index):
element_to_remove = rig.cloudrig_ui[index] element_to_remove = rig.cloudrig_ui[index]
fallback_parent = element_to_remove.parent
if self.recursive: if self.recursive:
for child in element_to_remove.children: for child in element_to_remove.children:
self.remove_element(rig, child.index) self.remove_element(rig, child.index)
else: else:
for child in element_to_remove.children: for child in element_to_remove.children:
child.parent_index = -1 child.parent = fallback_parent
for element in rig.cloudrig_ui: for element in rig.cloudrig_ui:
if element.parent_index > index: if element.parent_index > index: