Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Mon, 4 Jun 2018 07:39:04 +0000 (09:39 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 4 Jun 2018 07:39:04 +0000 (09:39 +0200)
186 files changed:
1  2 
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_deps.c
source/blender/editors/animation/anim_draw.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_intern.h
source/blender/editors/animation/anim_markers.c
source/blender/editors/animation/anim_ops.c
source/blender/editors/animation/drivers.c
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/armature_add.c
source/blender/editors/armature/armature_edit.c
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_naming.c
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/armature_relations.c
source/blender/editors/armature/armature_select.c
source/blender/editors/armature/armature_skinning.c
source/blender/editors/armature/armature_utils.c
source/blender/editors/armature/meshlaplacian.c
source/blender/editors/armature/pose_edit.c
source/blender/editors/armature/pose_group.c
source/blender/editors/armature/pose_lib.c
source/blender/editors/armature/pose_select.c
source/blender/editors/armature/pose_transform.c
source/blender/editors/armature/pose_utils.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editcurve_paint.c
source/blender/editors/curve/editfont.c
source/blender/editors/gpencil/drawgpencil.c
source/blender/editors/gpencil/gpencil_brush.c
source/blender/editors/gpencil/gpencil_convert.c
source/blender/editors/gpencil/gpencil_edit.c
source/blender/editors/gpencil/gpencil_ops.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/gpencil/gpencil_utils.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_armature.h
source/blender/editors/include/ED_gpencil.h
source/blender/editors/include/ED_keyframes_draw.h
source/blender/editors/include/ED_keyframing.h
source/blender/editors/include/ED_screen_types.h
source/blender/editors/include/ED_space_api.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/include/UI_icons.h
source/blender/editors/include/UI_interface.h
source/blender/editors/include/UI_resources.h
source/blender/editors/include/UI_view2d.h
source/blender/editors/io/io_collada.c
source/blender/editors/mesh/editface.c
source/blender/editors/mesh/editmesh_bevel.c
source/blender/editors/mesh/editmesh_knife.c
source/blender/editors/mesh/editmesh_loopcut.c
source/blender/editors/mesh/editmesh_select.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_data.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/metaball/mball_edit.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_bake_api.c
source/blender/editors/object/object_constraint.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_group.c
source/blender/editors/object/object_hook.c
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_transform.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/dynamicpaint_ops.c
source/blender/editors/physics/particle_boids.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_edit_undo.c
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_fluid.c
source/blender/editors/physics/physics_ops.c
source/blender/editors/physics/physics_pointcache.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_opengl.c
source/blender/editors/render/render_ops.c
source/blender/editors/render/render_preview.c
source/blender/editors/render/render_shading.c
source/blender/editors/render/render_update.c
source/blender/editors/render/render_view.c
source/blender/editors/screen/area.c
source/blender/editors/screen/glutil.c
source/blender/editors/screen/screen_context.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/screen/screendump.c
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_curve.c
source/blender/editors/sculpt_paint/paint_hide.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_2d.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_intern.h
source/blender/editors/sculpt_paint/sculpt_undo.c
source/blender/editors/sculpt_paint/sculpt_uv.c
source/blender/editors/space_action/action_buttons.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_intern.h
source/blender/editors/space_action/space_action.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_buttons/buttons_texture.c
source/blender/editors/space_buttons/space_buttons.c
source/blender/editors/space_clip/clip_dopesheet_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_console/console_draw.c
source/blender/editors/space_console/space_console.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/filesel.c
source/blender/editors/space_file/fsmenu.c
source/blender/editors/space_file/space_file.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/space_graph.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_edit.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_info/space_info.c
source/blender/editors/space_info/textview.c
source/blender/editors/space_nla/nla_channels.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_nla/space_nla.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_add.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_ops.c
source/blender/editors/space_node/node_templates.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/outliner_tree.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/space_script/space_script.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_intern.h
source/blender/editors/space_sequencer/sequencer_view.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_text/space_text.c
source/blender/editors/space_text/text_draw.c
source/blender/editors/space_text/text_ops.c
source/blender/editors/space_userpref/space_userpref.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_fly.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/space_view3d/view3d_project.c
source/blender/editors/space_view3d/view3d_ruler.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/editors/space_view3d/view3d_toolbar.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/util/ed_util.c
source/blender/editors/uvedit/uvedit_buttons.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/editors/uvedit/uvedit_ops.c
source/blender/editors/uvedit/uvedit_smart_stitch.c
source/blender/editors/uvedit/uvedit_unwrap_ops.c

@@@ -119,13 -116,14 +119,13 @@@ static void acf_generic_root_backdrop(b
        short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
        short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
        float color[3];
-       
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       
 -      glColor3fv(color);
        /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
        UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
 -      UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
 +      UI_draw_roundbox_3fvAlpha(true, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
  }
  
  
@@@ -233,18 -225,12 +233,18 @@@ static void acf_generic_channel_backdro
        short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
        float color[3];
  
-       
 +      unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
++
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
 -      glColor3fv(color);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +      immUniformColor3fv(color);
-       
        /* no rounded corners - just rectangular box */
 -      glRectf(offset, yminc,  v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
 +      immRectf(pos, offset, yminc,  v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
 +
 +      immUnbindProgram();
  }
  
  /* Indention + Offset ------------------------------------------- */
@@@ -432,16 -418,17 +432,16 @@@ static void acf_summary_backdrop(bAnimC
        const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
        View2D *v2d = &ac->ar->v2d;
        float color[3];
-       
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       
-       /* rounded corners on LHS only 
-        *      - top and bottom 
-        *      - special hack: make the top a bit higher, since we are first... 
 -      glColor3fv(color);
+       /* rounded corners on LHS only
+        *      - top and bottom
+        *      - special hack: make the top a bit higher, since we are first...
         */
        UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
 -      UI_draw_roundbox_gl_mode(GL_POLYGON, 0,  yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
 +      UI_draw_roundbox_3fvAlpha(true, 0,  yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
  }
  
  /* name for summary entries */
@@@ -649,15 -636,13 +649,15 @@@ static int acf_object_icon(bAnimListEle
                        return ICON_OUTLINER_OB_LATTICE;
                case OB_SPEAKER:
                        return ICON_OUTLINER_OB_SPEAKER;
 +              case OB_LIGHTPROBE:
 +                      return ICON_OUTLINER_OB_LIGHTPROBE;
                case OB_ARMATURE:
                        return ICON_OUTLINER_OB_ARMATURE;
-               case OB_FONT: 
+               case OB_FONT:
                        return ICON_OUTLINER_OB_FONT;
-               case OB_SURF: 
+               case OB_SURF:
                        return ICON_OUTLINER_OB_SURFACE;
-               case OB_EMPTY: 
+               case OB_EMPTY:
                        return ICON_OUTLINER_OB_EMPTY;
                default:
                        return ICON_OBJECT_DATA;
@@@ -826,13 -811,14 +826,13 @@@ static void acf_group_backdrop(bAnimCon
        short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
        short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
        float color[3];
-       
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       
 -      glColor3fv(color);
        /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
        UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
 -      UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
 +      UI_draw_roundbox_3fvAlpha(true, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
  }
  
  /* name for group entries */
@@@ -1082,13 -1068,14 +1082,13 @@@ static void acf_nla_controls_backdrop(b
        short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
        short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
        float color[3];
-       
        /* set backdrop drawing color */
        acf->get_backdrop_color(ac, ale, color);
-       
-       /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */       
 -      glColor3fv(color);
+       /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
        UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
 -      UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
 +      UI_draw_roundbox_3fvAlpha(true, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
  }
  
  /* name for nla controls expander entries */
@@@ -2028,14 -2015,14 +2028,14 @@@ static int acf_dspart_setting_flag(bAni
  {
        /* clear extra return data first */
        *neg = false;
-       
        switch (setting) {
                case ACHANNEL_SETTING_EXPAND: /* expanded */
 -                      return PART_DS_EXPAND;
 +                      return 0;
-                       
                case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
                        return ADT_NLA_EVAL_OFF;
-                       
                case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
                        *neg = true;
                        return ADT_CURVES_NOT_VISIBLE;
  }
  
  /* get pointer to the setting */
 -static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
 +static void *acf_dspart_setting_ptr(bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting, short *type)
  {
 -      ParticleSettings *part = (ParticleSettings *)ale->data;
 -
        /* clear extra return data first */
        *type = 0;
-       
        switch (setting) {
                case ACHANNEL_SETTING_EXPAND: /* expanded */
 -                      return GET_ACF_FLAG_PTR(part->flag, type);
 +                      return NULL;
-                       
                case ACHANNEL_SETTING_SELECT: /* selected */
                case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
                case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
 -                      if (part->adt)
 -                              return GET_ACF_FLAG_PTR(part->adt->flag, type);
                        return NULL;
-               
                default: /* unsupported */
                        return NULL;
        }
@@@ -3428,11 -3419,15 +3428,11 @@@ static void acf_nlaaction_backdrop(bAni
         *   so we ignore that and use our own when needed
         */
        nla_action_get_color(adt, (bAction *)ale->data, color);
-       
 -      if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
 -              /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
 -              glColor3fv(color);
 -      }
 -      else {
 -              float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
 -              glColor4f(color[0], color[1], color[2], alpha);
 -      }
 +      if (adt && (adt->flag & ADT_NLA_EDIT_ON))
 +              color[3] = 1.0f;
 +      else
 +              color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
  
        /* only on top left corner, to show that this channel sits on top of the preceding ones
         * while still linking into the action line strip to the right
@@@ -3829,11 -3824,11 +3829,11 @@@ void ANIM_channel_draw(bAnimContext *ac
                selected = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
        else
                selected = 0;
-               
        /* set blending again, as may not be set in previous step */
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
-       
        /* step 1) draw backdrop ...........................................  */
        if (acf->draw_backdrop)
                acf->draw_backdrop(ac, ale, yminc, ymaxc);
                        /* for F-Curves, draw color-preview of curve behind checkbox */
                        if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
                                FCurve *fcu = (FCurve *)ale->data;
-                               
-                               /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever 
-                                * color the curve has stored 
 +                              unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +                              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+                               /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever
+                                * color the curve has stored
                                 */
 -                              glColor3fv(fcu->color);
 +                              immUniformColor3fv(fcu->color);
-                               
                                /* just a solid color rect
                                 */
 -                              glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc);
 +                              immRectf(pos, offset, yminc, offset + ICON_WIDTH, ymaxc);
 +
 +                              immUnbindProgram();
                        }
                        /* icon is drawn as widget now... */
                        if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
  
                /* get name */
                acf->name(ale, name);
-               
                offset += 3;
 -              UI_fontstyle_draw_simple(fstyle, offset, ytext, name);
 +              UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col);
-               
                /* draw red underline if channel is disabled */
                if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
 +                      unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +                      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
                        /* FIXME: replace hardcoded color here, and check on extents! */
 -                      glColor3f(1.0f, 0.0f, 0.0f);
 -                      glLineWidth(2.0);
 -                      fdrawline((float)(offset), yminc,
 -                                (float)(v2d->cur.xmax), yminc);
 +                      immUniformColor3f(1.0f, 0.0f, 0.0f);
 +
 +                      glLineWidth(2.0f);
 +
 +                      immBegin(GWN_PRIM_LINES, 2);
 +                      immVertex2f(pos, (float)offset, yminc);
 +                      immVertex2f(pos, (float)v2d->cur.xmax, yminc);
 +                      immEnd();
 +
 +                      immUnbindProgram();
                }
        }
  
                short draw_sliders = 0;
                float ymin_ofs = 0.0f;
                float color[3];
-               
 +              unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
                /* get and set backdrop color */
                acf->get_backdrop_color(ac, ale, color);
 -              glColor3fv(color);
 +              immUniformColor3fv(color);
-               
                /* check if we need to show the sliders */
                if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
                        switch (ac->spacetype) {
                        /* adjust offset */
                        offset += SLIDER_WIDTH;
                }
-               
-               
                /* finally draw a backdrop rect behind these
-                *      - starts from the point where the first toggle/slider starts, 
+                *      - starts from the point where the first toggle/slider starts,
                 *      - ends past the space that might be reserved for a scroller
                 */
 -              glRectf(v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
 +              immRectf(pos, v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
 +
 +              immUnbindProgram();
        }
  }
  
@@@ -4048,16 -4021,7 +4048,16 @@@ static void achannel_setting_flush_widg
  
        if (ale_setting->type == ANIMTYPE_GPLAYER)
                WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
-       
 +      /* tag copy-on-write flushing (so that the settings will have an effect) */
 +      if (ale_setting->id) {
 +              DEG_id_tag_update(ale_setting->id, DEG_TAG_COPY_ON_WRITE);
 +      }
 +      if (ale_setting->adt && ale_setting->adt->action) {
 +              /* action is it's own datablock, so has to be tagged specifically... */
 +              DEG_id_tag_update(&ale_setting->adt->action->id, DEG_TAG_COPY_ON_WRITE);
 +      }
-       
++
        /* verify animation context */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return;
@@@ -4107,8 -4071,7 +4107,8 @@@ static void achannel_setting_slider_cb(
        ID *id = (ID *)id_poin;
        AnimData *adt = BKE_animdata_from_id(id);
        FCurve *fcu = (FCurve *)fcu_poin;
-       
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ReportList *reports = CTX_wm_reports(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *ts = scene->toolsettings;
                /* set the special 'replace' flag if on a keyframe */
                if (fcurve_frame_has_keyframe(fcu, cfra, 0))
                        flag |= INSERTKEY_REPLACE;
-               
                /* insert a keyframe for this F-Curve */
 -              done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
 +              done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-               
                if (done)
                        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        }
@@@ -4147,8 -4110,7 +4147,8 @@@ static void achannel_setting_slider_sha
        Key *key = (Key *)key_poin;
        KeyBlock *kb = (KeyBlock *)kb_poin;
        char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
-       
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ReportList *reports = CTX_wm_reports(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *ts = scene->toolsettings;
                /* set the special 'replace' flag if on a keyframe */
                if (fcurve_frame_has_keyframe(fcu, cfra, 0))
                        flag |= INSERTKEY_REPLACE;
-               
                /* insert a keyframe for this F-Curve */
 -              done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
 +              done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-               
                if (done)
                        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        }
@@@ -4199,8 -4161,7 +4199,8 @@@ static void achannel_setting_slider_nla
        PointerRNA ptr;
        PropertyRNA *prop;
        int index;
-       
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ReportList *reports = CTX_wm_reports(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *ts = scene->toolsettings;
                /* set the special 'replace' flag if on a keyframe */
                if (fcurve_frame_has_keyframe(fcu, cfra, 0))
                        flag |= INSERTKEY_REPLACE;
-               
                /* insert a keyframe for this F-Curve */
 -              done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
 +              done = insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, ts->keyframe_type, flag);
-               
                if (done)
                        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
        }
@@@ -1743,13 -1741,13 +1743,13 @@@ static int animchannels_delete_exec(bCo
                        }
                }
        }
-       
        /* cleanup */
        ANIM_animdata_freelist(&anim_data);
-       
        /* send notifier that things have changed */
        WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
 -      DAG_relations_tag_update(CTX_data_main(C));
 +      DEG_relations_tag_update(CTX_data_main(C));
  
        return OPERATOR_FINISHED;
  }
@@@ -2691,13 -2686,13 +2691,13 @@@ static int mouse_anim_channels(bContex
                        Base *base = (Base *)ale->data;
                        Object *ob = base->object;
                        AnimData *adt = ob->adt;
-                       
                        /* set selection status */
 -                      if ((ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
 +                      if (base->flag & BASE_SELECTABLED) {
                                if (selectmode == SELECT_INVERT) {
                                        /* swap select */
 -                                      base->flag ^= SELECT;
 -                                      ob->flag = base->flag;
 +                                      ED_object_base_select(base, BA_INVERT);
 +                                      BKE_scene_object_base_flag_sync_from_base(base);
  
                                        if (adt) adt->flag ^= ADT_UI_SELECTED;
                                }
@@@ -116,9 -112,9 +116,9 @@@ void ANIM_id_update(Scene *UNUSED(scene
                /* tag AnimData for refresh so that other views will update in realtime with these changes */
                if (adt)
                        adt->recalc |= ADT_RECALC_ANIM;
-                       
                /* set recalc flags */
 -              DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
 +              DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
        }
  }
  
  /* CURRENT FRAME DRAWING */
  
  /* Draw current frame number in a little green box beside the current frame indicator */
 -static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
 +void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
  {
-       
 +      Scene *scene = CTX_data_scene(C);
 +      const float time = scene->r.cfra + scene->r.subframe;
 +      const float cfra = (float)(time * scene->r.framelen);
 +      const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
++
        const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
 -      float xscale, yscale, x, y;
 -      char numstr[32] = "    t";  /* t is the character to start replacing from */
 +      unsigned char col[4];
 +      float color[4];
 +      float xscale, x, y;
 +      char numstr[32] = "  t  ";  /* t is the character to start replacing from */
 +      float hlen;
        int slen;
-       
        /* because the frame number text is subject to the same scaling as the contents of the view */
 -      UI_view2d_scale_get(v2d, &xscale, &yscale);
 -      glScalef(1.0f / xscale, 1.0f, 1.0f);
 +      UI_view2d_scale_get(v2d, &xscale, NULL);
 +      gpuPushMatrix();
 +      gpuScale2f(1.0f / xscale, 1.0f);
-       
-       /* get timecode string 
+       /* get timecode string
         *      - padding on str-buf passed so that it doesn't sit on the frame indicator
 -       *      - power = 0, gives 'standard' behavior for time
 -       *        but power = 1 is required for frames (to get integer frames)
         */
 -      if (time) {
 -              BLI_timecode_string_from_time(&numstr[4], sizeof(numstr) - 4, 0, FRA2TIME(cfra), FPS, U.timecode_style);
 +      if (show_time) {
 +              BLI_timecode_string_from_time(&numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style);
        }
        else {
 -              BLI_timecode_string_from_time_seconds(&numstr[4], sizeof(numstr) - 4, 1, cfra);
 +              BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra);
        }
  
        slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
-       
 +      hlen = slen * 0.5f;
        /* get starting coordinates for drawing */
        x = cfra * xscale;
 -      y = 0.9f * U.widget_unit;
 +      y = -0.1f * U.widget_unit;
  
        /* draw green box around/behind text */
 -      UI_ThemeColorShade(TH_CFRAME, 0);
 -      glRectf(x, y,  x + slen,  y + 0.75f * U.widget_unit);
 -
 -      /* draw current frame number - black text */
 -      UI_ThemeColor(TH_TEXT);
 -      UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
 +      UI_GetThemeColor4fv(TH_CFRAME, color);
 +      color[3] = 3.0f;
 +
 +      UI_draw_roundbox_corner_set(UI_CNR_ALL);
 +      UI_draw_roundbox_aa(true,
 +                          x - hlen - 0.1f * U.widget_unit,
 +                          y + 3.0f,
 +                          x + hlen + 0.1f * U.widget_unit,
 +                          y -3.0f + U.widget_unit,
 +                          0.1f * U.widget_unit,
 +                          color);
 +
 +      /* draw current frame number */
 +      UI_GetThemeColor4ubv(TH_TEXT_HI, col);
 +      UI_fontstyle_draw_simple(fstyle,
 +                               x - hlen - 0.15f * U.widget_unit,
 +                               y        + 0.28f * U.widget_unit,
 +                               numstr, col);
  
        /* restore view transform */
 -      glScalef(xscale, 1.0, 1.0);
 +      gpuPopMatrix();
  }
  
  /* General call for drawing current frame indicator in animation editor */
@@@ -163,18 -142,12 +163,18 @@@ void ANIM_draw_cfra(const bContext *C, 
  void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
  {
        Scene *scene = CTX_data_scene(C);
-       
        /* only draw this if preview range is set */
        if (PRVRANGEON) {
 -              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +              glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
                glEnable(GL_BLEND);
 -              glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
 +
 +              Gwn_VertFormat *format = immVertexFormat();
 +              unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +              immUniformThemeColorShadeAlpha(TH_ANIM_ACTIVE, -25, -30);
 +              //immUniformColor4f(0.8f, 0.44f, 0.1f, 0.2f); /* XXX: Fix this hardcoded color (anim_active) */
  
                /* only draw two separate 'curtains' if there's no overlap between them */
                if (PSFRA < PEFRA + end_frame_width) {
@@@ -132,20 -130,20 +132,20 @@@ static void animedit_get_yscale_factor(
  /* Note: there's a similar function in key.c (BKE_key_from_object) */
  static Key *actedit_get_shapekeys(bAnimContext *ac)
  {
 -      Scene *scene = ac->scene;
 +      ViewLayer *view_layer = ac->view_layer;
        Object *ob;
        Key *key;
-       
 -      ob = OBACT;
 +      ob = OBACT(view_layer);
-       if (ob == NULL) 
+       if (ob == NULL)
                return NULL;
-       
        /* XXX pinning is not available in 'ShapeKey' mode... */
        //if (saction->pin) return NULL;
-       
        /* shapekey data is stored with geometry data */
        key = BKE_key_from_object(ob);
-       
        if (key) {
                if (key->type == KEY_RELATIVE)
                        return key;
@@@ -230,27 -228,16 +230,27 @@@ static bool actedit_get_context(bAnimCo
                        ac->mode = saction->mode;
                        return true;
                }
-               
++
                case SACTCONT_DOPESHEET: /* DopeSheet */
                        /* update scene-pointer (no need to check for pinning yet, as not implemented) */
                        saction->ads.source = (ID *)ac->scene;
-                       
                        ac->datatype = ANIMCONT_DOPESHEET;
                        ac->data = &saction->ads;
-                       
                        ac->mode = saction->mode;
                        return true;
-               
 +              case SACTCONT_TIMELINE: /* Timeline */
 +                      /* update scene-pointer (no need to check for pinning yet, as not implemented) */
 +                      saction->ads.source = (ID *)ac->scene;
-                       
++
 +                      ac->datatype = ANIMCONT_TIMELINE;
 +                      ac->data = &saction->ads;
-                       
++
 +                      ac->mode = saction->mode;
 +                      return true;
-               
++
                default: /* unhandled yet */
                        ac->datatype = ANIMCONT_NONE;
                        ac->data = NULL;
@@@ -1683,19 -1668,18 +1683,19 @@@ static size_t animdata_filter_gpencil(b
  {
        bDopeSheet *ads = ac->ads;
        size_t items = 0;
-       
        if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
                Scene *scene = (Scene *)ads->source;
 +              ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
                Base *base;
  
                /* Active scene's GPencil block first - No parent item needed... */
                if (scene->gpd) {
                        items += animdata_filter_gpencil_data(anim_data, ads, scene->gpd, filter_mode);
                }
-               
                /* Objects in the scene */
 -              for (base = scene->base.first; base; base = base->next) {
 +              for (base = view_layer->object_bases.first; base; base = base->next) {
                        /* Only consider this object if it has got some GP data (saving on all the other tests) */
                        if (base->object && base->object->gpd) {
                                Object *ob = base->object;
                                 */
                                if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
                                        /* layer visibility - we check both object and base, since these may not be in sync yet */
 -                                      if ((scene->lay & (ob->lay | base->lay)) == 0) continue;
 +                                      if ((base->flag & BASE_VISIBLED) == 0) continue;
-                                       
                                        /* outliner restrict-flag */
                                        if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
                                }
-                               
                                /* check selection and object type filters */
 -                              if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) {
 +                              if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == scene->basact)*/) ) {
                                        /* only selected should be shown */
                                        continue;
                                }
                                 *      - used to ease the process of doing multiple-character choreographies
                                 */
                                if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
 -                                      if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
 +                                      if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
                                                continue;
                                }
-                               
                                /* finally, include this object's grease pencil datablock */
                                /* XXX: Should we store these under expanders per item? */
                                items += animdata_filter_gpencil_data(anim_data, ads, ob->gpd, filter_mode);
@@@ -1958,26 -1942,25 +1958,26 @@@ static size_t animdata_filter_ds_nodetr
  
  static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
  {
 -      SceneRenderLayer *srl;
 +      ViewLayer *view_layer;
        FreestyleLineSet *lineset;
        size_t items = 0;
-       
 -      for (srl = sce->r.layers.first; srl; srl = srl->next) {
 -              for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
 +      for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
 +              for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
                        if (lineset->linestyle) {
                                lineset->linestyle->id.tag |= LIB_TAG_DOIT;
                        }
                }
        }
-       
 -      for (srl = sce->r.layers.first; srl; srl = srl->next) {
 +      for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
                /* skip render layers without Freestyle enabled */
 -              if (!(srl->layflag & SCE_LAY_FRS))
 +              if ((view_layer->flag & VIEW_LAYER_FREESTYLE) == 0) {
                        continue;
 +              }
  
                /* loop over linesets defined in the render layer */
 -              for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
 +              for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
                        FreestyleLineStyle *linestyle = lineset->linestyle;
                        ListBase tmp_data = {NULL, NULL};
                        size_t tmp_items = 0;
@@@ -2074,8 -2055,26 +2074,8 @@@ static size_t animdata_filter_ds_textur
        /* get datatype specific data first */
        if (owner_id == NULL)
                return 0;
-       
        switch (GS(owner_id->name)) {
 -              case ID_MA:
 -              {
 -                      Material *ma = (Material *)owner_id;
 -                      mtex = (MTex **)(&ma->mtex);
 -                      break;
 -              }
 -              case ID_LA:
 -              {
 -                      Lamp *la = (Lamp *)owner_id;
 -                      mtex = (MTex **)(&la->mtex);
 -                      break;
 -              }
 -              case ID_WO:
 -              {
 -                      World *wo = (World *)owner_id;
 -                      mtex = (MTex **)(&wo->mtex);
 -                      break;
 -              }
                case ID_PA:
                {
                        ParticleSettings *part = (ParticleSettings *)owner_id;
@@@ -2119,9 -2118,13 +2119,9 @@@ static size_t animdata_filter_ds_materi
        {
                /* material's animation data */
                tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
-                       
 -              /* textures */
 -              if (!(ads->filterflag & ADS_FILTER_NOTEX))
 -                      tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)ma, filter_mode);
 -
                /* nodes */
-               if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) 
+               if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
                        tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)ma, ma->nodetree, filter_mode);
        }
        END_ANIMFILTER_SUBCHANNELS;
@@@ -2641,9 -2648,13 +2641,9 @@@ static size_t animdata_filter_ds_world(
        {
                /* animation data filtering */
                tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
-               
 -              /* textures for world */
 -              if (!(ads->filterflag & ADS_FILTER_NOTEX))
 -                      tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
 -
                /* nodes */
-               if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) 
+               if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
                        tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)wo, wo->nodetree, filter_mode);
        }
        END_ANIMFILTER_SUBCHANNELS;
@@@ -2832,13 -2843,13 +2832,13 @@@ static size_t animdata_filter_dopesheet
  }
  
  /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
 -static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode)
 +static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_mode)
  {
        Object *ob = base->object;
-       
        if (base->object == NULL)
                return false;
-       
        /* firstly, check if object can be included, by the following factors:
         *      - if only visible, must check for layer and also viewport visibility
         *              --> while tools may demand only visible, user setting takes priority
         */
        if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
                /* layer visibility - we check both object and base, since these may not be in sync yet */
 -              if ((scene->lay & (ob->lay | base->lay)) == 0)
 +              if ((base->flag & BASE_VISIBLED) == 0)
                        return false;
-               
                /* outliner restrict-flag */
                if (ob->restrictflag & OB_RESTRICT_VIEW)
                        return false;
         *      - used to ease the process of doing multiple-character choreographies
         */
        if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
 -              if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
 +              if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
                        return false;
        }
-       
        /* no reason to exclude this object... */
        return true;
  }
@@@ -2913,15 -2924,15 +2913,15 @@@ static int ds_base_sorting_cmp(const vo
  }
  
  /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
 -static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
 +static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, ViewLayer *view_layer, int filter_mode, size_t *r_usable_bases)
  {
        /* Create an array with space for all the bases, but only containing the usable ones */
 -      size_t tot_bases = BLI_listbase_count(&scene->base);
 +      size_t tot_bases = BLI_listbase_count(&view_layer->object_bases);
        size_t num_bases = 0;
-       
        Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
 -      for (Base *base = scene->base.first; base; base = base->next) {
 -              if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
 +      for (Base *base = view_layer->object_bases.first; base; base = base->next) {
 +              if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
                        sorted_bases[num_bases++] = base;
                }
        }
@@@ -2984,8 -2994,8 +2984,8 @@@ static size_t animdata_filter_dopesheet
                // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
                Base **sorted_bases;
                size_t num_bases;
-               
 -              sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
 +              sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases);
                if (sorted_bases) {
                        /* Add the necessary channels for these bases... */
                        for (size_t i = 0; i < num_bases; i++) {
@@@ -3244,17 -3254,8 +3244,17 @@@ size_t ANIM_animdata_filter(bAnimContex
                                items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
                                break;
                        }
-                       
-                       
 +                      /* Timeline Mode - Basically the same as dopesheet, except we only have the summary for now */
 +                      case ANIMCONT_TIMELINE:
 +                      {
 +                              /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
 +                              if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
 +                                      items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
 +                              break;
 +                      }
-                       
++
                        /* Special/Internal Use */
                        case ANIMCONT_CHANNEL: /* animation channel */
                        {
@@@ -335,44 -332,6 +335,44 @@@ void debug_markers_print_list(ListBase 
  
  /* ************* Marker Drawing ************ */
  
-       
 +static void draw_marker_name(
 +        const uiFontStyle *fstyle, TimeMarker *marker, const char *name,
 +        int cfra, const float xpos, const float ypixels)
 +{
 +      unsigned char text_col[4];
 +      float x, y;
 +
 +      /* minimal y coordinate which wouldn't be occluded by scroll */
 +      int min_y = 17.0f * UI_DPI_FAC;
++
 +      if (marker->flag & SELECT) {
 +              UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
 +              x = xpos + 4.0f * UI_DPI_FAC;
 +              y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
 +              y = max_ii(y, min_y);
 +      }
 +      else {
 +              UI_GetThemeColor4ubv(TH_TEXT, text_col);
 +              if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
 +                      x = xpos + 8.0f * UI_DPI_FAC;
 +                      y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
 +                      y = max_ii(y, min_y);
 +              }
 +              else {
 +                      x = xpos + 8.0f * UI_DPI_FAC;
 +                      y = 17.0f * UI_DPI_FAC;
 +              }
 +      }
 +
 +#ifdef DURIAN_CAMERA_SWITCH
 +      if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
 +              text_col[3] = 100;
 +      }
 +#endif
 +
 +      UI_fontstyle_draw_simple(fstyle, x, y, name, text_col);
 +}
 +
  /* function to draw markers */
  static void draw_marker(
          View2D *v2d, const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int flag,
        if (flag & DRAW_MARKERS_LINES)
  #endif
        {
 -              setlinestyle(3);
 +              Gwn_VertFormat *format = immVertexFormat();
 +              uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
  
 -              if (marker->flag & SELECT)
 -                      glColor4ub(255, 255, 255, 96);
 -              else
 -                      glColor4ub(0, 0, 0, 96);
 +              float viewport_size[4];
 +              glGetFloatv(GL_VIEWPORT, viewport_size);
 +              immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
 +
 +              if (marker->flag & SELECT) {
 +                      immUniformColor4f(1.0f, 1.0f, 1.0f, 0.38f);
 +              }
 +              else {
 +                      immUniformColor4f(0.0f, 0.0f, 0.0f, 0.38f);
 +              }
 +              immUniform1f("dash_width", 6.0f);
 +              immUniform1f("dash_factor", 0.5f);
  
 -              glBegin(GL_LINES);
 -              glVertex2f(xpos + 0.5f, 12.0f);
 -              glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
 -              glEnd();
 +              immBegin(GWN_PRIM_LINES, 2);
 +              immVertex2f(pos, xpos + 0.5f, 12.0f);
 +              immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
 +              immEnd();
  
 -              setlinestyle(0);
 +              immUnbindProgram();
        }
-       
        /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
        if (flag & DRAW_MARKERS_LOCAL) {
                icon_id = (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
                icon_id = (marker->flag & SELECT) ? ICON_MARKER_HLT :
                          ICON_MARKER;
        }
-       
 -      UI_icon_draw(xpos - 0.45f * UI_DPI_ICON_SIZE, UI_DPI_ICON_SIZE, icon_id);
 +      UI_icon_draw(xpos - 0.45f * UI_DPI_ICON_SIZE, yoffs + UI_DPI_ICON_SIZE, icon_id);
-       
        glDisable(GL_BLEND);
-       
        /* and the marker name too, shifted slightly to the top-right */
 -      if (marker->name[0]) {
 -              float x, y;
 -
 -              /* minimal y coordinate which wouldn't be occluded by scroll */
 -              int min_y = 17.0f * UI_DPI_FAC;
 -
 -              if (marker->flag & SELECT) {
 -                      UI_ThemeColor(TH_TEXT_HI);
 -                      x = xpos + 4.0f * UI_DPI_FAC;
 -                      y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
 -                      y = max_ii(y, min_y);
 -              }
 -              else {
 -                      UI_ThemeColor(TH_TEXT);
 -                      if ((marker->frame <= cfra) && (marker->frame + 5 > cfra)) {
 -                              x = xpos + 8.0f * UI_DPI_FAC;
 -                              y = (ypixels <= 39.0f * UI_DPI_FAC) ? (ypixels - 10.0f * UI_DPI_FAC) : 29.0f * UI_DPI_FAC;
 -                              y = max_ii(y, min_y);
 -                      }
 -                      else {
 -                              x = xpos + 8.0f * UI_DPI_FAC;
 -                              y = 17.0f * UI_DPI_FAC;
 -                      }
 -              }
 -
  #ifdef DURIAN_CAMERA_SWITCH
 -              if (marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
 -                      float col[4];
 -                      glGetFloatv(GL_CURRENT_COLOR, col);
 -                      col[3] = 0.4;
 -                      glColor4fv(col);
 -              }
 -#endif
 +      if (marker->camera) {
 +              draw_marker_name(fstyle, marker, marker->camera->id.name + 2, cfra, xpos, ypixels);
 +      }
 +      else if (marker->name[0]) {
 +              draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
 +      }
 +#else
 +      if (marker->name[0]) {
 +              draw_marker_name(fstyle, marker, marker->name, cfra, xpos, ypixels);
  
 -              UI_fontstyle_draw_simple(fstyle, x, y, marker->name);
        }
 +#endif
  }
  
  /* Draw Scene-Markers in time window */
@@@ -1172,10 -1132,10 +1172,10 @@@ static int ed_marker_select(bContext *C
                Base *base;
                TimeMarker *marker;
                int sel = 0;
-               
                if (!extend)
 -                      BKE_scene_base_deselect_all(scene);
 +                      BKE_view_layer_base_deselect_all(view_layer);
-               
                for (marker = markers->first; marker; marker = marker->next) {
                        if (marker->frame == cfra) {
                                sel = (marker->flag & SELECT);
@@@ -85,8 -85,8 +85,8 @@@ static int change_frame_poll(bContext *
                        return false;
                }
        }
-       
 -      CTX_wm_operator_poll_msg_set(C, "Expected an timeline/animation area to be active");
 +      CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
        return false;
  }
  
@@@ -276,116 -276,6 +276,116 @@@ static void ANIM_OT_change_frame(wmOper
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
-       
 +
 +/* ****************** Start/End Frame Operators *******************************/
 +
 +static int anim_set_end_frames_poll(bContext *C)
 +{
 +      ScrArea *sa = CTX_wm_area(C);
-       
++
 +      /* XXX temp? prevent changes during render */
 +      if (G.is_rendering) return false;
-       
++
 +      /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
 +       * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
 +       */
 +      if (sa) {
 +              if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
 +                      return true;
 +              }
 +      }
-       
++
 +      CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active");
 +      return false;
 +}
 +
 +static int anim_set_sfra_exec(bContext *C, wmOperator *UNUSED(op))
 +{
 +      Scene *scene = CTX_data_scene(C);
 +      int frame;
 +
 +      if (scene == NULL)
 +              return OPERATOR_CANCELLED;
 +
 +      frame = CFRA;
 +
 +      /* if Preview Range is defined, set the 'start' frame for that */
 +      if (PRVRANGEON)
 +              scene->r.psfra = frame;
 +      else
 +              scene->r.sfra = frame;
-       
++
 +      if (PEFRA < frame) {
 +              if (PRVRANGEON)
 +                      scene->r.pefra = frame;
 +              else
 +                      scene->r.efra = frame;
 +      }
-       
++
 +      WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-       
++
 +      return OPERATOR_FINISHED;
 +}
 +
 +static void ANIM_OT_start_frame_set(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name = "Set Start Frame";
 +      ot->idname = "ANIM_OT_start_frame_set";
 +      ot->description = "Set the start frame";
-       
++
 +      /* api callbacks */
 +      ot->exec = anim_set_sfra_exec;
 +      ot->poll = anim_set_end_frames_poll;
- }     
++
 +      /* flags */
 +      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-       
++}
 +
 +
 +static int anim_set_efra_exec(bContext *C, wmOperator *UNUSED(op))
 +{
 +      Scene *scene = CTX_data_scene(C);
 +      int frame;
 +
 +      if (scene == NULL)
 +              return OPERATOR_CANCELLED;
 +
 +      frame = CFRA;
 +
 +      /* if Preview Range is defined, set the 'end' frame for that */
 +      if (PRVRANGEON)
 +              scene->r.pefra = frame;
 +      else
 +              scene->r.efra = frame;
 +
 +      if (PSFRA > frame) {
 +              if (PRVRANGEON)
 +                      scene->r.psfra = frame;
 +              else
 +                      scene->r.sfra = frame;
 +      }
-       
++
 +      WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
-       
++
 +      return OPERATOR_FINISHED;
 +}
 +
 +static void ANIM_OT_end_frame_set(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name = "Set End Frame";
 +      ot->idname = "ANIM_OT_end_frame_set";
 +      ot->description = "Set the end frame";
-       
++
 +      /* api callbacks */
 +      ot->exec = anim_set_efra_exec;
 +      ot->poll = anim_set_end_frames_poll;
++
 +      /* flags */
 +      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +}
 +
  /* ****************** set preview range operator ****************************/
  
  static int previewrange_define_exec(bContext *C, wmOperator *op)
@@@ -492,13 -382,10 +492,13 @@@ void ED_operatortypes_anim(void
  {
        /* Animation Editors only -------------------------- */
        WM_operatortype_append(ANIM_OT_change_frame);
-       
 +      WM_operatortype_append(ANIM_OT_start_frame_set);
 +      WM_operatortype_append(ANIM_OT_end_frame_set);
-       
++
        WM_operatortype_append(ANIM_OT_previewrange_set);
        WM_operatortype_append(ANIM_OT_previewrange_clear);
-       
        /* Entire UI --------------------------------------- */
        WM_operatortype_append(ANIM_OT_keyframe_insert);
        WM_operatortype_append(ANIM_OT_keyframe_delete);
        WM_operatortype_append(ANIM_OT_keyframe_insert_button);
        WM_operatortype_append(ANIM_OT_keyframe_delete_button);
        WM_operatortype_append(ANIM_OT_keyframe_clear_button);
-       
-       
        WM_operatortype_append(ANIM_OT_driver_button_add);
        WM_operatortype_append(ANIM_OT_driver_button_remove);
 +      WM_operatortype_append(ANIM_OT_driver_button_edit);
        WM_operatortype_append(ANIM_OT_copy_driver_button);
        WM_operatortype_append(ANIM_OT_paste_driver_button);
  
@@@ -115,10 -112,11 +115,10 @@@ FCurve *verify_driver_fcurve(ID *id, co
                if (add > 0) {
                        BezTriple *bezt;
                        size_t i;
-                       
                        /* add some new driver data */
                        fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
-                       
 -                      fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
                        /* F-Modifier or Keyframes? */
                        // FIXME: replace these magic numbers with defines
                        if (add == 2) {
@@@ -845,9 -843,9 +845,9 @@@ static int add_driver_button_none(bCont
        if (success) {
                /* send updates */
                UI_context_update_anim_flag(C);
 -              DAG_relations_tag_update(CTX_data_main(C));
 +              DEG_relations_tag_update(CTX_data_main(C));
                WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
-               
                return OPERATOR_FINISHED;
        }
        else {
@@@ -943,10 -941,10 +943,10 @@@ static int remove_driver_button_exec(bC
        if (success) {
                /* send updates */
                UI_context_update_anim_flag(C);
 -              DAG_relations_tag_update(CTX_data_main(C));
 +              DEG_relations_tag_update(CTX_data_main(C));
                WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
        }
-       
        return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
  }
  
@@@ -968,46 -966,6 +968,46 @@@ void ANIM_OT_driver_button_remove(wmOpe
        RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array");
  }
  
-       
 +/* Edit Driver Button Operator ------------------------ */
 +
 +static int edit_driver_button_exec(bContext *C, wmOperator *op)
 +{
 +      PointerRNA ptr = {{NULL}};
 +      PropertyRNA *prop = NULL;
 +      int index;
 +      const bool all = 0; // RNA_boolean_get(op->ptr, "all");
 +
 +      /* try to find driver using property retrieved from UI */
 +      UI_context_active_but_prop_get(C, &ptr, &prop, &index);
 +
 +      if (all)
 +              index = -1;
 +
 +      if (ptr.id.data && ptr.data && prop) {
 +              UI_popover_panel_invoke(C, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports);
 +      }
 +
 +      return OPERATOR_INTERFACE;
 +}
 +
 +void ANIM_OT_driver_button_edit(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name = "Edit Driver";
 +      ot->idname = "ANIM_OT_driver_button_edit";
 +      ot->description = "Edit the drivers for the property connected represented by the highlighted button";
-       
++
 +      /* callbacks */
 +      ot->exec = edit_driver_button_exec;
 +      //op->poll = ??? // TODO: need to have some driver to be able to do this...
++
 +      /* flags */
 +      ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
 +
 +      /* properties */
 +      //RNA_def_boolean(ot->srna, "all", 1, "All", "Edit drivers for all elements of the array");
 +}
 +
  /* Copy Driver Button Operator ------------------------ */
  
  static int copy_driver_button_exec(bContext *C, wmOperator *op)
@@@ -1070,14 -1028,14 +1070,14 @@@ static int paste_driver_button_exec(bCo
                if (path) {
                        /* only copy the driver for the button that this was involved for */
                        success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
-                       
                        UI_context_update_anim_flag(C);
-                       
 -                      DAG_relations_tag_update(CTX_data_main(C));
 -                      DAG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
 +                      DEG_relations_tag_update(CTX_data_main(C));
 +                      DEG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
-                       
                        WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);  // XXX
-                       
                        MEM_freeN(path);
                }
        }
@@@ -478,95 -511,123 +478,95 @@@ void draw_keyframe_shape(float x, floa
        switch (key_type) {
                case BEZT_KEYTYPE_KEYFRAME:  /* must be full size */
                        break;
-               
                case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
 -                      hsize *= 0.85f;
 +                      size *= 0.85f;
                        break;
-               
                case BEZT_KEYTYPE_MOVEHOLD:  /* slightly smaller than normal keyframes (but by less than for breakdowns) */
 -                      //hsize *= 0.72f;
 -                      hsize *= 0.95f;
 +                      size *= 0.925f;
                        break;
-                       
                case BEZT_KEYTYPE_EXTREME:   /* slightly larger */
 -                      hsize *= 1.2f;
 +                      size *= 1.2f;
                        break;
-               
                default:
 -                      hsize -= 0.5f * key_type;
 -                      break;
 +                      size -= 0.8f * key_type;
        }
  
 -      /* adjust view transform before starting */
 -      glTranslatef(x, y, 0.0f);
 -      glScalef(1.0f / xscale * hsize, hsize, 1.0f);
 -
 -      /* anti-aliased lines for more consistent appearance */
 -      glEnable(GL_LINE_SMOOTH);
 +      unsigned char fill_col[4];
 +      unsigned char outline_col[4];
  
        /* draw! */
 -      if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) {
 -              float inner_col[4];
 -
 +      if (draw_fill) {
                /* get interior colors from theme (for selected and unselected only) */
                switch (key_type) {
                        case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
 -                      {
 -                              if (sel)  UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col);
 -                              else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col);
 +                              UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
                                break;
 -                      }
                        case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
 -                      {
 -                              if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col);
 -                              else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col);
 +                              UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
                                break;
 -                      }
                        case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
 -                      {
 -                              if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col);
 -                              else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
 +                              UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
                                break;
 -                      }
                        case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
 -                      {
                                /* XXX: Should these get their own theme options instead? */
 -                              if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col);
 -                              else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col);
 -
 -                              inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */
 +                              if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col);
 +                              else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col);
 +                              fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */
                                break;
 -                      }
                        case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
                        default:
 -                      {
 -                              if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col);
 -                              else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col);
 -                              break;
 -                      }
 +                              UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
                }
-               
-               /* NOTE: we don't use the straight alpha from the theme, or else effects such as 
+               /* NOTE: we don't use the straight alpha from the theme, or else effects such as
                 * graying out protected/muted channels doesn't work correctly!
                 */
 -              inner_col[3] *= alpha;
 -              glColor4fv(inner_col);
 -
 -              /* draw the "filled in" interior poly now */
 -              glCallList(displist2);
 +              fill_col[3] *= alpha;
 +
 +              if (!draw_outline) {
 +                      /* force outline color to match */
 +                      outline_col[0] = fill_col[0];
 +                      outline_col[1] = fill_col[1];
 +                      outline_col[2] = fill_col[2];
 +                      outline_col[3] = fill_col[3];
 +              }
        }
  
 -      if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) {
 -              float border_col[4];
 -
 +      if (draw_outline) {
                /* exterior - black frame */
 -              if (sel)  UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col);
 -              else  UI_GetThemeColor4fv(TH_KEYBORDER, border_col);
 -
 -              border_col[3] *= alpha;
 -              glColor4fv(border_col);
 -
 -              glCallList(displist1);
 +              UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
 +              outline_col[3] *= alpha;
 +
 +              if (!draw_fill) {
 +                      /* fill color needs to be (outline.rgb, 0) */
 +                      fill_col[0] = outline_col[0];
 +                      fill_col[1] = outline_col[1];
 +                      fill_col[2] = outline_col[2];
 +                      fill_col[3] = 0;
 +              }
        }
  
 -      glDisable(GL_LINE_SMOOTH);
 -
 -      /* restore view transform */
 -      glScalef(xscale / hsize, 1.0f / hsize, 1.0f);
 -      glTranslatef(-x, -y, 0.0f);
 +      immAttrib1f(size_id, size);
 +      immAttrib4ubv(color_id, fill_col);
 +      immAttrib4ubv(outline_color_id, outline_col);
 +      immVertex2f(pos_id, x, y);
  }
  
  static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
  {
 -      ActKeyColumn *ak;
 -      ActKeyBlock *ab;
 -      float alpha;
 -      float xscale;
 -
 -      const float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
 -      const float mhsize   = iconsize * 0.7f;
 +      const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
 +      const float half_icon_sz = 0.5f * icon_sz;
-       
        glEnable(GL_BLEND);
-       
 -      /* get View2D scaling factor */
 -      UI_view2d_scale_get(v2d, &xscale, NULL);
 -
        /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
        /* TODO: allow this opacity factor to be themed? */
 -      alpha = (channelLocked) ? 0.25f : 1.0f;
 +      float alpha = channelLocked ? 0.25f : 1.0f;
-       
        /* draw keyblocks */
        if (blocks) {
                float sel_color[4], unsel_color[4];
                copy_v4_v4(unsel_mhcol, unsel_color);
                unsel_mhcol[3] *= 0.8f;
  
 -              /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
 -              for (ab = blocks->first; ab; ab = ab->next) {
 +              unsigned int block_ct = 0;
 +              for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
                        if (actkeyblock_is_valid(ab, keys)) {
 -                              if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
 -                                      /* draw "moving hold" long-keyframe block - slightly smaller */
 -                                      if (ab->sel)
 -                                              glColor4fv(sel_mhcol);
 -                                      else
 -                                              glColor4fv(unsel_mhcol);
 -
 -                                      glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize);
 -                              }
 -                              else {
 -                                      /* draw standard long-keyframe block */
 -                                      if (ab->sel)
 -                                              glColor4fv(sel_color);
 -                                      else
 -                                              glColor4fv(unsel_color);
 -
 -                                      glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
 +                              block_ct++;
 +                      }
 +              }
 +
 +              if (block_ct > 0) {
 +                      Gwn_VertFormat *format = immVertexFormat();
 +                      unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +                      unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
 +                      immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
 +
 +                      immBegin(GWN_PRIM_TRIS, 6 * block_ct);
 +                      for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
 +                              if (actkeyblock_is_valid(ab, keys)) {
 +                                      if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
 +                                              /* draw "moving hold" long-keyframe block - slightly smaller */
 +                                              immRectf_fast_with_color(pos_id, color_id,
 +                                                                       ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
 +                                                                       (ab->sel) ? sel_mhcol : unsel_mhcol);
 +                                      }
 +                                      else {
 +                                              /* draw standard long-keyframe block */
 +                                              immRectf_fast_with_color(pos_id, color_id,
 +                                                                       ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
 +                                                                       (ab->sel) ? sel_color : unsel_color);
 +                                      }
                                }
                        }
 +                      immEnd();
 +                      immUnbindProgram();
                }
        }
-       
 -      /* draw keys */
        if (keys) {
 -              for (ak = keys->first; ak; ak = ak->next) {
 +              /* count keys */
 +              unsigned int key_ct = 0;
 +              for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
                        /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
                         *      - this might give some improvements, since we current have to flip between view/region matrices
                         */
@@@ -616,13 -611,10 +616,13 @@@ static short new_key_needed(FCurve *fcu
  /* ------------------ RNA Data-Access Functions ------------------ */
  
  /* Try to read value using RNA-properties obtained already */
 -static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index)
 +static float setting_get_rna_value(Depsgraph *depsgraph, PointerRNA *ptr, PropertyRNA *prop, int index)
  {
 +      PointerRNA ptr_eval;
        float value = 0.0f;
-       
 +      DEG_get_evaluated_rna_pointer(depsgraph, ptr, &ptr_eval);
-       
++
        switch (RNA_property_type(prop)) {
                case PROP_BOOLEAN:
                        if (RNA_property_array_check(prop))
@@@ -819,26 -811,21 +819,26 @@@ static float visualkey_get_value(Depsgr
         */
        if (ptr->type == &RNA_Object) {
                Object *ob = (Object *)ptr->data;
-               
 +              const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
                /* Loc code is specific... */
                if (strstr(identifier, "location")) {
 -                      return ob->obmat[3][array_index];
 +                      return ob_eval->obmat[3][array_index];
                }
-               
 -              copy_m4_m4(tmat, ob->obmat);
 -              rotmode = ob->rotmode;
 +              copy_m4_m4(tmat, ob_eval->obmat);
 +              rotmode = ob_eval->rotmode;
        }
        else if (ptr->type == &RNA_PoseBone) {
 +              Object *ob = (Object *)ptr->id.data;
                bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-               
 -              BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, tmat);
 -              rotmode = pchan->rotmode;
 +              const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
 +              bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
-               
++
 +              BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, tmat);
 +              rotmode = pchan_eval->rotmode;
-               
                /* Loc code is specific... */
                if (strstr(identifier, "location")) {
                        /* only use for non-connected bones */
                }
        }
        else {
 -              return setting_get_rna_value(ptr, prop, array_index);
 +              return setting_get_rna_value(depsgraph, ptr, prop, array_index);
        }
-       
        /* Rot/Scale code are common! */
        if (strstr(identifier, "rotation_euler")) {
                float eul[3];
        }
        else if (strstr(identifier, "scale")) {
                float scale[3];
-               
                mat4_to_size(scale, tmat);
-               
                return scale[array_index];
        }
-       
        /* as the function hasn't returned yet, read value from system in the default way */
 -      return setting_get_rna_value(ptr, prop, array_index);
 +      return setting_get_rna_value(depsgraph, ptr, prop, array_index);
  }
  
  /* ------------------------- Insert Key API ------------------------- */
   *    the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
   *    and extra keyframe filtering.
   */
 -bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
 +bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
  {
        float curval = 0.0f;
-       
        /* no F-Curve to add keyframe to? */
        if (fcu == NULL) {
                BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
                        cfra = 0.0f;
                }
        }
-       
        /* obtain value to give keyframe */
-       if ( (flag & INSERTKEY_MATRIX) && 
+       if ( (flag & INSERTKEY_MATRIX) &&
             (visualkey_can_use(&ptr, prop)) )
        {
-               /* visual-keying is only available for object and pchan datablocks, as 
-                * it works by keyframing using a value extracted from the final matrix 
+               /* visual-keying is only available for object and pchan datablocks, as
+                * it works by keyframing using a value extracted from the final matrix
                 * instead of using the kt system to extract a value.
                 */
 -              curval = visualkey_get_value(&ptr, prop, fcu->array_index);
 +              curval = visualkey_get_value(depsgraph, &ptr, prop, fcu->array_index);
        }
        else {
                /* read value from system */
 -              curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
 +              curval = setting_get_rna_value(depsgraph, &ptr, prop, fcu->array_index);
        }
-       
        /* only insert keyframes where they are needed */
        if (flag & INSERTKEY_NEEDED) {
                short insert_mode;
   *
   *    index of -1 keys all array indices
   */
 -short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
 +short insert_keyframe(Depsgraph *depsgraph, ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag)
- {     
+ {
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop = NULL;
        AnimData *adt;
                                        fcu->color_mode = FCURVE_COLOR_AUTO_YRGB;
                                }
                        }
-                       
                        /* insert keyframe */
 -                      ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, keytype, flag);
 +                      ret += insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, keytype, flag);
                }
        }
-       
        return ret;
  }
  
