Dynamically re-annotate a pointer property
I forgot to select one
Example below. Note I've used Scene properties to illustrate the concept, as it's simpler to put together using simple panel template code and column flow to layout, than making custom nodes. Pretty sure the same concepts apply.
The Scene.foo_int
property unregisters re-annotates and re registers the propertygroup class. The init
call is emulated by calling the rereg
update method.
import bpy
from bpy.props import BoolProperty, PointerProperty, IntProperty
class SequencerPosition(bpy.types.PropertyGroup):
__annotations__ = {}
pass
def rereg(self, context):
if getattr(SequencerPosition, "is_registered", False):
bpy.utils.unregister_class(SequencerPosition)
SequencerPosition.__annotations__.clear()
for i in range(self.foo_int):
SequencerPosition.__annotations__[f"value{i}"] = BoolProperty(
name=f"Value{i}",
description=f"Do something with value {i}")
bpy.utils.register_class(SequencerPosition)
bpy.types.Scene.foo = PointerProperty(type=SequencerPosition)
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
scene = context.scene
layout.prop(scene, "foo_int")
grid = layout.column_flow(columns=8)
for anno in SequencerPosition.__annotations__.keys():
grid.prop(scene.foo, anno, icon_only=True)
def register():
bpy.utils.register_class(HelloWorldPanel)
bpy.types.Scene.foo_int = IntProperty(min=0, max=32, update=rereg)
def unregister():
bpy.utils.unregister_class(HelloWorldPanel)
if __name__ == "__main__":
rereg(bpy.context.scene, bpy.context)
register()
Oh, and this won't really work if I have multiple instances of the
node, right?
Yes that's a catch on the dynamic registering, however can annotate the node with a maximum number, and only display so many based on a node int property
to demonstrate:
I've annotated the CustomNode with a max of 32 and used the int to set the layout
def draw_buttons(self, context, layout):
layout.label(text="Node settings")
layout.prop(self, "my_int_prop")
grid = layout.grid_flow(row_major=True, columns=4)
for i in range(self.my_int_prop):
grid.prop(self, f'value{i}', icon_only=True)