The problem is, I am trying to actually run the function clean_screen_layout() once the menu option is picked. Right now I have some bogus code in there (self.layout.operator(“screen.area_split”, text=“Clean Screen Layout”).direction = ‘VERTICAL’). Obviously. “screen.area_split” needs to be changed so it will call clean_screen_layout(). However, I can’t figure out the syntax on how to do it (nor can I find a similar example to imitate).
I think you need to sort out the creation of the menu code first and leave the code on the actual work to be done later. There are templates in Blender, but I suggest you look at the CGCookie tutorial on making a simple popup menu that you can find at http://cgcookie.com/blender/2013/05/23/creating-custom-menu-python-scripting/
If you use that as a template then about the only thing you need to add is the class for the clean screen. That class will probably need to be registered as well.
The goal is to call the function clean_screen_layout(), which deletes what I consider to be extraneous screen layouts (any layouts that end with a period followed by three numbers). I only had the split/unsplit code in there because I pulled that from another example I found on the forum and couldn’t figure out how to substitute my own function.
Thank you! That’s great. Is there some way to ensure that the button doesn’t slide off the screen? On a 1366x768 screen, if I select an object with a longish name in the outliner or in the scene, the button will slide off the screen, never to be seen again (until an object with a shorter name is selected).
If there isn’t a way to get around this, I would prefer to implement this like how I was originally trying to implement it – which was to save screen real estate and have an option under the Window menu in the Info panel. If you could fill in the piece of what I was missing there to call my custom function, that would be really helpful.
You can only append or prepend to existing draw functions, thus it’s possible to put the button as the left most element, even before the editor type selector.
Thanks – I got it working with the menu option. I did notice one thing, however. I wonder if this is a Blender bug (I’m using 2.72) or if there’s a way to work around this:
Create a new screen layout in a popout window by doing a shift+drag on one of the window splitters. This will create a “____.###” screen layout.
Leave that new window open, but go back to your original screen.
Run the clean screen layout code.
Click on the scene layout dropdown. Blender will crash.
This happens no matter if I use your way of deleting the screen layouts or if I use mine. If you do the above steps but close any .### windows that are in separate windows before running the clean screen code, Blender will not crash. Likewise, if the current screen layout is a .### window and you run the clean screen code, Blender will not crash. It’s only when a .### window is being shown in another Blender window.
How can I determine whether a screen layout is currently open in a Blender window? Mind you, I don’t want to check whether the screen layout is active in the current active Blender window that the code is being run from. I only want to check whether one of the other Blender windows has a .### screen layout. (If so, I won’t delete that layouts.)
That provides all of the possible screen layouts in the blend file – not the screen layouts that are currently visible when Blender is open.
What I’m trying to find are the screen layouts for all of the other “pop out” windows that are currently open. (I’m not sure what Blender calls these “pop out” windows – they’re the separate windows that open when you hold down shift while dragging on a window splitter.)
My mistake. I’m not sure why I was seeing what I was seeing before, but that code does indeed work as intended.
The final code:
bl_info = {
'name': "Simple Carnival Clean Screen Layouts",
'author': "CoDEmanX, Jeff Boller",
'version': (1, 0, 1),
'blender': (2, 6, 7),
'api': 44136,
'location': "Info panel -> 'Window' menu option -> 'Clean Screen Layouts'",
'description': "Deletes all screen layouts which end with .###",
'wiki_url': "3d.simplecarnival.com",
'tracker_url': "",
'category': "Object"}
import bpy
import re
class SimpleOperator(bpy.types.Operator):
"""Delete screen layouts which end with .###"""
bl_idname = "screen.clear"
bl_label = "Clean Screen Layouts"
def execute(self, context):
screen_name = context.screen.name
for screen in bpy.data.screens:
if re.match(".*\.\d{3}$", screen.name) is not None:
s = screen.name
allowed_to_delete = 1
# Make sure we don't have any windows that have this particular screen layout open. (Blender will crash.)
for window in bpy.context.window_manager.windows:
if (window.screen.name == s):
self.report({'WARNING'}, "Cannot delete screen layout '" + window.screen.name + "' because it is open.")
allowed_to_delete = 0
break
if (allowed_to_delete == 1):
bpy.ops.screen.delete({'window': context.window, 'screen': screen, 'region': None})
self.report({'INFO'}, "Deleted screen '" + s + "'")
screen = bpy.data.screens.get(screen_name)
if screen is not None:
context.window.screen = screen
return {'FINISHED'}
def draw_func(self, context):
layout = self.layout
layout.separator()
layout.operator(SimpleOperator.bl_idname, text=SimpleOperator.bl_label)
def register():
bpy.utils.register_class(SimpleOperator)
bpy.types.INFO_MT_window.append(draw_func)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
bpy.types.INFO_MT_header.remove(draw_func)
if __name__ == "__main__":
register()