Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
bl_info = { 'name': 'Move/Rotate/Scale - Vertex/Edge/Face - Workspaces in Context Menu', 'author': 'TBussinger', 'version': (1, 0, 0), 'blender': (4, 0, 0), 'location': 'Right-Click in any 3D View', 'description': 'Adds Move/Rotate/Scale - Vertex/Edge/Face - Workspaces to the 3D View context menus', 'category': '3D View', } import bpy from bpy.props import StringProperty # --- Workspace switcher (flyout) --- WORKSPACES = [ 'Layout', 'Modeling', 'Sculpting', 'UV Editing', 'Texture Paint', 'Shading', 'Animation', 'Rendering', 'Compositing', 'Geometry Nodes', 'Scripting' ] class WM_OT_switch_workspace_quick(bpy.types.Operator): bl_idname = 'wm.switch_workspace_quick' bl_label = 'Switch Workspace' bl_description = 'Switch the active workspace' bl_options = {'INTERNAL'} workspace: StringProperty(name='Workspace') @classmethod def description(cls, context, properties): ws = getattr(properties, 'workspace', '') return f'Switch to "{ws}" workspace' if ws else 'Switch the active workspace' def execute(self, context): ws = bpy.data.workspaces.get(self.workspace) if not ws: self.report({'WARNING'}, 'Workspace "%s" not found' % self.workspace) return {'CANCELLED'} context.window.workspace = ws return {'FINISHED'} class VIEW3D_MT_workspace_quick(bpy.types.Menu): bl_label = 'Workspaces' bl_idname = 'VIEW3D_MT_workspace_quick' def draw(self, context): layout = self.layout col = layout.column(align=True) for name in WORKSPACES: col.operator('wm.switch_workspace_quick', text=name).workspace = name # --- Context menu injection --- def draw_trs(self, context): layout = self.layout layout.separator() col = layout.column(align=True) col.label(text='Tools') col.operator('wm.tool_set_by_id', text='Move').name = 'builtin.move' col.operator('wm.tool_set_by_id', text='Rotate').name = 'builtin.rotate' col.operator('wm.tool_set_by_id', text='Scale').name = 'builtin.scale' col = layout.column(align=True) col.label(text='Select Mode') col.enabled = (context.mode == 'EDIT_MESH') col.operator('mesh.select_mode', text='Vertex', icon='VERTEXSEL').type = 'VERT' col.operator('mesh.select_mode', text='Edge', icon='EDGESEL').type = 'EDGE' col.operator('mesh.select_mode', text='Face', icon='FACESEL').type = 'FACE' layout.separator() op = layout.operator('wm.call_menu', text='Workspaces...') op.name = 'VIEW3D_MT_workspace_quick' MENUS = ( 'VIEW3D_MT_object_context_menu', 'VIEW3D_MT_edit_mesh_context_menu', 'VIEW3D_MT_edit_curve_context_menu', 'VIEW3D_MT_edit_armature_context_menu', 'VIEW3D_MT_pose_context_menu', ) classes = ( WM_OT_switch_workspace_quick, VIEW3D_MT_workspace_quick, ) def register(): for c in classes: bpy.utils.register_class(c) for menu_id in MENUS: menu = getattr(bpy.types, menu_id, None) if menu: menu.prepend(draw_trs) def unregister(): for menu_id in MENUS: menu = getattr(bpy.types, menu_id, None) if menu: try: menu.remove(draw_trs) except Exception: pass for c in reversed(classes): try: bpy.utils.unregister_class(c) except Exception: pass if __name__ == '__main__': try: unregister() except Exception: pass register()
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)