@@@ -1737,14 -1724,14 +1737,14 @@@ static int delete_key_v3d_exec(bContex
                        BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success);
                else
                        BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
-               
 -              DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_OB);
        }
        CTX_DATA_END;
-       
        /* send updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -1801,9 -1787,9 +1801,9 @@@ static int insert_key_button_exec(bCont
                         */
                        NlaStrip *strip = (NlaStrip *)ptr.data;
                        FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
-                       
                        if (fcu) {
 -                              success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
 +                              success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, 0);
                        }
                        else {
                                BKE_report(op->reports, RPT_ERROR,
                        /* Driven property - Find driver */
                        FCurve *fcu;
                        bool driven, special;
-                       
                        fcu = rna_get_fcurve_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
-                       
                        if (fcu && driven) {
 -                              success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
 +                              success = insert_keyframe_direct(depsgraph, op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
                        }
                }
                else {
                        /* standard properties */
                        path = RNA_path_from_ID_to_property(&ptr, prop);
-                       
                        if (path) {
-                               
 +                              const char *identifier = RNA_property_identifier(prop);
 +                              const char *group = NULL;
-                               
-                               
++
 +                              /* Special exception for keyframing transforms:
 +                               * Set "group" for this manually, instead of having them appearing at the bottom (ungrouped)
 +                               * part of the channels list. Leaving these ungrouped is not a nice user behaviour in this case.
 +                               *
 +                               * TODO: Perhaps we can extend this behaviour in future for other properties...
 +                               */
 +                              if (ptr.type == &RNA_PoseBone) {
 +                                      bPoseChannel *pchan = (bPoseChannel *)ptr.data;
 +                                      group = pchan->name;
 +                              }
 +                              else if ((ptr.type == &RNA_Object) &&
 +                                       (strstr(identifier, "location") || strstr(identifier, "rotation") || strstr(identifier, "scale")))
 +                              {
 +                                      /* NOTE: Keep this label in sync with the "ID" case in
 +                                       * keyingsets_utils.py :: get_transform_generators_base_info()
 +                                       */
 +                                      group = "Object Transforms";
 +                              }
++
++
                                if (all) {
                                        /* -1 indicates operating on the entire array (or the property itself otherwise) */
                                        index = -1;
                                }
-                               
 -                              success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, ts->keyframe_type, flag);
 +                              success = insert_keyframe(depsgraph, op->reports, ptr.id.data, NULL, group, path, index, cfra, ts->keyframe_type, flag);
-                               
                                MEM_freeN(path);
                        }
                        else {
@@@ -1049,16 -1047,15 +1049,16 @@@ int ANIM_apply_keyingset(bContext *C, L
                        case ID_OB: /* Object (or Object-Related) Keyframes */
                        {
                                Object *ob = (Object *)ksp->id;
-                               
                                // XXX: only object transforms?
 -                              DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
 +                              DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                                break;
                        }
                        default:
 +                              DEG_id_tag_update(ksp->id, DEG_TAG_COPY_ON_WRITE);
                                break;
                }
-               
                /* send notifiers for updates (this doesn't require context to work!) */
                WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
        }
@@@ -186,14 -187,14 +186,14 @@@ static int armature_click_extrude_exec(
                        newbone->parent = ebone;
                        newbone->flag |= BONE_CONNECTED;
                }
-               
 -              curs = ED_view3d_cursor3d_get(scene, v3d);
 -              copy_v3_v3(newbone->tail, curs);
 +              const View3DCursor *curs = ED_view3d_cursor3d_get(scene, v3d);
 +              copy_v3_v3(newbone->tail, curs->location);
                sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
-               
                if (a == 1)
                        newbone->tail[0] = -newbone->tail[0];
-               
                copy_m3_m4(mat, obedit->obmat);
                invert_m3_m3(imat, mat);
                mul_m3_v3(imat, newbone->tail);
@@@ -226,14 -227,14 +226,14 @@@ static int armature_click_extrude_invok
        scene = CTX_data_scene(C);
        ar = CTX_wm_region(C);
        v3d = CTX_wm_view3d(C);
-       
 -      fp = ED_view3d_cursor3d_get(scene, v3d);
 +      View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
-       
 -      copy_v3_v3(oldcurs, fp);
 +      copy_v3_v3(oldcurs, cursor->location);
  
        VECCOPY2D(mval_f, event->mval);
 -      ED_view3d_win_to_3d(v3d, ar, fp, mval_f, tvec);
 -      copy_v3_v3(fp, tvec);
 +      ED_view3d_win_to_3d(v3d, ar, cursor->location, mval_f, tvec);
 +      copy_v3_v3(cursor->location, tvec);
  
        /* extrude to the where new cursor is and store the operation result */
        retv = armature_click_extrude_exec(C, op);
@@@ -1009,10 -1010,10 +1009,10 @@@ static int armature_bone_primitive_add_
        EditBone *bone;
        float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
        char name[MAXBONENAME];
-       
        RNA_string_get(op->ptr, "name", name);
-       
 -      copy_v3_v3(curs, ED_view3d_cursor3d_get(CTX_data_scene(C), CTX_wm_view3d(C)));
 +      copy_v3_v3(curs, ED_view3d_cursor3d_get(CTX_data_scene(C), CTX_wm_view3d(C))->location);
  
        /* Get inverse point for head and orientation for tail */
        invert_m4_m4(obedit->imat, obedit->obmat);
@@@ -1073,15 -1074,16 +1073,15 @@@ void ARMATURE_OT_bone_primitive_add(wmO
  static int armature_subdivide_exec(bContext *C, wmOperator *op)
  {
        Object *obedit = CTX_data_edit_object(C);
 -      bArmature *arm = obedit->data;
        EditBone *newbone, *tbone;
        int cuts, i;
-       
        /* there may not be a number_cuts property defined (for 'simple' subdivide) */
        cuts = RNA_int_get(op->ptr, "number_cuts");
-       
        /* loop over all editable bones */
        // XXX the old code did this in reverse order though!
 -      CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
 +      CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
        {
                for (i = cuts + 1; i > 1; i--) {
                        /* compute cut ratio first */
@@@ -187,9 -186,9 +187,9 @@@ void ED_armature_origin_set(Object *ob
                sub_v3_v3(ebone->head, cent);
                sub_v3_v3(ebone->tail, cent);
        }
-       
        /* Turn the list into an armature */
 -      if (obedit == NULL) {
 +      if (is_editmode == false) {
                ED_armature_from_edit(arm);
                ED_armature_edit_free(arm);
        }
@@@ -318,13 -317,13 +318,13 @@@ static int armature_calc_roll_exec(bCon
                Scene *scene = CTX_data_scene(C);
                View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
                float cursor_local[3];
 -              const float   *cursor = ED_view3d_cursor3d_get(scene, v3d);
 +              const View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
-               
                invert_m4_m4(ob->imat, ob->obmat);
 -              copy_v3_v3(cursor_local, cursor);
 +              copy_v3_v3(cursor_local, cursor->location);
                mul_m4_v3(ob->imat, cursor_local);
  
-               
                /* cursor */
                for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
                        if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
@@@ -637,36 -637,21 +637,36 @@@ static int armature_fill_bones_exec(bCo
        ListBase points = {NULL, NULL};
        EditBone *newbone = NULL;
        int count;
 +      bool mixed_object_error = false;
  
        /* sanity checks */
 -      if (ELEM(NULL, obedit, arm))
 +      if (ELEM(NULL, obedit_active, obedit_active->data)) {
                return OPERATOR_CANCELLED;
 +      }
  
        /* loop over all bones, and only consider if visible */
 -      CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
 +      bArmature *arm = NULL;
 +      CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, visible_bones, bArmature *, arm_iter)
        {
 -              if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
 +              bool check = false;
 +              if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) {
                        fill_add_joint(ebone, 0, &points);
 -              if (ebone->flag & BONE_TIPSEL)
 +                      check = true;
 +              }
 +              if (ebone->flag & BONE_TIPSEL) {
                        fill_add_joint(ebone, 1, &points);
 +                      check = true;
 +              }
 +
 +              if (check) {
 +                      if (arm && (arm != arm_iter)) {
 +                              mixed_object_error = true;
 +                      }
 +                      arm = arm_iter;
 +              }
        }
        CTX_DATA_END;
-       
        /* the number of joints determines how we fill:
         *  1) between joint and cursor (joint=head, cursor=tail)
         *  2) between the two joints (order is dependent on active-bone/hierarchy)
                BKE_report(op->reports, RPT_ERROR, "No joints selected");
                return OPERATOR_CANCELLED;
        }
 -      else if (count == 1) {
 +      else if (mixed_object_error) {
 +              BKE_report(op->reports, RPT_ERROR, "Bones for different objects selected");
 +              BLI_freelistN(&points);
 +              return OPERATOR_CANCELLED;
 +      }
 +
 +      Object *obedit = NULL;
 +      {
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_EDIT, ob_iter) {
 +                      if (ob_iter->data == arm) {
 +                              obedit = ob_iter;
 +                      }
 +              }
 +              FOREACH_OBJECT_IN_MODE_END;
 +      }
 +      BLI_assert(obedit != NULL);
 +
 +      if (count == 1) {
                EditBonePoint *ebp;
                float curs[3];
-               
                /* Get Points - selected joint */
                ebp = points.first;
-               
                /* Get points - cursor (tail) */
                invert_m4_m4(obedit->imat, obedit->obmat);
 -              mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
 +              mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)->location);
-               
                /* Create a bone */
                newbone = add_points_bone(obedit, ebp->vec, curs);
        }
@@@ -377,9 -376,9 +377,9 @@@ static int armature_flip_names_exec(bCo
        ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
  
        BLI_freelistN(&bones_names);
-       
        /* since we renamed stuff... */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
        /* copied from #rna_Bone_update_renamed */
        /* redraw view */
@@@ -431,9 -430,9 +431,9 @@@ static int armature_autoside_names_exec
                        ED_armature_bone_rename(arm, ebone->name, newname);
        }
        CTX_DATA_END;
-       
        /* since we renamed stuff... */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@@ -129,13 -139,11 +129,13 @@@ void ED_operatortypes_armature(void
        WM_operatortype_append(POSE_OT_rotation_mode_set);
  
        WM_operatortype_append(POSE_OT_quaternions_flip);
-       
        WM_operatortype_append(POSE_OT_bone_layers);
  
-       
 +      WM_operatortype_append(POSE_OT_toggle_bone_selection_overlay);
++
        WM_operatortype_append(POSE_OT_propagate);
-       
        /* POSELIB */
        WM_operatortype_append(POSELIB_OT_browse_interactive);
        WM_operatortype_append(POSELIB_OT_apply_pose);
@@@ -365,8 -390,7 +365,8 @@@ void ED_keymap_armature(wmKeyConfig *ke
        WM_keymap_add_item(keymap, "ARMATURE_OT_layers_show_all", ACCENTGRAVEKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "ARMATURE_OT_armature_layers", MKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "POSE_OT_bone_layers", MKEY, KM_PRESS, 0, 0);
-       
 +      WM_keymap_add_item(keymap, "POSE_OT_toggle_bone_selection_overlay", ZKEY, KM_PRESS, 0, 0);
        /* special transforms: */
        /*  1) envelope/b-bone size */
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
@@@ -391,14 -388,14 +391,14 @@@ int join_armature_exec(bContext *C, wmO
                                        BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
                                }
                        }
-                       
                        /* Free the old object data */
 -                      ED_base_object_free_and_unlink(bmain, scene, base);
 +                      ED_object_base_free_and_unlink(bmain, scene, base->object);
                }
        }
        CTX_DATA_END;
-       
 -      DAG_relations_tag_update(bmain);  /* because we removed object(s) */
 +      DEG_relations_tag_update(bmain);  /* because we removed object(s) */
  
        ED_armature_from_edit(arm);
        ED_armature_edit_free(arm);
@@@ -596,49 -592,45 +596,49 @@@ static int separate_armature_exec(bCont
        /* TODO: use context iterators for this? */
        CTX_DATA_BEGIN(C, Base *, base, visible_bases)
        {
 -              if (base->object == obedit) base->flag |= SELECT;
 -              else base->flag &= ~SELECT;
 +              if (base->object == obedit) {
 +                      ED_object_base_select(base, BA_SELECT);
 +              }
 +              else {
 +                      ED_object_base_select(base, BA_DESELECT);
 +              }
        }
        CTX_DATA_END;
-       
        /* 1) store starting settings and exit editmode */
        oldob = obedit;
 -      oldbase = BASACT;
 +      oldbase = view_layer->basact;
        oldob->mode &= ~OB_MODE_POSE;
        //oldbase->flag &= ~OB_POSEMODE;
-       
        ED_armature_from_edit(obedit->data);
        ED_armature_edit_free(obedit->data);
-       
        /* 2) duplicate base */
 -      newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
 -      DAG_relations_tag_update(bmain);
 +      newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
 +      DEG_relations_tag_update(bmain);
  
        newob = newbase->object;
 -      newbase->flag &= ~SELECT;
 +      newbase->flag &= ~BASE_SELECTED;
  
  
        /* 3) remove bones that shouldn't still be around on both armatures */
        separate_armature_bones(oldob, 1);
        separate_armature_bones(newob, 0);
-       
-       
        /* 4) fix links before depsgraph flushes */ // err... or after?
        separated_armature_fix_links(oldob, newob);
-       
 -      DAG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
 -      DAG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
 +      DEG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
 +      DEG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
-       
-       
        /* 5) restore original conditions */
        obedit = oldob;
-       
        ED_armature_to_edit(obedit->data);
-       
        /* parents tips remain selected when connected children are removed. */
        ED_armature_edit_deselect_all(obedit);
  
@@@ -149,13 -86,12 +149,13 @@@ void *get_bone_from_selectbuffer
        short i;
        bool takeNext = false;
        int minsel = 0xffffffff, minunsel = 0xffffffff;
-       
        for (i = 0; i < hits; i++) {
                hitresult = buffer[3 + (i * 4)];
-               
                if (!(hitresult & BONESEL_NOSEL)) {
                        if (hitresult & BONESEL_ANY) {  /* to avoid including objects in selection */
 +                              Base *base = NULL;
                                bool sel;
  
                                hitresult &= ~(BONESEL_ANY);
                        }
                }
        }
-       
 -      if (firstunSel)
 +      if (firstunSel) {
 +              *r_base = firstunSel_base;
                return firstunSel;
 -      else
 +      }
 +      else {
 +              *r_base = firstSel_base;
                return firstSel;
 +      }
  }
  
  /* used by posemode as well editmode */
@@@ -253,30 -176,12 +253,30 @@@ void *get_nearest_bone
        // rect.xmin = ... mouseco!
        rect.xmin = rect.xmax = xy[0];
        rect.ymin = rect.ymax = xy[1];
-       
        hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
  
 -      if (hits > 0)
 -              return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true);
 +      *r_base = NULL;
 +
 +      if (hits > 0) {
 +              uint bases_len = 0;
 +              Base **bases;
 +
 +              if (vc.obedit != NULL) {
 +                      bases = BKE_view_layer_array_from_bases_in_mode(
 +                              vc.view_layer, &bases_len, {
 +                                  .object_mode = OB_MODE_EDIT});
 +              }
 +              else {
 +                      bases = BKE_object_pose_base_array_get(vc.view_layer, &bases_len);
 +              }
 +
 +              void *bone = get_bone_from_selectbuffer(
 +                      bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
  
 +              MEM_freeN(bases);
 +              return bone;
 +      }
        return NULL;
  }
  
@@@ -339,11 -243,11 +339,11 @@@ static int armature_select_linked_invok
                if (!curBone)
                        bone = NULL;
        }
-       
        ED_armature_edit_sync_selection(arm->edbo);
-       
 -      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
 +      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -627,21 -489,21 +627,21 @@@ bool ED_armature_edit_select_pick(bCont
        vc.mval[0] = mval[0];
        vc.mval[1] = mval[1];
  
 -      if (BIF_sk_selectStroke(C, mval, extend)) {
 -              return true;
 -      }
 -
 -      nearBone = get_nearest_editbonepoint(&vc, true, true, &selmask);
 +      nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
        if (nearBone) {
 -              bArmature *arm = obedit->data;
 +              ED_view3d_viewcontext_init_object(&vc, basact->object);
 +              bArmature *arm = vc.obedit->data;
  
                if (!extend && !deselect && !toggle) {
 -                      ED_armature_edit_deselect_all(obedit);
 +                      uint objects_len = 0;
 +                      Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, &objects_len);
 +                      ED_armature_edit_deselect_all_multi(objects, objects_len);
 +                      MEM_freeN(objects);
                }
-               
                /* by definition the non-root connected bones have no root point drawn,
                 * so a root selection needs to be delivered to the parent tip */
-               
                if (selmask & BONE_SELECTED) {
                        if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
                                /* click in a chain */
@@@ -162,8 -164,8 +162,8 @@@ static int dgroup_skinnable_cb(Object *
                                segments = bone->segments;
                        else
                                segments = 1;
-                       
 -                      if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
 +                      if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
                                if (!(defgroup = defgroup_find_name(ob, bone->name))) {
                                        defgroup = BKE_object_defgroup_add_name(ob, bone->name);
                                }
@@@ -373,8 -372,8 +373,8 @@@ static void add_verts_to_dgroups
  
        if (wpmode) {
                /* if in weight paint mode, use final verts from derivedmesh */
 -              DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 +              DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
-               
                if (dm->foreachMappedVert) {
                        mesh_get_mapped_verts_coords(dm, verts, mesh->totvert);
                        vertsfilled = 1;
        MEM_freeN(verts);
  }
  
 -void ED_object_vgroup_calc_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par,
 -                                  const int mode, const bool mirror)
 +void ED_object_vgroup_calc_from_armature(
 +        ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par,
 +        const int mode, const bool mirror)
  {
-       /* Lets try to create some vertex groups 
+       /* Lets try to create some vertex groups
         * based on the bones of the parent armature.
         */
        bArmature *arm = par->data;
@@@ -684,8 -683,8 +684,8 @@@ void ED_armature_from_edit(bArmature *a
                        BKE_pose_rebuild(obt, arm);
                }
        }
-       
 -      DAG_id_tag_update(&arm->id, 0);
 +      DEG_id_tag_update(&arm->id, 0);
  }
  
  void ED_armature_edit_free(struct bArmature *arm)
@@@ -1591,9 -1588,9 +1591,9 @@@ void ED_mesh_deform_bind_callback
        /* get mesh and cage mesh */
        mdb.vertexcos = MEM_callocN(sizeof(float) * 3 * totvert, "MeshDeformCos");
        mdb.totvert = totvert;
-       
 -      mdb.cagedm = cagedm;
 -      mdb.totcagevert = mdb.cagedm->getNumVerts(mdb.cagedm);
 +      mdb.cagemesh = cagemesh;
 +      mdb.totcagevert = mdb.cagemesh->totvert;
        mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
        copy_m4_m4(mdb.cagemat, cagemat);
  
@@@ -180,22 -167,17 +180,22 @@@ static bool pose_has_protected_selected
   *
   * To be called from various tools that do incremental updates
   */
 -void ED_pose_recalculate_paths(Scene *scene, Object *ob)
 +void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
  {
 +      struct Main *bmain = CTX_data_main(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ListBase targets = {NULL, NULL};
-       
        /* set flag to force recalc, then grab the relevant bones to target */
        ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
        animviz_get_object_motionpaths(ob, &targets);
-       
        /* recalculate paths, then free */
 -      animviz_calc_motionpaths(scene, &targets);
 +      animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
        BLI_freelistN(&targets);
-       
++
 +      /* tag armature object for copy on write - so paths will draw/redraw */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  
@@@ -313,11 -295,11 +313,11 @@@ static int pose_update_paths_exec(bCont
  
        /* calculate the bones that now have motionpaths... */
        /* TODO: only make for the selected bones? */
 -      ED_pose_recalculate_paths(scene, ob);
 +      ED_pose_recalculate_paths(C, scene, ob);
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -610,11 -592,11 +610,11 @@@ static void pose_copy_menu(Scene *scene
                if (ob->pose)
                        BKE_pose_tag_recalc(bmain, ob->pose);
        }
-       
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
-       
        BIF_undo_push("Copy Pose Attributes");
-       
  }
  #endif
  
  
  static int pose_flip_names_exec(bContext *C, wmOperator *op)
  {
 -      Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
 -      bArmature *arm;
 -
 -      /* paranoia checks */
 -      if (ELEM(NULL, ob, ob->pose))
 -              return OPERATOR_CANCELLED;
 -
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        const bool do_strip_numbers = RNA_boolean_get(op->ptr, "do_strip_numbers");
-       
 -      arm = ob->data;
 -
 -      ListBase bones_names = {NULL};
 -
 -      CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
 +      FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
        {
 -              BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
 -      }
 -      CTX_DATA_END;
 +              bArmature *arm = ob->data;
 +              ListBase bones_names = {NULL};
  
 -      ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
 +              {
 +                      BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
 +              }
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
  
 -      BLI_freelistN(&bones_names);
 +              ED_armature_bones_flip_names(arm, &bones_names, do_strip_numbers);
  
 -      /* since we renamed stuff... */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              BLI_freelistN(&bones_names);
-               
 -      /* note, notifier might evolve */
 -      WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
 +              /* since we renamed stuff... */
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +
 +              /* note, notifier might evolve */
 +              WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
 +      }
 +      FOREACH_OBJECT_IN_MODE_END;
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -692,9 -677,9 +692,9 @@@ static int pose_autoside_names_exec(bCo
                        ED_armature_bone_rename(arm, pchan->name, newname);
        }
        CTX_DATA_END;
-       
        /* since we renamed stuff... */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@@ -741,11 -726,11 +741,11 @@@ static int pose_bone_rotmode_exec(bCont
                pchan->rotmode = mode;
        }
        CTX_DATA_END;
-       
        /* notifiers and updates */
 -      DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
 +      DEG_id_tag_update((ID *)ob, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -815,16 -800,15 +815,16 @@@ static int pose_armature_layers_showall
         *      need to setup a RNA pointer so that we get the "update" callbacks for free...
         */
        RNA_id_pointer_create(&arm->id, &ptr);
-       
        for (i = 0; i < maxLayers; i++)
                layers[i] = 1;
-       
        RNA_boolean_set_array(&ptr, "layers", layers);
-       
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
 +      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
        /* done */
        return OPERATOR_FINISHED;
  }
@@@ -920,8 -903,8 +920,8 @@@ void ARMATURE_OT_armature_layers(wmOper
  /* Present a popup to get the layers that should be used */
  static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
  {
 -      int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
 +      int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-       
        /* get layers that are active already */
        CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
        {
@@@ -1022,14 -1004,15 +1022,14 @@@ static int armature_bone_layers_invoke(
  static int armature_bone_layers_exec(bContext *C, wmOperator *op)
  {
        Object *ob = CTX_data_edit_object(C);
 -      bArmature *arm = (ob) ? ob->data : NULL;
        PointerRNA ptr;
        int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-       
        /* get the values set in the operator properties */
        RNA_boolean_get_array(op->ptr, "layers", layers);
-       
        /* set layers of pchans based on the values set in the operator props */
 -      CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
 +      CTX_DATA_BEGIN_WITH_ID (C, EditBone *, ebone, selected_editable_bones, bArmature *, arm)
        {
                /* get pointer for pchan, and write flags this way */
                RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
@@@ -101,14 -98,13 +101,14 @@@ static int pose_group_remove_exec(bCont
        /* only continue if there's an object and pose */
        if (ELEM(NULL, ob, ob->pose))
                return OPERATOR_CANCELLED;
-       
        /* for now, just call the API function for this */
        BKE_pose_remove_group_index(ob->pose, ob->pose->active_group);
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
        return OPERATOR_FINISHED;
  }
  
@@@ -206,9 -202,9 +206,9 @@@ static int pose_group_assign_exec(bCont
        pose->active_group = RNA_int_get(op->ptr, "type");
        if (pose->active_group == 0)
                BKE_pose_add_group(ob->pose, NULL);
-       
        /* add selected bones to group then */
 -      CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
 +      FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
        {
                pchan->agrp_index = pose->active_group;
                done = true;
  
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
        /* report done status */
        if (done)
                return OPERATOR_FINISHED;
@@@ -254,21 -249,20 +254,21 @@@ static int pose_group_unassign_exec(bCo
        /* only continue if there's an object, and a pose there too */
        if (ELEM(NULL, ob, ob->pose))
                return OPERATOR_CANCELLED;
-       
        /* find selected bones to remove from all bone groups */
 -      CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
 +      FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
        {
                if (pchan->agrp_index) {
                        pchan->agrp_index = 0;
                        done = true;
                }
        }
 -      CTX_DATA_END;
 +      FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
        /* report done status */
        if (done)
                return OPERATOR_FINISHED;
@@@ -439,11 -432,11 +439,11 @@@ void POSE_OT_group_sort(wmOperatorType 
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  }
  
 -static void pose_group_select(bContext *C, Object *ob, bool select)
 +static void pose_group_select(Object *ob, bool select)
  {
        bPose *pose = ob->pose;
-       
 -      CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
 +      FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN (ob, pchan)
        {
                if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
                        if (select) {
@@@ -466,12 -459,12 +466,12 @@@ static int pose_group_select_exec(bCont
        /* only continue if there's an object, and a pose there too */
        if (ELEM(NULL, ob, ob->pose))
                return OPERATOR_CANCELLED;
-       
 -      pose_group_select(C, ob, 1);
 +      pose_group_select(ob, 1);
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -497,12 -490,12 +497,12 @@@ static int pose_group_deselect_exec(bCo
        /* only continue if there's an object, and a pose there too */
        if (ELEM(NULL, ob, ob->pose))
                return OPERATOR_CANCELLED;
-       
 -      pose_group_select(C, ob, 0);
 +      pose_group_select(ob, 0);
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -498,10 -497,9 +498,10 @@@ static int poselib_add_exec(bContext *C
        /* use Keying Set to determine what to store for the pose */
        ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_SELECTED_ID); /* this includes custom props :)*/
        ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
-       
        /* store new 'active' pose number */
        act->active_marker = BLI_listbase_count(&act->markers);
 +      DEG_id_tag_update(&act->id, DEG_TAG_COPY_ON_WRITE);
  
        /* done */
        return OPERATOR_FINISHED;
@@@ -605,18 -603,17 +605,18 @@@ static int poselib_remove_exec(bContex
                        }
                }
        }
-       
        /* remove poselib from list */
        BLI_freelinkN(&act->markers, marker);
-       
        /* fix active pose number */
        act->active_marker = 0;
-       
-       /* send notifiers for this - using keyframe editing notifiers, since action 
-        * may be being shown in anim editors as active action 
+       /* send notifiers for this - using keyframe editing notifiers, since action
+        * may be being shown in anim editors as active action
         */
        WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
 +      DEG_id_tag_update(&act->id, DEG_TAG_COPY_ON_WRITE);
  
        /* done */
        return OPERATOR_FINISHED;
@@@ -1104,11 -1101,11 +1104,11 @@@ static void poselib_preview_apply(bCont
                 */
                // FIXME: shouldn't this use the builtin stuff?
                if ((pld->arm->flag & ARM_DELAYDEFORM) == 0)
 -                      DAG_id_tag_update(&pld->ob->id, OB_RECALC_DATA);  /* sets recalc flags */
 +                      DEG_id_tag_update(&pld->ob->id, OB_RECALC_DATA);  /* sets recalc flags */
                else
 -                      BKE_pose_where_is(pld->scene, pld->ob);
 +                      BKE_pose_where_is(CTX_data_depsgraph(C), pld->scene, pld->ob);
        }
-       
        /* do header print - if interactively previewing */
        if (pld->state == PL_PREVIEW_RUNNING) {
                if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
@@@ -1623,21 -1620,21 +1623,21 @@@ static void poselib_preview_cleanup(bCo
                /* change active pose setting */
                act->active_marker = BLI_findindex(&act->markers, marker) + 1;
                action_set_activemarker(act, marker, NULL);
-               
                /* Update event for pose and deformation children */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
-               
                /* updates */
                if (IS_AUTOKEY_MODE(scene, NORMAL)) {
                        //remake_action_ipos(ob->action);
                }
                else
 -                      BKE_pose_where_is(scene, ob);
 +                      BKE_pose_where_is(CTX_data_depsgraph(C), scene, ob);
        }
-       
        /* Request final redraw of the view. */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, pld->ob);
-       
        /* free memory used for backups and searching */
        poselib_backup_free_data(pld);
        BLI_freelistN(&pld->searchp);
@@@ -124,14 -122,11 +124,14 @@@ void ED_pose_bone_select(Object *ob, bP
                 * (see rna_Bone_select_update() in rna_armature.c for details)
                 */
                if (arm->flag & ARM_HAS_VIZ_DEPS) {
 -                      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
-               
                /* send necessary notifiers */
                WM_main_add_notifier(NC_GEOM | ND_DATA, ob);
-               
++
 +              /* tag armature for copy-on-write update (since act_bone is in armature not object) */
 +              DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
        }
  }
  
@@@ -143,20 -138,16 +143,20 @@@ bool ED_armature_pose_select_pick_with_
  {
        Object *ob = base->object;
        Bone *nearBone;
-       
        if (!ob || !ob->pose) return 0;
  
 -      nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1, do_nearest);
 +      Object *ob_act = OBACT(view_layer);
 +      Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
 +
 +      /* Callers happen to already get the active base */
 +      Base *base_dummy = NULL;
 +      nearBone = get_bone_from_selectbuffer(&base, 1, obedit != NULL, buffer, hits, 1, do_nearest, &base_dummy);
-       
        /* if the bone cannot be affected, don't do anything */
        if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
 -              Object *ob_act = OBACT;
                bArmature *arm = ob->data;
-               
                /* since we do unified select, we don't shift+select a bone if the
                 * armature object was not active yet.
                 * note, special exception for armature mode so we can do multi-select
                        if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
                                if (nearBone == arm->act_bone) {
                                        ED_vgroup_select_by_name(ob_act, nearBone->name);
 -                                      DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
 +                                      DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
                                }
                        }
-                       /* if there are some dependencies for visualizing armature state 
-                        * (e.g. Mask Modifier in 'Armature' mode), force update 
+                       /* if there are some dependencies for visualizing armature state
+                        * (e.g. Mask Modifier in 'Armature' mode), force update
                         */
                        else if (arm->flag & ARM_HAS_VIZ_DEPS) {
-                               /* NOTE: ob not ob_act here is intentional - it's the source of the 
+                               /* NOTE: ob not ob_act here is intentional - it's the source of the
                                 *       bones being selected  [T37247]
                                 */
 -                              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        }
-                       
++
 +                      /* tag armature for copy-on-write update (since act_bone is in armature not object) */
 +                      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
                }
        }
-       
        return nearBone != NULL;
  }
  
@@@ -266,58 -249,6 +266,58 @@@ void ED_pose_deselect_all(Object *ob, i
        }
  }
  
-               
 +static bool ed_pose_is_any_selected(Object *ob, bool ignore_visibility)
 +{
 +      bArmature *arm = ob->data;
 +      for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 +              if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
 +                      if (pchan->bone->flag & BONE_SELECTED) {
 +                              return true;
 +                      }
 +              }
 +      }
 +      return false;
 +}
 +
 +static bool ed_pose_is_any_selected_multi(Object **objects, uint objects_len, bool ignore_visibility)
 +{
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              Object *ob_iter = objects[ob_index];
 +              if (ed_pose_is_any_selected(ob_iter, ignore_visibility)) {
 +                      return true;
 +              }
 +      }
 +      return false;
 +}
 +
 +void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_mode, const bool ignore_visibility)
 +{
 +      if (select_mode == SEL_TOGGLE) {
 +              select_mode = ed_pose_is_any_selected_multi(
 +                      objects, objects_len, ignore_visibility) ? SEL_DESELECT : SEL_SELECT;
 +      }
 +
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              Object *ob_iter = objects[ob_index];
 +              bArmature *arm = ob_iter->data;
-               
++
 +              ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility);
-               
++
 +              /* if there are some dependencies for visualizing armature state
 +               * (e.g. Mask Modifier in 'Armature' mode), force update
 +               */
 +              if (arm->flag & ARM_HAS_VIZ_DEPS) {
 +                      /* NOTE: ob not ob_act here is intentional - it's the source of the
 +                       *       bones being selected  [T37247]
 +                       */
 +                      DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
 +              }
++
 +              /* need to tag armature for cow updates, or else selection doesn't update */
 +              DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
 +      }
 +}
 +
  /* ***************** Selections ********************** */
  
  static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
        /* stop when unconnected child is encountered, or when unselectable bone is encountered */
        if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
                return;
-       
 -      /* XXX old cruft! use notifiers instead */
 -      //select_actionchannel_by_name (ob->action, bone->name, !(shift));
 -
        if (extend)
                bone->flag &= ~BONE_SELECTED;
        else
@@@ -352,8 -287,6 +352,8 @@@ static int pose_select_connected_invoke
        if (!bone)
                return OPERATOR_CANCELLED;
  
-       
 +      bArmature *arm = base->object->data;
++
        /* Select parents */
        for (curBone = bone; curBone; curBone = next) {
                /* ignore bone if cannot be selected */
                else
                        next = NULL;
        }
-       
        /* Select children */
        for (curBone = bone->childbase.first; curBone; curBone = next)
 -              selectconnected_posebonechildren(ob, curBone, extend);
 +              selectconnected_posebonechildren(base->object, curBone, extend);
-       
        /* updates */
 -      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
 +      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
-       
        if (arm->flag & ARM_HAS_VIZ_DEPS) {
                /* mask modifier ('armature' mode), etc. */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
        }
-       
 +      /* need to tag armature for cow updates, or else selection doesn't update */
 +      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -401,8 -331,8 +401,8 @@@ void POSE_OT_select_linked(wmOperatorTy
        ot->name = "Select Connected";
        ot->idname = "POSE_OT_select_linked";
        ot->description = "Select bones related to selected ones by parent/child relationships";
-       
 -      /* api callbacks */
 +      /* callbacks */
        /* leave 'exec' unset */
        ot->invoke = pose_select_connected_invoke;
        ot->poll = pose_select_linked_poll;
  static int pose_de_select_all_exec(bContext *C, wmOperator *op)
  {
        int action = RNA_enum_get(op->ptr, "action");
-       
        Scene *scene = CTX_data_scene(C);
 -      Object *ob = ED_object_context(C);
 -      bArmature *arm = ob->data;
        int multipaint = scene->toolsettings->multipaint;
  
        if (action == SEL_TOGGLE) {
                action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
        }
  
-       
 +      Object *ob_prev = NULL;
++
        /*      Set the flags */
 -      CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
 +      CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
        {
 +              bArmature *arm = ob->data;
                pose_do_bone_select(pchan, action);
 +
 +              if (ob_prev != ob) {
 +                      /* weightpaint or mask modifiers need depsgraph updates */
 +                      if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
 +                              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      }
 +                      /* need to tag armature for cow updates, or else selection doesn't update */
 +                      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
 +                      ob_prev = ob;
 +              }
        }
        CTX_DATA_END;
  
@@@ -579,10 -480,18 +579,10 @@@ static int pose_select_constraint_targe
                }
        }
        CTX_DATA_END;
-       
        if (!found)
                return OPERATOR_CANCELLED;
-       
 -      /* updates */
 -      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
 -
 -      if (arm->flag & ARM_HAS_VIZ_DEPS) {
 -              /* mask modifier ('armature' mode), etc. */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 -      }
 -
        return OPERATOR_FINISHED;
  }
  
@@@ -668,18 -577,15 +668,18 @@@ static int pose_select_hierarchy_exec(b
        if (changed == false) {
                return OPERATOR_CANCELLED;
        }
-       
        /* updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-       
        if (arm->flag & ARM_HAS_VIZ_DEPS) {
                /* mask modifier ('armature' mode), etc. */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
  
 +      /* tag armature for copy-on-write update (since act_bone is in armature not object) */
 +      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -916,18 -822,15 +916,18 @@@ static int pose_select_grouped_exec(bCo
                        printf("pose_select_grouped() - Unknown selection type %u\n", type);
                        break;
        }
-       
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
        if (arm->flag & ARM_HAS_VIZ_DEPS) {
                /* mask modifier ('armature' mode), etc. */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
-       
 +      /* need to tag armature for cow updates, or else selection doesn't update */
 +      DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
-       
++
        /* report done status */
        if (changed)
                return OPERATOR_FINISHED;
@@@ -970,63 -873,59 +970,63 @@@ void POSE_OT_select_grouped(wmOperatorT
  static int pose_select_mirror_exec(bContext *C, wmOperator *op)
  {
        Object *ob_act = CTX_data_active_object(C);
 -      Object *ob = BKE_object_pose_armature_get(ob_act);
 -      bArmature *arm;
 -      bPoseChannel *pchan, *pchan_mirror_act = NULL;
 -      const bool active_only = RNA_boolean_get(op->ptr, "only_active");
 -      const bool extend = RNA_boolean_get(op->ptr, "extend");
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      if ((ob && (ob->mode & OB_MODE_POSE)) == 0) {
 -              return OPERATOR_CANCELLED;
 -      }
 -
 -      arm = ob->data;
 +      FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob)
 +      {
 +              bArmature *arm;
 +              bPoseChannel *pchan, *pchan_mirror_act = NULL;
 +              const bool active_only = RNA_boolean_get(op->ptr, "only_active");
 +              const bool extend = RNA_boolean_get(op->ptr, "extend");
  
 -      for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 -              const int flag = (pchan->bone->flag & BONE_SELECTED);
 -              PBONE_PREV_FLAG_SET(pchan, flag);
 -      }
 +              arm = ob->data;
  
 -      for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 -              if (PBONE_SELECTABLE(arm, pchan->bone)) {
 -                      bPoseChannel *pchan_mirror;
 -                      int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
 +              for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 +                      const int flag = (pchan->bone->flag & BONE_SELECTED);
 +                      PBONE_PREV_FLAG_SET(pchan, flag);
 +              }
  
 -                      if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
 -                          (PBONE_VISIBLE(arm, pchan_mirror->bone)))
 -                      {
 -                              const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
 -                              flag_new |= flag_mirror;
 +              for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
 +                      if (PBONE_SELECTABLE(arm, pchan->bone)) {
 +                              bPoseChannel *pchan_mirror;
 +                              int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
 +
 +                              if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
 +                                  (PBONE_VISIBLE(arm, pchan_mirror->bone)))
 +                              {
 +                                      const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
 +                                      flag_new |= flag_mirror;
 +
 +                                      if (pchan->bone == arm->act_bone) {
 +                                              pchan_mirror_act = pchan_mirror;
 +                                      }
  
 -                              if (pchan->bone == arm->act_bone) {
 -                                      pchan_mirror_act = pchan_mirror;
 +                                      /* skip all but the active or its mirror */
 +                                      if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
 +                                              continue;
 +                                      }
                                }
  
 -                              /* skip all but the active or its mirror */
 -                              if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
 -                                      continue;
 -                              }
 +                              pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) | flag_new;
                        }
 -
 -                      pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) | flag_new;
                }
 -      }
  
 -      if (pchan_mirror_act) {
 -              arm->act_bone = pchan_mirror_act->bone;
 +              if (pchan_mirror_act) {
 +                      arm->act_bone = pchan_mirror_act->bone;
  
 -              /* in weightpaint we select the associated vertex group too */
 -              if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
 -                      ED_vgroup_select_by_name(ob_act, pchan_mirror_act->name);
 -                      DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
 +                      /* in weightpaint we select the associated vertex group too */
 +                      if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
 +                              ED_vgroup_select_by_name(ob_act, pchan_mirror_act->name);
 +                              DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
 +                      }
                }
 -      }
  
 -      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
 +              WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-               
++
 +              /* need to tag armature for cow updates, or else selection doesn't update */
 +              DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE);
 +      }
 +      FOREACH_OBJECT_IN_MODE_END;
  
        return OPERATOR_FINISHED;
  }
  /* Pose Apply */
  
  /* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
 -static void applyarmature_fix_boneparents(Scene *scene, Object *armob)
 +static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      Main *bmain = CTX_data_main(C);
        Object workob, *ob;
-       
        /* go through all objects in database */
 -      for (ob = G.main->object.first; ob; ob = ob->id.next) {
 +      for (ob = bmain->object.first; ob; ob = ob->id.next) {
                /* if parent is bone in this armature, apply corrections */
                if ((ob->parent == armob) && (ob->partype == PARBONE)) {
-                       /* apply current transform from parent (not yet destroyed), 
+                       /* apply current transform from parent (not yet destroyed),
                         * then calculate new parent inverse matrix
                         */
                        BKE_object_apply_mat4(ob, ob->obmat, false, false);
-                       
 -                      BKE_object_workob_calc_parent(scene, ob, &workob);
 +                      BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
                        invert_m4_m4(ob->parentinv, workob.obmat);
                }
        }
@@@ -123,18 -116,17 +123,18 @@@ static int apply_armature_pose2bones_ex
  
        /* Get editbones of active armature to alter */
        ED_armature_to_edit(arm);
-       
        /* get pose of active object and move it out of posemode */
        pose = ob->pose;
-       
        for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
 +              const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
                curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
-               
                /* simply copy the head/tail values from pchan over to curbone */
 -              copy_v3_v3(curbone->head, pchan->pose_head);
 -              copy_v3_v3(curbone->tail, pchan->pose_tail);
 +              copy_v3_v3(curbone->head, pchan_eval->pose_head);
 +              copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
-               
                /* fix roll:
                 *      1. find auto-calculated roll value for this bone now
                 *      2. remove this from the 'visual' y-rotation
                        sub_v3_v3v3(delta, curbone->tail, curbone->head);
                        vec_roll_to_mat3(delta, 0.0f, premat);
                        invert_m3_m3(imat, premat);
-                       
                        /* get pchan 'visual' matrix */
 -                      copy_m3_m4(pmat, pchan->pose_mat);
 +                      copy_m3_m4(pmat, pchan_eval->pose_mat);
-                       
                        /* remove auto from visual and get euler rotation */
                        mul_m3_m3m3(tmat, imat, pmat);
                        mat3_to_eul(eul, tmat);
                 * then clear the pchan values (so we don't get a double-up)
                 */
                if (pchan->bone->segments > 1) {
 -                      curbone->curveInX += pchan->curveInX;
 -                      curbone->curveInY += pchan->curveInY;
 -                      curbone->curveOutX += pchan->curveOutX;
 -                      curbone->curveOutY += pchan->curveOutY;
 -                      curbone->roll1 += pchan->roll1;
 -                      curbone->roll2 += pchan->roll2;
 -                      curbone->ease1 += pchan->ease1;
 -                      curbone->ease2 += pchan->ease2;
 -                      curbone->scaleIn += pchan->scaleIn;
 -                      curbone->scaleOut += pchan->scaleOut;
 -
 +                      /* combine rest/pose values  */
 +                      curbone->curveInX += pchan_eval->curveInX;
 +                      curbone->curveInY += pchan_eval->curveInY;
 +                      curbone->curveOutX += pchan_eval->curveOutX;
 +                      curbone->curveOutY += pchan_eval->curveOutY;
 +                      curbone->roll1 += pchan_eval->roll1;
 +                      curbone->roll2 += pchan_eval->roll2;
 +                      curbone->ease1 += pchan_eval->ease1;
 +                      curbone->ease2 += pchan_eval->ease2;
 +                      curbone->scaleIn += pchan_eval->scaleIn;
 +                      curbone->scaleOut += pchan_eval->scaleOut;
-                       
++
 +                      /* reset pose values */
                        pchan->curveInX = pchan->curveOutX = 0.0f;
                        pchan->curveInY = pchan->curveOutY = 0.0f;
                        pchan->roll1 = pchan->roll2 = 0.0f;
        /* convert editbones back to bones, and then free the edit-data */
        ED_armature_from_edit(arm);
        ED_armature_edit_free(arm);
-       
        /* flush positions of posebones */
 -      BKE_pose_where_is(scene, ob);
 +      BKE_pose_where_is(depsgraph, scene, ob);
-       
        /* fix parenting of objects which are bone-parented */
 -      applyarmature_fix_boneparents(scene, ob);
 +      applyarmature_fix_boneparents(C, scene, ob);
-       
        /* note, notifier might evolve */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-       
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
        return OPERATOR_FINISHED;
  }
  
@@@ -230,41 -219,38 +230,41 @@@ void POSE_OT_armature_apply(wmOperatorT
  /* set the current pose as the restpose */
  static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
 -
 -      /* don't check if editmode (should be done by caller) */
 -      if (ob->type != OB_ARMATURE)
 -              return OPERATOR_CANCELLED;
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
  
 -      /* loop over all selected pchans
 -       *
 -       * TODO, loop over children before parents if multiple bones
 -       * at once are to be predictable*/
 -      CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
 +      FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob)
        {
 -              float delta_mat[4][4];
 -
 -              /* chan_mat already contains the delta transform from rest pose to pose-mode pose
 -               * as that is baked into there so that B-Bones will work. Once we've set this as the
 -               * new raw-transform components, don't recalc the poses yet, otherwise IK result will
 -               * change, thus changing the result we may be trying to record.
 -               */
 -              /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
 -               *     Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
 -               */
 -              BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, delta_mat);
 +              /* loop over all selected pchans
 +               *
 +               * TODO, loop over children before parents if multiple bones
 +               * at once are to be predictable*/
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan)
 +              {
 +                      const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
 +                      bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
 +                      float delta_mat[4][4];
-                       
++
 +                      /* chan_mat already contains the delta transform from rest pose to pose-mode pose
 +                       * as that is baked into there so that B-Bones will work. Once we've set this as the
-                        * new raw-transform components, don't recalc the poses yet, otherwise IK result will 
++                       * new raw-transform components, don't recalc the poses yet, otherwise IK result will
 +                       * change, thus changing the result we may be trying to record.
 +                       */
 +                      /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset (see T38251).
 +                       *     Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
 +                       */
 +                      BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, delta_mat);
-                       
 -              BKE_pchan_apply_mat4(pchan, delta_mat, true);
 -      }
 -      CTX_DATA_END;
 +                      BKE_pchan_apply_mat4(pchan, delta_mat, true);
 +              }
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
-               
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
 -      /* note, notifier might evolve */
 -      WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
 +              /* note, notifier might evolve */
 +              WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
 +      }
 +      FOREACH_OBJECT_IN_MODE_END;
  
        return OPERATOR_FINISHED;
  }
