Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 11 May 2018 18:13:07 +0000 (20:13 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 11 May 2018 18:13:07 +0000 (20:13 +0200)
1  2 
release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/mesh/mesh_ops.c
source/blender/windowmanager/intern/wm_event_system.c

index f69fba9f60385ccf93f7a4909f2634dc75169f5d,6334a2ee87ec99d0cd286050f98e5ec0800eab5c..7fc7f787b3f24384419e52b6e7000724a34b2e88
@@@ -34,7 -34,6 +34,7 @@@ class VIEW3D_HT_header(Header)
          layout = self.layout
  
          view = context.space_data
 +        shading = view.shading
          # mode_string = context.mode
          obj = context.active_object
          toolsettings = context.tool_settings
          row = layout.row(align=True)
          row.template_header()
  
 +        mode = 'OBJECT' if obj is None else obj.mode
 +        act_mode_item = bpy.types.Object.bl_rna.properties['mode'].enum_items[mode]
 +        layout.operator_menu_enum("object.mode_set", "mode", text=act_mode_item.name, icon=act_mode_item.icon)
 +        del act_mode_item
 +
 +        layout.template_header_3D_mode()
 +
          VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
  
          # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
          row = layout
 +        shading_type = view.shading.type
 +        shading_item = bpy.types.View3DShading.bl_rna.properties['type'].enum_items[shading_type]
 +        row.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_shading", text=shading_item.name, icon=shading_item.icon)
 +        row.popover(space_type='VIEW_3D', region_type='HEADER', panel_type="VIEW3D_PT_overlay", text="Overlays", icon='WIRE')
 +
          layout.template_header_3D()
  
          if obj:
 -            mode = obj.mode
 +            # Set above:
 +            # mode = obj.mode
 +
              # Particle edit
              if mode == 'PARTICLE_EDIT':
                  row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
  
              # Occlude geometry
 -            if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
 +            if ((shading.type not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
                      (mode in {'WEIGHT_PAINT', 'VERTEX_PAINT'})):
                  row.prop(view, "use_occlude_geometry", text="")
  
@@@ -247,6 -232,13 +247,6 @@@ class VIEW3D_MT_transform_base(Menu)
      def draw(self, context):
          layout = self.layout
  
 -        layout.operator("transform.translate", text="Grab/Move")
 -        # TODO: sub-menu for grab per axis
 -        layout.operator("transform.rotate", text="Rotate")
 -        # TODO: sub-menu for rot per axis
 -        layout.operator("transform.resize", text="Scale")
 -        # TODO: sub-menu for scale per axis
 -
          layout.separator()
  
          layout.operator("transform.tosphere", text="To Sphere")
@@@ -309,12 -301,6 +309,12 @@@ class VIEW3D_MT_transform_object(VIEW3D
          layout.operator("object.randomize_transform")
          layout.operator("object.align")
  
 +        # TODO: there is a strange context bug here.
 +        """
 +        layout.operator_context = 'INVOKE_REGION_WIN'
 +        layout.operator("object.transform_axis_target")
 +        """
 +
  
  # Armature EditMode extensions to Transform menu
  class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base):
@@@ -465,6 -451,7 +465,6 @@@ class VIEW3D_MT_view(Menu)
              layout.operator("view3d.view_selected", text="View Selected (Quad View)").use_all_regions = True
  
          layout.operator("view3d.view_all").center = False
 -        layout.operator("view3d.localview", text="View Global/Local")
          layout.operator("view3d.view_persportho")
  
          layout.separator()
@@@ -677,8 -664,12 +677,8 @@@ class VIEW3D_MT_select_object(Menu)
  
          layout.operator("object.select_all").action = 'TOGGLE'
          layout.operator("object.select_all", text="Inverse").action = 'INVERT'
 -
 -        layout.separator()
 -
          layout.operator("object.select_random", text="Random")
          layout.operator("object.select_mirror", text="Mirror")
 -        layout.operator("object.select_by_layer", text="Select All by Layer")
          layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
          layout.operator("object.select_camera", text="Select Camera")
  
@@@ -1192,23 -1183,13 +1192,23 @@@ class INFO_MT_mesh_add(Menu)
      bl_label = "Mesh"
  
      def draw(self, context):
 -        from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
 -
          layout = self.layout
  
          layout.operator_context = 'INVOKE_REGION_WIN'
  
 -        VIEW3D_PT_tools_add_object.draw_add_mesh(layout)
 +        layout.operator("mesh.primitive_plane_add", text="Plane", icon='MESH_PLANE')
 +        layout.operator("mesh.primitive_cube_add", text="Cube", icon='MESH_CUBE')
 +        layout.operator("mesh.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
 +        layout.operator("mesh.primitive_uv_sphere_add", text="UV Sphere", icon='MESH_UVSPHERE')
 +        layout.operator("mesh.primitive_ico_sphere_add", text="Ico Sphere", icon='MESH_ICOSPHERE')
 +        layout.operator("mesh.primitive_cylinder_add", text="Cylinder", icon='MESH_CYLINDER')
 +        layout.operator("mesh.primitive_cone_add", text="Cone", icon='MESH_CONE')
 +        layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
 +
 +        layout.separator()
 +
 +        layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
 +        layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
  
  
  class INFO_MT_curve_add(Menu):
      bl_label = "Curve"
  
      def draw(self, context):
 -        from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
          layout = self.layout
  
          layout.operator_context = 'INVOKE_REGION_WIN'
  
 -        VIEW3D_PT_tools_add_object.draw_add_curve(layout)
 +        layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
 +        layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
 +
 +        layout.separator()
 +
 +        layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
 +        layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
 +        layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
 +
 +        layout.separator()
 +
 +        layout.operator("curve.draw", icon='LINE_DATA')
  
  
  class INFO_MT_surface_add(Menu):
      bl_label = "Surface"
  
      def draw(self, context):
 -        from .space_view3d_toolbar import VIEW3D_PT_tools_add_object
          layout = self.layout
  
          layout.operator_context = 'INVOKE_REGION_WIN'
  
 -        VIEW3D_PT_tools_add_object.draw_add_surface(layout)
 +        layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
 +        layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
 +
 +        layout.separator()
 +
 +        layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
 +        layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
 +        layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
 +
 +        layout.separator()
 +
 +        layout.operator("curve.draw", icon='LINE_DATA')
  
  
  class INFO_MT_metaball_add(Menu):
@@@ -1317,17 -1278,6 +1317,17 @@@ class INFO_MT_lamp_add(Menu)
          layout.operator_enum("object.lamp_add", "type")
  
  
 +class INFO_MT_lightprobe_add(Menu):
 +    bl_idname = "INFO_MT_lightprobe_add"
 +    bl_label = "Light Probe"
 +
 +    def draw(self, context):
 +        layout = self.layout
 +
 +        layout.operator_context = 'INVOKE_REGION_WIN'
 +        layout.operator_enum("object.lightprobe_add", "type")
 +
 +
  class INFO_MT_camera_add(Menu):
      bl_idname = "INFO_MT_camera_add"
      bl_label = "Camera"
@@@ -1376,8 -1326,6 +1376,8 @@@ class INFO_MT_add(Menu)
  
          layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP')
          layout.separator()
 +        layout.menu("INFO_MT_lightprobe_add", icon='OUTLINER_OB_LIGHTPROBE')
 +        layout.separator()
  
          layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_FORCE_FIELD')
          layout.separator()
@@@ -1436,6 -1384,8 +1436,6 @@@ class VIEW3D_MT_object(Menu)
  
      def draw(self, context):
          layout = self.layout
 -        view = context.space_data
 -        is_local_view = (view.local_view is not None)
  
          layout.menu("VIEW3D_MT_undo_redo")
  
          layout.menu("VIEW3D_MT_mirror")
          layout.menu("VIEW3D_MT_object_clear")
          layout.menu("VIEW3D_MT_object_apply")
 +        layout.menu("VIEW3D_MT_object_shading")
  
          layout.separator()
  
          layout.operator("object.duplicate_move")
          layout.operator("object.duplicate_move_linked")
          layout.operator("object.join")
 -        if is_local_view:
 -            layout.operator_context = 'EXEC_REGION_WIN'
 -            layout.operator("object.move_to_layer", text="Move out of Local View")
 -            layout.operator_context = 'INVOKE_REGION_WIN'
 -        else:
 -            layout.operator("object.move_to_layer", text="Move to Layer...")
 -
          layout.separator()
          layout.menu("VIEW3D_MT_make_links", text="Make Links...")
          layout.menu("VIEW3D_MT_object_relations")
          layout.separator()
  
          layout.menu("VIEW3D_MT_object_animation")
 +        layout.menu("VIEW3D_MT_object_rigid_body")
  
          layout.separator()
  
  
          layout.separator()
  
 -        layout.menu("VIEW3D_MT_object_game")
 -
 -        layout.separator()
 -
 -        layout.menu("VIEW3D_MT_object_showhide")
 -
          layout.operator_menu_enum("object.convert", "target")
  
  
@@@ -1498,32 -1459,6 +1498,32 @@@ class VIEW3D_MT_object_animation(Menu)
          layout.operator("nla.bake", text="Bake Action...")
  
  
 +class VIEW3D_MT_object_rigid_body(Menu):
 +    bl_label = "Rigid Body"
 +
 +    def draw(self, context):
 +        layout = self.layout
 +
 +        layout.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
 +        layout.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
 +
 +        layout.separator()
 +
 +        layout.operator("rigidbody.objects_remove", text="Remove")
 +
 +        layout.separator()
 +
 +        layout.operator("rigidbody.shape_change", text="Change Shape")
 +        layout.operator("rigidbody.mass_calculate", text="Calculate Mass")
 +        layout.operator("rigidbody.object_settings_copy", text="Copy from Active")
 +        layout.operator("object.visual_transform_apply", text="Apply Transformation")
 +        layout.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
 +
 +        layout.separator()
 +
 +        layout.operator("rigidbody.connect", text="Connect")
 +
 +
  class VIEW3D_MT_object_clear(Menu):
      bl_label = "Clear"
  
@@@ -1614,39 -1549,52 +1614,39 @@@ class VIEW3D_MT_object_specials(Menu)
  
              layout.operator_context = 'INVOKE_REGION_WIN'
  
 -            if scene.render.use_shading_nodes:
 -                emission_node = None
 -                if lamp.node_tree:
 -                    for node in lamp.node_tree.nodes:
 -                        if getattr(node, "type", None) == 'EMISSION':
 -                            emission_node = node
 -                            break
 -
 -                if emission_node is not None:
 -                    props = layout.operator("wm.context_modal_mouse", text="Strength")
 -                    props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.node_tree" \
 -                                           ".nodes[\"" + emission_node.name + "\"]" \
 -                                           ".inputs[\"Strength\"].default_value"
 -                    props.header_text = "Lamp Strength: %.3f"
 -                    props.input_scale = 0.1
 -
 -                if lamp.type == 'AREA':
 -                    props = layout.operator("wm.context_modal_mouse", text="Size X")
 -                    props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.size"
 -                    props.header_text = "Lamp Size X: %.3f"
 +            emission_node = None
 +            if lamp.node_tree:
 +                for node in lamp.node_tree.nodes:
 +                    if getattr(node, "type", None) == 'EMISSION':
 +                        emission_node = node
 +                        break
  
 -                    if lamp.shape == 'RECTANGLE':
 -                        props = layout.operator("wm.context_modal_mouse", text="Size Y")
 -                        props.data_path_iter = "selected_editable_objects"
 -                        props.data_path_item = "data.size_y"
 -                        props.header_text = "Lamp Size Y: %.3f"
 +            if emission_node is not None:
 +                props = layout.operator("wm.context_modal_mouse", text="Strength")
 +                props.data_path_iter = "selected_editable_objects"
 +                props.data_path_item = "data.node_tree" \
 +                                       ".nodes[\"" + emission_node.name + "\"]" \
 +                                       ".inputs[\"Strength\"].default_value"
 +                props.header_text = "Lamp Strength: %.3f"
 +                props.input_scale = 0.1
  
 -                elif lamp.type in {'SPOT', 'POINT', 'SUN'}:
 -                    props = layout.operator("wm.context_modal_mouse", text="Size")
 -                    props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.shadow_soft_size"
 -                    props.header_text = "Lamp Size: %.3f"
 -            else:
 -                props = layout.operator("wm.context_modal_mouse", text="Energy")
 +            if lamp.type == 'AREA':
 +                props = layout.operator("wm.context_modal_mouse", text="Size X")
                  props.data_path_iter = "selected_editable_objects"
 -                props.data_path_item = "data.energy"
 -                props.header_text = "Lamp Energy: %.3f"
 +                props.data_path_item = "data.size"
 +                props.header_text = "Lamp Size X: %.3f"
  
 -                if lamp.type in {'SPOT', 'AREA', 'POINT'}:
 -                    props = layout.operator("wm.context_modal_mouse", text="Falloff Distance")
 +                if lamp.shape == 'RECTANGLE':
 +                    props = layout.operator("wm.context_modal_mouse", text="Size Y")
                      props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.distance"
 -                    props.input_scale = 0.1
 -                    props.header_text = "Lamp Falloff Distance: %.1f"
 +                    props.data_path_item = "data.size_y"
 +                    props.header_text = "Lamp Size Y: %.3f"
 +
 +            elif lamp.type in {'SPOT', 'POINT', 'SUN'}:
 +                props = layout.operator("wm.context_modal_mouse", text="Size")
 +                props.data_path_iter = "selected_editable_objects"
 +                props.data_path_item = "data.shadow_soft_size"
 +                props.header_text = "Lamp Size: %.3f"
  
              if lamp.type == 'SPOT':
                  layout.separator()
                  props.input_scale = -0.01
                  props.header_text = "Spot Blend: %.2f"
  
 -                if not scene.render.use_shading_nodes:
 -                    props = layout.operator("wm.context_modal_mouse", text="Clip Start")
 -                    props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.shadow_buffer_clip_start"
 -                    props.input_scale = 0.05
 -                    props.header_text = "Clip Start: %.2f"
 -
 -                    props = layout.operator("wm.context_modal_mouse", text="Clip End")
 -                    props.data_path_iter = "selected_editable_objects"
 -                    props.data_path_item = "data.shadow_buffer_clip_end"
 -                    props.input_scale = 0.05
 -                    props.header_text = "Clip End: %.2f"
 -
          layout.separator()
  
          props = layout.operator("object.isolate_type_render")
          props = layout.operator("object.hide_render_clear_all")
  
  
 +class VIEW3D_MT_object_shading(Menu):
 +    # XXX, this menu is a place to store shading operator in object mode
 +    bl_label = "Shading"
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.operator("object.shade_smooth", text="Smooth")
 +        layout.operator("object.shade_flat", text="Flat")
 +
 +
  class VIEW3D_MT_object_apply(Menu):
      bl_label = "Apply"
  
@@@ -1804,6 -1755,20 +1804,6 @@@ class VIEW3D_MT_object_quick_effects(Me
          layout.operator("object.quick_fluid")
  
  
 -class VIEW3D_MT_object_showhide(Menu):
 -    bl_label = "Show/Hide"
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        layout.operator("object.hide_view_clear", text="Show Hidden")
 -
 -        layout.separator()
 -
 -        layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
 -        layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
 -
 -
  class VIEW3D_MT_make_single_user(Menu):
      bl_label = "Make Single User"
  
          props.object = props.obdata = True
          props.material = props.texture = props.animation = False
  
 -        props = layout.operator("object.make_single_user", text="Object & Data & Materials+Tex")
 -        props.object = props.obdata = props.material = props.texture = True
 +        props = layout.operator("object.make_single_user", text="Object & Data & Materials")
 +        props.object = props.obdata = props.material = True
          props.animation = False
  
 -        props = layout.operator("object.make_single_user", text="Materials+Tex")
 -        props.material = props.texture = True
 +        props = layout.operator("object.make_single_user", text="Materials")
 +        props.material = True
          props.object = props.obdata = props.animation = False
  
          props = layout.operator("object.make_single_user", text="Object Animation")
          props.animation = True
 -        props.object = props.obdata = props.material = props.texture = False
 +        props.object = props.obdata = props.material = False
  
  
  class VIEW3D_MT_make_links(Menu):
          layout.operator("object.join_uvs")  # stupid place to add this!
  
  
 -class VIEW3D_MT_object_game(Menu):
 -    bl_label = "Game"
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        layout.operator("object.logic_bricks_copy", text="Copy Logic Bricks")
 -        layout.operator("object.game_physics_copy", text="Copy Physics Properties")
 -
 -        layout.separator()
 -
 -        layout.operator("object.game_property_copy", text="Replace Properties").operation = 'REPLACE'
 -        layout.operator("object.game_property_copy", text="Merge Properties").operation = 'MERGE'
 -        layout.operator_menu_enum("object.game_property_copy", "property", text="Copy Properties...")
 -
 -        layout.separator()
 -
 -        layout.operator("object.game_property_clear")
 -
 -
  class VIEW3D_MT_brush(Menu):
      bl_label = "Brush"
  
@@@ -2002,18 -1987,17 +2002,18 @@@ class VIEW3D_MT_vertex_group(Menu)
  class VIEW3D_MT_paint_weight(Menu):
      bl_label = "Weights"
  
 -    def draw(self, context):
 -        layout = self.layout
 +    @staticmethod
 +    def draw_generic(layout, is_editmode=False):
  
 -        layout.menu("VIEW3D_MT_undo_redo")
 +        if not is_editmode:
 +            layout.menu("VIEW3D_MT_undo_redo")
  
 -        layout.separator()
 +            layout.separator()
  
 -        layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC'
 -        layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES'
 +            layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC'
 +            layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES'
  
 -        layout.separator()
 +            layout.separator()
  
          layout.operator("object.vertex_group_normalize_all", text="Normalize All")
          layout.operator("object.vertex_group_normalize", text="Normalize")
          layout.operator("object.vertex_group_levels", text="Levels")
          layout.operator("object.vertex_group_smooth", text="Smooth")
  
 -        props = layout.operator("object.data_transfer", text="Transfer Weights")
 -        props.use_reverse_transfer = True
 -        props.data_type = 'VGROUP_WEIGHTS'
 +        if not is_editmode:
 +            props = layout.operator("object.data_transfer", text="Transfer Weights")
 +            props.use_reverse_transfer = True
 +            props.data_type = 'VGROUP_WEIGHTS'
  
          layout.operator("object.vertex_group_limit_total", text="Limit Total")
          layout.operator("object.vertex_group_fix", text="Fix Deforms")
  
 -        layout.separator()
  
 -        layout.operator("paint.weight_set")
 +        if not is_editmode:
 +            layout.separator()
 +
 +            layout.operator("paint.weight_set")
 +
 +    def draw(self, context):
 +        self.draw_generic(self.layout, is_editmode=False);
  
  
  class VIEW3D_MT_sculpt(Menu):
@@@ -2521,8 -2499,6 +2521,8 @@@ class VIEW3D_MT_edit_mesh(Menu)
          layout.separator()
  
          layout.menu("VIEW3D_MT_edit_mesh_normals")
 +        layout.menu("VIEW3D_MT_edit_mesh_shading")
 +        layout.menu("VIEW3D_MT_edit_mesh_weights")
          layout.menu("VIEW3D_MT_edit_mesh_clean")
  
          layout.separator()
@@@ -2654,8 -2630,10 +2654,10 @@@ class VIEW3D_MT_edit_mesh_vertices(Menu
  
          layout.operator("mesh.merge")
          layout.operator("mesh.remove_doubles")
-         layout.operator("mesh.rip_move")
-         layout.operator("mesh.rip_move_fill")
+         props = layout.operator("mesh.rip_move")
+         props.MESH_OT_rip.use_fill = False
+         props = layout.operator("mesh.rip_move", text="Rip Fill")
+         props.MESH_OT_rip.use_fill = True
          layout.operator("mesh.rip_edge_move")
          layout.operator("mesh.split")
          layout.operator_menu_enum("mesh.separate", "type")
@@@ -2827,33 -2805,6 +2829,33 @@@ class VIEW3D_MT_edit_mesh_normals(Menu)
          layout.separator()
  
          layout.operator("mesh.flip_normals")
 +        layout.operator("mesh.set_normals_from_faces", text="Set From Faces")
 +
 +
 +class VIEW3D_MT_edit_mesh_shading(Menu):
 +    bl_label = "Shading"
 +
 +    def draw(self, context):
 +        layout = self.layout
 +
 +        layout.label(text="Faces:")
 +        layout.operator("mesh.faces_shade_smooth", text="Smooth")
 +        layout.operator("mesh.faces_shade_flat", text="Flat")
 +        layout.label(text="Edges:")
 +        layout.operator("mesh.mark_sharp", text="Smooth").clear = True
 +        layout.operator("mesh.mark_sharp", text="Sharp")
 +        layout.label(text="Vertices:")
 +        props = layout.operator("mesh.mark_sharp", text="Smooth")
 +        props.use_verts = True
 +        props.clear = True
 +        layout.operator("mesh.mark_sharp", text="Sharp").use_verts = True
 +
 +
 +class VIEW3D_MT_edit_mesh_weights(Menu):
 +    bl_label = "Weights"
 +
 +    def draw(self, context):
 +        VIEW3D_MT_paint_weight.draw_generic(self.layout, is_editmode=True)
  
  
  class VIEW3D_MT_edit_mesh_clean(Menu):
@@@ -3528,179 -3479,68 +3530,179 @@@ class VIEW3D_PT_view3d_name(Panel)
                  row.prop(bone, "name", text="")
  
  
 -class VIEW3D_PT_view3d_display(Panel):
 +class VIEW3D_PT_shading(Panel):
      bl_space_type = 'VIEW_3D'
 -    bl_region_type = 'UI'
 -    bl_label = "Display"
 -    bl_options = {'DEFAULT_CLOSED'}
 +    bl_region_type = 'HEADER'
 +    bl_label = "Shading"
  
      @classmethod
      def poll(cls, context):
 +        return True
 +
 +    def draw(self, context):
 +        layout = self.layout
 +
          view = context.space_data
 -        return (view)
 +        shading = view.shading
 +
 +        col = layout.column()
 +        col.prop(shading, "type", expand=True)
 +
 +        if shading.type == 'SOLID':
 +            col.separator()
 +            col.row().prop(shading, "color_type", expand=True)
 +
 +            if shading.color_type == 'SINGLE':
 +                col.separator()
 +                col.row().prop(shading, "single_color", text="")
 +
 +        if shading.type in ('SOLID', 'TEXTURED'):
 +            col.separator()
 +            col.row().prop(shading, "light", expand=True)
 +            if shading.light == 'STUDIO':
 +                col.row().template_icon_view(shading, "studio_light")
 +
 +            col.separator()
 +
 +            row = col.row()
 +            row.prop(shading, "show_shadows")
 +            sub = row.row()
 +            sub.active = shading.show_shadows
 +            sub.prop(shading, "shadow_intensity", text="")
 +
 +            col.prop(shading, "show_object_overlap")
 +
 +
 +class VIEW3D_PT_overlay(Panel):
 +    bl_space_type = 'VIEW_3D'
 +    bl_region_type = 'HEADER'
 +    bl_label = "Overlay"
 +
 +    @classmethod
 +    def poll(cls, context):
 +        return True
  
      def draw(self, context):
          layout = self.layout
  
          view = context.space_data
 +        overlay = view.overlay
          scene = context.scene
 +        toolsettings = context.tool_settings
 +        display_all = overlay.show_overlays
  
          col = layout.column()
 -        col.prop(view, "show_only_render")
 +        col.prop(overlay, "show_overlays")
 +        col.separator()
          col.prop(view, "show_world")
  
          col = layout.column()
 -        display_all = not view.show_only_render
          col.active = display_all
 -        col.prop(view, "show_outline_selected")
 -        col.prop(view, "show_all_objects_origin")
 -        col.prop(view, "show_relationship_lines")
 +        col.prop(overlay, "show_cursor")
 +
 +        col = layout.column()
 +        col.active = display_all
 +        col.prop(overlay, "show_outline_selected")
 +        col.prop(overlay, "show_all_objects_origin")
 +        col.prop(overlay, "show_relationship_lines")
 +        col.prop(overlay, "show_face_orientation")
 +        col.prop(overlay, "show_backface_culling")
  
          col = layout.column()
          col.active = display_all
          split = col.split(percentage=0.55)
 -        split.prop(view, "show_floor", text="Grid Floor")
 +        split.prop(overlay, "show_floor", text="Grid Floor")
  
          row = split.row(align=True)
 -        row.prop(view, "show_axis_x", text="X", toggle=True)
 -        row.prop(view, "show_axis_y", text="Y", toggle=True)
 -        row.prop(view, "show_axis_z", text="Z", toggle=True)
 +        row.prop(overlay, "show_axis_x", text="X", toggle=True)
 +        row.prop(overlay, "show_axis_y", text="Y", toggle=True)
 +        row.prop(overlay, "show_axis_z", text="Z", toggle=True)
  
          sub = col.column(align=True)
 -        sub.active = bool(view.show_floor or view.region_quadviews or not view.region_3d.is_perspective)
 +        sub.active = bool(overlay.show_floor or view.region_quadviews or not view.region_3d.is_perspective)
          subsub = sub.column(align=True)
 -        subsub.active = view.show_floor
 -        subsub.prop(view, "grid_lines", text="Lines")
 -        sub.prop(view, "grid_scale", text="Scale")
 +        subsub.active = overlay.show_floor
 +        subsub.prop(overlay, "grid_lines", text="Lines")
 +        sub.prop(overlay, "grid_scale", text="Scale")
          subsub = sub.column(align=True)
          subsub.active = scene.unit_settings.system == 'NONE'
 -        subsub.prop(view, "grid_subdivisions", text="Subdivisions")
 +        subsub.prop(overlay, "grid_subdivisions", text="Subdivisions")
  
 -        layout.separator()
  
 -        layout.operator("screen.region_quadview", text="Toggle Quad View")
  
 -        if view.region_quadviews:
 -            region = view.region_quadviews[2]
 +        if context.mode == 'EDIT_MESH':
 +            col.separator()
 +            col.label(text="Edit Mode:")
 +
 +            col.prop(overlay, "show_occlude_wire")
 +
 +            col.prop(overlay, "show_weight")
 +            col.label("Show Zero Weights:")
 +            col.row().prop(toolsettings, "vertex_group_user", expand=True)
 +
 +            col.label(text="Normals:")
 +            row = col.row(align=True)
 +
 +            row.prop(overlay, "show_vertex_normals", text="", icon='VERTEXSEL')
 +            row.prop(overlay, "show_split_normals", text="", icon='LOOPSEL')
 +            row.prop(overlay, "show_face_normals", text="", icon='FACESEL')
 +
 +            sub = row.row(align=True)
 +            sub.active = overlay.show_vertex_normals or overlay.show_face_normals or overlay.show_split_normals
 +            sub.prop(overlay, "normals_length", text="Size")
 +
 +        elif context.mode == 'POSE':
 +            col.separator()
 +            col.label(text="Pose Mode:")
 +
              col = layout.column()
 -            col.prop(region, "lock_rotation")
 -            row = col.row()
 -            row.enabled = region.lock_rotation
 -            row.prop(region, "show_sync_view")
 -            row = col.row()
 -            row.enabled = region.lock_rotation and region.show_sync_view
 -            row.prop(region, "use_box_clip")
 +            col.active = display_all
 +            col.prop(overlay, "transparent_bones")
 +            col.prop(overlay, "show_bone_selection")
 +
 +        elif context.mode == 'EDIT_ARMATURE':
 +            col.separator()
 +            col.label(text="Edit Armature:")
 +
 +            col = layout.column()
 +            col.active = display_all
 +            col.prop(overlay, "transparent_bones")
 +
 +        elif context.mode in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
 +            col.separator()
 +            col.label(text="Paint Mode:")
 +
 +            if context.mode in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
 +                col.prop(overlay, "show_paint_wire")
 +
 +            col.prop(view, "show_mode_shade_override")
 +
 +
 +class VIEW3D_PT_quad_view(Panel):
 +    bl_space_type = 'VIEW_3D'
 +    bl_region_type = 'UI'
 +    bl_label = "Quad View"
 +    bl_options = {'DEFAULT_CLOSED'}
 +
 +    @classmethod
 +    def poll(cls, context):
 +        view = context.space_data
 +        return view.region_quadviews
 +
 +    def draw(self, context):
 +        layout = self.layout
 +
 +        view = context.space_data
 +
 +        region = view.region_quadviews[2]
 +        col = layout.column()
 +        col.prop(region, "lock_rotation")
 +        row = col.row()
 +        row.enabled = region.lock_rotation
 +        row.prop(region, "show_sync_view")
 +        row = col.row()
 +        row.enabled = region.lock_rotation and region.show_sync_view
 +        row.prop(region, "use_box_clip")
  
  
  class VIEW3D_PT_view3d_stereo(Panel):
          split.prop(view, "stereo_3d_volume_alpha", text="Alpha")
  
  
 -class VIEW3D_PT_view3d_shading(Panel):
 -    bl_space_type = 'VIEW_3D'
 -    bl_region_type = 'UI'
 -    bl_label = "Shading"
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        view = context.space_data
 -        scene = context.scene
 -        gs = scene.game_settings
 -        obj = context.object
 -
 -        col = layout.column()
 -
 -        if not scene.render.use_shading_nodes:
 -            col.prop(gs, "material_mode", text="")
 -
 -        if view.viewport_shade == 'SOLID':
 -            col.prop(view, "show_textured_solid")
 -            col.prop(view, "use_matcap")
 -            if view.use_matcap:
 -                col.template_icon_view(view, "matcap_icon")
 -        if view.viewport_shade == 'TEXTURED' or context.mode == 'PAINT_TEXTURE':
 -            if scene.render.use_shading_nodes or gs.material_mode != 'GLSL':
 -                col.prop(view, "show_textured_shadeless")
 -
 -        col.prop(view, "show_backface_culling")
 -
 -        if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
 -            if obj and obj.mode == 'EDIT':
 -                col.prop(view, "show_occlude_wire")
 -
 -        fx_settings = view.fx_settings
 -
 -        if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
 -            sub = col.column()
 -            sub.active = view.region_3d.view_perspective == 'CAMERA'
 -            sub.prop(fx_settings, "use_dof")
 -            col.prop(fx_settings, "use_ssao", text="Ambient Occlusion")
 -            if fx_settings.use_ssao:
 -                ssao_settings = fx_settings.ssao
 -                subcol = col.column(align=True)
 -                subcol.prop(ssao_settings, "factor")
 -                subcol.prop(ssao_settings, "distance_max")
 -                subcol.prop(ssao_settings, "attenuation")
 -                subcol.prop(ssao_settings, "samples")
 -                subcol.prop(ssao_settings, "color")
 -
 -
  class VIEW3D_PT_view3d_motion_tracking(Panel):
      bl_space_type = 'VIEW_3D'
      bl_region_type = 'UI'
@@@ -3801,6 -3691,8 +3803,6 @@@ class VIEW3D_PT_view3d_meshdisplay(Pane
          if with_freestyle:
              col.prop(mesh, "show_edge_seams", text="Seams")
  
 -        layout.prop(mesh, "show_weight")
 -
          col = split.column()
          col.label()
          if not with_freestyle:
  
          col = layout.column()
  
 -        col.separator()
 -        col.label(text="Normals:")
 -        row = col.row(align=True)
 -
 -        row.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
 -        row.prop(mesh, "show_normal_loop", text="", icon='LOOPSEL')
 -        row.prop(mesh, "show_normal_face", text="", icon='FACESEL')
 -
 -        sub = row.row(align=True)
 -        sub.active = mesh.show_normal_vertex or mesh.show_normal_face or mesh.show_normal_loop
 -        sub.prop(scene.tool_settings, "normal_size", text="Size")
 -
          col.separator()
          split = layout.split()
          col = split.column()
@@@ -3895,6 -3799,113 +3897,6 @@@ class VIEW3D_PT_view3d_curvedisplay(Pan
          col.prop(context.scene.tool_settings, "normal_size", text="Normal Size")
  
  
 -class VIEW3D_PT_background_image(Panel):
 -    bl_space_type = 'VIEW_3D'
 -    bl_region_type = 'UI'
 -    bl_label = "Background Images"
 -    bl_options = {'DEFAULT_CLOSED'}
 -
 -    def draw_header(self, context):
 -        view = context.space_data
 -
 -        self.layout.prop(view, "show_background_images", text="")
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        view = context.space_data
 -        use_multiview = context.scene.render.use_multiview
 -
 -        col = layout.column()
 -        col.operator("view3d.background_image_add", text="Add Image")
 -
 -        for i, bg in enumerate(view.background_images):
 -            layout.active = view.show_background_images
 -            box = layout.box()
 -            row = box.row(align=True)
 -            row.prop(bg, "show_expanded", text="", emboss=False)
 -            if bg.source == 'IMAGE' and bg.image:
 -                row.prop(bg.image, "name", text="", emboss=False)
 -            elif bg.source == 'MOVIE_CLIP' and bg.clip:
 -                row.prop(bg.clip, "name", text="", emboss=False)
 -            else:
 -                row.label(text="Not Set")
 -
 -            if bg.show_background_image:
 -                row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_OFF')
 -            else:
 -                row.prop(bg, "show_background_image", text="", emboss=False, icon='RESTRICT_VIEW_ON')
 -
 -            row.operator("view3d.background_image_remove", text="", emboss=False, icon='X').index = i
 -
 -            box.prop(bg, "view_axis", text="Axis")
 -
 -            if bg.show_expanded:
 -                row = box.row()
 -                row.prop(bg, "source", expand=True)
 -
 -                has_bg = False
 -                if bg.source == 'IMAGE':
 -                    row = box.row()
 -                    row.template_ID(bg, "image", open="image.open")
 -                    if bg.image is not None:
 -                        box.template_image(bg, "image", bg.image_user, compact=True)
 -                        has_bg = True
 -
 -                        if use_multiview and bg.view_axis in {'CAMERA', 'ALL'}:
 -                            box.prop(bg.image, "use_multiview")
 -
 -                            column = box.column()
 -                            column.active = bg.image.use_multiview
 -
 -                            column.label(text="Views Format:")
 -                            column.row().prop(bg.image, "views_format", expand=True)
 -
 -                            sub = column.box()
 -                            sub.active = bg.image.views_format == 'STEREO_3D'
 -                            sub.template_image_stereo_3d(bg.image.stereo_3d_format)
 -
 -                elif bg.source == 'MOVIE_CLIP':
 -                    box.prop(bg, "use_camera_clip")
 -
 -                    column = box.column()
 -                    column.active = not bg.use_camera_clip
 -                    column.template_ID(bg, "clip", open="clip.open")
 -
 -                    if bg.clip:
 -                        column.template_movieclip(bg, "clip", compact=True)
 -
 -                    if bg.use_camera_clip or bg.clip:
 -                        has_bg = True
 -
 -                    column = box.column()
 -                    column.active = has_bg
 -                    column.prop(bg.clip_user, "proxy_render_size", text="")
 -                    column.prop(bg.clip_user, "use_render_undistorted")
 -
 -                if has_bg:
 -                    col = box.column()
 -                    col.prop(bg, "opacity", slider=True)
 -                    col.row().prop(bg, "draw_depth", expand=True)
 -
 -                    if bg.view_axis in {'CAMERA', 'ALL'}:
 -                        col.row().prop(bg, "frame_method", expand=True)
 -
 -                    box = col.box()
 -                    row = box.row()
 -                    row.prop(bg, "offset_x", text="X")
 -                    row.prop(bg, "offset_y", text="Y")
 -
 -                    row = box.row()
 -                    row.prop(bg, "use_flip_x")
 -                    row.prop(bg, "use_flip_y")
 -
 -                    row = box.row()
 -                    if bg.view_axis != 'CAMERA':
 -                        row.prop(bg, "rotation")
 -                        row.prop(bg, "size")
 -
 -
  class VIEW3D_PT_transform_orientations(Panel):
      bl_space_type = 'VIEW_3D'
      bl_region_type = 'UI'
      def draw(self, context):
          layout = self.layout
  
 -        view = context.space_data
 -        orientation = view.current_orientation
 +        scene = context.scene
 +        orientation = scene.current_orientation
  
          row = layout.row(align=True)
 -        row.prop(view, "transform_orientation", text="")
 +        row.prop(scene, "transform_orientation", text="")
          row.operator("transform.create_orientation", text="", icon='ZOOMIN')
  
          if orientation:
              row.operator("transform.delete_orientation", text="", icon='X')
  
  
 -class VIEW3D_PT_etch_a_ton(Panel):
 -    bl_space_type = 'VIEW_3D'
 -    bl_region_type = 'UI'
 -    bl_label = "Skeleton Sketching"
 -    bl_options = {'DEFAULT_CLOSED'}
 -
 -    @classmethod
 -    def poll(cls, context):
 -        scene = context.space_data
 -        ob = context.active_object
 -        return scene and ob and ob.type == 'ARMATURE' and ob.mode == 'EDIT'
 -
 -    def draw_header(self, context):
 -        layout = self.layout
 -        toolsettings = context.scene.tool_settings
 -
 -        layout.prop(toolsettings, "use_bone_sketching", text="")
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        toolsettings = context.scene.tool_settings
 -
 -        col = layout.column()
 -
 -        col.prop(toolsettings, "use_etch_quick")
 -        col.prop(toolsettings, "use_etch_overdraw")
 -
 -        col.separator()
 -
 -        col.prop(toolsettings, "etch_convert_mode")
 -
 -        if toolsettings.etch_convert_mode == 'LENGTH':
 -            col.prop(toolsettings, "etch_length_limit")
 -        elif toolsettings.etch_convert_mode == 'ADAPTIVE':
 -            col.prop(toolsettings, "etch_adaptive_limit")
 -        elif toolsettings.etch_convert_mode == 'FIXED':
 -            col.prop(toolsettings, "etch_subdivision_number")
 -        elif toolsettings.etch_convert_mode == 'RETARGET':
 -            col.prop(toolsettings, "etch_template")
 -            col.prop(toolsettings, "etch_roll_mode")
 -
 -            col.separator()
 -
 -            colsub = col.column(align=True)
 -            colsub.prop(toolsettings, "use_etch_autoname")
 -            sub = colsub.column(align=True)
 -            sub.enabled = not toolsettings.use_etch_autoname
 -            sub.prop(toolsettings, "etch_number")
 -            sub.prop(toolsettings, "etch_side")
 -
 -        col.separator()
 -
 -        col.operator("sketch.convert", text="Convert to Bones")
 -        col.operator("sketch.delete", text="Delete Strokes")
 -
 -
  class VIEW3D_PT_context_properties(Panel):
      bl_space_type = 'VIEW_3D'
      bl_region_type = 'UI'
@@@ -4007,25 -4075,24 +4009,25 @@@ classes = 
      INFO_MT_edit_armature_add,
      INFO_MT_armature_add,
      INFO_MT_lamp_add,
 +    INFO_MT_lightprobe_add,
      INFO_MT_camera_add,
      INFO_MT_add,
      VIEW3D_MT_undo_redo,
      VIEW3D_MT_object_relations,
      VIEW3D_MT_object,
      VIEW3D_MT_object_animation,
 +    VIEW3D_MT_object_rigid_body,
      VIEW3D_MT_object_clear,
      VIEW3D_MT_object_specials,
 +    VIEW3D_MT_object_shading,
      VIEW3D_MT_object_apply,
      VIEW3D_MT_object_parent,
      VIEW3D_MT_object_track,
      VIEW3D_MT_object_group,
      VIEW3D_MT_object_constraints,
      VIEW3D_MT_object_quick_effects,
 -    VIEW3D_MT_object_showhide,
      VIEW3D_MT_make_single_user,
      VIEW3D_MT_make_links,
 -    VIEW3D_MT_object_game,
      VIEW3D_MT_brush,
      VIEW3D_MT_brush_paint_modes,
      VIEW3D_MT_paint_vertex,
      VIEW3D_MT_edit_mesh_edges_data,
      VIEW3D_MT_edit_mesh_faces,
      VIEW3D_MT_edit_mesh_normals,
 +    VIEW3D_MT_edit_mesh_shading,
 +    VIEW3D_MT_edit_mesh_weights,
      VIEW3D_MT_edit_mesh_clean,
      VIEW3D_MT_edit_mesh_delete,
      VIEW3D_MT_edit_mesh_showhide,
      VIEW3D_PT_view3d_properties,
      VIEW3D_PT_view3d_cursor,
      VIEW3D_PT_view3d_name,
 -    VIEW3D_PT_view3d_display,
 +    VIEW3D_PT_quad_view,
      VIEW3D_PT_view3d_stereo,
 -    VIEW3D_PT_view3d_shading,
      VIEW3D_PT_view3d_motion_tracking,
      VIEW3D_PT_view3d_meshdisplay,
      VIEW3D_PT_view3d_meshstatvis,
      VIEW3D_PT_view3d_curvedisplay,
 -    VIEW3D_PT_background_image,
 +    VIEW3D_PT_shading,
 +    VIEW3D_PT_overlay,
      VIEW3D_PT_transform_orientations,
 -    VIEW3D_PT_etch_a_ton,
      VIEW3D_PT_context_properties,
  )
  
index dc9cd29a0af0f0bdc1b99679777f2bd69277711b,daf0b51f594bf213871cad4910863030aa8cc89c..9f3ef6f958da739103d83db55af1e70057b831b4
@@@ -77,16 -77,12 +77,16 @@@ void ED_operatortypes_mesh(void
        WM_operatortype_append(MESH_OT_primitive_monkey_add);
        WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
        WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
 +
 +      WM_operatortype_append(MESH_OT_primitive_cube_add_manipulator);
 +
        WM_operatortype_append(MESH_OT_duplicate);
        WM_operatortype_append(MESH_OT_remove_doubles);
        WM_operatortype_append(MESH_OT_spin);
        WM_operatortype_append(MESH_OT_screw);
  
        WM_operatortype_append(MESH_OT_extrude_region);
 +      WM_operatortype_append(MESH_OT_extrude_context);
        WM_operatortype_append(MESH_OT_extrude_faces_indiv);
        WM_operatortype_append(MESH_OT_extrude_edges_indiv);
        WM_operatortype_append(MESH_OT_extrude_verts_indiv);
  #endif
        WM_operatortype_append(MESH_OT_vertices_smooth);
        WM_operatortype_append(MESH_OT_vertices_smooth_laplacian);
 -      WM_operatortype_append(MESH_OT_noise);
        WM_operatortype_append(MESH_OT_flip_normals);
        WM_operatortype_append(MESH_OT_rip);
        WM_operatortype_append(MESH_OT_rip_edge);
        WM_operatortype_append(MESH_OT_blend_from_shape);
        WM_operatortype_append(MESH_OT_shape_propagate_to_all);
 -      
 +
 +      /* editmesh_polybuild */
 +      WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
 +      WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
 +      WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
 +      WM_operatortype_append(MESH_OT_polybuild_hover);
 +
        WM_operatortype_append(MESH_OT_uv_texture_add);
        WM_operatortype_append(MESH_OT_uv_texture_remove);
        WM_operatortype_append(MESH_OT_vertex_color_add);
        WM_operatortype_append(MESH_OT_bisect);
        WM_operatortype_append(MESH_OT_symmetrize);
        WM_operatortype_append(MESH_OT_symmetry_snap);
 -
 -#ifdef WITH_GAMEENGINE
 -      WM_operatortype_append(MESH_OT_navmesh_make);
 -      WM_operatortype_append(MESH_OT_navmesh_face_copy);
 -      WM_operatortype_append(MESH_OT_navmesh_face_add);
 -      WM_operatortype_append(MESH_OT_navmesh_reset);
 -      WM_operatortype_append(MESH_OT_navmesh_clear);
 -#endif
  }
  
  #if 0 /* UNUSED, remove? */
@@@ -244,16 -243,6 +244,6 @@@ void ED_operatormacros_mesh(void
        ot = WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", "Rip polygons and move the result",
                                          OPTYPE_UNDO | OPTYPE_REGISTER);
        otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
-       RNA_boolean_set(otmacro->ptr, "use_fill", false);
-       otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
-       RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", false);
-       /* annoying we can't pass 'use_fill' through the macro */
-       ot = WM_operatortype_append_macro("MESH_OT_rip_move_fill", "Rip Fill", "Rip-fill polygons and move the result",
-                                         OPTYPE_UNDO | OPTYPE_REGISTER);
-       otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
-       RNA_boolean_set(otmacro->ptr, "use_fill", true);
        otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", false);
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", false);
  
 +      ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move", "Extrude Region and Move",
 +                                        "Extrude context and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
 +      otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_context");
 +      otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
 +      RNA_enum_set(otmacro->ptr, "proportional", 0);
 +      RNA_boolean_set(otmacro->ptr, "mirror", false);
 +
        ot = WM_operatortype_append_macro("MESH_OT_extrude_region_shrink_fatten", "Extrude Region and Shrink/Fatten",
                                          "Extrude region and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
        otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
        otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
        RNA_boolean_set(otmacro->ptr, "mirror", false);
 +
 +
 +      ot = WM_operatortype_append_macro(
 +              "MESH_OT_polybuild_face_at_cursor_move", "Face At Cursor Move", "",
 +              OPTYPE_UNDO | OPTYPE_REGISTER);
 +      WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor");
 +      otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
 +      RNA_enum_set(otmacro->ptr, "proportional", 0);
 +      RNA_boolean_set(otmacro->ptr, "mirror", false);
 +
 +      ot = WM_operatortype_append_macro(
 +              "MESH_OT_polybuild_split_at_cursor_move", "Split At Cursor Move", "",
 +              OPTYPE_UNDO | OPTYPE_REGISTER);
 +      WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor");
 +      otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
 +      RNA_enum_set(otmacro->ptr, "proportional", 0);
 +      RNA_boolean_set(otmacro->ptr, "mirror", false);
  }
  
  /* note mesh keymap also for other space? */
@@@ -428,8 -393,16 +418,16 @@@ void ED_keymap_mesh(wmKeyConfig *keycon
  
        WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
  
-       WM_keymap_add_item(keymap, "MESH_OT_rip_move", VKEY, KM_PRESS, 0, 0);
-       WM_keymap_add_item(keymap, "MESH_OT_rip_move_fill", VKEY, KM_PRESS, KM_ALT, 0);
+       kmi = WM_keymap_add_item(keymap, "MESH_OT_rip_move", VKEY, KM_PRESS, 0, 0);
+       {
+               PointerRNA macro_ptr = RNA_pointer_get(kmi->ptr, "MESH_OT_rip");
+               RNA_boolean_set(&macro_ptr, "use_fill", false);
+       }
+       kmi = WM_keymap_add_item(keymap, "MESH_OT_rip_move", VKEY, KM_PRESS, KM_ALT, 0);
+       {
+               PointerRNA macro_ptr = RNA_pointer_get(kmi->ptr, "MESH_OT_rip");
+               RNA_boolean_set(&macro_ptr, "use_fill", true);
+       }
  
        WM_keymap_add_item(keymap, "MESH_OT_rip_edge_move", DKEY, KM_PRESS, KM_ALT, 0);
  
index f0bd033f0336c59284e22814a31f12ef5828edb4,f8bebf3898b8021dc269562837dcd53a2405671b..b141433a58f01fc961489d3455b05374b03919d5
  #include "BKE_context.h"
  #include "BKE_idprop.h"
  #include "BKE_global.h"
 +#include "BKE_layer.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_screen.h"
 +#include "BKE_workspace.h"
  
  #include "BKE_sound.h"
  
  
  #include "RNA_access.h"
  
 -#include "GPU_debug.h"
 -
  #include "UI_interface.h"
  
  #include "PIL_time.h"
  
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
  #include "wm.h"
  #include "wm_window.h"
  #include "wm_event_system.h"
@@@ -87,8 -86,6 +87,8 @@@
  
  #include "RNA_enum_types.h"
  
 +#include "DEG_depsgraph.h"
 +
  /* Motion in pixels allowed before we don't consider single/double click. */
  #define WM_EVENT_CLICK_WIGGLE_ROOM 2
  
@@@ -185,6 -182,7 +185,6 @@@ static bool wm_test_duplicate_notifier(
  /* XXX: in future, which notifiers to send to other windows? */
  void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference)
  {
 -      ARegion *ar;
        wmWindowManager *wm = CTX_wm_manager(C);
        wmNotifier *note;
  
        
        note->window = CTX_wm_window(C);
        
 -      ar = CTX_wm_region(C);
 -      if (ar)
 -              note->swinid = ar->swinid;
 -      
        note->category = type & NOTE_CATEGORY;
        note->data = type & NOTE_DATA;
        note->subtype = type & NOTE_SUBTYPE;
@@@ -248,14 -250,6 +248,14 @@@ void WM_main_remove_notifier_reference(
                                wm_notifier_clear(note);
                        }
                }
 +
 +              /* Remap instead. */
 +#if 0
 +              if (wm->message_bus) {
 +                      WM_msg_id_remove(wm->message_bus, reference);
 +              }
 +#endif
 +
        }
  }
  
@@@ -275,17 -269,6 +275,17 @@@ void WM_main_remap_editor_id_reference(
                        }
                }
        }
 +
 +      wmWindowManager *wm = bmain->wm.first;
 +      if (wm && wm->message_bus) {
 +              struct wmMsgBus *mbus = wm->message_bus;
 +              if (new_id != NULL) {
 +                      WM_msg_id_update(mbus, old_id, new_id);
 +              }
 +              else {
 +                      WM_msg_id_remove(mbus, old_id);
 +              }
 +      }
  }
  
  static void wm_notifier_clear(wmNotifier *note)
@@@ -305,20 -288,15 +305,20 @@@ void wm_event_do_refresh_wm_and_depsgra
  
        /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
        for (wmWindow *win = wm->windows.first; win; win = win->next) {
 -              win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen);
 +              const Scene *scene = WM_window_get_active_scene(win);
 +              const bScreen *screen = WM_window_get_active_screen(win);
 +
 +              win_combine_v3d_datamask |= ED_view3d_screen_datamask(scene, screen);
        }
  
        /* cached: editor refresh callbacks now, they get context */
        for (wmWindow *win = wm->windows.first; win; win = win->next) {
 +              const bScreen *screen = WM_window_get_active_screen(win);
 +              Scene *scene = WM_window_get_active_scene(win);
                ScrArea *sa;
  
                CTX_wm_window_set(C, win);
 -              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 +              for (sa = screen->areabase.first; sa; sa = sa->next) {
                        if (sa->do_refresh) {
                                CTX_wm_area_set(C, sa);
                                ED_area_do_refresh(C, sa);
                        Main *bmain = CTX_data_main(C);
  
                        /* copied to set's in scene_update_tagged_recursive() */
 -                      win->screen->scene->customdata_mask = win_combine_v3d_datamask;
 +                      scene->customdata_mask = win_combine_v3d_datamask;
  
                        /* XXX, hack so operators can enforce datamasks [#26482], gl render */
 -                      win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
 +                      scene->customdata_mask |= scene->customdata_mask_modal;
  
 -                      BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
 +                      WorkSpace *workspace = WM_window_get_active_workspace(win);
 +
 +                      BKE_workspace_update_tagged(bmain, workspace, scene);
                }
        }
  
@@@ -354,12 -330,9 +354,12 @@@ void wm_event_do_notifiers(bContext *C
        
        if (wm == NULL)
                return;
 -      
 +
 +      /* disable? - keep for now since its used for window level notifiers. */
 +#if 1
        /* cache & catch WM level notifiers, such as frame change, scene/screen set */
        for (win = wm->windows.first; win; win = win->next) {
 +              Scene *scene = WM_window_get_active_scene(win);
                bool do_anim = false;
                
                CTX_wm_window_set(C, win);
                        }
                        if (note->window == win) {
                                if (note->category == NC_SCREEN) {
 -                                      if (note->data == ND_SCREENBROWSE) {
 +                                      if (note->data == ND_WORKSPACE_SET) {
 +                                              WorkSpace *ref_ws = note->reference;
 +
 +                                              UI_popup_handlers_remove_all(C, &win->modalhandlers);
 +
 +                                              ED_workspace_change(ref_ws, C, wm, win);
 +                                              if (G.debug & G_DEBUG_EVENTS)
 +                                                      printf("%s: Workspace set %p\n", __func__, note->reference);
 +                                      }
 +                                      else if (note->data == ND_WORKSPACE_DELETE) {
 +                                              WorkSpace *workspace = note->reference;
 +
 +                                              ED_workspace_delete(workspace, CTX_data_main(C), C, wm);   // XXX hrms, think this over!
 +                                              if (G.debug & G_DEBUG_EVENTS)
 +                                                      printf("%s: Workspace delete %p\n", __func__, workspace);
 +                                      }
 +                                      else if (note->data == ND_LAYOUTBROWSE) {
 +                                              bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference);
 +
                                                /* free popup handlers only [#35434] */
                                                UI_popup_handlers_remove_all(C, &win->modalhandlers);
  
  
 -                                              ED_screen_set(C, note->reference);  // XXX hrms, think this over!
 -                                              CLOG_INFO(WM_LOG_EVENTS, 1, "screen set %p", note->reference);
 +                                              ED_screen_change(C, ref_screen);  /* XXX hrms, think this over! */
 +                                              if (G.debug & G_DEBUG_EVENTS)
 +                                                      printf("%s: screen set %p\n", __func__, note->reference);
                                        }
 -                                      else if (note->data == ND_SCREENDELETE) {
 -                                              ED_screen_delete(C, note->reference);   // XXX hrms, think this over!
 -                                              CLOG_INFO(WM_LOG_EVENTS, 1, "screen delete %p", note->reference);
 +                                      else if (note->data == ND_LAYOUTDELETE) {
 +                                              WorkSpace *workspace = WM_window_get_active_workspace(win);
 +                                              WorkSpaceLayout *layout = note->reference;
 +
 +                                              ED_workspace_layout_delete(workspace, layout, C);   // XXX hrms, think this over!
 +                                              if (G.debug & G_DEBUG_EVENTS)
 +                                                      printf("%s: screen delete %p\n", __func__, note->reference);
                                        }
                                }
                        }
  
                        if (note->window == win ||
 -                          (note->window == NULL && (note->reference == NULL || note->reference == win->screen->scene)))
 +                          (note->window == NULL && (note->reference == NULL || note->reference == scene)))
                        {
                                if (note->category == NC_SCENE) {
                                        if (note->data == ND_FRAME)
                                }
                        }
                        if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) {
 -                              ED_info_stats_clear(win->screen->scene);
 +                              ViewLayer *view_layer = CTX_data_view_layer(C);
 +                              ED_info_stats_clear(view_layer);
                                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
                        }
                }
                if (do_anim) {
  
                        /* XXX, quick frame changes can cause a crash if framechange and rendering
 -                       * collide (happens on slow scenes), BKE_scene_update_for_newframe can be called
 +                       * collide (happens on slow scenes), BKE_scene_graph_update_for_newframe can be called
                         * twice which can depgraph update the same object at once */
                        if (G.is_rendering == false) {
 -
                                /* depsgraph gets called, might send more notifiers */
 -                              ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1);
 +                              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                              ED_update_for_newframe(CTX_data_main(C), depsgraph);
                        }
                }
        }
        /* the notifiers are sent without context, to keep it clean */
        while ((note = BLI_pophead(&wm->queue))) {
                for (win = wm->windows.first; win; win = win->next) {
 -                      
 +                      Scene *scene = WM_window_get_active_scene(win);
 +                      bScreen *screen = WM_window_get_active_screen(win);
 +                      WorkSpace *workspace = WM_window_get_active_workspace(win);
 +
                        /* filter out notifiers */
 -                      if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) {
 +                      if (note->category == NC_SCREEN &&
 +                          note->reference &&
 +                          note->reference != screen &&
 +                          note->reference != workspace &&
 +                          note->reference != WM_window_get_active_layout(win))
 +                      {
                                /* pass */
                        }
 -                      else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) {
 +                      else if (note->category == NC_SCENE && note->reference && note->reference != scene) {
                                /* pass */
                        }
                        else {
 -                              ScrArea *sa;
                                ARegion *ar;
  
                                /* XXX context in notifiers? */
                                /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */
                                ED_screen_do_listen(C, note);
  
 -                              for (ar = win->screen->regionbase.first; ar; ar = ar->next) {
 -                                      ED_region_do_listen(win->screen, NULL, ar, note);
 +                              for (ar = screen->regionbase.first; ar; ar = ar->next) {
 +                                      ED_region_do_listen(screen, NULL, ar, note, scene);
                                }
 -                              
 -                              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 -                                      ED_area_do_listen(win->screen, sa, note);
 +
 +                              ED_screen_areas_iter(win, screen, sa) {
 +                                      ED_area_do_listen(screen, sa, note, scene, workspace);
                                        for (ar = sa->regionbase.first; ar; ar = ar->next) {
 -                                              ED_region_do_listen(win->screen, sa, ar, note);
 +                                              ED_region_do_listen(screen, sa, ar, note, scene);
                                        }
                                }
                        }
                
                MEM_freeN(note);
        }
 -      
 +#endif /* if 1 (postpone disabling for in favor of message-bus), eventually. */
 +
 +      /* Handle message bus. */
 +      {
 +              for (win = wm->windows.first; win; win = win->next) {
 +                      CTX_wm_window_set(C, win);
 +                      WM_msgbus_handle(wm->message_bus, C);
 +              }
 +              CTX_wm_window_set(C, NULL);
 +      }
 +
        wm_event_do_refresh_wm_and_depsgraph(C);
  }
  
@@@ -614,39 -546,6 +614,39 @@@ int WM_operator_poll_context(bContext *
        return wm_operator_call_internal(C, ot, NULL, NULL, context, true);
  }
  
 +bool WM_operator_check_ui_empty(wmOperatorType *ot)
 +{
 +      if (ot->macro.first != NULL) {
 +              /* for macros, check all have exec() we can call */
 +              wmOperatorTypeMacro *otmacro;
 +              for (otmacro = ot->macro.first; otmacro; otmacro = otmacro->next) {
 +                      wmOperatorType *otm = WM_operatortype_find(otmacro->idname, 0);
 +                      if (otm && !WM_operator_check_ui_empty(otm)) {
 +                              return false;
 +                      }
 +              }
 +              return true;
 +      }
 +
 +      /* Assume a ui callback will draw something. */
 +      if (ot->ui) {
 +              return false;
 +      }
 +
 +      PointerRNA ptr;
 +      WM_operator_properties_create_ptr(&ptr, ot);
 +      RNA_STRUCT_BEGIN (&ptr, prop)
 +      {
 +              int flag = RNA_property_flag(prop);
 +              if (flag & PROP_HIDDEN) {
 +                      continue;
 +              }
 +              return false;
 +      }
 +      RNA_STRUCT_END;
 +      return true;
 +}
 +
  /**
   * Sets the active region for this space from the context.
   *
@@@ -805,7 -704,7 +805,7 @@@ static void wm_operator_reports(bContex
                        CTX_wm_region_set(C, ar_prev);
                }
        }
 -
 +      
        if (retval & OPERATOR_FINISHED) {
                CLOG_STR_INFO_N(WM_LOG_OPERATORS, 1, WM_operator_pystring(C, op, false, true));
  
@@@ -977,14 -876,7 +977,14 @@@ int WM_operator_call_notest(bContext *C
   */
  int WM_operator_repeat(bContext *C, wmOperator *op)
  {
 -      return wm_operator_exec(C, op, true, true);
 +      const OperatorRepeatContextHandle *context_info;
 +      int retval;
 +
 +      context_info = ED_operator_repeat_prepare_context(C, op);
 +      retval = wm_operator_exec(C, op, true, true);
 +      ED_operator_repeat_reset_context(C, context_info);
 +
 +      return retval;
  }
  /**
   * \return true if #WM_operator_repeat can run
@@@ -1130,48 -1022,60 +1130,60 @@@ static void wm_region_mouse_co(bContex
  }
  
  #if 1 /* may want to disable operator remembering previous state for testing */
- bool WM_operator_last_properties_init(wmOperator *op)
+ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_properties)
  {
        bool changed = false;
+       IDPropertyTemplate val = {0};
+       IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
+       PropertyRNA *iterprop;
  
-       if (op->type->last_properties) {
-               IDPropertyTemplate val = {0};
-               IDProperty *replaceprops = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
-               PropertyRNA *iterprop;
-               CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
-               iterprop = RNA_struct_iterator_property(op->type->srna);
-               RNA_PROP_BEGIN (op->ptr, itemptr, iterprop)
-               {
-                       PropertyRNA *prop = itemptr.data;
-                       if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
-                               if (!RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */
-                                       const char *identifier = RNA_property_identifier(prop);
-                                       IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, identifier);
-                                       if (idp_src) {
-                                               IDProperty *idp_dst = IDP_CopyProperty(idp_src);
-                                               /* note - in the future this may need to be done recursively,
-                                                * but for now RNA doesn't access nested operators */
-                                               idp_dst->flag |= IDP_FLAG_GHOST;
-                                               /* add to temporary group instead of immediate replace,
-                                                * because we are iterating over this group */
-                                               IDP_AddToGroup(replaceprops, idp_dst);
-                                               changed = true;
-                                       }
+       CLOG_INFO(WM_LOG_OPERATORS, 1, "loading previous properties for '%s'", op->type->idname);
+       iterprop = RNA_struct_iterator_property(op->type->srna);
+       RNA_PROP_BEGIN (op->ptr, itemptr, iterprop)
+       {
+               PropertyRNA *prop = itemptr.data;
+               if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
+                       if (!RNA_property_is_set(op->ptr, prop)) { /* don't override a setting already set */
+                               const char *identifier = RNA_property_identifier(prop);
+                               IDProperty *idp_src = IDP_GetPropertyFromGroup(last_properties, identifier);
+                               if (idp_src) {
+                                       IDProperty *idp_dst = IDP_CopyProperty(idp_src);
+                                       /* note - in the future this may need to be done recursively,
+                                        * but for now RNA doesn't access nested operators */
+                                       idp_dst->flag |= IDP_FLAG_GHOST;
+                                       /* add to temporary group instead of immediate replace,
+                                        * because we are iterating over this group */
+                                       IDP_AddToGroup(replaceprops, idp_dst);
+                                       changed = true;
                                }
                        }
                }
-               RNA_PROP_END;
-               IDP_MergeGroup(op->properties, replaceprops, true);
-               IDP_FreeProperty(replaceprops);
-               MEM_freeN(replaceprops);
        }
+       RNA_PROP_END;
+       IDP_MergeGroup(op->properties, replaceprops, true);
+       IDP_FreeProperty(replaceprops);
+       MEM_freeN(replaceprops);
+       return changed;
+ }
  
+ bool WM_operator_last_properties_init(wmOperator *op)
+ {
+       bool changed = false;
+       if (op->type->last_properties) {
+               changed |= operator_last_properties_init_impl(op, op->type->last_properties);
+               for (wmOperator *opm = op->macro.first; opm; opm = opm->next) {
+                       IDProperty *idp_src = IDP_GetPropertyFromGroup(op->type->last_properties, opm->idname);
+                       if (idp_src) {
+                               changed |= operator_last_properties_init_impl(opm, idp_src);
+                       }
+               }
+       }
        return changed;
  }
  
@@@ -1247,8 -1151,8 +1259,8 @@@ static int wm_operator_invoke
  
                if ((event == NULL) || (event->type != MOUSEMOVE)) {
                        CLOG_INFO(WM_LOG_HANDLERS, 2,
 -                                "handle evt %d win %d op %s",
 -                                event ? event->type : 0, CTX_wm_screen(C)->subwinactive, ot->idname);
 +                                "handle evt %d win %p op %s",
 +                                event ? event->type : 0, CTX_wm_screen(C)->active_region, ot->idname);
                }
  
                if (op->type->invoke && event) {
@@@ -1585,22 -1489,17 +1597,22 @@@ void wm_event_free_handler(wmEventHandl
  /* only set context when area/region is part of screen */
  static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event)
  {
 +      wmWindow *win = CTX_wm_window(C);
        bScreen *screen = CTX_wm_screen(C);
        
        if (screen && handler->op) {
                if (handler->op_area == NULL)
                        CTX_wm_area_set(C, NULL);
                else {
 -                      ScrArea *sa;
 -                      
 -                      for (sa = screen->areabase.first; sa; sa = sa->next)
 -                              if (sa == handler->op_area)
 +                      ScrArea *sa = NULL;
 +
 +                      ED_screen_areas_iter(win, screen, sa_iter) {
 +                              if (sa_iter == handler->op_area) {
 +                                      sa = sa_iter;
                                        break;
 +                              }
 +                      }
 +
                        if (sa == NULL) {
                                /* when changing screen layouts with running modal handlers (like render display), this
                                 * is not an error to print */
@@@ -1711,36 -1610,6 +1723,36 @@@ int WM_userdef_event_map(int kmitype
        return kmitype;
  }
  
 +/**
 + * Use so we can check if 'wmEvent.type' is released in modal operators.
 + *
 + * An alternative would be to add a 'wmEvent.type_nokeymap'... or similar.
 + */
 +int WM_userdef_event_type_from_keymap_type(int kmitype)
 +{
 +      switch (kmitype) {
 +              case SELECTMOUSE:
 +                      return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
 +              case ACTIONMOUSE:
 +                      return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
 +              case EVT_TWEAK_S:
 +                      return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
 +              case EVT_TWEAK_A:
 +                      return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
 +              case EVT_TWEAK_L:
 +                      return LEFTMOUSE;
 +              case EVT_TWEAK_M:
 +                      return MIDDLEMOUSE;
 +              case EVT_TWEAK_R:
 +                      return RIGHTMOUSE;
 +              case WHEELOUTMOUSE:
 +                      return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
 +              case WHEELINMOUSE:
 +                      return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
 +      }
 +
 +      return kmitype;
 +}
  
  static int wm_eventmatch(const wmEvent *winevent, wmKeyMapItem *kmi)
  {
@@@ -1889,7 -1758,7 +1901,7 @@@ static int wm_handler_operator_call(bCo
                        wm_handler_op_context(C, handler, event);
                        wm_region_mouse_co(C, event);
                        wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
 -                      
 +
                        if (ot->flag & OPTYPE_UNDO)
                                wm->op_undo_depth++;
  
                                        CTX_wm_region_set(C, NULL);
                                }
  
 +                              /* update manipulators during modal handlers */
 +                              wm_manipulatormaps_handled_modal_update(C, event, handler);
 +
                                /* remove modal handler, operator itself should have been canceled and freed */
                                if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
 -                                      WM_cursor_grab_disable(CTX_wm_window(C), NULL);
 +                                      /* set cursor back to the default for the region */
 +                                      wmWindow *win = CTX_wm_window(C);
 +                                      WM_cursor_grab_disable(win, NULL);
 +                                      ED_region_cursor_set(win, CTX_wm_area(C), CTX_wm_region(C));
  
                                        BLI_remlink(handlers, handler);
                                        wm_event_free_handler(handler);
@@@ -1993,14 -1856,13 +2005,14 @@@ static int wm_handler_fileselect_do(bCo
        int action = WM_HANDLER_CONTINUE;
  
        switch (val) {
 -              case EVT_FILESELECT_FULL_OPEN: 
 +              case EVT_FILESELECT_FULL_OPEN:
                {
                        ScrArea *sa;
 -                              
 -                      /* sa can be null when window A is active, but mouse is over window B */
 -                      /* in this case, open file select in original window A */
 -                      if (handler->op_area == NULL) {
 +
 +                      /* sa can be null when window A is active, but mouse is over window B
 +                       * in this case, open file select in original window A. Also don't
 +                       * use global areas. */
 +                      if (handler->op_area == NULL || ED_area_is_global(handler->op_area)) {
                                bScreen *screen = CTX_wm_screen(C);
                                sa = (ScrArea *)screen->areabase.first;
                        }
@@@ -2312,139 -2174,6 +2324,139 @@@ static int wm_handlers_do_intern(bConte
                                        }
                                }
                        }
 +                      else if (handler->manipulator_map) {
 +                              ScrArea *area = CTX_wm_area(C);
 +                              ARegion *region = CTX_wm_region(C);
 +                              wmManipulatorMap *mmap = handler->manipulator_map;
 +                              wmManipulator *mpr = wm_manipulatormap_highlight_get(mmap);
 +
 +                              if (region->manipulator_map != handler->manipulator_map) {
 +                                      WM_manipulatormap_tag_refresh(handler->manipulator_map);
 +                              }
 +
 +                              wm_manipulatormap_handler_context(C, handler);
 +                              wm_region_mouse_co(C, event);
 +
 +                              /* handle manipulator highlighting */
 +                              if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
 +                                      int part;
 +                                      mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
 +                                      wm_manipulatormap_highlight_set(mmap, C, mpr, part);
 +                                      if (mpr != NULL) {
 +                                              WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_manipulatormap_tooltip_init);
 +                                      }
 +                              }
 +                              else {
 +                                      /* Either we operate on a single highlighted item
 +                                       * or groups attached to the selected manipulators.
 +                                       * To simplify things both cases loop over an array of items. */
 +                                      wmManipulatorGroup *mgroup_first;
 +                                      bool is_mgroup_single;
 +
 +                                      if (ISMOUSE(event->type)) {
 +                                              /* Keep mpr set as-is, just fake single selection. */
 +                                              if (mpr) {
 +                                                      mgroup_first = mpr->parent_mgroup;
 +                                              }
 +                                              else {
 +                                                      mgroup_first = NULL;
 +                                              }
 +                                              is_mgroup_single = true;
 +                                      }
 +                                      else {
 +                                              if (WM_manipulatormap_is_any_selected(mmap)) {
 +                                                      const ListBase *groups = WM_manipulatormap_group_list(mmap);
 +                                                      mgroup_first = groups->first;
 +                                              }
 +                                              else {
 +                                                      mgroup_first = NULL;
 +                                              }
 +                                              is_mgroup_single = false;
 +                                      }
 +
 +                                      /* Don't use from now on. */
 +                                      mpr = NULL;
 +
 +                                      for (wmManipulatorGroup *mgroup = mgroup_first; mgroup; mgroup = mgroup->next) {
 +                                              /* get user customized keymap from default one */
 +
 +                                              if ((is_mgroup_single == false) &&
 +                                                  /* We might want to change the logic here and use some kind of manipulator edit-mode.
 +                                                   * For now just use keymap when a selection exists. */
 +                                                  wm_manipulatorgroup_is_any_selected(mgroup) == false)
 +                                              {
 +                                                      continue;
 +                                              }
 +
 +                                              const wmKeyMap *keymap = WM_keymap_active(wm, mgroup->type->keymap);
 +                                              wmKeyMapItem *kmi;
 +
 +                                              PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
 +
 +                                              if (!keymap->poll || keymap->poll(C)) {
 +                                                      PRINT("pass\n");
 +                                                      for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
 +                                                              if (wm_eventmatch(event, kmi)) {
 +                                                                      wmOperator *op = handler->op;
 +
 +                                                                      PRINT("%s:     item matched '%s'\n", __func__, kmi->idname);
 +
 +                                                                      /* weak, but allows interactive callback to not use rawkey */
 +                                                                      event->keymap_idname = kmi->idname;
 +
 +                                                                      CTX_wm_manipulator_group_set(C, mgroup);
 +
 +                                                                      /* handler->op is called later, we want keymap op to be triggered here */
 +                                                                      handler->op = NULL;
 +                                                                      action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
 +                                                                      handler->op = op;
 +
 +                                                                      CTX_wm_manipulator_group_set(C, NULL);
 +
 +                                                                      if (action & WM_HANDLER_BREAK) {
 +                                                                              if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
 +                                                                                      printf("%s:       handled - and pass on! '%s'\n",
 +                                                                                             __func__, kmi->idname);
 +                                                                              }
 +                                                                              break;
 +                                                                      }
 +                                                                      else {
 +                                                                              if (action & WM_HANDLER_HANDLED) {
 +                                                                                      if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
 +                                                                                              printf("%s:       handled - and pass on! '%s'\n",
 +                                                                                                     __func__, kmi->idname);
 +                                                                                      }
 +                                                                              }
 +                                                                              else {
 +                                                                                      PRINT("%s:       un-handled '%s'\n",
 +                                                                                            __func__, kmi->idname);
 +                                                                              }
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                              }
 +                                              else {
 +                                                      PRINT("fail\n");
 +                                              }
 +
 +                                              if (action & WM_HANDLER_BREAK) {
 +                                                      break;
 +                                              }
 +
 +                                              if (is_mgroup_single) {
 +                                                      break;
 +                                              }
 +                                      }
 +                              }
 +
 +                              /* restore the area */
 +                              CTX_wm_area_set(C, area);
 +                              CTX_wm_region_set(C, region);
 +
 +                              if (handler->op) {
 +                                      action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
 +                              }
 +                      }
                        else {
                                /* modal, swallows all */
                                action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
@@@ -2559,15 -2288,13 +2571,15 @@@ static int wm_event_inside_i(wmEvent *e
  
  static ScrArea *area_event_inside(bContext *C, const int xy[2])
  {
 +      wmWindow *win = CTX_wm_window(C);
        bScreen *screen = CTX_wm_screen(C);
 -      ScrArea *sa;
        
 -      if (screen)
 -              for (sa = screen->areabase.first; sa; sa = sa->next)
 +      if (screen) {
 +              ED_screen_areas_iter(win, screen, sa) {
                        if (BLI_rcti_isect_pt_v(&sa->totrct, xy))
                                return sa;
 +              }
 +      }
        return NULL;
  }
  
@@@ -2625,19 -2352,17 +2637,19 @@@ static void wm_paintcursor_test(bContex
  
  static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event)
  {
 +      bScreen *screen = WM_window_get_active_screen(win);
 +
        if (BLI_listbase_is_empty(&wm->drags)) {
                return;
        }
        
        if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
        }
        else if (event->type == ESCKEY) {
                WM_drag_free_list(&wm->drags);
  
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
        }
        else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
                event->type = EVT_DROP;
                event->customdatafree = 1;
                
                /* clear drop icon */
 -              win->screen->do_draw_drag = true;
 +              screen->do_draw_drag = true;
                
                /* restore cursor (disabled, see wm_dragdrop.c) */
                // WM_cursor_modal_restore(win);
        }
 -      
 -      /* overlap fails otherwise */
 -      if (win->screen->do_draw_drag)
 -              if (win->drawmethod == USER_DRAW_OVERLAP)
 -                      win->screen->do_draw = true;
 -      
  }
  
  /* filter out all events of the pie that spawned the last pie unless it's a release event */
@@@ -2686,28 -2417,22 +2698,28 @@@ void wm_event_do_handlers(bContext *C
  
        /* update key configuration before handling events */
        WM_keyconfig_update(wm);
 +      WM_manipulatorconfig_update(CTX_data_main(C));
  
        for (win = wm->windows.first; win; win = win->next) {
 +              bScreen *screen = WM_window_get_active_screen(win);
                wmEvent *event;
 -              
 -              if (win->screen == NULL)
 +
 +              /* some safty checks - these should always be set! */
 +              BLI_assert(WM_window_get_active_scene(win));
 +              BLI_assert(WM_window_get_active_screen(win));
 +              BLI_assert(WM_window_get_active_workspace(win));
 +
 +              if (screen == NULL)
                        wm_event_free_all(win);
                else {
 -                      Scene *scene = win->screen->scene;
 -                      
 +                      Scene *scene = WM_window_get_active_scene(win);
 +
                        if (scene) {
 -                              int is_playing_sound = BKE_sound_scene_playing(win->screen->scene);
 +                              int is_playing_sound = BKE_sound_scene_playing(scene);
                                
                                if (is_playing_sound != -1) {
                                        bool is_playing_screen;
                                        CTX_wm_window_set(C, win);
 -                                      CTX_wm_screen_set(C, win->screen);
                                        CTX_data_scene_set(C, scene);
                                        
                                        is_playing_screen = (ED_screen_animation_playing(wm) != NULL);
                                                        int ncfra = time * (float)FPS + 0.5f;
                                                        if (ncfra != scene->r.cfra) {
                                                                scene->r.cfra = ncfra;
 -                                                              ED_update_for_newframe(CTX_data_main(C), scene, 1);
 +                                                              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                                                              ED_update_for_newframe(CTX_data_main(C), depsgraph);
                                                                WM_event_add_notifier(C, NC_WINDOW, NULL);
                                                        }
                                                }
                while ( (event = win->queue.first) ) {
                        int action = WM_HANDLER_CONTINUE;
  
 +                      /* active screen might change during handlers, update pointer */
 +                      screen = WM_window_get_active_screen(win);
 +
                        if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
                                printf("\n%s: Handling event\n", __func__);
 -
                                WM_event_print(event);
                        }
  
                        CTX_wm_window_set(C, win);
  
                        /* Clear tool-tip on mouse move. */
 -                      if (win->screen->tool_tip && win->screen->tool_tip->exit_on_event) {
 +                      if (screen->tool_tip && screen->tool_tip->exit_on_event) {
                                if (ISMOUSE(event->type)) {
                                        WM_tooltip_clear(C, win);
                                }
                                return;
  
                        /* check for a tooltip */
 -                      {
 -                              bScreen *screen = CTX_wm_window(C)->screen;
 +                      if (screen == WM_window_get_active_screen(win)) {
                                if (screen->tool_tip && screen->tool_tip->timer) {
                                        if ((event->type == TIMER) && (event->customdata == screen->tool_tip->timer)) {
                                                WM_tooltip_init(C, win);
                        wm_tweakevent_test(C, event, action);
  
                        if ((action & WM_HANDLER_BREAK) == 0) {
 -                              ScrArea *sa;
                                ARegion *ar;
        
                                /* Note: setting subwin active should be done here, after modal handlers have been done */
                                if (event->type == MOUSEMOVE) {
                                        /* state variables in screen, cursors. Also used in wm_draw.c, fails for modal handlers though */
 -                                      ED_screen_set_subwinactive(C, event);
 +                                      ED_screen_set_active_region(C, &event->x);
                                        /* for regions having custom cursors */
                                        wm_paintcursor_test(C, event);
                                }
                                }
  #endif
  
 -                              for (sa = win->screen->areabase.first; sa; sa = sa->next) {
 +                              ED_screen_areas_iter(win, screen, sa) {
                                        /* after restoring a screen from SCREENMAXIMIZED we have to wait
                                         * with the screen handling till the region coordinates are updated */
 -                                      if (win->screen->skip_handling == true) {
 +                                      if (screen->skip_handling == true) {
                                                /* restore for the next iteration of wm_event_do_handlers */
 -                                              win->screen->skip_handling = false;
 +                                              screen->skip_handling = false;
                                                break;
                                        }
  
                                                                                        wm_drags_check_ops(C, event);
                                                                                }
                                                                        }
 -                                                                      
 +
 +#ifdef USE_WORKSPACE_TOOL
 +                                                                      /* How to solve properly?
 +                                                                       *
 +                                                                       * Handlers are stored in each region,
 +                                                                       * however the tool-system swaps keymaps often and isn't stored
 +                                                                       * per region.
 +                                                                       *
 +                                                                       * Need to investigate how this could be done better.
 +                                                                       * We might need to add a more dynamic handler type that uses a callback
 +                                                                       * to fetch its current keymap.
 +                                                                       */
 +                                                                      wmEventHandler sneaky_handler = {NULL};
 +                                                                      if (ar->regiontype == RGN_TYPE_WINDOW) {
 +                                                                              WorkSpace *workspace = WM_window_get_active_workspace(win);
 +                                                                              if (workspace->tool.keymap[0] &&
 +                                                                                  workspace->tool.spacetype == sa->spacetype)
 +                                                                              {
 +                                                                                      wmKeyMap *km = WM_keymap_find_all(
 +                                                                                              C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW);
 +                                                                                      if (km != NULL) {
 +                                                                                              sneaky_handler.keymap = km;
 +                                                                                              /* Handle widgets first. */
 +                                                                                              wmEventHandler *handler_last = ar->handlers.last;
 +                                                                                              while (handler_last && handler_last->manipulator_map == NULL) {
 +                                                                                                      handler_last = handler_last->prev;
 +                                                                                              }
 +                                                                                              /* Head of list or after last manipulator. */
 +                                                                                              BLI_insertlinkafter(&ar->handlers, handler_last, &sneaky_handler);
 +                                                                                      }
 +                                                                              }
 +                                                                      }
 +#endif /* USE_WORKSPACE_TOOL */
 +
                                                                        action |= wm_handlers_do(C, event, &ar->handlers);
  
 +#ifdef USE_WORKSPACE_TOOL
 +                                                                      if (sneaky_handler.keymap) {
 +                                                                              BLI_remlink(&ar->handlers, &sneaky_handler);
 +                                                                      }
 +#endif /* USE_WORKSPACE_TOOL */
 +
                                                                        /* fileread case (python), [#29489] */
                                                                        if (CTX_wm_window(C) == NULL)
                                                                                return;
  
        /* update key configuration after handling events */
        WM_keyconfig_update(wm);
 -
 -      GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
 +      WM_manipulatorconfig_update(CTX_data_main(C));
  }
  
  /* ********** filesector handling ************ */
@@@ -2996,26 -2682,24 +3008,26 @@@ void WM_event_add_fileselect(bContext *
                
                if (handler->type == WM_HANDLER_FILESELECT) {
                        bScreen *screen = CTX_wm_screen(C);
 -                      ScrArea *sa;
 +                      bool cancel_handler = true;
  
                        /* find the area with the file selector for this handler */
 -                      for (sa = screen->areabase.first; sa; sa = sa->next) {
 +                      ED_screen_areas_iter(win, screen, sa) {
                                if (sa->spacetype == SPACE_FILE) {
                                        SpaceFile *sfile = sa->spacedata.first;
  
                                        if (sfile->op == handler->op) {
                                                CTX_wm_area_set(C, sa);
                                                wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_CANCEL);
 +                                              cancel_handler = false;
                                                break;
                                        }
                                }
                        }
  
                        /* if not found we stop the handler without changing the screen */
 -                      if (!sa)
 +                      if (cancel_handler) {
                                wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL);
 +                      }
                }
        }
        
@@@ -3069,34 -2753,6 +3081,34 @@@ wmEventHandler *WM_event_add_modal_hand
        return handler;
  }
  
 +/**
 + * Modal handlers store a pointer to an area which might be freed while the handler runs.
 + * Use this function to NULL all handler pointers to \a old_area.
 + */
 +void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
 +{
 +      for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
 +              /* fileselect handler is quite special... it needs to keep old area stored in handler, so don't change it */
 +              if ((handler->op_area == old_area) && (handler->type != WM_HANDLER_FILESELECT)) {
 +                      handler->op_area = new_area;
 +              }
 +      }
 +}
 +
 +/**
 + * Modal handlers store a pointer to a region which might be freed while the handler runs.
 + * Use this function to NULL all handler pointers to \a old_region.
 + */
 +void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region)
 +{
 +      for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
 +              if (handler->op_region == old_region) {
 +                      handler->op_region = new_region;
 +                      handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW;
 +              }
 +      }
 +}
 +
  wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
  {
        wmEventHandler *handler;