Greetings, fellow earthlings!
I am new to blender and want to dive into Python.
Have been dabbling in maxscript for a while, so I am not totally new to programming, but feel a little overwhelmed. As a little exercise I want to create a button somewhere in the info panel.
(Preferably in between “Window” and Help")
A thread on this forum (How to make floating windows/panels) and the blender templates got me jumpstarted, but my code does not work, as I do not get a menu button.
Could somebody please help me?
import bpy
class CustomMenu(bpy.types.Menu):
bl_label = "mMenu"
bl_idname = "OBJECT_MT_mMenu"
def openuveditor():
obj_original_area = bpy.context.area
obj_original_type = obj_original_area.type
obj_original_area.type = 'IMAGE_EDITOR'
bpy.ops.screen.area_dupli('INVOKE_DEFAULT')
obj_original_area.type = obj_original_type
def draw(self, context):
layout = self.layout
layout.operator("openuveditor()")
def draw_item(self, context):
layout = self.layout
layout.menu(CustomMenu.bl_idname)
def register():
bpy.utils.register_class(CustomMenu)
bpy.types.INFO_HT_header.append(draw_item)
def unregister():
bpy.utils.unregister_class(CustomMenu)
bpy.types.INFO_HT_header.remove(draw_item)
if __name__ == "__main__":
register()
Oookay, so after a few hours of more tutorials (I can recommend this series: https://www.youtube.com/watch?v=K0yb4sZ7B4g), I think I understand more.
The workflow would be to first create an operator which I can then load through a button, right?
So I am trying to register that class, but it throws an error message:
Traceback (most recent call last):
File “<blender_console>”, line 1, in
File “C:\Program Files\Blender Foundation\blender-2.80.0-git.0e8bd6ba8a2-windows64\2.80\scripts\modules\bpy\ops.py”, line 192, in call
ret = op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.mops.openuveditor.poll() failed, context is incorrect
I believe the “context” behind the main definition (how would you call that parameter, is it an argument?) is the wrong part, however I am unsure what else to put there…
Here is my code for now, derived from the threadI linked earlier and the “simple operator” template:
import bpy
def main(contex):
bl_idname = "mops.openuveditor"
bl_label = "UV Editor"
obj_original_area = bpy.context.area
obj_original_type = obj_original_area.type
obj_original_area.type = 'IMAGE_EDITOR'
bpy.ops.screen.area_dupli('INVOKE_DEFAULT')
obj_original_area.type = obj_original_type
class OpenUVEditor(bpy.types.Operator):
"""Tooltip"""
bl_idname = "mops.openuveditor"
bl_label = "Open UV Editor"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
main(contex)
return {'FINISHED'}
def register():
bpy.utils.register_class(OpenUVEditor)
def unregister():
bpy.utils.unregister_class(OpenUVEditor)
if __name__ == "__main__":
register()
# test call
#bpy.ops.mops.openuveditor()
Maybe somebody wants to tell me what an idiot I am for doing everything wrong? I can take it!
(As long as you tell me how to do it right, too, that is…)
Okay, got it to work… mostly… still trying to change the new window’s size and position and save them in global variables.
Ideally i would also like to load the diffuse image of the selected object in the background automatically, if it has any.
Should I keep posting? For anybody who’s interested, here is the working code:
bl_info = {
"name": "mMenu",
"author": "morph3us",
"version": (0, 1),
"blender": (2, 79, 0),
"location": "Info Menu",
"description": "Adds a new menu in the info toolbar",
"warning": "",
"wiki_url": "",
"category": "Menu",
}
import bpy
def fn_openuvedit():
bl_idname = "mops_openuveditor"
bl_label = "UV Editor"
obj_original_area = bpy.context.area
obj_original_type = obj_original_area.type
obj_original_area.type = 'IMAGE_EDITOR'
bpy.ops.screen.area_dupli('INVOKE_DEFAULT')
obj_original_area.type = obj_original_type
class op_openuvedit(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.op_openuvedit"
bl_label = "Open UV Editor Window"
def execute(self, context):
fn_openuvedit()
return {'FINISHED'}
class obj_mmenu(bpy.types.Menu):
bl_label = "mMenu"
bl_idname = "OBJECT_MT_mMenu"
def draw(self, context):
layout = self.layout
layout.operator("object.op_openuvedit")
def draw_item(self, context):
layout = self.layout
layout.menu(obj_mmenu.bl_idname)
def register():
bpy.utils.register_class(op_openuvedit)
bpy.utils.register_class(obj_mmenu)
bpy.types.INFO_HT_header.append(draw_item)
def unregister():
bpy.utils.unregister_class(op_openuvedit)
bpy.utils.unregister_class(obj_mmenu)
bpy.types.INFO_HT_header.remove(draw_item)
if __name__ == "__main__":
register()
Hey good Job. I try to do the same but with 2.8
I edited the startup script to get the results I want but it is not a nice solution. I would love to call a script trough blender to add the menu after the launch as you did. So if you are able to convert your code to 2.8 I would be more than happy to know how