bpy.types
All widgets and operators dynamically appear in the bpy.types listing object. Care must be taken to give your operator a unique class name, and a unique 'bl_idname'. By not giving a unique name you can override blender's default behavior or interface. For example lets override the INFO menu with extra buttons.
class INFO_HT_header(bpy.types.Header):
bl_space_type = 'INFO'
def draw(self, context):
layout = self.layout
wm = context.window_manager
window = context.window
scene = context.scene
rd = scene.render
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER', text="")
#layout.operator("ogre_export", text="Ogre")
row = layout.row(align=True)
sub = row.row(align=True)
sub.menu("INFO_MT_instances")
sub.menu("INFO_MT_groups")
sub.menu("INFO_MT_actors")
sub.menu("INFO_MT_dynamics")
if True: #context.area.show_menus:
sub.menu("INFO_MT_file")
sub.menu("INFO_MT_add")
if rd.use_game_engine: sub.menu("INFO_MT_game")
else: sub.menu("INFO_MT_render")
layout.separator()
if window.screen.show_fullscreen:
layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
layout.separator()
else:
layout.template_ID(context.window, "screen", new="screen.new", unlink="screen.delete")
layout.separator()
layout.template_running_jobs()
layout.template_reports_banner()
layout.separator()
if rd.has_multiple_engines:
layout.prop(rd, "engine", text="")
layout.template_header()
if context.area.show_menus:
layout.template_ID(context.screen, "scene", new="scene.new", unlink="scene.delete")
layout.label(text=scene.statistics())
layout.menu( "INFO_MT_help" )
else:
screen = context.screen
row = layout.row(align=True)
row.operator("screen.frame_jump", text="", icon='REW').end = False
row.operator("screen.keyframe_jump", text="", icon='PREV_KEYFRAME').next = False
if not screen.is_animation_playing:
row.operator("screen.animation_play", text="", icon='PLAY_REVERSE').reverse = True
row.operator("screen.animation_play", text="", icon='PLAY')
else:
sub = row.row()
sub.scale_x = 2.0
sub.operator("screen.animation_play", text="", icon='PAUSE')
row.operator("screen.keyframe_jump", text="", icon='NEXT_KEYFRAME').next = True
row.operator("screen.frame_jump", text="", icon='FF').end = True
row = layout.row(align=True)
if not scene.use_preview_range:
row.prop(scene, "frame_start", text="Start")
row.prop(scene, "frame_end", text="End")
else:
row.prop(scene, "frame_preview_start", text="Start")
row.prop(scene, "frame_preview_end", text="End")
layout.prop(scene, "frame_current", text="")
def gather_instances():
instances = {}
for ob in bpy.data.objects:
if ob.data and ob.data.users > 1:
if ob.data not in instances: instances[ ob.data ] = []
instances[ ob.data ].append( ob )
return instances
def select_instances( context, name ):
for ob in bpy.data.objects: ob.select = False
ob = bpy.data.objects[ name ]
if ob.data:
inst = gather_instances()
for ob in inst[ ob.data ]: ob.select = True
bpy.context.scene.objects.active = ob
def select_group( context, name, options={} ):
for ob in bpy.data.objects: ob.select = False
for grp in bpy.data.groups:
if grp.name == name:
bpy.context.scene.objects.active = grp.objects[0]
for ob in grp.objects: ob.select = True
class INFO_MT_instances(bpy.types.Menu):
bl_label = "Instances"
def draw(self, context):
layout = self.layout
inst = gather_instances()
for data in inst:
ob = inst[data][0]
op = layout.operator("select_instances", text=ob.name) # operator has no variable for button name?
op.mystring = ob.name
layout.separator()
class INFO_MT_instance(bpy.types.Operator):
'''select instance group'''
bl_idname = "select_instances"
bl_label = "Select Instance Group"
bl_options = {'REGISTER', 'UNDO'}
mystring= StringProperty(name="MyString", description="...", maxlen=1024, default="my string")
@classmethod
def poll(cls, context): return True
def invoke(self, context, event):
print( 'invoke select_instances op', event )
select_instances( context, self.mystring )
return {'FINISHED'}
class INFO_MT_groups(bpy.types.Menu):
bl_label = "Groups"
def draw(self, context):
layout = self.layout
for group in bpy.data.groups:
op = layout.operator("select_group", text=group.name) # operator no variable for button name?
op.mystring = group.name
layout.separator()
class INFO_MT_group(bpy.types.Operator):
'''select group'''
bl_idname = "select_group"
bl_label = "Select Group"
bl_options = {'REGISTER', 'UNDO'}
mystring= StringProperty(name="MyString", description="...", maxlen=1024, default="my string")
@classmethod
def poll(cls, context): return True
def invoke(self, context, event):
select_group( context, self.mystring )
return {'FINISHED'}
class INFO_MT_actors(bpy.types.Menu):
bl_label = "Actors"
def draw(self, context):
layout = self.layout
for ob in bpy.data.objects:
if ob.game.use_actor:
op = layout.operator("select_actor", text=ob.name)
op.mystring = ob.name
layout.separator()
class INFO_MT_actor(bpy.types.Operator):
'''select actor'''
bl_idname = "select_actor"
bl_label = "Select Actor"
bl_options = {'REGISTER', 'UNDO'} # Options for this panel type
mystring= StringProperty(name="MyString", description="...", maxlen=1024, default="my string")
@classmethod
def poll(cls, context): return True
def invoke(self, context, event):
bpy.data.objects[self.mystring].select = True
return {'FINISHED'}
class INFO_MT_dynamics(bpy.types.Menu):
bl_label = "Dynamics"
def draw(self, context):
layout = self.layout
for ob in bpy.data.objects:
if ob.game.physics_type in 'DYNAMIC SOFT_BODY RIGID_BODY'.split():
op = layout.operator("select_dynamic", text=ob.name)
op.mystring = ob.name
layout.separator()
class INFO_MT_dynamic(bpy.types.Operator):
'''select dynamic'''
bl_idname = "select_dynamic"
bl_label = "Select Dynamic"
bl_options = {'REGISTER', 'UNDO'} # Options for this panel type
mystring= StringProperty(name="MyString", description="...", maxlen=1024, default="my string")
@classmethod
def poll(cls, context): return True
def invoke(self, context, event):
bpy.data.objects[self.mystring].select = True
return {'FINISHED'}