@@@ -577,15 -563,15 +577,15 @@@ static int pose_paste_exec(bContext *C
                }
        }
        BKE_main_free(tmp_bmain);
-       
        /* Update event for pose and deformation children. */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
-       
        /* Recalculate paths if any of the bones have paths... */
        if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
 -              ED_pose_recalculate_paths(scene, ob);
 +              ED_pose_recalculate_paths(C, scene, ob);
        }
-       
        /* Notifiers for updates, */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
  
@@@ -777,70 -764,47 +777,70 @@@ static int pose_clear_transform_generic
        }
  
        /* only clear relevant transforms for selected bones */
 -      CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter)
        {
 -              /* run provided clearing function */
 -              clear_func(pchan);
 +              Object *ob_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms)
 +              ListBase dsources = {NULL, NULL};
 +              bool changed = false;
  
 -              /* do auto-keyframing as appropriate */
 -              if (autokeyframe_cfra_can_key(scene, &ob->id)) {
 -                      /* clear any unkeyed tags */
 -                      if (pchan->bone)
 -                              pchan->bone->flag &= ~BONE_UNKEYED;
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob_iter, pchan)
 +              {
 +                      /* run provided clearing function */
 +                      clear_func(pchan);
 +                      changed = true;
 +
 +                      /* do auto-keyframing as appropriate */
 +                      if (autokeyframe_cfra_can_key(scene, &ob_iter->id)) {
 +                              /* clear any unkeyed tags */
 +                              if (pchan->bone) {
 +                                      pchan->bone->flag &= ~BONE_UNKEYED;
 +                              }
 +                              /* tag for autokeying later */
 +                              ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan);
-                               
 -                      /* tag for autokeying later */
 -                      autokey = 1;
 -              }
 -              else {
 -                      /* add unkeyed tags */
 -                      if (pchan->bone)
 -                              pchan->bone->flag |= BONE_UNKEYED;
 +#if 1                 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */
 +                              bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
 +                              clear_func(pchan_eval);
 +#endif
 +                      }
 +                      else {
 +                              /* add unkeyed tags */
 +                              if (pchan->bone) {
 +                                      pchan->bone->flag |= BONE_UNKEYED;
 +                              }
 +                      }
                }
 -      }
 -      CTX_DATA_END;
 +              FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
  
 -      /* perform autokeying on the bones if needed */
 -      if (autokey) {
 -              /* get KeyingSet to use */
 -              KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
 +              if (changed) {
 +                      changed_multi = true;
  
 -              /* insert keyframes */
 -              ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
 +                      /* perform autokeying on the bones if needed */
 +                      if (!BLI_listbase_is_empty(&dsources)) {
 +                              /* get KeyingSet to use */
 +                              KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
  
 -              /* now recalculate paths */
 -              if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
 -                      ED_pose_recalculate_paths(scene, ob);
 -      }
 +                              /* insert keyframes */
 +                              ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                              /* now recalculate paths */
 +                              if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
 +                                      ED_pose_recalculate_paths(C, scene, ob_iter);
 +                              }
  
 -      /* note, notifier might evolve */
 -      WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
 +                              BLI_freelistN(&dsources);
 +                      }
  
 -      return OPERATOR_FINISHED;
 +                      DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
 +
 +                      /* note, notifier might evolve */
 +                      WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob_iter);
 +              }
 +      }
 +      FOREACH_OBJECT_IN_MODE_END;
 +
 +      return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
  }
  
  /* --------------- */
