(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:
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(
# Supported Types: Panel, Label, Row, only when Element Type of parent element is Property.
name="Parent Values",
@ -1573,12 +1582,13 @@ class CloudRig_UIElement(PropertyGroup):
if not self.should_draw or not layout:
return
remove_op_ui = layout
if self.element_type == 'PANEL':
# 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.label(text=self.display_name)
if not layout:
return
remove_op_ui = header
if self.element_type == 'LABEL':
if self.display_name:
layout.label(text=self.display_name)
@ -1593,6 +1603,11 @@ class CloudRig_UIElement(PropertyGroup):
if self.element_type == 'OPERATOR':
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:
child.draw(context, layout)
@ -1663,6 +1678,9 @@ class CloudRig_UIElement(PropertyGroup):
feed_op_props(op_props, self.op_kwargs)
return op_props
def __repr__(self):
return self.identifier
class CLOUDRIG_PT_custom_ui(CLOUDRIG_PT_base):
bl_idname = "CLOUDRIG_PT_custom_ui"

View File

@ -13,7 +13,7 @@ from bpy.types import (
Modifier,
)
from typing import Any
from bpy.props import StringProperty, BoolProperty, CollectionProperty
from bpy.props import StringProperty, BoolProperty, CollectionProperty, IntProperty
from collections import OrderedDict
from ..generation.cloudrig import (
unquote_custom_prop_name,
@ -1203,6 +1203,7 @@ def redraw_viewport():
class UIPathProperty(PropertyGroup):
name: StringProperty()
index: IntProperty()
ui_path: StringProperty()
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.props import CollectionProperty, StringProperty, IntProperty, BoolProperty
import bpy
class CLOUDRIG_OT_ui_element_add(Operator):
"""Add a UI element"""
@ -12,11 +15,94 @@ class CLOUDRIG_OT_ui_element_add(Operator):
# by this operator, when the "OK" button is clicked.
__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):
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'}
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 = [
CLOUDRIG_OT_ui_element_add
CLOUDRIG_OT_ui_element_add,
CLOUDRIG_OT_ui_element_remove,
]