We are currently developing an application using the Python GUI for Blender and I am hard up in making it dynamic. The main idea is when a button is clicked, a certain menu will be filled up with menu items and images are generated… can someone help me about this? thanks! I would really appreciate your help!
I think this may help, this short program has an if statement in the draw function. When an operator executes the value the if statement is dependent on toggles (therefore the result to the screen changes). The second operator in this program draws a new panel each time it is called. It is very messy though, it is hot where I am, too hot to make it neat and correct the spelling.
# Dynamic Blender GUI using Python
# Example
import bpy
from bpy.props import FloatProperty, PointerProperty, BoolProperty, IntProperty
# ##### ID PROPERTIES #####
class property_class(bpy.types.IDPropertyGroup):
"""
Fake module like class
bpy.context.active_object.book_props
"""
pass
# ##### OPERATORS #####
class BOOK_OT_Change(bpy.types.Operator):
"""Make A Change"""
bl_idname = "object.change"
bl_label = "Make A Change"
bl_description = "It Works"
def execute(self, context):
ob = context.active_object
props = ob.new_props
if not props.changed:
props.p0 = 2 * props.b0
props.p1 = 2 * props.b1
props.p2 = 2 * props.b2
props.changed = True
else:
props.b0 = props.p0 / 2
props.b1 = props.p1 / 2
props.b2 = props.p2 / 2
props.changed = False
return {'FINISHED'}
class BOOK_OT_newpanel(bpy.types.Operator):
"""Make A Change"""
bl_idname = "object.panel"
bl_label = "Make Another Change"
bl_description = "It Works"
def execute(self, context):
props = context.active_object.new_props
class OBJECT_PT_NotUseFul(bpy.types.Panel):
props = context.active_object.new_props
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "modifier"
bl_label = "A Panel"
bl_idname = "object.mine%i" % props.count
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
row = col.row()
if props.changed:
row.prop(props, "p0", slider=True)
row.prop(props, "p1", slider=True)
row.prop(props, "p2", slider=True)
else:
row.prop(props, "b0")
row.prop(props, "b1")
row.prop(props, "b2")
col.operator("object.change")
# Causes an Error
try:
bpy.types.register("object.mine%i" % count)
except:
pass
props.count += 1
return {'FINISHED'}
# #### PANEL #####
class OBJECT_PT_UseFul(bpy.types.Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "modifier"
bl_label = "A Panel"
def draw(self, context):
layout = self.layout
props = context.active_object.new_props
col = layout.column(align=True)
row = col.row()
if props.changed:
row.prop(props, "p0", slider=True)
row.prop(props, "p1", slider=True)
row.prop(props, "p2", slider=True)
else:
row.prop(props, "b0")
row.prop(props, "b1")
row.prop(props, "b2")
col.operator("object.change")
col.operator("object.panel")
# ##### REGISTER #####
def register():
# Object Properties
bpy.types.Object.new_props = PointerProperty(type=property_class)
property_class.p0 = FloatProperty(name="Num1", default=1)
property_class.p1 = FloatProperty(name="Wha??", default=1)
property_class.p2 = FloatProperty(name="Up", default=1)
property_class.b0 = FloatProperty(name="The")
property_class.b1 = FloatProperty(name="Sky")
property_class.b2 = FloatProperty(name="Up")
property_class.changed = BoolProperty(default=False)
property_class.count = IntProperty(default=0)
def unregister():
property_class.p0
property_class.p1
property_class.p2
property_class.b0
property_class.b1
property_class.b2
property_class.changed
try:
del bpy.types.Object.new_props
except:
pass
if __name__ == "__main__":
# unregistering is only done automatically when run as add-on
bpy.types.unregister(OBJECT_PT_UseFul)
if __name__ == "__main__":
register()
What do you mean by images (render, texture, material?)
Hope this helps, good luck.
Nice examle ilent2. I have a question. How can we remove the created panel? Is it possible?
To unregister a panel you call bpy.types.unregister(‘PANEL’). So, an example with the script above:
Add this:
class PANEL_OT_remove(bpy.types.Operator):
"""Make A Change"""
bl_idname = "object.remove"
bl_label = "Remove A Change"
bl_description = "It Works"
def execute(self, context):
bpy.types.unregister(OBJECT_PT_UseFul)
#props.count += 1
return {'FINISHED'}
and add this line to the draw function of the panel:
col.operator(“object.remove”, icon=‘CANCEL’)
This will remove The first panel. If you want to remove additional panels you create you will need to somehow store the names of these panels.
Thanks for the info ilent2.
I think this is not the way to do it.
I had recently the same problem. Just using the ‘poll’ function of a Panel is sufficient to decide whether or not to display it.
A multi-step UI can then be achieved using new boolean Property:
def poll(cls,context):
scene = context.scene
show = (scene.step1 == 0)
return show
Sorry I have no time to post a full example. If someone is still interested. Let me know
i tested first script in 636
but get an error on line 9 ?
dynamicpanel1.blend\dynamicpanel1.py", line 9, in <module>
AttributeError: ‘RNA_Types’ object has no attribute ‘IDPropertyGroup’
anybody knows how to correct this
by the way very interesting example
and would like to see the last example
might be usefull in futur !
thanks and happy 2.5