@@@ -933,62 -897,58 +933,62 @@@ void POSE_OT_transforms_clear(wmOperato
  
  static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
  {
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        Scene *scene = CTX_data_scene(C);
 -      Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
        float cframe = (float)CFRA;
        const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
-       
 -      if ((ob->adt) && (ob->adt->action)) {
 -              /* XXX: this is just like this to avoid contaminating anything else;
 -               * just pose values should change, so this should be fine
 -               */
 -              bPose *dummyPose = NULL;
 -              Object workob = {{NULL}};
 -              bPoseChannel *pchan;
 +      FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob)
 +      {
 +              if ((ob->adt) && (ob->adt->action)) {
 +                      /* XXX: this is just like this to avoid contaminating anything else;
 +                       * just pose values should change, so this should be fine
 +                       */
 +                      bPose *dummyPose = NULL;
 +                      Object workob = {{NULL}};
 +                      bPoseChannel *pchan;
-                       
 -              /* execute animation step for current frame using a dummy copy of the pose */
 -              BKE_pose_copy_data(&dummyPose, ob->pose, 0);
 +                      /* execute animation step for current frame using a dummy copy of the pose */
 +                      BKE_pose_copy_data(&dummyPose, ob->pose, 0);
-                       
 -              BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
 -              workob.type = OB_ARMATURE;
 -              workob.data = ob->data;
 -              workob.adt = ob->adt;
 -              workob.pose = dummyPose;
 +                      BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
 +                      workob.type = OB_ARMATURE;
 +                      workob.data = ob->data;
 +                      workob.adt = ob->adt;
 +                      workob.pose = dummyPose;
  
 -              BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
 +                      BKE_animsys_evaluate_animdata(NULL, scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
-                       
 -              /* copy back values, but on selected bones only  */
 -              for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
 -                      pose_bone_do_paste(ob, pchan, only_select, 0);
 -              }
 +                      /* copy back values, but on selected bones only  */
 +                      for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
 +                              pose_bone_do_paste(ob, pchan, only_select, 0);
 +                      }
-                       
 -              /* free temp data - free manually as was copied without constraints */
 -              for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
 -                      if (pchan->prop) {
 -                              IDP_FreeProperty(pchan->prop);
 -                              MEM_freeN(pchan->prop);
 +                      /* free temp data - free manually as was copied without constraints */
 +                      for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
 +                              if (pchan->prop) {
 +                                      IDP_FreeProperty(pchan->prop);
 +                                      MEM_freeN(pchan->prop);
 +                              }
                        }
-                       
++
 +                      /* was copied without constraints */
 +                      BLI_freelistN(&dummyPose->chanbase);
 +                      MEM_freeN(dummyPose);
 +              }
 +              else {
 +                      /* no animation, so just reset whole pose to rest pose
 +                       * (cannot just restore for selected though)
 +                       */
 +                      BKE_pose_rest(ob->pose);
                }
-               
 -              /* was copied without constraints */
 -              BLI_freelistN(&dummyPose->chanbase);
 -              MEM_freeN(dummyPose);
 -      }
 -      else {
 -              /* no animation, so just reset whole pose to rest pose
 -               * (cannot just restore for selected though)
 -               */
 -              BKE_pose_rest(ob->pose);
 +              /* notifiers and updates */
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
        }
 -
 -      /* notifiers and updates */
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 -      WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
 +      FOREACH_OBJECT_IN_MODE_END;
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -183,19 -182,18 +183,19 @@@ void poseAnim_mapping_free(ListBase *pf
  /* helper for apply() / reset() - refresh the data */
  void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        bArmature *arm = (bArmature *)ob->data;
-       
-       /* old optimize trick... this enforces to bypass the depgraph 
+       /* old optimize trick... this enforces to bypass the depgraph
         *      - note: code copied from transform_generics.c -> recalcData()
         */
        /* FIXME: shouldn't this use the builtin stuff? */
        if ((arm->flag & ARM_DELAYDEFORM) == 0)
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
        else
 -              BKE_pose_where_is(scene, ob);
 +              BKE_pose_where_is(depsgraph, scene, ob);
-       
 -      /* note, notifier might evolve */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); /* otherwise animation doesn't get updated */
        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
  }
  
