(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.
3 changed files with 112 additions and 7 deletions
Showing only changes of commit e3ec87b486 - Show all commits

View File

@ -1471,6 +1471,15 @@ class CloudRig_UIElement(PropertyGroup):
if elem == self: if elem == self:
return i return i
@property
def identifier(self):
id = self.display_name
parent = self.parent
while parent:
id = parent.display_name + " -> " + id
parent = parent.parent
return id
parent_values: StringProperty( parent_values: StringProperty(
# Supported Types: Panel, Label, Row, only when Element Type of parent element is Property. # Supported Types: Panel, Label, Row, only when Element Type of parent element is Property.
name="Parent Values", name="Parent Values",
@ -1573,12 +1582,13 @@ 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
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.
header, layout = layout.panel(idname=str(self.index) + self.display_name) header, layout = layout.panel(idname=str(self.index) + self.display_name)
header.label(text=self.display_name) header.label(text=self.display_name)
if not layout: remove_op_ui = header
return
if self.element_type == 'LABEL': if self.element_type == 'LABEL':
if self.display_name: if self.display_name:
layout.label(text=self.display_name) layout.label(text=self.display_name)
@ -1593,6 +1603,11 @@ 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 self.id_data.cloudrig.ui_edit_mode:
remove_op_ui.operator('object.cloudrig_ui_element_remove', text="", icon='X').element_index = self.index
if not layout:
return
for child in self.children: for child in self.children:
child.draw(context, layout) child.draw(context, layout)
@ -1663,6 +1678,9 @@ class CloudRig_UIElement(PropertyGroup):
feed_op_props(op_props, self.op_kwargs) feed_op_props(op_props, self.op_kwargs)
return op_props return op_props
def __repr__(self):
return self.identifier
class CLOUDRIG_PT_custom_ui(CLOUDRIG_PT_base): class CLOUDRIG_PT_custom_ui(CLOUDRIG_PT_base):
bl_idname = "CLOUDRIG_PT_custom_ui" bl_idname = "CLOUDRIG_PT_custom_ui"

View File

@ -13,7 +13,7 @@ from bpy.types import (
Modifier, Modifier,
) )
from typing import Any from typing import Any
from bpy.props import StringProperty, BoolProperty, CollectionProperty from bpy.props import StringProperty, BoolProperty, CollectionProperty, IntProperty
from collections import OrderedDict from collections import OrderedDict
from ..generation.cloudrig import ( from ..generation.cloudrig import (
unquote_custom_prop_name, unquote_custom_prop_name,
@ -1203,6 +1203,7 @@ def redraw_viewport():
class UIPathProperty(PropertyGroup): class UIPathProperty(PropertyGroup):
name: StringProperty() name: StringProperty()
index: IntProperty()
ui_path: StringProperty() ui_path: StringProperty()
current: StringProperty(description="Current value of this property. Used for pre-filling the Parent Values field") current: StringProperty(description="Current value of this property. Used for pre-filling the Parent Values field")

View File

@ -1,5 +1,8 @@
from ..generation.cloudrig import CloudRig_UIElement from ..generation.cloudrig import CloudRig_UIElement, find_cloudrig
from .properties_ui import UIPathProperty
from bpy.types import Operator from bpy.types import Operator
from bpy.props import CollectionProperty, StringProperty, IntProperty, BoolProperty
import bpy
class CLOUDRIG_OT_ui_element_add(Operator): class CLOUDRIG_OT_ui_element_add(Operator):
"""Add a UI element""" """Add a UI element"""
@ -12,11 +15,94 @@ class CLOUDRIG_OT_ui_element_add(Operator):
# by this operator, when the "OK" button is clicked. # by this operator, when the "OK" button is clicked.
__annotations__ = CloudRig_UIElement.__annotations__ __annotations__ = CloudRig_UIElement.__annotations__
parent_element: StringProperty(name="Parent Element")
@classmethod
def poll(cls, context):
rig = find_cloudrig(context)
if not rig:
return False
return True
def invoke(self, context, _event):
context.scene.cloudrig_ui_parent_selector.clear()
rig = find_cloudrig(context)
for ui_element in rig.cloudrig_ui:
if ui_element.element_type in {'PANEL', 'LABEL', 'ROW'}:
parent_option = context.scene.cloudrig_ui_parent_selector.add()
parent_option.name = ui_element.identifier
parent_option.index = ui_element.index
return context.window_manager.invoke_props_dialog(self, width=500)
def draw(self, context):
layout = self.layout
layout.use_property_decorate = False
layout.use_property_split = True
layout.prop(self, 'element_type')
layout.prop(self, 'display_name')
if self.element_type in {'PANEL', 'LABEL', 'ROW'}:
layout.prop_search(self, 'parent_element', context.scene, 'cloudrig_ui_parent_selector')
def execute(self, context): def execute(self, context):
rig = find_cloudrig(context)
new_ui_element = rig.cloudrig_ui.add()
new_ui_element.display_name = self.display_name
new_ui_element.element_type = self.element_type
if self.parent_element:
new_ui_element.parent_index = context.scene.cloudrig_ui_parent_selector[self.parent_element].index
return {'FINISHED'} return {'FINISHED'}
class CLOUDRIG_OT_ui_element_remove(Operator):
"""Remove this UI element.\n\n""" \
"""Ctrl: Do not remove children"""
bl_idname = "object.cloudrig_ui_element_remove"
bl_label = "Remove UI Element"
bl_options = {'INTERNAL', 'REGISTER', 'UNDO'}
element_index: IntProperty()
recursive: BoolProperty(default=True)
@classmethod
def poll(cls, context):
return find_cloudrig(context)
def invoke(self, context, event):
self.recursive = not event.ctrl
return self.execute(context)
def execute(self, context):
rig = find_cloudrig(context)
self.remove_element(rig, self.element_index)
return {'FINISHED'}
def remove_element(self, rig, index):
element_to_remove = rig.cloudrig_ui[index]
if self.recursive:
for child in element_to_remove.children:
self.remove_element(rig, child.index)
else:
for child in element_to_remove.children:
child.parent_index = -1
for element in rig.cloudrig_ui:
if element.parent_index > index:
element.parent_index -= 1
rig.cloudrig_ui.remove(index)
def register():
bpy.types.Scene.cloudrig_ui_parent_selector = CollectionProperty(
type=UIPathProperty
)
registry = [ registry = [
CLOUDRIG_OT_ui_element_add CLOUDRIG_OT_ui_element_add,
CLOUDRIG_OT_ui_element_remove,
] ]