@@@ -4075,8 -4058,8 +4075,8 @@@ static int merge_nurb(bContext *C, wmOp
        BKE_curve_nurb_active_set(obedit->data, NULL);
  
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
 -      DAG_id_tag_update(obedit->data, 0);
 +      DEG_id_tag_update(obedit->data, 0);
-       
        return OPERATOR_FINISHED;
  }
  
@@@ -4537,13 -4520,13 +4537,13 @@@ static int spin_invoke(bContext *C, wmO
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = ED_view3d_context_rv3d(C);
        float axis[3] = {0.0f, 0.0f, 1.0f};
-       
        if (rv3d)
                copy_v3_v3(axis, rv3d->viewinv[2]);
-       
 -      RNA_float_set_array(op->ptr, "center", ED_view3d_cursor3d_get(scene, v3d));
 +      RNA_float_set_array(op->ptr, "center", ED_view3d_cursor3d_get(scene, v3d)->location);
        RNA_float_set_array(op->ptr, "axis", axis);
-       
        return spin_exec(C, op);
  }
  
@@@ -6015,9 -5999,9 +6015,9 @@@ static int shade_smooth_exec(bContext *
                        else nu->flag &= ~CU_SMOOTH;
                }
        }
-       
        WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
 -      DAG_id_tag_update(obedit->data, 0);
 +      DEG_id_tag_update(obedit->data, 0);
  
        return OPERATOR_FINISHED;
  }
@@@ -6130,8 -6114,8 +6130,8 @@@ int join_curve_exec(bContext *C, wmOper
                                                nu = nu->next;
                                        }
                                }
-                       
 -                              ED_base_object_free_and_unlink(bmain, scene, base);
 +                              ED_object_base_free_and_unlink(bmain, scene, base->object);
                        }
                }
        }
@@@ -433,9 -428,9 +433,9 @@@ static void txt_add_object(bContext *C
        char *s;
        int a;
        float rot[3] = {0.f, 0.f, 0.f};
-       
 -      obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
 -      base = scene->basact;
 +      obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL);
 +      base = view_layer->basact;
  
        /* seems to assume view align ? TODO - look into this, could be an operator option */
        ED_object_base_init_transform(C, base, NULL, rot);
@@@ -236,46 -158,27 +236,46 @@@ static void gp_draw_stroke_buffer(cons
                         * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
                         */
                        if (fabsf(pt->pressure - oldpressure) > 0.2f) {
 -                              glEnd();
 +                              /* need to have 2 points to avoid immEnd assert error */
 +                              if (draw_points < 2) {
 +                                      gp_set_tpoint_varying_color(pt - 1, ink, color);
 +                                      immVertex2iv(pos, &(pt - 1)->x);
 +                              }
 +
 +                              immEnd();
 +                              draw_points = 0;
 +
                                glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
 -                              glBegin(GL_LINE_STRIP);
 +                              immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1);
  
                                /* need to roll-back one point to ensure that there are no gaps in the stroke */
-                               if (i != 0) { 
+                               if (i != 0) {
 -                                      gp_set_color_and_tpoint((pt - 1), ink);
 +                                      gp_set_tpoint_varying_color(pt - 1, ink, color);
 +                                      immVertex2iv(pos, &(pt - 1)->x);
 +                                      ++draw_points;
                                }
  
 -                              /* now the point we want... */
 -                              gp_set_color_and_tpoint(pt, ink);
 -
 -                              oldpressure = pt->pressure;
 -                      }
 -                      else {
 -                              gp_set_color_and_tpoint(pt, ink);
 +                              oldpressure = pt->pressure; /* reset our threshold */
                        }
 +
 +                      /* now the point we want */
 +                      gp_set_tpoint_varying_color(pt, ink, color);
 +                      immVertex2iv(pos, &pt->x);
 +                      ++draw_points;
 +              }
 +              /* need to have 2 points to avoid immEnd assert error */
 +              if (draw_points < 2) {
 +                      gp_set_tpoint_varying_color(pt - 1, ink, color);
 +                      immVertex2iv(pos, &(pt - 1)->x);
                }
 -              glEnd();
 +      }
 +
 +      immEnd();
 +      immUnbindProgram();
  
 -              if (G.debug & G_DEBUG) setlinestyle(0);
 +      // draw fill
 +      if (fill_ink[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
 +              gp_draw_stroke_buffer_fill(points, totpoints, fill_ink);
        }
  }
  
@@@ -375,28 -309,59 +375,28 @@@ static void gp_draw_stroke_volumetric_2
  
  /* draw a 3D stroke in "volumetric" style */
  static void gp_draw_stroke_volumetric_3d(
 -        bGPDspoint *points, int totpoints, short thickness,
 -        short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4])
 +        const bGPDspoint *points, int totpoints, short thickness,
 +        const float ink[4])
  {
 -      GLUquadricObj *qobj = gluNewQuadric();
 -
 -      float base_modelview[4][4], modelview[4][4];
 -      float base_loc[3];
 -
 -      bGPDspoint *pt;
 -      int i;
 -      float fpt[3];
 -
 -      /* Get the basic modelview matrix we use for performing calculations */
 -      glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
 -      copy_v3_v3(base_loc, base_modelview[3]);
 -
 -      /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
 -       * - We need to knock out the rotation so that we are
 -       *   simply left with a camera-facing billboard
 -       * - The scale factors here are chosen so that the thickness
 -       *   is relatively reasonable. Otherwise, it gets far too
 -       *   large!
 -       */
 -      scale_m4_fl(modelview, 0.1f);
 -
 -      /* draw each point as a disk... */
 -      glPushMatrix();
 -
 -      for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
 -              /* color of point */
 -              gp_set_point_color(pt, ink);
 -
 -              mul_v3_m4v3(fpt, diff_mat, &pt->x);
 -
 -              /* apply translation to base_modelview, so that the translated point is put in the right place */
 -              translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]);
 -
 -              /* copy the translation component to the billboard matrix we're going to use,
 -               * then reset the base matrix to the original values so that we can do the same
 -               * for the next point without accumulation/pollution effects
 -               */
 -              copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
 -              copy_v3_v3(base_modelview[3], base_loc);     /* restore */
 -
 -              /* apply our billboard matrix for drawing... */
 -              glLoadMatrixf((float *)modelview);
 -
 -              /* draw the disk using the current state... */
 -              gluDisk(qobj, 0.0,  pt->pressure * thickness, 32, 1);
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 +      unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
 +      unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
 +      GPU_enable_program_point_size();
 +      immBegin(GWN_PRIM_POINTS, totpoints);
 +
 +      const bGPDspoint *pt = points;
 +      for (int i = 0; i < totpoints && pt; i++, pt++) {
-               gp_set_point_varying_color(pt, ink, color);             
++              gp_set_point_varying_color(pt, ink, color);
 +              immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
 +              immVertex3fv(pos, &pt->x);                   /* we can adjust size in vertex shader based on view/projection! */
        }
  
 -      glPopMatrix();
 -      gluDeleteQuadric(qobj);
 +      immEnd();
 +      immUnbindProgram();
 +      GPU_disable_program_point_size();
  }
  
  
@@@ -636,36 -619,28 +636,36 @@@ static void gp_draw_stroke_3d(const bGP
                 * Note: we want more visible levels of pressures when thickness is bigger.
                 */
                if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
 -                      glEnd();
 +                      /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
 +                      if (draw_points < 2) {
 +                              const bGPDspoint *pt2 = pt - 1;
 +                              mul_v3_m4v3(fpt, diff_mat, &pt2->x);
 +                              immVertex3fv(pos, fpt);
 +                      }
 +                      immEnd();
 +                      draw_points = 0;
 +
                        curpressure = pt->pressure;
                        glLineWidth(max_ff(curpressure * thickness, 1.0f));
 -                      glBegin(GL_LINE_STRIP);
 +                      immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
  
                        /* need to roll-back one point to ensure that there are no gaps in the stroke */
-                       if (i != 0) { 
+                       if (i != 0) {
 -                              pt2 = pt - 1;
 +                              const bGPDspoint *pt2 = pt - 1;
                                mul_v3_m4v3(fpt, diff_mat, &pt2->x);
 -                              glVertex3fv(fpt);
 +                              gp_set_point_varying_color(pt2, ink, color);
 +                              immVertex3fv(pos, fpt);
 +                              ++draw_points;
                        }
 -
 -                      /* now the point we want... */
 -                      mul_v3_m4v3(fpt, diff_mat, &pt->x);
 -                      glVertex3fv(fpt);
 -              }
 -              else {
 -                      mul_v3_m4v3(fpt, diff_mat, &pt->x);
 -                      glVertex3fv(fpt);
                }
 -              /* saves first point to use in cyclic */
 -              if (i == 0) {
 +
 +              /* now the point we want */
 +              mul_v3_m4v3(fpt, diff_mat, &pt->x);
 +              immVertex3fv(pos, fpt);
 +              ++draw_points;
 +
 +              if (cyclic && i == 0) {
 +                      /* save first point to use in cyclic */
                        copy_v3_v3(cyclic_fpt, fpt);
                }
        }
@@@ -1428,9 -1447,12 +1428,9 @@@ static void gp_draw_data_layers
                if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
                    (gpf->flag & GP_FRAME_PAINT))
                {
 -                      /* Set color for drawing buffer stroke - since this may not be set yet */
 -                      // glColor4fv(gpl->color);
 -
                        /* Buffer stroke needs to be drawn with a different linestyle
                         * to help differentiate them from normal strokes.
-                        * 
+                        *
                         * It should also be noted that sbuffer contains temporary point types
                         * i.e. tGPspoints NOT bGPDspoints
                         */
@@@ -1461,16 -1483,15 +1461,16 @@@ static void gp_draw_status_text(const b
        if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
                const char *printable = IFACE_("GPencil Stroke Editing");
                float       printable_size[2];
 -              int xco, yco;
  
 -              BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
 +              int font_id = BLF_default();
 +
 +              BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-               
 -              xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
 -              yco = (rect.ymax - U.widget_unit);
 +              int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
 +              int yco = (rect.ymax - U.widget_unit);
  
                /* text label */
 -              UI_ThemeColor(TH_TEXT_HI);
 +              UI_FontThemeColor(font_id, TH_TEXT_HI);
  #ifdef WITH_INTERNATIONAL
                BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
  #else
@@@ -1642,11 -1671,12 +1642,11 @@@ void ED_gpencil_draw_view2d(const bCont
        ScrArea *sa = CTX_wm_area(C);
        ARegion *ar = CTX_wm_region(C);
        Scene *scene = CTX_data_scene(C);
 -      bGPdata *gpd;
        int dflag = 0;
-       
        /* check that we have grease-pencil stuff to draw */
        if (sa == NULL) return;
 -      gpd = ED_gpencil_data_get_active(C); // XXX
 +      bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
        if (gpd == NULL) return;
  
        /* special hack for Image Editor */
@@@ -1725,7 -1750,8 +1725,7 @@@ void ED_gpencil_draw_view3d(wmWindowMan
        }
  
        /* draw it! */
-       gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);    
+       gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
 -
  }
  
  void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
@@@ -404,11 -404,11 +404,11 @@@ static void gp_brush_grab_calc_dvec(tGP
        if (gso->sa->spacetype == SPACE_VIEW3D) {
                View3D *v3d = gso->sa->spacedata.first;
                RegionView3D *rv3d = gso->ar->regiondata;
 -              float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d);
 +              float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d)->location;
                float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-               
                float mval_f[2];
-               
                /* convert from 2D screenspace to 3D... */
                mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
                mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
@@@ -504,9 -504,9 +504,9 @@@ static void gp_brush_calc_midpoint(tGP_
                 */
                View3D *v3d = gso->sa->spacedata.first;
                RegionView3D *rv3d = gso->ar->regiondata;
 -              float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d);
 +              float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d)->location;
                float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
-               
                float mval_f[2] = {UNPACK2(gso->mval)};
                float mval_prj[2];
                float dvec[3];
@@@ -177,9 -172,9 +177,9 @@@ static void gp_strokepoint_convertcoord
                copy_v3_v3(p3d, &pt->x);
        }
        else {
 -              const float *fp = ED_view3d_cursor3d_get(scene, v3d);
 +              const float *fp = ED_view3d_cursor3d_get(scene, v3d)->location;
                float mvalf[2];
-               
                /* get screen coordinate */
                if (gps->flag & GP_STROKE_2DSPACE) {
                        View2D *v2d = &ar->v2d;
@@@ -488,17 -482,17 +488,17 @@@ static void gp_stroke_path_animation(bC
                        printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
                }
        }
-       
        if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
                float cfra;
-               
                /* Linear extrapolation! */
                fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
-               
                cu->ctime = 0.0f;
                cfra = (float)gtd->start_frame;
 -              insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
 +              insert_keyframe_direct(depsgraph, reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
-               
                cu->ctime = cu->pathlen;
                if (gtd->realtime) {
                        cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
                if (G.debug & G_DEBUG) {
                        printf("GP Stroke Path Conversion: Starting keying!\n");
                }
-               
 -              gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
 +              gp_stroke_path_animation_add_keyframes(depsgraph, reports, ptr, prop, fcu, cu, gtd, rng, time_range,
                                                       nbr_gaps, tot_gaps_time);
-               
                BLI_rng_free(rng);
        }
-       
        /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
        calchandles_fcurve(fcu);
-       
        if (G.debug & G_DEBUG) {
                printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
                for (i = 0; i < gtd->num_points; i++) {
                }
                printf("\n\n");
        }
-       
        WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-       
        /* send updates */
 -      DAG_id_tag_update(&cu->id, 0);
 +      DEG_id_tag_update(&cu->id, 0);
  }
  
  #undef MIN_TIME_DELTA
@@@ -1136,12 -1128,12 +1136,12 @@@ static void gp_layer_to_curve(bContext 
        Object *ob;
        Curve *cu;
        Nurb *nu = NULL;
 -      Base *base_orig = BASACT, *base_new = NULL;
 +      Base *base_new = NULL;
        float minmax_weights[2] = {1.0f, 0.0f};
-       
        /* camera framing */
        rctf subrect, *subrect_ptr = NULL;
-       
        /* error checking */
        if (ELEM(NULL, gpd, gpl, gpf))
                return;
         */
        ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
        cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
 -      base_new = BKE_scene_base_add(scene, ob);
 +      BKE_collection_object_add(bmain, collection, ob);
 +      base_new = BKE_view_layer_base_find(view_layer, ob);
-       
        cu->flag |= CU_3D;
-       
        gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
-       
        /* add points to curve */
        for (gps = gpf->strokes.first; gps; gps = gps->next) {
                const bool add_start_point = (link_strokes && !(prev_gps));
                        BKE_nurb_type_convert(nu, CU_POLY, false);
                }
        }
-       
        /* set the layer and select */
 -      base_new->lay  = ob->lay  = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
 -      base_new->flag = ob->flag = base_new->flag | SELECT;
 +      base_new->flag |= SELECT;
 +      BKE_scene_object_base_flag_sync_from_base(base_new);
  }
  
  /* --- */
@@@ -1296,8 -1287,7 +1296,8 @@@ static int gp_convert_poll(bContext *C
        bGPDframe *gpf = NULL;
        ScrArea *sa = CTX_wm_area(C);
        Scene *scene = CTX_data_scene(C);
-       
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
         * and if we are not in edit mode!
         */
@@@ -1448,11 -1438,11 +1448,11 @@@ static void gp_convert_ui(bContext *C, 
        uiLayout *layout = op->layout;
        wmWindowManager *wm = CTX_wm_manager(C);
        PointerRNA ptr;
-       
        RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-       
        /* Main auto-draw call */
 -      uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0');
 +      uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
  }
  
  void GPENCIL_OT_convert(wmOperatorType *ot)
@@@ -1459,13 -1457,13 +1459,13 @@@ void GPENCIL_OT_snap_to_grid(wmOperator
  static int gp_snap_to_cursor(bContext *C, wmOperator *op)
  {
        bGPdata *gpd = ED_gpencil_data_get_active(C);
-       
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
-       
        const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
 -      const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d);
 +      const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d)->location;
-       
        for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                /* only editable and visible layers are considered */
                if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
@@@ -1547,11 -1545,11 +1547,11 @@@ void GPENCIL_OT_snap_to_cursor(wmOperat
  static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op))
  {
        bGPdata *gpd = ED_gpencil_data_get_active(C);
-       
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
-       
 -      float *cursor = ED_view3d_cursor3d_get(scene, v3d);
 +      float *cursor = ED_view3d_cursor3d_get(scene, v3d)->location;
        float centroid[3] = {0.0f};
        float min[3], max[3];
        size_t count = 0;
                        }
                }
        }
-       
 -      if (v3d->around == V3D_AROUND_CENTER_MEAN && count) {
 +      if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN && count) {
                mul_v3_fl(centroid, 1.0f / (float)count);
                copy_v3_v3(cursor, centroid);
        }
@@@ -2103,19 -2101,18 +2103,19 @@@ static int gp_strokes_reproject_exec(bC
        Scene *scene = CTX_data_scene(C);
        GP_SpaceConversion gsc = {NULL};
        eGP_ReprojectModes mode = RNA_boolean_get(op->ptr, "type");
-       
        /* init space conversion stuff */
        gp_point_conversion_init(C, &gsc);
-       
        /* init autodist for geometry projection */
        if (mode == GP_REPROJECT_SURFACE) {
 +              struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
                view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
 -              ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0);
 +              ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0);
        }
-       
        // TODO: For deforming geometry workflow, create new frames?
-       
        /* Go through each editable + selected stroke, adjusting each of its points one by one... */
        GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
        {
@@@ -290,26 -290,48 +290,26 @@@ static void ed_keymap_gpencil_editing(w
        /* Move to Layer */
        WM_keymap_add_item(keymap, "GPENCIL_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
  
 -      /* Select drawing brush using index */
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ONEKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 0);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", TWOKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 1);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", THREEKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 2);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", FOURKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 3);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", FIVEKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 4);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", SIXKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 5);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", SEVENKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 6);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", EIGHTKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 7);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", NINEKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 8);
 -      kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ZEROKEY, KM_PRESS, 0, 0);
 -      RNA_int_set(kmi->ptr, "index", 9);
 -
        /* Transform Tools */
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0);
-       
        WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0);
-       
        WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0);
-       
        kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0);
        RNA_enum_set(kmi->ptr, "mode", TFM_GPENCIL_SHRINKFATTEN);
-       
        /* Proportional Editing */
        ED_keymap_proportional_cycle(keyconf, keymap);
        ED_keymap_proportional_editmode(keyconf, keymap, true);
@@@ -116,8 -112,7 +116,8 @@@ typedef enum eGPencil_PaintFlags 
   */
  typedef struct tGPsdata {
        Scene *scene;       /* current scene from context */
-       
 +      struct Depsgraph *depsgraph;
        wmWindow *win;      /* window where painting originated */
        ScrArea *sa;        /* area where painting originated */
        ARegion *ar;        /* region where painting originated */
@@@ -236,8 -231,8 +236,8 @@@ static bool gpencil_project_check(tGPsd
  static void gp_get_3d_reference(tGPsdata *p, float vec[3])
  {
        View3D *v3d = p->sa->spacedata.first;
 -      const float *fp = ED_view3d_cursor3d_get(p->scene, v3d);
 +      const float *fp = ED_view3d_cursor3d_get(p->scene, v3d)->location;
-       
        /* the reference point used depends on the owner... */
  #if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
        if (p->ownerPtr.type == &RNA_Object) {
@@@ -642,12 -636,11 +642,12 @@@ static short gp_stroke_addpoint
                         */
                        if (gpencil_project_check(p)) {
                                View3D *v3d = p->sa->spacedata.first;
-                               
                                view3d_region_operator_needs_opengl(p->win, p->ar);
 -                              ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
 +                              ED_view3d_autodist_init(
 +                                      p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
                        }
-                       
                        /* convert screen-coordinates to appropriate coordinates (and store them) */
                        gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
                        /* if axis locked, reproject to plane locked (only in 3d space) */
@@@ -1245,11 -1238,12 +1245,11 @@@ static void gp_stroke_doeraser(tGPsdat
        if (p->sa->spacetype == SPACE_VIEW3D) {
                if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
                        View3D *v3d = p->sa->spacedata.first;
 -
                        view3d_region_operator_needs_opengl(p->win, p->ar);
 -                      ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
 +                      ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
                }
        }
-       
        /* loop over all layers too, since while it's easy to restrict editing to
         * only a subset of layers, it is harder to perform the same erase operation
         * on multiple layers...
@@@ -1397,15 -1391,14 +1397,15 @@@ static bool gp_session_initdata(bContex
                        printf("Error: No active view for painting\n");
                return 0;
        }
-       
        /* pass on current scene and window */
        p->scene = CTX_data_scene(C);
 +      p->depsgraph = CTX_data_depsgraph(C);
        p->win = CTX_wm_window(C);
-       
        unit_m4(p->imat);
        unit_m4(p->mat);
-       
        switch (curarea->spacetype) {
                /* supported views first */
                case SPACE_VIEW3D:
@@@ -1732,10 -1724,10 +1732,10 @@@ static void gp_paint_initstroke(tGPsdat
                if (p->sa->spacetype == SPACE_VIEW3D) {
                        View3D *v3d = p->sa->spacedata.first;
                        RegionView3D *rv3d = p->ar->regiondata;
-                       
                        /* for camera view set the subrect */
                        if (rv3d->persp == RV3D_CAMOB) {
 -                              ED_view3d_calc_camera_border(p->scene, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
 +                              ED_view3d_calc_camera_border(p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
                                p->subrect = &p->subrect_data;
                        }
                }
@@@ -1810,12 -1802,12 +1810,12 @@@ static void gp_paint_strokeend(tGPsdat
         */
        if (gpencil_project_check(p)) {
                View3D *v3d = p->sa->spacedata.first;
-               
                /* need to restore the original projection settings before packing up */
                view3d_region_operator_needs_opengl(p->win, p->ar);
 -              ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
 +              ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
        }
-       
        /* check if doing eraser or not */
        if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
                /* simplify stroke before transferring? */
@@@ -1974,9 -1953,9 +1974,9 @@@ static int gpencil_draw_init(bContext *
                gpencil_draw_exit(C, op);
                return 0;
        }
-       
        /* init painting data */
 -      gp_paint_initstroke(p, paintmode);
 +      gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
        if (p->status == GP_STATUS_ERROR) {
                gpencil_draw_exit(C, op);
                return 0;
@@@ -2075,8 -2054,8 +2075,8 @@@ static void gpencil_draw_apply(wmOperat
                        /* finish off old stroke */
                        gp_paint_strokeend(p);
                        /* And start a new one!!! Else, projection errors! */
 -                      gp_paint_initstroke(p, p->paintmode);
 +                      gp_paint_initstroke(p, p->paintmode, depsgraph);
-                       
                        /* start a new stroke, starting from previous point */
                        /* XXX Must manually reset inittime... */
                        /* XXX We only need to reuse previous point if overflow! */
@@@ -2209,11 -2188,11 +2209,11 @@@ static void gpencil_draw_apply_event(wm
        RNA_float_set_array(&itemptr, "mouse", mousef);
        RNA_float_set(&itemptr, "pressure", p->pressure);
        RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
-       
        RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
-       
        /* apply the current latest drawing point */
 -      gpencil_draw_apply(op, p);
 +      gpencil_draw_apply(op, p, depsgraph);
  
        /* force refresh */
        ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */