Merge branch 'master' into blender2.8
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Fri, 30 Nov 2018 11:16:19 +0000 (12:16 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Fri, 30 Nov 2018 11:16:19 +0000 (12:16 +0100)
1  2 
CMakeLists.txt
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_utils.c
source/blender/editors/space_view3d/view3d_view.c

diff --combined CMakeLists.txt
index 5741588b6af859a0cd9e43237ad9058d6ab8f70b,7359151d9a3891c44dab031ce0e20d61eff48b57..092eb926afb36db7507beffbbda7f092d0ab78b0
@@@ -164,6 -164,7 +164,6 @@@ option_defaults_init
        _init_OPENCOLORIO
        _init_SDL
        _init_FFTW3
 -      _init_GAMEENGINE
        _init_OPENSUBDIV
  )
  
@@@ -184,6 -185,7 +184,6 @@@ elseif(WIN32
        set(_init_JACK                           OFF)
  elseif(APPLE)
        set(_init_JACK                           OFF)
 -      set(_init_OPENSUBDIV                     OFF)
  endif()
  
  
@@@ -231,12 -233,19 +231,12 @@@ option(WITH_FFTW3         "Enable FFTW
  option(WITH_BULLET        "Enable Bullet (Physics Engine)" ON)
  option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
  mark_as_advanced(WITH_SYSTEM_BULLET)
 -option(WITH_GAMEENGINE    "Enable Game Engine" ${_init_GAMEENGINE})
 -if(APPLE)
 -      set(WITH_GAMEENGINE_DECKLINK OFF)
 -else()
 -      option(WITH_GAMEENGINE_DECKLINK "Support BlackMagicDesign DeckLink cards in the Game Engine" ON)
 -endif()
 -option(WITH_PLAYER        "Build Player" OFF)
  option(WITH_OPENCOLORIO   "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
  
  # Compositor
  option(WITH_COMPOSITOR         "Enable the tile based nodal compositor" ON)
  
- option(WITH_OPENSUBDIV    "Enable OpenSubdiv for surface subdivision" _init_OPENSUBDIV)
+ option(WITH_OPENSUBDIV    "Enable OpenSubdiv for surface subdivision" ${_init_OPENSUBDIV})
  
  option(WITH_OPENVDB       "Enable features relying on OpenVDB" OFF)
  option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" OFF)
@@@ -311,6 -320,7 +311,6 @@@ option(WITH_IMAGE_TIFF          "Enabl
  option(WITH_IMAGE_DDS           "Enable DDS Image Support" ON)
  option(WITH_IMAGE_CINEON        "Enable CINEON and DPX Image Support" ON)
  option(WITH_IMAGE_HDR           "Enable HDR Image Support" ON)
 -option(WITH_IMAGE_FRAMESERVER   "Enable image FrameServer Support for rendering" ON)
  
  # Audio/Video format support
  option(WITH_CODEC_AVI           "Enable Blenders own AVI file support (raw/jpeg)" ON)
@@@ -373,16 -383,10 +373,16 @@@ if(UNIX AND NOT APPLE
  endif()
  
  option(WITH_PYTHON_INSTALL       "Copy system python into the blender install folder" ON)
 -if(WITH_PYTHON_INSTALL)
 -      option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder"  ON)
 +if(WIN32 OR APPLE)
 +      # Windows and macOS have this bundled with Python libraries.
 +elseif(WITH_PYTHON_INSTALL OR (WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE))
        set(PYTHON_NUMPY_PATH            "" CACHE PATH "Path to python site-packages or dist-packages containing 'numpy' module")
        mark_as_advanced(PYTHON_NUMPY_PATH)
 +      set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON_NUMPY_PATH}/numpy/core/include CACHE PATH "Path to the include directory of the numpy module")
 +      mark_as_advanced(PYTHON_NUMPY_INCLUDE_DIRS)
 +endif()
 +if(WITH_PYTHON_INSTALL)
 +      option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder"  ON)
  
        if(UNIX AND NOT APPLE)
                option(WITH_PYTHON_INSTALL_REQUESTS "Copy system requests into the blender install folder" ON)
@@@ -465,18 -469,28 +465,18 @@@ endif(
  
  # OpenGL
  
 -option(WITH_GLEW_MX             "Support multiple GLEW contexts (experimental)"                                                                     OFF )
 +option(WITH_OPENGL              "When off limits visibility of the opengl headers to just bf_gpu and gawain (temporary option for development purposes)" ON)
  option(WITH_GLEW_ES             "Switches to experimental copy of GLEW that has support for OpenGL ES. (temporary option for development purposes)" OFF)
  option(WITH_GL_EGL              "Use the EGL OpenGL system library instead of the platform specific OpenGL system library (CGL, glX, or WGL)"       OFF)
 -option(WITH_GL_PROFILE_COMPAT   "Support using the OpenGL 'compatibility' profile. (deprecated)"                                                    ON )
 -option(WITH_GL_PROFILE_CORE     "Support using the OpenGL 3.2+ 'core' profile."                                                                     OFF)
  option(WITH_GL_PROFILE_ES20     "Support using OpenGL ES 2.0. (thru either EGL or the AGL/WGL/XGL 'es20' profile)"                                  OFF)
  
  mark_as_advanced(
 -      WITH_GLEW_MX
 +      WITH_OPENGL
        WITH_GLEW_ES
        WITH_GL_EGL
 -      WITH_GL_PROFILE_COMPAT
 -      WITH_GL_PROFILE_CORE
        WITH_GL_PROFILE_ES20
  )
  
 -if(WITH_GL_PROFILE_COMPAT)
 -      set(WITH_GLU ON)
 -else()
 -      set(WITH_GLU OFF)
 -endif()
 -
  if(WIN32)
        option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
        mark_as_advanced(WITH_GL_ANGLE)
@@@ -599,13 -613,17 +599,13 @@@ endif(
  #-----------------------------------------------------------------------------
  # Check for conflicting/unsupported configurations
  
 -if(NOT WITH_BLENDER AND NOT WITH_PLAYER AND NOT WITH_CYCLES_STANDALONE)
 +if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE)
        message(FATAL_ERROR
 -              "At least one of WITH_BLENDER or WITH_PLAYER or "
 -              "WITH_CYCLES_STANDALONE must be enabled, nothing to do!"
 +              "At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE "
 +              "must be enabled, nothing to do!"
        )
  endif()
  
 -if(NOT WITH_GAMEENGINE AND WITH_PLAYER)
 -      message(FATAL_ERROR "WITH_PLAYER requires WITH_GAMEENGINE")
 -endif()
 -
  if(NOT WITH_AUDASPACE)
        if(WITH_OPENAL)
                message(WARNING "WITH_OPENAL requires WITH_AUDASPACE which is disabled")
                message(WARNING "WITH_JACK requires WITH_AUDASPACE which is disabled")
                set(WITH_JACK OFF)
        endif()
 -      if(WITH_GAMEENGINE)
 -              message(FATAL_ERROR "WITH_GAMEENGINE requires WITH_AUDASPACE")
 -      endif()
  endif()
  
  if(NOT WITH_SDL AND WITH_GHOST_SDL)
  endif()
  
  # python module, needs some different options
 -if(WITH_PYTHON_MODULE AND WITH_PLAYER)
 -      message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PLAYER to be OFF")
 -endif()
 -
  if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
        message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
  endif()
@@@ -649,10 -674,15 +649,10 @@@ if(NOT WITH_BOOST
        endmacro()
  
        set_and_warn(WITH_CYCLES         OFF)
 -      set_and_warn(WITH_AUDASPACE      OFF)
        set_and_warn(WITH_INTERNATIONAL  OFF)
        set_and_warn(WITH_OPENVDB        OFF)
        set_and_warn(WITH_OPENCOLORIO    OFF)
 -
 -      set_and_warn(WITH_OPENAL         OFF)  # depends on AUDASPACE
 -      set_and_warn(WITH_GAMEENGINE     OFF)  # depends on AUDASPACE
 -      set_and_warn(WITH_PLAYER         OFF)  # depends on GAMEENGINE
 -elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL OR
 +elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
         WITH_OPENVDB OR WITH_OPENCOLORIO)
        # Keep enabled
  else()
@@@ -715,9 -745,30 +715,9 @@@ if(WITH_BUILDINFO
  endif()
  
  if(WITH_AUDASPACE)
 -      if(WITH_SYSTEM_AUDASPACE)
 -              set(AUDASPACE_DEFINITIONS
 -                      -DWITH_AUDASPACE
 -                      -DWITH_SYSTEM_AUDASPACE
 -                      "-DAUD_DEVICE_H=<AUD_Device.h>"
 -                      "-DAUD_SPECIAL_H=<AUD_Special.h>"
 -                      "-DAUD_SOUND_H=<AUD_Sound.h>"
 -                      "-DAUD_HANDLE_H=<AUD_Handle.h>"
 -                      "-DAUD_SEQUENCE_H=<AUD_Sequence.h>"
 -                      "-DAUD_TYPES_H=<AUD_Types.h>"
 -                      "-DAUD_PYTHON_H=<python/PyAPI.h>"
 -              )
 -      else()
 -              set(AUDASPACE_C_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/intern/audaspace/intern")
 -              set(AUDASPACE_PY_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/intern/audaspace/intern")
 -              set(AUDASPACE_DEFINITIONS
 -                      -DWITH_AUDASPACE
 -                      "-DAUD_DEVICE_H=<AUD_C-API.h>"
 -                      "-DAUD_SPECIAL_H=<AUD_C-API.h>"
 -                      "-DAUD_SOUND_H=<AUD_C-API.h>"
 -                      "-DAUD_HANDLE_H=<AUD_C-API.h>"
 -                      "-DAUD_SEQUENCE_H=<AUD_C-API.h>"
 -                      "-DAUD_TYPES_H=<AUD_Space.h>"
 -              )
 +      if(NOT WITH_SYSTEM_AUDASPACE)
 +              set(AUDASPACE_C_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/audaspace/bindings/C" "${CMAKE_BINARY_DIR}/extern/audaspace")
 +              set(AUDASPACE_PY_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/audaspace/bindings")
        endif()
  endif()
  
@@@ -981,15 -1032,19 +981,15 @@@ endif(
  find_package(OpenGL)
  blender_include_dirs_sys("${OPENGL_INCLUDE_DIR}")
  
 -if(WITH_GLU)
 -      list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_glu_LIBRARY}")
 -      list(APPEND GL_DEFINITIONS -DWITH_GLU)
 +if(WITH_OPENGL)
 +      add_definitions(-DWITH_OPENGL)
  endif()
  
  if(WITH_SYSTEM_GLES)
        find_package_wrapper(OpenGLES)
  endif()
  
 -if(WITH_GL_PROFILE_COMPAT OR WITH_GL_PROFILE_CORE)
 -      list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_gl_LIBRARY}")
 -
 -elseif(WITH_GL_PROFILE_ES20)
 +if(WITH_GL_PROFILE_ES20)
        if(WITH_SYSTEM_GLES)
                if(NOT OPENGLES_LIBRARY)
                        message(FATAL_ERROR
  
        endif()
  
 +else()
 +      list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_gl_LIBRARY}")
 +
  endif()
  
  if(WITH_GL_EGL)
  
  endif()
  
 -if(WITH_GL_PROFILE_COMPAT)
 -      list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_COMPAT)
 -endif()
 -
 -if(WITH_GL_PROFILE_CORE)
 -      list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
 -endif()
 -
  if(WITH_GL_PROFILE_ES20)
        list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_ES20)
 +else()
 +      list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
  endif()
  
  if(WITH_GL_EGL)
@@@ -1139,6 -1197,10 +1139,6 @@@ endif(
  #-----------------------------------------------------------------------------
  # Configure GLEW
  
 -if(WITH_GLEW_MX)
 -      list(APPEND GL_DEFINITIONS -DWITH_GLEW_MX)
 -endif()
 -
  if(WITH_SYSTEM_GLEW)
        find_package(GLEW)
  
                message(FATAL_ERROR "GLEW is required to build Blender. Install it or disable WITH_SYSTEM_GLEW.")
        endif()
  
 -      if(WITH_GLEW_MX)
 -              set(BLENDER_GLEW_LIBRARIES ${GLEW_MX_LIBRARY})
 -      else()
 -              set(BLENDER_GLEW_LIBRARIES ${GLEW_LIBRARY})
 -      endif()
 +      set(BLENDER_GLEW_LIBRARIES ${GLEW_LIBRARY})
  else()
        if(WITH_GLEW_ES)
                set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew-es/include")
                list(APPEND GL_DEFINITIONS -DGLEW_STATIC -DWITH_GLEW_ES)
  
                # These definitions remove APIs from glew.h, making GLEW smaller, and catching unguarded API usage
 -              if(NOT WITH_GL_PROFILE_ES20)
 +              if(WITH_GL_PROFILE_ES20)
 +                      list(APPEND GL_DEFINITIONS -DGLEW_ES_ONLY)
 +              else()
                        # No ES functions are needed
                        list(APPEND GL_DEFINITIONS -DGLEW_NO_ES)
 -              elseif(NOT (WITH_GL_PROFILE_CORE OR WITH_GL_PROFILE_COMPAT))
 -                      # ES is enabled, but the other functions are all disabled
 -                      list(APPEND GL_DEFINITIONS -DGLEW_ES_ONLY)
                endif()
  
                if(WITH_GL_PROFILE_ES20)
  
  endif()
  
 -if(NOT WITH_GLU)
 -      list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
 -endif()
 +list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
  
  #-----------------------------------------------------------------------------
  # Configure Bullet
@@@ -1438,7 -1507,6 +1438,7 @@@ elseif(CMAKE_C_COMPILER_ID MATCHES "MSV
                # warning level:
                "/W3"
                "/w34062"  # switch statement contains 'default' but no 'case' labels
 +              "/w34189"  # local variable is initialized but not referenced
                # disable:
                "/wd4018"  # signed/unsigned mismatch
                "/wd4146"  # unary minus operator applied to unsigned type, result still unsigned
@@@ -1483,14 -1551,9 +1483,14 @@@ if(WITH_PYTHON
        endif()
  
        if(WIN32 OR APPLE)
 -              # pass, we have this in an archive to extract
 -      elseif(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY)
 -              find_python_package(numpy)
 +              # Windows and macOS have this bundled with Python libraries.
 +      elseif((WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY) OR (WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE))
 +              if(("${PYTHON_NUMPY_PATH}" STREQUAL "") OR (${PYTHON_NUMPY_PATH} MATCHES NOTFOUND))
 +                      find_python_package(numpy)
 +                      unset(PYTHON_NUMPY_INCLUDE_DIRS CACHE)
 +                      set(PYTHON_NUMPY_INCLUDE_DIRS ${PYTHON_NUMPY_PATH}/numpy/core/include CACHE PATH "Path to the include directory of the numpy module")
 +                      mark_as_advanced(PYTHON_NUMPY_INCLUDE_DIRS)
 +              endif()
        endif()
  
        if(WIN32 OR APPLE)
        (CMAKE_C_COMPILER_ID MATCHES "Clang" AND (NOT MSVC)) OR
        (CMAKE_C_COMPILER_ID MATCHES "Intel")
  )
 -      # Use C99 + GNU extensions, works with GCC, Clang, ICC
 -      if(WITH_C11)
 -              set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
 -      else()
 -              set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
 -      endif()
 +      # Use C11 + GNU extensions, works with GCC, Clang, ICC
 +      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
  endif()
  
  # Include warnings first, so its possible to disable them with user defined flags
@@@ -1569,7 -1636,7 +1569,7 @@@ if(WITH_GTESTS
        include(GTestTesting)
  endif()
  
 -if(WITH_BLENDER OR WITH_PLAYER)
 +if(WITH_BLENDER)
        add_subdirectory(intern)
        add_subdirectory(extern)
  
@@@ -1594,6 -1661,13 +1594,6 @@@ if(WITH_BLENDER
  endif()
  
  
 -#-----------------------------------------------------------------------------
 -# Blender Player
 -if(WITH_PLAYER)
 -      add_subdirectory(source/blenderplayer)
 -endif()
 -
 -
  #-----------------------------------------------------------------------------
  # Testing
  add_subdirectory(tests)
@@@ -1608,6 -1682,9 +1608,6 @@@ include(build_files/cmake/packaging.cma
  if(WITH_BLENDER)
        openmp_delayload(blender)
  endif()
 -if(WITH_PLAYER)
 -      openmp_delayload(blenderplayer)
 -endif()
  
  #-----------------------------------------------------------------------------
  # Print Final Configuration
@@@ -1641,6 -1718,8 +1641,6 @@@ if(FIRST_RUN
        message(STATUS "C++ Compiler: \"${CMAKE_CXX_COMPILER_ID}\"")
  
        info_cfg_text("Build Options:")
 -      info_cfg_option(WITH_GAMEENGINE)
 -      info_cfg_option(WITH_PLAYER)
        info_cfg_option(WITH_BULLET)
        info_cfg_option(WITH_IK_SOLVER)
        info_cfg_option(WITH_IK_ITASC)
  
        info_cfg_text("OpenGL:")
        info_cfg_option(WITH_GLEW_ES)
 -      info_cfg_option(WITH_GLU)
        info_cfg_option(WITH_GL_EGL)
 -      info_cfg_option(WITH_GL_PROFILE_COMPAT)
 -      info_cfg_option(WITH_GL_PROFILE_CORE)
        info_cfg_option(WITH_GL_PROFILE_ES20)
        if(WIN32)
                info_cfg_option(WITH_GL_ANGLE)
index abd607a4f1907544dafac4d4f7db32e092510216,679498ab16d48f3b48b4cb0f38025d341c5ad2ad..ae093b2f9e223f62aa7dac9371b4a14766141e2e
@@@ -36,7 -36,6 +36,7 @@@
  #include <float.h>
  
  #include "DNA_armature_types.h"
 +#include "DNA_camera_types.h"
  #include "DNA_curve_types.h"
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h"
  #include "BLI_math.h"
  #include "BLI_utildefines.h"
  
 +#include "BKE_action.h"
  #include "BKE_armature.h"
 +#include "BKE_camera.h"
  #include "BKE_context.h"
  #include "BKE_font.h"
 +#include "BKE_gpencil.h"
 +#include "BKE_layer.h"
  #include "BKE_library.h"
  #include "BKE_main.h"
  #include "BKE_object.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_screen.h"
 -#include "BKE_action.h"
 -
  
 -#include "BIF_gl.h"
 -#include "BIF_glutil.h"
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
  
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
  
  #include "RNA_access.h"
  #include "RNA_define.h"
@@@ -78,8 -74,8 +78,8 @@@
  #include "ED_screen.h"
  #include "ED_transform.h"
  #include "ED_mesh.h"
 -#include "ED_gpencil.h"
  #include "ED_view3d.h"
 +#include "ED_transform_snap_object_context.h"
  
  #include "UI_resources.h"
  
@@@ -137,7 -133,6 +137,7 @@@ typedef struct ViewOpsData 
        ARegion *ar;
        View3D *v3d;
        RegionView3D *rv3d;
 +      Depsgraph *depsgraph;
  
        /** Needed for continuous zoom. */
        wmTimer *timer;
@@@ -223,7 -218,6 +223,7 @@@ static void viewops_data_alloc(bContex
        /* store data */
        op->customdata = vod;
        vod->bmain = CTX_data_main(C);
 +      vod->depsgraph = CTX_data_depsgraph(C);
        vod->scene = CTX_data_scene(C);
        vod->sa = CTX_wm_area(C);
        vod->ar = CTX_wm_region(C);
@@@ -251,12 -245,8 +251,12 @@@ static bool view3d_orbit_calc_center(bC
        static float lastofs[3] = {0, 0, 0};
        bool is_set = false;
  
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
 -      Object *ob_act = OBACT;
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
 +      View3D *v3d = CTX_wm_view3d(C);
 +      Object *ob_act_eval = OBACT(view_layer_eval);
 +      Object *ob_act = DEG_get_original_object(ob_act_eval);
  
        if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
            /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
                 */
                if (ob_act->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
                        float stroke[3];
 -                      BKE_paint_stroke_get_average(scene, ob_act, stroke);
 +                      BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
                        copy_v3_v3(lastofs, stroke);
                }
                else {
 -                      copy_v3_v3(lastofs, ob_act->obmat[3]);
 +                      copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
                }
                is_set = true;
        }
        else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
 -              Curve *cu = ob_act->data;
 +              Curve *cu = ob_act_eval->data;
                EditFont *ef = cu->editfont;
                int i;
  
                }
                mul_v2_fl(lastofs, 1.0f / 4.0f);
  
 -              mul_m4_v3(ob_act->obmat, lastofs);
 +              mul_m4_v3(ob_act_eval->obmat, lastofs);
  
                is_set = true;
        }
        else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
                /* object mode use boundbox centers */
 -              View3D *v3d = CTX_wm_view3d(C);
 -              Base *base;
 +              Base *base_eval;
                unsigned int tot = 0;
                float select_center[3];
  
                zero_v3(select_center);
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (TESTBASE(v3d, base)) {
 +              for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASE(v3d, base_eval)) {
                                /* use the boundbox if we can */
 -                              Object *ob = base->object;
 +                              Object *ob_eval = base_eval->object;
  
 -                              if (ob->bb && !(ob->bb->flag & BOUNDBOX_DIRTY)) {
 +                              if (ob_eval->bb && !(ob_eval->bb->flag & BOUNDBOX_DIRTY)) {
                                        float cent[3];
  
 -                                      BKE_boundbox_calc_center_aabb(ob->bb, cent);
 +                                      BKE_boundbox_calc_center_aabb(ob_eval->bb, cent);
  
 -                                      mul_m4_v3(ob->obmat, cent);
 +                                      mul_m4_v3(ob_eval->obmat, cent);
                                        add_v3_v3(select_center, cent);
                                }
                                else {
 -                                      add_v3_v3(select_center, ob->obmat[3]);
 +                                      add_v3_v3(select_center, ob_eval->obmat[3]);
                                }
                                tot++;
                        }
@@@ -375,7 -366,6 +375,7 @@@ static void viewops_data_create
          bContext *C, wmOperator *op, const wmEvent *event,
          enum eViewOpsFlag viewops_flag)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ViewOpsData *vod = op->customdata;
        RegionView3D *rv3d = vod->rv3d;
  
                negate_v3_v3(fallback_depth_pt, rv3d->ofs);
  
                vod->use_dyn_ofs = ED_view3d_autodist(
 -                      vod->bmain, vod->scene, vod->ar, vod->v3d,
 +                      depsgraph, vod->ar, vod->v3d,
                        event->mval, vod->dyn_ofs, true, fallback_depth_pt);
        }
        else {
        }
  
        if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
 -              if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
 +              if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
                        /* If we're switching from camera view to the perspective one,
                         * need to tag viewport update, so camera vuew and borders
                         * are properly updated.
  
        /* set the view from the camera, if view locking is enabled.
         * we may want to make this optional but for now its needed always */
-       ED_view3d_camera_lock_init_ex(depsgraph, vod->v3d, vod->rv3d, false);
 -      ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
++      ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
  
        vod->init.dist = rv3d->dist;
        vod->init.camzoom = rv3d->camzoom;
  static void viewops_data_free(bContext *C, wmOperator *op)
  {
        ARegion *ar;
 +#if 0
        Paint *p = BKE_paint_get_active_from_context(C);
 -
 +#endif
        if (op->customdata) {
                ViewOpsData *vod = op->customdata;
                ar = vod->ar;
                ar = CTX_wm_region(C);
        }
  
 +#if 0
        if (p && (p->flags & PAINT_FAST_NAVIGATE))
 +#endif
                ED_region_tag_redraw(ar);
  }
  
@@@ -584,6 -571,13 +584,6 @@@ void viewrotate_modal_keymap(wmKeyConfi
  
        keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items);
  
 -      /* items for modal map */
 -      WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -      WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -
 -      WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE);
 -      WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE);
 -
        /* disabled mode switching for now, can re-implement better, later on */
  #if 0
        WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
@@@ -808,7 -802,7 +808,7 @@@ static void viewrotate_apply(ViewOpsDat
        vod->prev.event_xy[0] = event_xy[0];
        vod->prev.event_xy[1] = event_xy[1];
  
 -      ED_view3d_camera_lock_sync(vod->v3d, rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -1106,6 -1100,7 +1106,6 @@@ static void view3d_ndof_pan_zoom
  
  static void view3d_ndof_orbit(
          const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
 -        /* optional, can be NULL*/
          ViewOpsData *vod, const bool apply_dyn_ofs)
  {
        View3D *v3d = sa->spacedata.first;
  
        BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
  
 -      ED_view3d_persp_ensure(v3d, ar);
 +      ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
  
        rv3d->view = RV3D_VIEW_USER;
  
@@@ -1304,7 -1299,6 +1304,7 @@@ static int ndof_orbit_invoke(bContext *
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                ViewOpsData *vod;
                View3D *v3d;
                RegionView3D *rv3d;
                /* off by default, until changed later this function */
                rv3d->rot_angle = 0.0f;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress != P_FINISHING) {
                        const bool has_rotation = NDOF_HAS_ROTATE;
                        }
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(vod->ar);
  
@@@ -1373,7 -1367,6 +1373,7 @@@ static int ndof_orbit_zoom_invoke(bCont
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                ViewOpsData *vod;
                View3D *v3d;
                RegionView3D *rv3d;
                /* off by default, until changed later this function */
                rv3d->rot_angle = 0.0f;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress == P_FINISHING) {
                        /* pass */
                        ED_view3d_distance_set(rv3d, 0.0f);
  
                        if (has_rotation) {
 -                              view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false);
 +                              view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
                        }
  
                        ED_view3d_distance_set(rv3d, dist_backup);
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(vod->ar);
  
@@@ -1478,7 -1471,6 +1478,7 @@@ static int ndof_pan_invoke(bContext *C
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                View3D *v3d = CTX_wm_view3d(C);
                RegionView3D *rv3d = CTX_wm_region_view3d(C);
                const wmNDOFMotionData *ndof = event->customdata;
                if (!(has_translate || has_zoom))
                        return OPERATOR_CANCELLED;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress != P_FINISHING) {
                        ScrArea *sa = CTX_wm_area(C);
                        }
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(CTX_wm_region(C));
  
@@@ -1548,7 -1540,7 +1548,7 @@@ static int ndof_all_invoke(bContext *C
  void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "NDOF Move View";
 +      ot->name = "NDOF Pan View";
        ot->description = "Pan and rotate the view with the 3D mouse";
        ot->idname = "VIEW3D_OT_ndof_all";
  
@@@ -1636,7 -1628,7 +1636,7 @@@ static void viewmove_apply(ViewOpsData 
        vod->prev.event_xy[0] = x;
        vod->prev.event_xy[1] = y;
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -1738,7 -1730,7 +1738,7 @@@ void VIEW3D_OT_move(wmOperatorType *ot
  {
  
        /* identifiers */
 -      ot->name = "Move View";
 +      ot->name = "Pan View";
        ot->description = "Move the view";
        ot->idname = "VIEW3D_OT_move";
  
@@@ -1781,6 -1773,10 +1781,6 @@@ void viewzoom_modal_keymap(wmKeyConfig 
  
        keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items);
  
 -      /* items for modal map */
 -      WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -      WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -
        /* disabled mode switching for now, can re-implement better, later on */
  #if 0
        WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
   * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
   */
  static void view_zoom_to_window_xy_camera(
 -        Scene *scene, View3D *v3d,
 +        Scene *scene, Depsgraph *depsgraph, View3D *v3d,
          ARegion *ar, float dfac, const int zoom_xy[2])
  {
        RegionView3D *rv3d = ar->regiondata;
                float pt_dst[2];
                float delta_px[2];
  
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false);
                BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
  
                rv3d->camzoom = camzoom_new;
                CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
  
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false);
                BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
  
                BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
@@@ -1993,7 -1989,7 +1993,7 @@@ static void viewzoom_apply_camera
                /* calculate inverted, then invert again (needed because of camera zoom scaling) */
                zfac = 1.0f / zfac;
                view_zoom_to_window_xy_camera(
 -                      vod->scene, vod->v3d,
 +                      vod->scene, vod->depsgraph, vod->v3d,
                        vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
        }
  
@@@ -2031,7 -2027,7 +2031,7 @@@ static void viewzoom_apply_3d
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -2113,7 -2109,6 +2113,7 @@@ static int viewzoom_modal(bContext *C, 
  
  static int viewzoom_exec(bContext *C, wmOperator *op)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d;
        RegionView3D *rv3d;
                const float step = 1.2f;
                /* this min and max is also in viewmove() */
                if (use_cam_zoom) {
 -                      view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
 +                      view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
                }
                else {
                        if (rv3d->dist < dist_range[1]) {
        else {
                const float step = 1.0f / 1.2f;
                if (use_cam_zoom) {
 -                      view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
 +                      view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
                }
                else {
                        if (rv3d->dist > dist_range[0]) {
  
        ED_view3d_depth_tag_update(rv3d);
  
 -      ED_view3d_camera_lock_sync(v3d, rv3d);
 +      ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
        ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
  
        ED_region_tag_redraw(ar);
@@@ -2312,6 -2307,10 +2312,6 @@@ void viewdolly_modal_keymap(wmKeyConfi
  
        keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
  
 -      /* items for modal map */
 -      WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -      WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 -
        /* disabled mode switching for now, can re-implement better, later on */
  #if 0
        WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
@@@ -2372,7 -2371,7 +2372,7 @@@ static void viewdolly_apply(ViewOpsDat
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -2473,7 -2472,7 +2473,7 @@@ static int viewdolly_exec(bContext *C, 
  
        ED_view3d_depth_tag_update(rv3d);
  
 -      ED_view3d_camera_lock_sync(v3d, rv3d);
 +      ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
  
        ED_region_tag_redraw(ar);
  
@@@ -2507,8 -2506,7 +2507,8 @@@ static int viewdolly_invoke(bContext *C
        if (vod->rv3d->persp != RV3D_PERSP) {
                if (vod->rv3d->persp == RV3D_CAMOB) {
                        /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
 -                      ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
 +                      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                      ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
                }
                else {
                        vod->rv3d->persp = RV3D_PERSP;
@@@ -2642,7 -2640,7 +2642,7 @@@ static void view3d_from_minmax
                }
  
                if (ok_dist) {
 -                      new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN);
 +                      new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), persp, true, (size / 2) * VIEW3D_MARGIN);
                        if (rv3d->is_persp) {
                                /* don't zoom closer than the near clipping plane */
                                new_dist = max_ff(new_dist, v3d->near * 1.5f);
@@@ -2697,9 -2695,8 +2697,9 @@@ static int view3d_all_exec(bContext *C
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        Scene *scene = CTX_data_scene(C);
 -      Base *base;
 -      float *curs;
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
 +      Base *base_eval;
        const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
        const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
                                  /* any one of the regions may be locked */
  
        if (center) {
                /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
 -              curs = ED_view3d_cursor3d_get(scene, v3d);
 +              View3DCursor *cursor = &scene->cursor;
                zero_v3(min);
                zero_v3(max);
 -              zero_v3(curs);
 +              zero_v3(cursor->location);
 +              unit_qt(cursor->rotation);
        }
        else {
                INIT_MINMAX(min, max);
        }
  
 -      for (base = scene->base.first; base; base = base->next) {
 -              if (BASE_VISIBLE(v3d, base)) {
 +      for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
 +              if (BASE_VISIBLE(v3d, base_eval)) {
                        changed = true;
  
 -                      if (skip_camera && base->object == v3d->camera) {
 +                      Object *ob = DEG_get_original_object(base_eval->object);
 +                      if (skip_camera && ob == v3d->camera) {
                                continue;
                        }
  
 -                      BKE_object_minmax(base->object, min, max, false);
 +                      BKE_object_minmax(base_eval->object, min, max, false);
                }
        }
        if (!changed) {
                view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
        }
  
 +      if (center) {
 +              DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
 +      }
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -2791,16 -2782,13 +2791,16 @@@ void VIEW3D_OT_view_all(wmOperatorType 
  /* like a localview without local!, was centerview() in 2.4x */
  static int viewselected_exec(bContext *C, wmOperator *op)
  {
 -      Main *bmain = CTX_data_main(C);
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        Scene *scene = CTX_data_scene(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
        bGPdata *gpd = CTX_data_gpencil_data(C);
 -      const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
 -      Object *ob = OBACT;
 +      const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
 +      const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map &&
 +                                WM_gizmomap_is_any_selected(ar->gizmo_map));
 +      Object *ob_eval = OBACT(view_layer_eval);
        Object *obedit = CTX_data_edit_object(C);
        float min[3], max[3];
        bool ok = false, ok_dist = true;
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
        INIT_MINMAX(min, max);
 -
 -      if (is_gp_edit) {
 -              ob = NULL;
 +      if (is_face_map) {
 +              ob_eval = NULL;
        }
  
 -      if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
 +      if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
                /* hard-coded exception, we look for the one selected armature */
                /* this is weak code this way, we should make a generic active/selection callback interface once... */
 -              Base *base;
 -              for (base = scene->base.first; base; base = base->next) {
 -                      if (TESTBASELIB(v3d, base)) {
 -                              if (base->object->type == OB_ARMATURE)
 -                                      if (base->object->mode & OB_MODE_POSE)
 +              Base *base_eval;
 +              for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASELIB(v3d, base_eval)) {
 +                              if (base_eval->object->type == OB_ARMATURE)
 +                                      if (base_eval->object->mode & OB_MODE_POSE)
                                                break;
                        }
                }
 -              if (base)
 -                      ob = base->object;
 +              if (base_eval)
 +                      ob_eval = base_eval->object;
        }
  
 -
        if (is_gp_edit) {
                CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
                {
                        /* we're only interested in selected points here... */
                        if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) {
 -                              if (ED_gpencil_stroke_minmax(gps, true, min, max)) {
 -                                      ok = true;
 -                              }
 +                              ok |= BKE_gpencil_stroke_minmax(gps, true, min, max);
                        }
                }
                CTX_DATA_END;
 +
 +              if ((ob_eval) && (ok)) {
 +                      add_v3_v3(min, ob_eval->obmat[3]);
 +                      add_v3_v3(max, ob_eval->obmat[3]);
 +              }
 +      }
 +      else if (ob_eval && (ob_eval->type == OB_GPENCIL)) {
 +              ok |= BKE_gpencil_data_minmax(ob_eval, gpd, min, max);
 +      }
 +      else if (is_face_map) {
 +              ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max);
        }
        else if (obedit) {
 -              ok = ED_view3d_minmax_verts(obedit, min, max);    /* only selected */
 +              /* only selected */
 +              FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->mode, ob_eval_iter) {
 +                      ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
 +              }
 +              FOREACH_OBJECT_IN_MODE_END;
        }
 -      else if (ob && (ob->mode & OB_MODE_POSE)) {
 -              ok = BKE_pose_minmax(ob, min, max, true, true);
 +      else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
 +              FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, ob_eval->mode, ob_eval_iter) {
 +                      ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
 +              }
 +              FOREACH_OBJECT_IN_MODE_END;
        }
 -      else if (BKE_paint_select_face_test(ob)) {
 -              ok = paintface_minmax(ob, min, max);
 +      else if (BKE_paint_select_face_test(ob_eval)) {
 +              ok = paintface_minmax(ob_eval, min, max);
        }
 -      else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
 -              ok = PE_minmax(bmain, scene, min, max);
 +      else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
 +              ok = PE_minmax(scene, view_layer_eval, min, max);
        }
 -      else if (ob &&
 -               (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
 +      else if (ob_eval &&
 +               (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
        {
 -              BKE_paint_stroke_get_average(scene, ob, min);
 +              BKE_paint_stroke_get_average(scene, ob_eval, min);
                copy_v3_v3(max, min);
                ok = true;
                ok_dist = 0; /* don't zoom */
        }
        else {
 -              Base *base;
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (TESTBASE(v3d, base)) {
 +              Base *base_eval;
 +              for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASE(v3d, base_eval)) {
  
 -                              if (skip_camera && base->object == v3d->camera) {
 +                              if (skip_camera && base_eval->object == v3d->camera) {
                                        continue;
                                }
  
                                /* account for duplis */
 -                              if (BKE_object_minmax_dupli(bmain, scene, base->object, min, max, false) == 0)
 -                                      BKE_object_minmax(base->object, min, max, false);  /* use if duplis not found */
 +                              if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0)
 +                                      BKE_object_minmax(base_eval->object, min, max, false);  /* use if duplis not found */
  
                                ok = 1;
                        }
@@@ -2978,14 -2952,14 +2978,14 @@@ static int view_lock_to_active_exec(bCo
        Object *obact = CTX_data_active_object(C);
  
        if (v3d) {
 -
                ED_view3d_lock_clear(v3d);
  
                v3d->ob_centre = obact; /* can be NULL */
  
                if (obact && obact->type == OB_ARMATURE) {
                        if (obact->mode & OB_MODE_POSE) {
 -                              bPoseChannel *pcham_act = BKE_pose_channel_active(obact);
 +                              Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), obact);
 +                              bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval);
                                if (pcham_act) {
                                        BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone));
                                }
@@@ -3043,7 -3017,7 +3043,7 @@@ static int viewcenter_cursor_exec(bCont
  
                /* non camera center */
                float new_ofs[3];
 -              negate_v3_v3(new_ofs, ED_view3d_cursor3d_get(scene, v3d));
 +              negate_v3_v3(new_ofs, scene->cursor.location);
                ED_view3d_smooth_view(
                        C, v3d, ar, smooth_viewtx,
                        &(const V3D_SmoothParams) {.ofs = new_ofs});
@@@ -3077,12 -3051,13 +3077,12 @@@ void VIEW3D_OT_view_center_cursor(wmOpe
  
  static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
  {
 -      Main *bmain = CTX_data_main(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
  
        if (rv3d) {
 +              struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
                float new_ofs[3];
                const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
  
                view3d_operator_needs_opengl(C);
  
 -              if (ED_view3d_autodist(bmain, scene, ar, v3d, event->mval, new_ofs, false, NULL)) {
 +              if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) {
                        /* pass */
                }
                else {
@@@ -3130,7 -3105,6 +3130,7 @@@ void VIEW3D_OT_view_center_pick(wmOpera
  
  static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        float xfac, yfac;
        float size[2];
  
        rv3d->camdx = rv3d->camdy = 0.0f;
  
 -      ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
 +      ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
  
        /* 4px is just a little room from the edge of the area */
        xfac = (float)ar->winx / (float)(size[0] + 4);
@@@ -3223,14 -3197,18 +3223,14 @@@ static int render_border_exec(bContext 
        rcti rect;
        rctf vb, border;
  
 -      const bool camera_only = RNA_boolean_get(op->ptr, "camera_only");
 -
 -      if (camera_only && rv3d->persp != RV3D_CAMOB)
 -              return OPERATOR_PASS_THROUGH;
 -
 -      /* get border select values using rna */
 +      /* get box select values using rna */
        WM_operator_properties_border_to_rcti(op, &rect);
  
        /* calculate range */
  
        if (rv3d->persp == RV3D_CAMOB) {
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
 +              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
        }
        else {
                vb.xmin = 0;
                        v3d->flag2 |= V3D_RENDER_BORDER;
        }
  
 +      if (rv3d->persp == RV3D_CAMOB) {
 +              DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
 +      }
        return OPERATOR_FINISHED;
  }
  
  void VIEW3D_OT_render_border(wmOperatorType *ot)
  {
 -      PropertyRNA *prop;
 -
        /* identifiers */
        ot->name = "Set Render Border";
        ot->description = "Set the boundaries of the border render and enable border render";
        ot->idname = "VIEW3D_OT_render_border";
  
        /* api callbacks */
 -      ot->invoke = WM_gesture_border_invoke;
 +      ot->invoke = WM_gesture_box_invoke;
        ot->exec = render_border_exec;
 -      ot->modal = WM_gesture_border_modal;
 -      ot->cancel = WM_gesture_border_cancel;
 +      ot->modal = WM_gesture_box_modal;
 +      ot->cancel = WM_gesture_box_cancel;
  
        ot->poll = ED_operator_view3d_active;
  
  
        /* properties */
        WM_operator_properties_border(ot);
 -
 -      prop = RNA_def_boolean(ot->srna, "camera_only", false, "Camera Only",
 -                             "Set render border for camera view and final render only");
 -      RNA_def_property_flag(prop, PROP_HIDDEN);
  }
  
  /** \} */
@@@ -3335,9 -3316,6 +3335,9 @@@ static int clear_render_border_exec(bCo
        border->xmax = 1.0f;
        border->ymax = 1.0f;
  
 +      if (rv3d->persp == RV3D_CAMOB) {
 +              DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
 +      }
        return OPERATOR_FINISHED;
  }
  
@@@ -3364,9 -3342,11 +3364,9 @@@ void VIEW3D_OT_clear_render_border(wmOp
  
  static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
  {
 -      Main *bmain = CTX_data_main(C);
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      Scene *scene = CTX_data_scene(C);
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
        /* Zooms in on a border drawn by the user */
        float new_ofs[3];
  
        /* ZBuffer depth vars */
 -      bglMats mats;
        float depth_close = FLT_MAX;
 -      double cent[2],  p[3];
 +      float cent[2],  p[3];
  
        /* note; otherwise opengl won't work */
        view3d_operator_needs_opengl(C);
  
 -      /* get border select values using rna */
 +      /* get box select values using rna */
        WM_operator_properties_border_to_rcti(op, &rect);
  
        /* check if zooming in/out view */
        ED_view3d_dist_range_get(v3d, dist_range);
  
        /* Get Z Depths, needed for perspective, nice for ortho */
 -      bgl_get_mats(&mats);
 -      ED_view3d_draw_depth(bmain, scene, ar, v3d, true);
 +      ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, v3d, true);
  
        {
                /* avoid allocating the whole depth buffer */
                MEM_SAFE_FREE(depth_temp.depths);
        }
  
 -      cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2;
 -      cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2;
 +      cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
 +      cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
  
        if (rv3d->is_persp) {
 -              double p_corner[3];
 +              float p_corner[3];
  
                /* no depths to use, we cant do anything! */
                if (depth_close == FLT_MAX) {
                        return OPERATOR_CANCELLED;
                }
                /* convert border to 3d coordinates */
 -              if ((!gluUnProject(cent[0], cent[1], depth_close,
 -                                 mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                 &p[0], &p[1], &p[2])) ||
 -                  (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close,
 -                                 mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                 &p_corner[0], &p_corner[1], &p_corner[2])))
 +              if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) ||
 +                  (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
                {
                        return OPERATOR_CANCELLED;
                }
  
 -              dvec[0] = p[0] - p_corner[0];
 -              dvec[1] = p[1] - p_corner[1];
 -              dvec[2] = p[2] - p_corner[2];
 -
 -              new_ofs[0] = -p[0];
 -              new_ofs[1] = -p[1];
 -              new_ofs[2] = -p[2];
 +              sub_v3_v3v3(dvec, p, p_corner);
 +              negate_v3_v3(new_ofs, p);
  
                new_dist = len_v3(dvec);
  
                new_dist = rv3d->dist;
  
                /* convert the drawn rectangle into 3d space */
 -              if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close,
 -                                                         mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                                         &p[0], &p[1], &p[2]))
 -              {
 -                      new_ofs[0] = -p[0];
 -                      new_ofs[1] = -p[1];
 -                      new_ofs[2] = -p[2];
 +              if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) {
 +                      negate_v3_v3(new_ofs, p);
                }
                else {
                        float mval_f[2];
        /* clamp after because we may have been zooming out */
        CLAMP(new_dist, dist_range[0], dist_range[1]);
  
 +      /* TODO(campbell): 'is_camera_lock' not currently working well. */
 +      const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
 +      if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) {
 +              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +              ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP);
 +      }
 +
        ED_view3d_smooth_view(
                C, v3d, ar, smooth_viewtx,
                &(const V3D_SmoothParams) {.ofs = new_ofs, .dist = &new_dist});
        return OPERATOR_FINISHED;
  }
  
 -static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 -{
 -      View3D *v3d = CTX_wm_view3d(C);
 -      RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -
 -      /* if in camera view do not exec the operator so we do not conflict with set render border*/
 -      if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d))
 -              return WM_gesture_border_invoke(C, op, event);
 -      else
 -              return OPERATOR_PASS_THROUGH;
 -}
 -
  void VIEW3D_OT_zoom_border(wmOperatorType *ot)
  {
        /* identifiers */
        ot->idname = "VIEW3D_OT_zoom_border";
  
        /* api callbacks */
 -      ot->invoke = view3d_zoom_border_invoke;
 +      ot->invoke = WM_gesture_box_invoke;
        ot->exec = view3d_zoom_border_exec;
 -      ot->modal = WM_gesture_border_modal;
 -      ot->cancel = WM_gesture_border_cancel;
 +      ot->modal = WM_gesture_box_modal;
 +      ot->cancel = WM_gesture_box_cancel;
  
        ot->poll = ED_operator_region_view3d_active;
  
        ot->flag = 0;
  
        /* properties */
 -      WM_operator_properties_gesture_border_zoom(ot);
 +      WM_operator_properties_gesture_box_zoom(ot);
  }
  
  /** \} */
   * Sets the view to 1:1 camera/render-pixel.
   * \{ */
  
 -static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
 +static void view3d_set_1_to_1_viewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
  {
        RegionView3D *rv3d = ar->regiondata;
        float size[2];
        int im_width = (scene->r.size * scene->r.xsch) / 100;
  
 -      ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
 +      ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
  
        rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
        CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
  
  static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
  
        View3D *v3d;
        /* no NULL check is needed, poll checks */
        ED_view3d_context_user_region(C, &v3d, &ar);
  
 -      view3d_set_1_to_1_viewborder(scene, ar, v3d);
 +      view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
  
        WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
  
@@@ -3577,7 -3577,7 +3577,7 @@@ void VIEW3D_OT_zoom_camera_1_to_1(wmOpe
  /** \} */
  
  /* -------------------------------------------------------------------- */
 -/** \name View Axis/Type Operator
 +/** \name View Axis Operator
   * \{ */
  
  static const EnumPropertyItem prop_view_items[] = {
        {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"},
        {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"},
        {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"},
 -      {RV3D_VIEW_CAMERA, "CAMERA", ICON_CAMERA_DATA, "Camera", "View From the Active Camera"},
        {0, NULL, 0, NULL, NULL}
  };
  
  
  /* would like to make this a generic function - outside of transform */
  
 +/**
 + * \param align_to_quat: When not NULL, set the axis relative to this rotation.
 + */
  static void axis_set_view(
          bContext *C, View3D *v3d, ARegion *ar,
          const float quat_[4],
 -        short view, int perspo, bool align_active,
 +        short view, int perspo,
 +        const float *align_to_quat,
          const int smooth_viewtx)
  {
        RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
  
        normalize_qt_qt(quat, quat_);
  
 -      if (align_active) {
 -              /* align to active object */
 -              Object *obact = CTX_data_active_object(C);
 -              if (obact == NULL) {
 -                      /* no active object, ignore this option */
 -                      align_active = false;
 -              }
 -              else {
 -                      float obact_quat[4];
 -                      float twmat[3][3];
 -
 -                      /* same as transform manipulator when normal is set */
 -                      ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE);
 -
 -                      mat3_to_quat(obact_quat, twmat);
 -                      invert_qt_normalized(obact_quat);
 -                      mul_qt_qtqt(quat, quat, obact_quat);
 -
 -                      rv3d->view = view = RV3D_VIEW_USER;
 -              }
 +      if (align_to_quat) {
 +              mul_qt_qtqt(quat, quat, align_to_quat);
 +              rv3d->view = view = RV3D_VIEW_USER;
        }
  
 -      if (align_active == false) {
 +      if (align_to_quat == NULL) {
                rv3d->view = view;
        }
  
                dist = rv3d->dist;
  
                /* so we animate _from_ the camera location */
 -              ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL);
 +              Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera);
 +              ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
  
                ED_view3d_smooth_view(
                        C, v3d, ar, smooth_viewtx,
        }
  }
  
 -static int viewnumpad_exec(bContext *C, wmOperator *op)
 +static int view_axis_exec(bContext *C, wmOperator *op)
  {
        View3D *v3d;
        ARegion *ar;
        RegionView3D *rv3d;
 -      Scene *scene = CTX_data_scene(C);
        static int perspo = RV3D_PERSP;
 -      int viewnum, nextperspo;
 -      bool align_active;
 +      int viewnum;
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
        /* no NULL check is needed, poll checks */
        ED_view3d_smooth_view_force_finish(C, v3d, ar);
  
        viewnum = RNA_enum_get(op->ptr, "type");
 -      align_active = RNA_boolean_get(op->ptr, "align_active");
  
 -      /* Use this to test if we started out with a camera */
 +      float align_quat_buf[4];
 +      float *align_quat = NULL;
  
 -      if (rv3d->persp == RV3D_CAMOB) {
 -              nextperspo = rv3d->lpersp;
 -      }
 -      else {
 -              nextperspo = perspo;
 +      if (RNA_boolean_get(op->ptr, "align_active")) {
 +              /* align to active object */
 +              Object *obact = CTX_data_active_object(C);
 +              if (obact != NULL) {
 +                      float twmat[3][3];
 +                      /* same as transform gizmo when normal is set */
 +                      ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE);
 +                      align_quat = align_quat_buf;
 +                      mat3_to_quat(align_quat, twmat);
 +                      invert_qt_normalized(align_quat);
 +              }
        }
  
 -      if (RV3D_VIEW_IS_AXIS(viewnum)) {
 -              float quat[4];
 +      if (RNA_boolean_get(op->ptr, "relative")) {
 +              float z_rel[3];
  
 -              ED_view3d_quat_from_axis_view(viewnum, quat);
 -              axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_active, smooth_viewtx);
 +              if (viewnum == RV3D_VIEW_RIGHT) {
 +                      negate_v3_v3(z_rel, rv3d->viewinv[0]);
 +              }
 +              else if (viewnum == RV3D_VIEW_LEFT) {
 +                      copy_v3_v3(z_rel, rv3d->viewinv[0]);
 +              }
 +              else if (viewnum == RV3D_VIEW_TOP) {
 +                      negate_v3_v3(z_rel, rv3d->viewinv[1]);
 +              }
 +              else if (viewnum == RV3D_VIEW_BOTTOM) {
 +                      copy_v3_v3(z_rel, rv3d->viewinv[1]);
 +              }
 +              else if (viewnum == RV3D_VIEW_FRONT) {
 +                      negate_v3_v3(z_rel, rv3d->viewinv[2]);
 +              }
 +              else if (viewnum == RV3D_VIEW_BACK) {
 +                      copy_v3_v3(z_rel, rv3d->viewinv[2]);
 +              }
 +              else {
 +                      BLI_assert(0);
 +              }
 +
 +              float angle_max = FLT_MAX;
 +              int view_closest = -1;
 +              for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
 +                      float quat[4];
 +                      float mat[3][3];
 +                      ED_view3d_quat_from_axis_view(i, quat);
 +                      quat[0] *= -1.0f;
 +                      quat_to_mat3(mat, quat);
 +                      if (align_quat) {
 +                              mul_qt_qtqt(quat, quat, align_quat);
 +                      }
 +                      const float angle_test = angle_normalized_v3v3(z_rel, mat[2]);
 +                      if (angle_max > angle_test) {
 +                              angle_max = angle_test;
 +                              view_closest = i;
 +                      }
 +              }
 +              if (view_closest == -1) {
 +                      view_closest = RV3D_VIEW_FRONT;
 +              }
 +              viewnum = view_closest;
        }
 -      else if (viewnum == RV3D_VIEW_CAMERA) {
 -              if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
 -                      /* lastview -  */
  
 -                      if (rv3d->persp != RV3D_CAMOB) {
 -                              Object *ob = OBACT;
 +      /* Use this to test if we started out with a camera */
 +      const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
 +      float quat[4];
 +      ED_view3d_quat_from_axis_view(viewnum, quat);
 +      axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx);
 +
 +      perspo = rv3d->persp;
  
 -                              if (!rv3d->smooth_timer) {
 -                                      /* store settings of current view before allowing overwriting with camera view
 -                                       * only if we're not currently in a view transition */
 +      return OPERATOR_FINISHED;
 +}
  
 -                                      ED_view3d_lastview_store(rv3d);
 -                              }
 +
 +void VIEW3D_OT_view_axis(wmOperatorType *ot)
 +{
 +      PropertyRNA *prop;
 +
 +      /* identifiers */
 +      ot->name = "View Axis";
 +      ot->description = "Use a preset viewpoint";
 +      ot->idname = "VIEW3D_OT_view_axis";
 +
 +      /* api callbacks */
 +      ot->exec = view_axis_exec;
 +      ot->poll = ED_operator_rv3d_user_region_poll;
 +
 +      /* flags */
 +      ot->flag = 0;
 +
 +      ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
 +      RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
 +      prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 +      prop = RNA_def_boolean(ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 +}
 +
 +/** \} */
 +
 +/* -------------------------------------------------------------------- */
 +/** \name View Camera Operator
 + * \{ */
 +
 +static int view_camera_exec(bContext *C, wmOperator *op)
 +{
 +      View3D *v3d;
 +      ARegion *ar;
 +      RegionView3D *rv3d;
 +      const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
 +
 +      /* no NULL check is needed, poll checks */
 +      ED_view3d_context_user_region(C, &v3d, &ar);
 +      rv3d = ar->regiondata;
 +
 +      ED_view3d_smooth_view_force_finish(C, v3d, ar);
 +
 +      if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
 +              /* lastview -  */
 +
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              Scene *scene = CTX_data_scene(C);
 +
 +              if (rv3d->persp != RV3D_CAMOB) {
 +                      Object *ob = OBACT(view_layer);
 +
 +                      if (!rv3d->smooth_timer) {
 +                              /* store settings of current view before allowing overwriting with camera view
 +                               * only if we're not currently in a view transition */
 +
 +                              ED_view3d_lastview_store(rv3d);
 +                      }
  
  #if 0
 -                              if (G.qual == LR_ALTKEY) {
 -                                      if (oldcamera && is_an_active_object(oldcamera)) {
 -                                              v3d->camera = oldcamera;
 -                                      }
 -                                      handle_view3d_lock();
 +                      if (G.qual == LR_ALTKEY) {
 +                              if (oldcamera && is_an_active_object(oldcamera)) {
 +                                      v3d->camera = oldcamera;
                                }
 +                              handle_view3d_lock();
 +                      }
  #endif
  
 -                              /* first get the default camera for the view lock type */
 -                              if (v3d->scenelock) {
 -                                      /* sets the camera view if available */
 +                      /* first get the default camera for the view lock type */
 +                      if (v3d->scenelock) {
 +                              /* sets the camera view if available */
 +                              v3d->camera = scene->camera;
 +                      }
 +                      else {
 +                              /* use scene camera if one is not set (even though we're unlocked) */
 +                              if (v3d->camera == NULL) {
                                        v3d->camera = scene->camera;
                                }
 -                              else {
 -                                      /* use scene camera if one is not set (even though we're unlocked) */
 -                                      if (v3d->camera == NULL) {
 -                                              v3d->camera = scene->camera;
 -                                      }
 -                              }
 +                      }
  
 -                              /* if the camera isn't found, check a number of options */
 -                              if (v3d->camera == NULL && ob && ob->type == OB_CAMERA)
 -                                      v3d->camera = ob;
 +                      /* if the camera isn't found, check a number of options */
 +                      if (v3d->camera == NULL && ob && ob->type == OB_CAMERA)
 +                              v3d->camera = ob;
  
 -                              if (v3d->camera == NULL)
 -                                      v3d->camera = BKE_scene_camera_find(scene);
 +                      if (v3d->camera == NULL)
 +                              v3d->camera = BKE_view_layer_camera_find(view_layer);
  
 -                              /* couldnt find any useful camera, bail out */
 -                              if (v3d->camera == NULL)
 -                                      return OPERATOR_CANCELLED;
 +                      /* couldn't find any useful camera, bail out */
 +                      if (v3d->camera == NULL)
 +                              return OPERATOR_CANCELLED;
  
 -                              /* important these don't get out of sync for locked scenes */
 -                              if (v3d->scenelock)
 -                                      scene->camera = v3d->camera;
 +                      /* important these don't get out of sync for locked scenes */
 +                      if (v3d->scenelock)
 +                              scene->camera = v3d->camera;
  
 -                              /* finally do snazzy view zooming */
 -                              rv3d->persp = RV3D_CAMOB;
 -                              ED_view3d_smooth_view(
 -                                      C, v3d, ar, smooth_viewtx,
 -                                      &(const V3D_SmoothParams) {
 -                                          .camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat,
 -                                          .dist = &rv3d->dist, .lens = &v3d->lens});
 -                      }
 -                      else {
 -                              /* return to settings of last view */
 -                              /* does view3d_smooth_view too */
 -                              axis_set_view(C, v3d, ar,
 -                                            rv3d->lviewquat,
 -                                            rv3d->lview, rv3d->lpersp, 0,
 -                                            smooth_viewtx);
 -                      }
 +                      /* finally do snazzy view zooming */
 +                      rv3d->persp = RV3D_CAMOB;
 +                      ED_view3d_smooth_view(
 +                              C, v3d, ar, smooth_viewtx,
 +                              &(const V3D_SmoothParams) {
 +                                  .camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat,
 +                                  .dist = &rv3d->dist, .lens = &v3d->lens});
 +              }
 +              else {
 +                      /* return to settings of last view */
 +                      /* does view3d_smooth_view too */
 +                      axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx);
                }
        }
  
 -      if (rv3d->persp != RV3D_CAMOB) perspo = rv3d->persp;
 -
        return OPERATOR_FINISHED;
  }
  
 -
 -void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
 +void VIEW3D_OT_view_camera(wmOperatorType *ot)
  {
 -      PropertyRNA *prop;
 -
        /* identifiers */
 -      ot->name = "View Numpad";
 -      ot->description = "Use a preset viewpoint";
 -      ot->idname = "VIEW3D_OT_viewnumpad";
 +      ot->name = "View Camera";
 +      ot->description = "Toggle the camera view";
 +      ot->idname = "VIEW3D_OT_view_camera";
  
        /* api callbacks */
 -      ot->exec = viewnumpad_exec;
 +      ot->exec = view_camera_exec;
        ot->poll = ED_operator_rv3d_user_region_poll;
  
        /* flags */
        ot->flag = 0;
 -
 -      ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
 -      RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
 -      prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
  /** \} */
@@@ -3943,8 -3867,7 +3943,8 @@@ static int vieworbit_exec(bContext *C, 
                        float quat_new[4];
  
                        if (view_opposite == RV3D_VIEW_USER) {
 -                              ED_view3d_persp_ensure(v3d, ar);
 +                              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                              ED_view3d_persp_ensure(depsgraph, v3d, ar);
                        }
  
                        if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@@ -4069,7 -3992,7 +4069,7 @@@ static void viewroll_apply(ViewOpsData 
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -4303,8 -4226,8 +4303,8 @@@ static int viewpan_invoke(bContext *C, 
  void VIEW3D_OT_view_pan(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "View Pan";
 -      ot->description = "Pan the view";
 +      ot->name = "Pan View Direction";
 +      ot->description = "Pan the view in a given direction";
        ot->idname = "VIEW3D_OT_view_pan";
  
        /* api callbacks */
@@@ -4402,67 -4325,52 +4402,67 @@@ void VIEW3D_OT_navigate(wmOperatorType 
  /** \name Background Image Add Operator
   * \{ */
  
 -static BGpic *background_image_add(bContext *C)
 +
 +static Camera *background_image_camera_from_context(bContext *C)
  {
 +      /* Needed to support drag-and-drop & camera buttons context. */
        View3D *v3d = CTX_wm_view3d(C);
 -
 -      return ED_view3d_background_image_new(v3d);
 +      if (v3d != NULL) {
 +              if (v3d->camera && v3d->camera->data && v3d->camera->type == OB_CAMERA) {
 +                      return v3d->camera->data;
 +              }
 +              return NULL;
 +      }
 +      else {
 +              return CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
 +      }
  }
  
  static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      background_image_add(C);
 +      Camera *cam = background_image_camera_from_context(C);
 +      BKE_camera_background_image_new(cam);
  
        return OPERATOR_FINISHED;
  }
  
  static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
  {
 -      View3D *v3d = CTX_wm_view3d(C);
 +      Camera *cam = background_image_camera_from_context(C);
        Image *ima;
 -      BGpic *bgpic;
 +      CameraBGImage *bgpic;
  
        ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
        /* may be NULL, continue anyway */
  
 -      bgpic = background_image_add(C);
 +      bgpic = BKE_camera_background_image_new(cam);
        bgpic->ima = ima;
  
 -      v3d->flag |= V3D_DISPBGPICS;
 +      cam->flag |= CAM_SHOW_BG_IMAGE;
  
 -      WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 +      WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
  
        return OPERATOR_FINISHED;
  }
  
 +static bool background_image_add_poll(bContext *C)
 +{
 +      return background_image_camera_from_context(C) != NULL;
 +}
 +
  void VIEW3D_OT_background_image_add(wmOperatorType *ot)
  {
        /* identifiers */
        /* note: having key shortcut here is bad practice,
         * but for now keep because this displays when dragging an image over the 3D viewport */
 -      ot->name   = "Add Background Image (Ctrl for Empty Object)";
 -      ot->description = "Add a new background image (Ctrl for Empty Object)";
 +      ot->name   = "Add Background Image";
 +      ot->description = "Add a new background image";
        ot->idname = "VIEW3D_OT_background_image_add";
  
        /* api callbacks */
        ot->invoke = background_image_add_invoke;
        ot->exec   = background_image_add_exec;
 -      ot->poll   = ED_operator_view3d_active;
 +      ot->poll   = background_image_add_poll;
  
        /* flags */
        ot->flag   = OPTYPE_UNDO;
  
  static int background_image_remove_exec(bContext *C, wmOperator *op)
  {
 -      View3D *v3d = CTX_wm_view3d(C);
 +      Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
        const int index = RNA_int_get(op->ptr, "index");
 -      BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index);
 +      CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index);
  
        if (bgpic_rem) {
 -              if (bgpic_rem->source == V3D_BGPIC_IMAGE) {
 +              if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) {
                        id_us_min((ID *)bgpic_rem->ima);
                }
 -              else if (bgpic_rem->source == V3D_BGPIC_MOVIE) {
 +              else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) {
                        id_us_min((ID *)bgpic_rem->clip);
                }
  
 -              ED_view3d_background_image_remove(v3d, bgpic_rem);
 +              BKE_camera_background_image_remove(cam, bgpic_rem);
  
 -              WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 +              WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
                return OPERATOR_FINISHED;
        }
        else {
@@@ -4513,7 -4421,7 +4513,7 @@@ void VIEW3D_OT_background_image_remove(
  
        /* api callbacks */
        ot->exec   = background_image_remove_exec;
 -      ot->poll   = ED_operator_view3d_active;
 +      ot->poll   = ED_operator_camera;
  
        /* flags */
        ot->flag   = 0;
@@@ -4551,12 -4459,11 +4551,12 @@@ void ED_view3d_clipping_local(RegionVie
                calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat);
  }
  
 +#if 0 /* TODO Missing from 2.8 drawing code. Find a solution to support clip border then uncomment it. */
 +
  static int view3d_clipping_exec(bContext *C, wmOperator *op)
  {
 +      ARegion *ar = CTX_wm_region(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      ViewContext vc;
 -      bglMats mats;
        rcti rect;
  
        WM_operator_properties_border_to_rcti(op, &rect);
        rv3d->rflag |= RV3D_CLIPPING;
        rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
  
 -      /* note; otherwise opengl won't work */
 -      view3d_operator_needs_opengl(C);
 -
 -      ED_view3d_viewcontext_init(C, &vc);
 -      view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
 -      ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect);
 +      /* NULL object because we don't want it in object space */
 +      ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
  
        return OPERATOR_FINISHED;
  }
@@@ -4583,7 -4494,7 +4583,7 @@@ static int view3d_clipping_invoke(bCont
                return OPERATOR_FINISHED;
        }
        else {
 -              return WM_gesture_border_invoke(C, op, event);
 +              return WM_gesture_box_invoke(C, op, event);
        }
  }
  
@@@ -4598,8 -4509,8 +4598,8 @@@ void VIEW3D_OT_clip_border(wmOperatorTy
        /* api callbacks */
        ot->invoke = view3d_clipping_invoke;
        ot->exec = view3d_clipping_exec;
 -      ot->modal = WM_gesture_border_modal;
 -      ot->cancel = WM_gesture_border_cancel;
 +      ot->modal = WM_gesture_box_modal;
 +      ot->cancel = WM_gesture_box_cancel;
  
        ot->poll = ED_operator_region_view3d_active;
  
        /* properties */
        WM_operator_properties_border(ot);
  }
 +#endif
  
  /** \} */
  
  
  /* cursor position in vec, result in vec, mval in region coords */
  /* note: cannot use event->mval here (called by object_add() */
 -void ED_view3d_cursor3d_position(bContext *C, const int mval[2], float cursor_co[3])
 +void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, float cursor_co[3])
  {
 -      Main *bmain = CTX_data_main(C);
 -      Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = ar->regiondata;
                ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ );
        }
  
 -      if (U.uiflag & USER_DEPTH_CURSOR) {  /* maybe this should be accessed some other way */
 +      if (use_depth) {  /* maybe this should be accessed some other way */
 +              struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +
                view3d_operator_needs_opengl(C);
 -              if (ED_view3d_autodist(bmain, scene, ar, v3d, mval, cursor_co, true, NULL))
 +              if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) {
                        depth_used = true;
 +              }
        }
  
        if (depth_used == false) {
        }
  }
  
 -void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
 +void ED_view3d_cursor3d_position_rotation(
 +        bContext *C, const int mval[2],
 +        const bool use_depth, enum eV3DCursorOrient orientation,
 +        float cursor_co[3], float cursor_quat[4])
  {
 +      Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
 +      ARegion *ar = CTX_wm_region(C);
 +      RegionView3D *rv3d = ar->regiondata;
 +
 +      /* XXX, caller should check. */
 +      if (rv3d == NULL)
 +              return;
  
 -      float *cursor_co_curr = ED_view3d_cursor3d_get(scene, v3d);
 -      float  cursor_co_prev[3];
 +      ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co);
 +
 +      if (orientation == V3D_CURSOR_ORIENT_NONE) {
 +              /* pass */
 +      }
 +      else if (orientation == V3D_CURSOR_ORIENT_VIEW) {
 +              copy_qt_qt(cursor_quat, rv3d->viewquat);
 +              cursor_quat[0] *= -1.0f;
 +      }
 +      else if (orientation == V3D_CURSOR_ORIENT_XFORM) {
 +              float mat[3][3];
 +              ED_transform_calc_orientation_from_type(C, mat);
 +              mat3_to_quat(cursor_quat, mat);
 +      }
 +      else if (orientation == V3D_CURSOR_ORIENT_GEOM) {
 +              copy_qt_qt(cursor_quat, rv3d->viewquat);
 +              cursor_quat[0] *= -1.0f;
 +
 +              const float mval_fl[2] = {UNPACK2(mval)};
 +              float ray_no[3];
 +              float ray_co[3];
 +
 +              struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
 +                      bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d);
 +
 +              float obmat[4][4];
 +              Object *ob_dummy = NULL;
 +              float dist_px = 0;
 +              if (ED_transform_snap_object_project_view3d_ex(
 +                      snap_context,
 +                      SCE_SNAP_MODE_FACE,
 +                      &(const struct SnapObjectParams){
 +                          .snap_select = SNAP_ALL,
 +                          .use_object_edit_cage = false,
 +                      },
 +                      mval_fl, &dist_px,
 +                      ray_co, ray_no, NULL,
 +                      &ob_dummy, obmat))
 +              {
 +                      if (use_depth) {
 +                              copy_v3_v3(cursor_co, ray_co);
 +                      }
 +
 +                      float tquat[4];
 +
 +                      /* Math normal (Z). */
 +                      {
 +                              float z_src[3] = {0, 0, 1};
 +                              mul_qt_v3(cursor_quat, z_src);
 +                              rotation_between_vecs_to_quat(tquat, z_src, ray_no);
 +                              mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
 +                      }
 +
 +                      /* Match object matrix (X). */
 +                      {
 +                              const float ortho_axis_dot[3] = {
 +                                      dot_v3v3(ray_no, obmat[0]),
 +                                      dot_v3v3(ray_no, obmat[1]),
 +                                      dot_v3v3(ray_no, obmat[2]),
 +                              };
 +                              const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
 +                              float x_src[3] = {1, 0, 0};
 +                              float x_dst[3];
 +                              mul_qt_v3(cursor_quat, x_src);
 +                              project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
 +                              normalize_v3(x_dst);
 +                              rotation_between_vecs_to_quat(tquat, x_src, x_dst);
 +                              mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
 +                      }
 +              }
 +              ED_transform_snap_object_context_destroy(snap_context);
 +      }
 +}
 +
 +void ED_view3d_cursor3d_update(
 +        bContext *C, const int mval[2],
 +        const bool use_depth, enum eV3DCursorOrient orientation)
 +{
 +      Scene *scene = CTX_data_scene(C);
 +      View3D *v3d = CTX_wm_view3d(C);
 +      ARegion *ar = CTX_wm_region(C);
 +      RegionView3D *rv3d = ar->regiondata;
  
 -      copy_v3_v3(cursor_co_prev, cursor_co_curr);
 +      View3DCursor *cursor_curr = &scene->cursor;
 +      View3DCursor  cursor_prev = *cursor_curr;
  
 -      ED_view3d_cursor3d_position(C, mval, cursor_co_curr);
 +      ED_view3d_cursor3d_position_rotation(
 +              C, mval,
 +              use_depth, orientation,
 +              cursor_curr->location, cursor_curr->rotation);
  
        /* offset the cursor lock to avoid jumping to new offset */
        if (v3d->ob_centre_cursor) {
 -              ARegion *ar = CTX_wm_region(C);
 -              RegionView3D *rv3d = ar->regiondata;
 -
                if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
  
                        float co_2d_curr[2], co_2d_prev[2];
  
                        if ((ED_view3d_project_float_global(
 -                                   ar, cursor_co_prev, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
 +                                   ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
                            (ED_view3d_project_float_global(
 -                                  ar, cursor_co_curr, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
 +                                  ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
                        {
                                rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f);
                                rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f);
                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
        else
                WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
 +
 +      {
 +              struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +              WM_msg_publish_rna_prop(
 +                      mbus, &scene->id, scene, Scene, cursor_location);
 +      }
 +
 +      DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
  }
  
 -static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
 +static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
  {
 -      ED_view3d_cursor3d_update(C, event->mval);
 +      bool use_depth = (U.uiflag & USER_DEPTH_CURSOR);
 +      {
 +              PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth");
 +              if (RNA_property_is_set(op->ptr, prop)) {
 +                      use_depth = RNA_property_boolean_get(op->ptr, prop);
 +              }
 +              else {
 +                      RNA_property_boolean_set(op->ptr, prop, use_depth);
 +              }
 +      }
 +      const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation");
 +      ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation);
  
        return OPERATOR_FINISHED;
  }
@@@ -4831,147 -4630,128 +4831,147 @@@ void VIEW3D_OT_cursor3d(wmOperatorType 
  
        /* flags */
  //    ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
 -}
 -
 -/** \} */
  
 -/* -------------------------------------------------------------------- */
 -/** \name Transform Manipulator Operator
 - * \{ */
 -
 -static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 -{
 -      View3D *v3d = CTX_wm_view3d(C);
 -
 -      if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
 -      if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
 -
 -      /* note; otherwise opengl won't work */
 -      view3d_operator_needs_opengl(C);
 -
 -      if (BIF_do_manipulator(C, event, op) == 0)
 -              return OPERATOR_PASS_THROUGH;
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void VIEW3D_OT_manipulator(wmOperatorType *ot)
 -{
        PropertyRNA *prop;
 +      static const EnumPropertyItem orientation_items[] = {
 +              {V3D_CURSOR_ORIENT_NONE,    "NONE",  0, "None", "Leave orientation unchanged"},
 +              {V3D_CURSOR_ORIENT_VIEW,    "VIEW",  0, "View", "Orient to the viewport"},
 +              {V3D_CURSOR_ORIENT_XFORM,   "XFORM", 0, "Transform", "Orient to the current transform setting"},
 +              {V3D_CURSOR_ORIENT_GEOM,    "GEOM",  0, "Geometry", "Match the surface normal"},
 +              {0, NULL, 0, NULL, NULL}
 +      };
  
 -      /* identifiers */
 -      ot->name = "3D Manipulator";
 -      ot->description = "Manipulate selected item by axis";
 -      ot->idname = "VIEW3D_OT_manipulator";
 -
 -      /* api callbacks */
 -      ot->invoke = manipulator_invoke;
 -
 -      ot->poll = ED_operator_view3d_active;
 -
 -      /* properties to pass to transform */
 -      Transform_Properties(ot, P_CONSTRAINT);
 +      prop = RNA_def_boolean(
 +              ot->srna, "use_depth", true, "Surface Project",
 +              "Project onto the surface");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  
 -      prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the "
 -                             "two axes that have not been clicked (translate/scale only)");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 +      prop = RNA_def_enum(
 +              ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW,
 +              "Orientation", "Preset viewpoint to use");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
  /** \} */
  
  /* -------------------------------------------------------------------- */
 -/** \name Enable Transform Manipulator Operator
 +/** \name Toggle Shading Operator
   * \{ */
  
 -static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 +static const EnumPropertyItem prop_shading_type_items[] = {
 +      {OB_WIRE, "WIREFRAME", 0, "Wireframe", "Toggle wireframe shading"},
 +      {OB_SOLID, "SOLID", 0, "Solid", "Toggle solid shading"},
 +      {OB_MATERIAL, "MATERIAL", 0, "LookDev", "Toggle lookdev shading"},
 +      {OB_RENDER, "RENDERED", 0, "Rendered", "Toggle rendered shading"},
 +      {0, NULL, 0, NULL, NULL}
 +};
 +
 +static int toggle_shading_exec(bContext *C, wmOperator *op)
  {
 +      Main *bmain = CTX_data_main(C);
        View3D *v3d = CTX_wm_view3d(C);
 +      ScrArea *sa = CTX_wm_area(C);
 +      int type = RNA_enum_get(op->ptr, "type");
  
 -      v3d->twtype = 0;
 -
 -      if (RNA_boolean_get(op->ptr, "translate"))
 -              v3d->twtype |= V3D_MANIP_TRANSLATE;
 -      if (RNA_boolean_get(op->ptr, "rotate"))
 -              v3d->twtype |= V3D_MANIP_ROTATE;
 -      if (RNA_boolean_get(op->ptr, "scale"))
 -              v3d->twtype |= V3D_MANIP_SCALE;
 +      if (type == OB_SOLID) {
 +              if (v3d->shading.type != type) {
 +                      v3d->shading.type = type;
 +              }
 +              else if (v3d->shading.type == OB_WIRE) {
 +                      v3d->shading.type = OB_SOLID;
 +              }
 +              else {
 +                      v3d->shading.type = OB_WIRE;
 +              }
 +      }
 +      else {
 +              char *prev_type = (
 +                      (type == OB_WIRE) ?
 +                      &v3d->shading.prev_type_wire :
 +                      &v3d->shading.prev_type);
 +              if (v3d->shading.type == type) {
 +                      if (*prev_type == type || !ELEM(*prev_type, OB_WIRE, OB_SOLID, OB_MATERIAL, OB_RENDER)) {
 +                              *prev_type = OB_SOLID;
 +                      }
 +                      v3d->shading.type = *prev_type;
 +              }
 +              else {
 +                      *prev_type = v3d->shading.type;
 +                      v3d->shading.type = type;
 +              }
 +      }
  
 +      ED_view3d_shade_update(bmain, v3d, sa);
        WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
  
        return OPERATOR_FINISHED;
  }
  
 -void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
 +void VIEW3D_OT_toggle_shading(wmOperatorType *ot)
  {
        PropertyRNA *prop;
  
        /* identifiers */
 -      ot->name = "Enable 3D Manipulator";
 -      ot->description = "Enable the transform manipulator for use";
 -      ot->idname = "VIEW3D_OT_enable_manipulator";
 +      ot->name = "Toggle Shading Type";
 +      ot->description = "Toggle shading type in 3D viewport";
 +      ot->idname = "VIEW3D_OT_toggle_shading";
  
        /* api callbacks */
 -      ot->invoke = enable_manipulator_invoke;
 +      ot->exec = toggle_shading_exec;
        ot->poll = ED_operator_view3d_active;
  
 -      /* properties */
 -      prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 -      prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 -      prop = RNA_def_boolean(ot->srna, "scale", 0, "Scale", "Enable the scale manipulator");
 +      prop = RNA_def_enum(ot->srna, "type", prop_shading_type_items, 0, "Type", "Shading type to toggle");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
  /** \} */
  
 +
  /* -------------------------------------------------------------------- */
 -/** \name Toggle Render Shading Operator
 +/** \name Toggle XRay
   * \{ */
  
 -static int toggle_render_exec(bContext *C, wmOperator *UNUSED(op))
 +static int toggle_xray_exec(bContext *C, wmOperator *op)
  {
        View3D *v3d = CTX_wm_view3d(C);
 -      if (v3d->drawtype == OB_RENDER) {
 -              v3d->drawtype = v3d->prev_drawtype;
 +      ScrArea *sa = CTX_wm_area(C);
 +      Object *obact = CTX_data_active_object(C);
 +
 +      if (obact &&
 +          ((obact->mode & OB_MODE_POSE) ||
 +           ((obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact))))
 +      {
 +              v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECT;
        }
        else {
 -              v3d->prev_drawtype = v3d->drawtype;
 -              v3d->drawtype = OB_RENDER;
 +              const bool xray_active = (
 +                      (obact && (obact->mode & OB_MODE_EDIT)) ||
 +                      ELEM(v3d->shading.type, OB_WIRE, OB_SOLID));
 +
 +              if (v3d->shading.type == OB_WIRE) {
 +                      v3d->shading.flag ^= V3D_SHADING_XRAY_BONE;
 +              }
 +              else {
 +                      v3d->shading.flag ^= V3D_SHADING_XRAY;
 +              }
 +              if (!xray_active) {
 +                      BKE_report(op->reports, RPT_INFO, "X-Ray not available in current mode");
 +              }
        }
 -      ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C));
 -      WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 +
 +      ED_area_tag_redraw(sa);
 +
        return OPERATOR_FINISHED;
  }
  
 -void VIEW3D_OT_toggle_render(wmOperatorType *ot)
 +void VIEW3D_OT_toggle_xray(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "Toggle Rendered Shading";
 -      ot->description = "Toggle rendered shading mode of the viewport";
 -      ot->idname = "VIEW3D_OT_toggle_render";
 +      ot->name = "Toggle X-Ray";
 +      ot->idname = "VIEW3D_OT_toggle_xray";
  
        /* api callbacks */
 -      ot->exec = toggle_render_exec;
 +      ot->exec = toggle_xray_exec;
        ot->poll = ED_operator_view3d_active;
  }
  
index add84655682c976feaba884180f00618b37ea3e7,68582644f345863cf567d546b35719afcc503004..d20dfa10923be62dc70963229bd1f29e169c07f2
@@@ -36,7 -36,6 +36,7 @@@
  #include "DNA_curve_types.h"
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h"
 +#include "DNA_world_types.h"
  
  #include "MEM_guardedalloc.h"
  
  
  #include "BKE_camera.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */
  #include "BKE_main.h"
  #include "BKE_object.h"
  #include "BKE_screen.h"
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
 +
  #include "BIF_gl.h"
  #include "BIF_glutil.h"
  
 +#include "GPU_matrix.h"
 +
  #include "WM_api.h"
  #include "WM_types.h"
  
@@@ -66,8 -61,6 +66,8 @@@
  #include "ED_screen.h"
  #include "ED_view3d.h"
  
 +#include "UI_resources.h"
 +
  #include "view3d_intern.h"  /* own include */
  
  /* -------------------------------------------------------------------- */
   *
   * \{ */
  
 -float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
 +void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float r_color[3])
  {
 -      if (v3d && v3d->localvd) return v3d->cursor;
 -      else return scene->cursor;
 +      switch (v3d->shading.background_type) {
 +              case V3D_SHADING_BACKGROUND_WORLD:
 +                      copy_v3_v3(r_color, &scene->world->horr);
 +                      break;
 +              case V3D_SHADING_BACKGROUND_VIEWPORT:
 +                      copy_v3_v3(r_color, v3d->shading.background_color);
 +                      break;
 +              case V3D_SHADING_BACKGROUND_THEME:
 +              default:
 +                      UI_GetThemeColor3fv(TH_HIGH_GRAD, r_color);
 +                      break;
 +      }
 +}
 +
 +void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3])
 +{
 +      const View3DCursor *cursor = &scene->cursor;
 +      quat_to_mat3(mat, cursor->rotation);
 +}
 +
 +void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4])
 +{
 +      const View3DCursor *cursor = &scene->cursor;
 +      quat_to_mat4(mat, cursor->rotation);
 +      copy_v3_v3(mat[3], cursor->location);
  }
  
  Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
@@@ -127,7 -97,6 +127,7 @@@ void ED_view3d_dist_range_get
   * \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
   */
  bool ED_view3d_clip_range_get(
 +        Depsgraph *depsgraph,
          const View3D *v3d, const RegionView3D *rv3d,
          float *r_clipsta, float *r_clipend,
          const bool use_ortho_factor)
        CameraParams params;
  
        BKE_camera_params_init(&params);
 -      BKE_camera_params_from_view3d(&params, v3d, rv3d);
 +      BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
  
        if (use_ortho_factor && params.is_ortho) {
                const float fac = 2.0f / (params.clipend - params.clipsta);
  }
  
  bool ED_view3d_viewplane_get(
 +        Depsgraph *depsgraph,
          const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
          rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
  {
        CameraParams params;
  
        BKE_camera_params_init(&params);
 -      BKE_camera_params_from_view3d(&params, v3d, rv3d);
 +      BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
        BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
  
        if (r_viewplane) *r_viewplane = params.viewplane;
@@@ -188,7 -156,7 +188,7 @@@ void view3d_operator_needs_opengl(cons
        view3d_region_operator_needs_opengl(win, ar);
  }
  
 -void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
 +void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar)
  {
        /* for debugging purpose, context should always be OK */
        if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
        else {
                RegionView3D *rv3d = ar->regiondata;
  
 -              wmSubWindowSet(win, ar->swinid);
 -              glMatrixMode(GL_PROJECTION);
 -              glLoadMatrixf(rv3d->winmat);
 -              glMatrixMode(GL_MODELVIEW);
 -              glLoadMatrixf(rv3d->viewmat);
 +              wmViewport(&ar->winrct); // TODO: bad
 +              GPU_matrix_projection_set(rv3d->winmat);
 +              GPU_matrix_set(rv3d->viewmat);
        }
  }
  
@@@ -261,7 -231,6 +261,7 @@@ bool ED_view3d_context_activate(bContex
  /** \name View Clipping Utilities
   *
   * \{ */
 +
  void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
  {
        int val;
        }
  }
  
 -void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
 +void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
  {
 -      float modelview[4][4];
 -      double xs, ys, p[3];
 -      int val, flip_sign, a;
 -
 -      /* near zero floating point values can give issues with gluUnProject
 -       * in side view on some implementations */
 -      if (fabs(mats->modelview[0]) < 1e-6) mats->modelview[0] = 0.0;
 -      if (fabs(mats->modelview[5]) < 1e-6) mats->modelview[5] = 0.0;
 -
 -      /* Set up viewport so that gluUnProject will give correct values */
 -      mats->viewport[0] = 0;
 -      mats->viewport[1] = 0;
 +      /* init in case unproject fails */
 +      memset(bb->vec, 0, sizeof(bb->vec));
  
        /* four clipping planes and bounding volume */
        /* first do the bounding volume */
 -      for (val = 0; val < 4; val++) {
 -              xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
 -              ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
 +      for (int val = 0; val < 4; val++) {
 +              float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
 +              float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
 +
 +              ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
 +              ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
 +      }
  
 -              gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
 -              copy_v3fl_v3db(bb->vec[val], p);
 +      /* optionally transform to object space */
 +      if (ob) {
 +              float imat[4][4];
 +              invert_m4_m4(imat, ob->obmat);
  
 -              gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
 -              copy_v3fl_v3db(bb->vec[4 + val], p);
 +              for (int val = 0; val < 8; val++) {
 +                      mul_m4_v3(imat, bb->vec[val]);
 +              }
        }
  
        /* verify if we have negative scale. doing the transform before cross
         * product flips the sign of the vector compared to doing cross product
         * before transform then, so we correct for that. */
 -      for (a = 0; a < 16; a++)
 -              ((float *)modelview)[a] = mats->modelview[a];
 -      flip_sign = is_negative_m4(modelview);
 +      int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
  
        ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
  }
@@@ -405,15 -379,14 +405,15 @@@ void ED_view3d_lock_clear(View3D *v3d
   * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
   * otherwise switching out of camera view may jump to a different part of the scene.
   */
 -void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
 +void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const char persp)
  {
        BLI_assert(rv3d->persp == RV3D_CAMOB);
        BLI_assert(persp != RV3D_CAMOB);
  
        if (v3d->camera) {
 -              rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
 -              ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
 +              Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
 +              rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
 +              ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
        }
  
        if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
   *
   * shared with NDOF.
   */
 -bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
 +bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar)
  {
        RegionView3D *rv3d = ar->regiondata;
        const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
                if (rv3d->persp == RV3D_CAMOB) {
                        /* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
                        char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
 -                      ED_view3d_persp_switch_from_camera(v3d, rv3d, persp);
 +                      ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp);
                }
                else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
                        rv3d->persp = RV3D_PERSP;
@@@ -474,21 -447,20 +474,21 @@@ bool ED_view3d_camera_lock_check(const 
   * Apply the camera object transformation to the view-port.
   * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
   */
 -void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
 +void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
  {
        if (ED_view3d_camera_lock_check(v3d, rv3d)) {
 +              Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
                if (calc_dist) {
                        /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
 -                      rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
 +                      rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
                }
 -              ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
 +              ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
        }
  }
  
 -void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
 +void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
  {
-       ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
 -      ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
++      ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
  }
  
  /**
   *
   * \return true if the camera is moved.
   */
 -bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
 +bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
  {
        if (ED_view3d_camera_lock_check(v3d, rv3d)) {
                ObjectTfmProtectedChannels obtfm;
                        while (root_parent->parent) {
                                root_parent = root_parent->parent;
                        }
 +                      Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
 +                      Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent);
  
                        ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
  
 -                      normalize_m4_m4(tmat, v3d->camera->obmat);
 +                      normalize_m4_m4(tmat, ob_camera_eval->obmat);
  
                        invert_m4_m4(imat, tmat);
                        mul_m4_m4m4(diff_mat, view_mat, imat);
  
 -                      mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
 +                      mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat);
  
                        BKE_object_tfm_protected_backup(root_parent, &obtfm);
                        BKE_object_apply_mat4(root_parent, parent_mat, true, false);
  
                        ob_update = v3d->camera;
                        while (ob_update) {
 -                              DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
 +                              DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
                                WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
                                ob_update = ob_update->parent;
                        }
                        /* always maintain the same scale */
                        const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
                        BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
 -                      ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
 +                      ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
                        BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
  
 -                      DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
 +                      DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
                        WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
                }
  
@@@ -624,7 -594,6 +624,7 @@@ bool ED_view3d_camera_lock_autokey
  /** \} */
  
  
 +
  /* -------------------------------------------------------------------- */
  /** \name Box View Support
   *
@@@ -909,17 -878,22 +909,17 @@@ static float view_autodist_depth_margin
   * \param fallback_depth_pt: Use this points depth when no depth can be found.
   */
  bool ED_view3d_autodist(
 -        Main *bmain, Scene *scene, ARegion *ar, View3D *v3d,
 +        Depsgraph *depsgraph, ARegion *ar, View3D *v3d,
          const int mval[2], float mouse_worldloc[3],
          const bool alphaoverride, const float fallback_depth_pt[3])
  {
 -      bglMats mats; /* ZBuffer depth vars */
        float depth_close;
 -      double cent[2],  p[3];
        int margin_arr[] = {0, 2, 4};
        int i;
        bool depth_ok = false;
  
        /* Get Z Depths, needed for perspective, nice for ortho */
 -      ED_view3d_draw_depth(bmain, scene, ar, v3d, alphaoverride);
 -
 -      /* call after in case settings have been modified since last drawing, see: T47089 */
 -      bgl_get_mats(&mats);
 +      ED_view3d_draw_depth(depsgraph, ar, v3d, alphaoverride);
  
        /* Attempt with low margin's first */
        i = 0;
        } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
  
        if (depth_ok) {
 -              cent[0] = (double)mval[0] + 0.5;
 -              cent[1] = (double)mval[1] + 0.5;
 +              float centx = (float)mval[0] + 0.5f;
 +              float centy = (float)mval[1] + 0.5f;
  
 -              if (gluUnProject(cent[0], cent[1], depth_close,
 -                               mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
 -              {
 -                      mouse_worldloc[0] = (float)p[0];
 -                      mouse_worldloc[1] = (float)p[1];
 -                      mouse_worldloc[2] = (float)p[2];
 +              if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
                        return true;
                }
        }
        }
  }
  
 -void ED_view3d_autodist_init(Main *bmain, Scene *scene, ARegion *ar, View3D *v3d, int mode)
 +void ED_view3d_autodist_init(Depsgraph *depsgraph,
 +        ARegion *ar, View3D *v3d, int mode)
  {
        /* Get Z Depths, needed for perspective, nice for ortho */
        switch (mode) {
                case 0:
 -                      ED_view3d_draw_depth(bmain, scene, ar, v3d, true);
 +                      ED_view3d_draw_depth(depsgraph, ar, v3d, true);
                        break;
                case 1:
 -                      ED_view3d_draw_depth_gpencil(scene, ar, v3d);
 +              {
 +                      Scene *scene = DEG_get_evaluated_scene(depsgraph);
 +                      ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d);
                        break;
 +              }
        }
  }
  
  /* no 4x4 sampling, run #ED_view3d_autodist_init first */
 -bool ED_view3d_autodist_simple(
 -        ARegion *ar, const int mval[2], float mouse_worldloc[3],
 -        int margin, float *force_depth)
 +bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
 +                               int margin, float *force_depth)
  {
 -      bglMats mats; /* ZBuffer depth vars, could cache? */
        float depth;
 -      double cent[2],  p[3];
  
        /* Get Z Depths, needed for perspective, nice for ortho */
        if (force_depth)
        if (depth == FLT_MAX)
                return false;
  
 -      cent[0] = (double)mval[0] + 0.5;
 -      cent[1] = (double)mval[1] + 0.5;
 -
 -      bgl_get_mats(&mats);
 -
 -      if (!gluUnProject(cent[0], cent[1], depth,
 -                        mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
 -      {
 -              return false;
 -      }
 -
 -      mouse_worldloc[0] = (float)p[0];
 -      mouse_worldloc[1] = (float)p[1];
 -      mouse_worldloc[2] = (float)p[2];
 -      return true;
 +      float centx = (float)mval[0] + 0.5f;
 +      float centy = (float)mval[1] + 0.5f;
 +      return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
  }
  
  bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
@@@ -1076,7 -1066,6 +1076,7 @@@ float ED_view3d_radius_to_dist_ortho(co
   */
  float ED_view3d_radius_to_dist(
          const View3D *v3d, const ARegion *ar,
 +        const struct Depsgraph *depsgraph,
          const char persp, const bool use_aspect,
          const float radius)
  {
                        BKE_camera_params_init(&params);
                        params.clipsta = v3d->near;
                        params.clipend = v3d->far;
 -                      BKE_camera_params_from_object(&params, v3d->camera);
 +                      Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
 +                      BKE_camera_params_from_object(&params, camera_eval);
  
                        lens = params.lens;
                        sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
@@@ -1288,7 -1276,7 +1288,7 @@@ bool ED_view3d_lock(RegionView3D *rv3d
   * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
   * \param dist The view distance from ofs, normally from RegionView3D.dist.
   */
 -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
 +void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist)
  {
        float nmat[3][3];
  
@@@ -1333,14 -1321,13 +1333,14 @@@ void ED_view3d_to_m4(float mat[4][4], c
  
  /**
   * Set the RegionView3D members from an objects transformation and optionally lens.
 + * \param depsgraph The depsgraph to get the evaluated object for the lens calculation.
   * \param ob The object to set the view to.
   * \param ofs The view offset to be set, normally from RegionView3D.ofs.
   * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
   * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
   * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
   */
 -void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
 +void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
  {
        ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
  
  
  /**
   * Set the object transformation from RegionView3D members.
 + * \param depsgraph The depsgraph to get the evaluated object parent for the transformation calculation.
   * \param ob The object which has the transformation assigned.
   * \param ofs The view offset, normally from RegionView3D.ofs.
   * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
   * \param dist The view distance from ofs, normally from RegionView3D.dist.
   */
 -void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
 +void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs[3], const float quat[4], const float dist)
  {
        float mat[4][4];
        ED_view3d_to_m4(mat, ofs, quat, dist);
 -      BKE_object_apply_mat4(ob, mat, true, true);
 +
 +      Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
 +      BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
  }
  
  /** \} */
@@@ -1393,7 -1377,7 +1393,7 @@@ float ED_view3d_depth_read_cached(cons
  }
  
  bool ED_view3d_depth_read_cached_normal(
 -        const ViewContext *vc, const bglMats *mats, const int mval[2],
 +        const ViewContext *vc, const int mval[2],
          float r_normal[3])
  {
        /* Note: we could support passing in a radius.
  
                        const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
                        if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
 -                              if (ED_view3d_depth_unproject(ar, mats, mval_ofs, depth, coords[i])) {
 +                              if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
                                        depths_valid[i] = true;
                                }
                        }
  }
  
  bool ED_view3d_depth_unproject(
 -        const ARegion *ar, const bglMats *mats,
 +        const ARegion *ar,
          const int mval[2], const double depth,
          float r_location_world[3])
  {
 -      double p[3];
 -      if (gluUnProject(
 -              (double)ar->winrct.xmin + mval[0] + 0.5,
 -              (double)ar->winrct.ymin + mval[1] + 0.5,
 -              depth, mats->modelview, mats->projection, (const GLint *)mats->viewport,
 -              &p[0], &p[1], &p[2]))
 -      {
 -              copy_v3fl_v3db(r_location_world, p);
 -              return true;
 -      }
 -      return false;
 +      float centx = (float)mval[0] + 0.5f;
 +      float centy = (float)mval[1] + 0.5f;
 +      return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
  }
  
  void ED_view3d_depth_tag_update(RegionView3D *rv3d)
  }
  
  /** \} */
 -
 -/* -------------------------------------------------------------------- */
 -/** \name Background Image Utilities
 - * \{ */
 -
 -BGpic *ED_view3d_background_image_new(View3D *v3d)
 -{
 -      BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image");
 -
 -      bgpic->rotation = 0.0f;
 -      bgpic->size = 5.0f;
 -      bgpic->blend = 0.5f;
 -      bgpic->iuser.fie_ima = 2;
 -      bgpic->iuser.ok = 1;
 -      bgpic->view = 0; /* 0 for all */
 -      bgpic->flag |= V3D_BGPIC_EXPANDED;
 -
 -      BLI_addtail(&v3d->bgpicbase, bgpic);
 -
 -      return bgpic;
 -}
 -
 -void ED_view3d_background_image_remove(View3D *v3d, BGpic *bgpic)
 -{
 -      BLI_remlink(&v3d->bgpicbase, bgpic);
 -
 -      MEM_freeN(bgpic);
 -}
 -
 -void ED_view3d_background_image_clear(View3D *v3d)
 -{
 -      BGpic *bgpic = v3d->bgpicbase.first;
 -
 -      while (bgpic) {
 -              BGpic *next_bgpic = bgpic->next;
 -
 -              ED_view3d_background_image_remove(v3d, bgpic);
 -
 -              bgpic = next_bgpic;
 -      }
 -}
 -
 -/** \} */
index 4a637443a8ddf1bb4846bff8c133929f91063584,92f226f72de3077f8e775600390f125e33061881..98ae57e9c426614aaee5460d8a162840e06b9ebf
  #include "BKE_action.h"
  #include "BKE_camera.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_object.h"
  #include "BKE_global.h"
 +#include "BKE_layer.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  
 -#include "BIF_gl.h"
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
  
  #include "UI_resources.h"
  
 +#include "GPU_glew.h"
  #include "GPU_select.h"
 +#include "GPU_matrix.h"
 +#include "GPU_state.h"
  
  #include "WM_api.h"
  #include "WM_types.h"
  
 +#include "ED_object.h"
  #include "ED_screen.h"
  
 -#ifdef WITH_GAMEENGINE
 -#  include "BLI_listbase.h"
 -#  include "BLI_callbacks.h"
 -
 -#  include "GPU_draw.h"
 -
 -#  include "BL_System.h"
 -#endif
 +#include "DRW_engine.h"
  
  #include "view3d_intern.h"  /* own include */
  
@@@ -123,7 -125,7 +123,7 @@@ static void view3d_smooth_view_state_re
  /* the arguments are the desired situation */
  void ED_view3d_smooth_view_ex(
          /* avoid passing in the context */
 -        wmWindowManager *wm, wmWindow *win, ScrArea *sa,
 +        const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *sa,
          View3D *v3d, ARegion *ar, const int smooth_viewtx,
          const V3D_SmoothParams *sview)
  {
         * we allow camera option locking to initialize the view settings from the camera.
         */
        if (sview->camera == NULL && sview->camera_old == NULL) {
-               ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true);
 -              ED_view3d_camera_lock_init(v3d, rv3d);
++              ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
        }
  
        /* store the options we want to end with */
        }
  
        if (sview->camera) {
 -              sms.dst.dist = ED_view3d_offset_distance(sview->camera->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
 -              ED_view3d_from_object(sview->camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
 +              Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
 +              sms.dst.dist = ED_view3d_offset_distance(ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK);
 +              ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
                sms.to_camera = true; /* restore view3d values in end */
        }
  
        /* skip smooth viewing for render engine draw */
 -      if (smooth_viewtx && v3d->drawtype != OB_RENDER) {
 +      if (smooth_viewtx && v3d->shading.type != OB_RENDER) {
                bool changed = false; /* zero means no difference */
  
                if (sview->camera_old != sview->camera)
                if (changed) {
                        /* original values */
                        if (sview->camera_old) {
 -                              sms.src.dist = ED_view3d_offset_distance(sview->camera_old->obmat, rv3d->ofs, 0.0f);
 +                              Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old);
 +                              sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f);
                                /* this */
 -                              ED_view3d_from_object(sview->camera_old, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
 +                              ED_view3d_from_object(ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
                        }
                        /* grid draw as floor */
                        if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
                        /* ensure it shows correct */
                        if (sms.to_camera) {
                                /* use ortho if we move from an ortho view to an ortho camera */
 +                              Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera);
                                rv3d->persp = (((rv3d->is_persp == false) &&
 -                                              (sview->camera->type == OB_CAMERA) &&
 -                                              (((Camera *)sview->camera->data)->type == CAM_ORTHO)) ?
 +                                              (ob_camera_eval->type == OB_CAMERA) &&
 +                                              (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ?
                                                RV3D_ORTHO : RV3D_PERSP);
                        }
  
                        rv3d->dist = sms.dst.dist;
                        v3d->lens = sms.dst.lens;
  
 -                      ED_view3d_camera_lock_sync(v3d, rv3d);
 +                      ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
                }
  
                if (rv3d->viewlock & RV3D_BOXVIEW) {
@@@ -282,13 -281,11 +282,13 @@@ void ED_view3d_smooth_view
          View3D *v3d, ARegion *ar, const int smooth_viewtx,
          const struct V3D_SmoothParams *sview)
  {
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        wmWindowManager *wm = CTX_wm_manager(C);
        wmWindow *win = CTX_wm_window(C);
        ScrArea *sa = CTX_wm_area(C);
  
        ED_view3d_smooth_view_ex(
 +              depsgraph,
                wm, win, sa,
                v3d, ar, smooth_viewtx,
                sview);
  /* only meant for timer usage */
  static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool sync_boxview)
  {
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        RegionView3D *rv3d = ar->regiondata;
        struct SmoothView3DStore *sms = rv3d->sms;
        float step, step_inv;
                else {
                        view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
  
 -                      ED_view3d_camera_lock_sync(v3d, rv3d);
 +                      ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
                        ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
                }
  
                rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
                v3d->lens  = sms->dst.lens * step + sms->src.lens * step_inv;
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
                if (ED_screen_animation_playing(CTX_wm_manager(C))) {
                        ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
                }
@@@ -409,9 -405,8 +409,9 @@@ void ED_view3d_smooth_view_force_finish
  
                /* force update of view matrix so tools that run immediately after
                 * can use them without redrawing first */
 +              Depsgraph *depsgraph = CTX_data_depsgraph(C);
                Scene *scene = CTX_data_scene(C);
 -              ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL);
 +              ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
        }
  }
  
@@@ -438,7 -433,6 +438,7 @@@ void VIEW3D_OT_smoothview(wmOperatorTyp
  
  static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        View3D *v3d;
        ARegion *ar;
        RegionView3D *rv3d;
  
        BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
  
 -      ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
 +      ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
  
        BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag);
  
 -      DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
 +      DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
        rv3d->persp = RV3D_CAMOB;
  
        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera);
@@@ -509,30 -503,29 +509,30 @@@ void VIEW3D_OT_camera_to_view(wmOperato
   * meant to take into account vertex/bone selection for eg. */
  static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
  {
 -      Main *bmain = CTX_data_main(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);  /* can be NULL */
        Object *camera_ob = v3d ? v3d->camera : scene->camera;
 +      Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
  
        float r_co[3]; /* the new location to apply */
        float r_scale; /* only for ortho cameras */
  
 -      if (camera_ob == NULL) {
 +      if (camera_ob_eval == NULL) {
                BKE_report(op->reports, RPT_ERROR, "No active camera");
                return OPERATOR_CANCELLED;
        }
  
        /* this function does all the important stuff */
 -      if (BKE_camera_view_frame_fit_to_scene(bmain, scene, v3d, camera_ob, r_co, &r_scale)) {
 +      if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) {
                ObjectTfmProtectedChannels obtfm;
                float obmat_new[4][4];
  
 -              if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) {
 +              if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
                        ((Camera *)camera_ob->data)->ortho_scale = r_scale;
                }
  
 -              copy_m4_m4(obmat_new, camera_ob->obmat);
 +              copy_m4_m4(obmat_new, camera_ob_eval->obmat);
                copy_v3_v3(obmat_new[3], r_co);
  
                /* only touch location */
                BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
  
                /* notifiers */
 -              DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
 +              DEG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
                return OPERATOR_FINISHED;
        }
@@@ -696,14 -689,14 +696,14 @@@ void VIEW3D_OT_object_as_camera(wmOpera
  /**
   * \param rect optional for picking (can be NULL).
   */
 -void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect)
 +void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect)
  {
        RegionView3D *rv3d = ar->regiondata;
        rctf viewplane;
        float clipsta, clipend;
        bool is_ortho;
  
 -      is_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
 +      is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
        rv3d->is_persp = !is_ortho;
  
  #if 0
        }
  
        if (is_ortho) {
 -              wmOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
 +              GPU_matrix_ortho_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
        }
        else {
 -              wmFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
 +              GPU_matrix_frustum_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
        }
  
        /* update matrix in 3d view region */
 -      glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat);
 +      GPU_matrix_projection_get(rv3d->winmat);
  }
  
  static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
  /**
   * Sets #RegionView3D.viewmat
   *
 + * \param depsgraph: Depsgraph.
   * \param scene: Scene for camera and cursor location.
   * \param v3d: View 3D space data.
   * \param rv3d: 3D region which stores the final matrices.
   * \note don't set windows active in here, is used by renderwin too.
   */
  void view3d_viewmatrix_set(
 -        Scene *scene,
 +        Depsgraph *depsgraph, Scene *scene,
          const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
  {
        if (rv3d->persp == RV3D_CAMOB) {      /* obs/camera */
                if (v3d->camera) {
 -                      BKE_object_where_is_calc(scene, v3d->camera);
 -                      obmat_to_viewmat(rv3d, v3d->camera);
 +                      Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
 +                      BKE_object_where_is_calc(depsgraph, scene, ob_camera_eval);
 +                      obmat_to_viewmat(rv3d, ob_camera_eval);
                }
                else {
                        quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
                quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
                if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist;
                if (v3d->ob_centre) {
 -                      Object *ob = v3d->ob_centre;
 +                      Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre);
                        float vec[3];
  
 -                      copy_v3_v3(vec, ob->obmat[3]);
 -                      if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
 -                              bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone);
 +                      copy_v3_v3(vec, ob_eval->obmat[3]);
 +                      if (ob_eval->type == OB_ARMATURE && v3d->ob_centre_bone[0]) {
 +                              bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_centre_bone);
                                if (pchan) {
                                        copy_v3_v3(vec, pchan->pose_mat[3]);
 -                                      mul_m4_v3(ob->obmat, vec);
 +                                      mul_m4_v3(ob_eval->obmat, vec);
                                }
                        }
                        translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
                }
                else if (v3d->ob_centre_cursor) {
                        float vec[3];
 -                      copy_v3_v3(vec, ED_view3d_cursor3d_get(scene, (View3D *)v3d));
 +                      copy_v3_v3(vec, scene->cursor.location);
                        translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
                        use_lock_ofs = true;
                }
@@@ -858,71 -849,6 +858,71 @@@ void view3d_opengl_select_cache_end(voi
        GPU_select_cache_end();
  }
  
 +struct DrawSelectLoopUserData {
 +      uint  pass;
 +      uint  hits;
 +      uint *buffer;
 +      uint  buffer_len;
 +      const rcti *rect;
 +      char gpu_select_mode;
 +};
 +
 +static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
 +{
 +      bool continue_pass = false;
 +      struct DrawSelectLoopUserData *data = user_data;
 +      if (stage == DRW_SELECT_PASS_PRE) {
 +              GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
 +              /* always run POST after PRE. */
 +              continue_pass = true;
 +      }
 +      else if (stage == DRW_SELECT_PASS_POST) {
 +              int hits = GPU_select_end();
 +              if (data->pass == 0) {
 +                      /* quirk of GPU_select_end, only take hits value from first call. */
 +                      data->hits = hits;
 +              }
 +              if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) {
 +                      data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS;
 +                      continue_pass = (hits > 0);
 +              }
 +              data->pass += 1;
 +      }
 +      else {
 +              BLI_assert(0);
 +      }
 +      return continue_pass;
 +
 +}
 +
 +eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const Scene *scene, const Object *obact)
 +{
 +      if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
 +              if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) &&
 +                  BKE_object_pose_armature_get((Object *)obact))
 +              {
 +                      return VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK;
 +              }
 +              return VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK;
 +      }
 +      return VIEW3D_SELECT_FILTER_NOP;
 +}
 +
 +/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */
 +static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
 +{
 +      const Object *obact = user_data;
 +      return BKE_object_is_mode_compat(ob, obact->mode);
 +}
 +
 +/** Implement #VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK for special case when
 + * we want to select pose bones (this doesn't switch modes). */
 +static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data)
 +{
 +      const Object *ob_pose = user_data;
 +      return (DEG_get_original_object(ob) == ob_pose);
 +}
 +
  /**
   * \warning be sure to account for a negative return value
   * This is an error, "Too many objects in select buffer"
   */
  int view3d_opengl_select(
          ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
 -        eV3DSelectMode select_mode)
 +        eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
  {
        struct bThemeState theme_state;
 +      Depsgraph *depsgraph = vc->depsgraph;
        Scene *scene = vc->scene;
        View3D *v3d = vc->v3d;
        ARegion *ar = vc->ar;
        rcti rect;
 -      int hits;
 -      const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
 +      int hits = 0;
 +      const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL);
        const bool is_pick_select = (U.gpu_select_pick_deph != 0);
        const bool do_passes = (
                (is_pick_select == false) &&
                (select_mode == VIEW3D_SELECT_PICK_NEAREST) &&
                GPU_select_query_check_active());
        const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
 +      bool draw_surface = true;
  
        char gpu_select_mode;
  
 -      /* case not a border select */
 +      /* case not a box select */
        if (input->xmin == input->xmax) {
                /* seems to be default value for bones only now */
                BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12);
                }
        }
  
 +      struct {
 +              DRW_ObjectFilterFn fn;
 +              void *user_data;
 +      } object_filter = {NULL, NULL};
 +      switch (select_filter) {
 +              case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK:
 +              {
 +                      Object *obact = OBACT(vc->view_layer);
 +                      if (obact && obact->mode != OB_MODE_OBJECT) {
 +                              object_filter.fn = drw_select_filter_object_mode_lock;
 +                              object_filter.user_data = obact;
 +                      }
 +                      break;
 +              }
 +              case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK:
 +              {
 +                      Object *obact = OBACT(vc->view_layer);
 +                      BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT));
 +                      Object *ob_pose = BKE_object_pose_armature_get(obact);
 +
 +                      object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint;
 +                      object_filter.user_data = ob_pose;
 +                      break;
 +              }
 +              case VIEW3D_SELECT_FILTER_NOP:
 +                      break;
 +
 +      }
 +
        /* Tools may request depth outside of regular drawing code. */
        UI_Theme_Store(&theme_state);
        UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
                goto finally;
        }
  
 +      /* All of the queries need to be perform on the drawing context. */
 +      DRW_opengl_context_enable();
 +
        G.f |= G_PICKSEL;
  
        /* Important we use the 'viewmat' and don't re-calculate since
         * the object & bone view locking takes 'rect' into account, see: T51629. */
 -      ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
 +      ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
  
 -      if (v3d->drawtype > OB_WIRE) {
 -              v3d->zbuf = true;
 -              glEnable(GL_DEPTH_TEST);
 +      if (v3d->shading.type > OB_WIRE) {
 +              GPU_depth_test(true);
        }
  
 -      if (vc->rv3d->rflag & RV3D_CLIPPING)
 +      if (vc->rv3d->rflag & RV3D_CLIPPING) {
                ED_view3d_clipping_set(vc->rv3d);
 +      }
  
 -      GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
 -
 -      ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
 -
 -      hits = GPU_select_end();
 -
 -      /* second pass, to get the closest object to camera */
 -      if (do_passes && (hits > 0)) {
 -              GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
 -
 -              ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
 +      /* If in xray mode, we select the wires in priority. */
 +      if ((v3d->shading.flag & V3D_XRAY_FLAG(v3d)) && use_nearest) {
 +              /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
 +               * because the OpenGL context created & destroyed inside this function. */
 +              struct DrawSelectLoopUserData drw_select_loop_user_data = {
 +                      .pass = 0,
 +                      .hits = 0,
 +                      .buffer = buffer,
 +                      .buffer_len = bufsize,
 +                      .rect = &rect,
 +                      .gpu_select_mode = gpu_select_mode,
 +              };
 +              draw_surface = false;
 +              DRW_draw_select_loop(
 +                      depsgraph, ar, v3d,
 +                      use_obedit_skip, draw_surface, use_nearest, &rect,
 +                      drw_select_loop_pass, &drw_select_loop_user_data,
 +                      object_filter.fn, object_filter.user_data);
 +              hits = drw_select_loop_user_data.hits;
 +              /* FIX: This cleanup the state before doing another selection pass.
 +               * (see T56695) */
 +              GPU_select_cache_end();
 +      }
  
 -              GPU_select_end();
 +      if (hits == 0) {
 +              /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop
 +               * because the OpenGL context created & destroyed inside this function. */
 +              struct DrawSelectLoopUserData drw_select_loop_user_data = {
 +                      .pass = 0,
 +                      .hits = 0,
 +                      .buffer = buffer,
 +                      .buffer_len = bufsize,
 +                      .rect = &rect,
 +                      .gpu_select_mode = gpu_select_mode,
 +              };
 +              draw_surface = true;
 +              DRW_draw_select_loop(
 +                      depsgraph, ar, v3d,
 +                      use_obedit_skip, draw_surface, use_nearest, &rect,
 +                      drw_select_loop_pass, &drw_select_loop_user_data,
 +                      object_filter.fn, object_filter.user_data);
 +              hits = drw_select_loop_user_data.hits;
        }
  
        G.f &= ~G_PICKSEL;
 -      ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
 +      ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
  
 -      if (v3d->drawtype > OB_WIRE) {
 -              v3d->zbuf = 0;
 -              glDisable(GL_DEPTH_TEST);
 +      if (v3d->shading.type > OB_WIRE) {
 +              GPU_depth_test(false);
        }
  
        if (vc->rv3d->rflag & RV3D_CLIPPING)
                ED_view3d_clipping_disable();
  
 +      DRW_opengl_context_disable();
 +
  finally:
 +
        if (hits < 0) printf("Too many objects in select buffer\n");  /* XXX make error message */
  
        UI_Theme_Restore(&theme_state);
  
  static unsigned int free_localbit(Main *bmain)
  {
 -      unsigned int lay;
        ScrArea *sa;
        bScreen *sc;
  
 -      lay = 0;
 +      unsigned short local_view_bits = 0;
  
        /* sometimes we loose a localview: when an area is closed */
        /* check all areas: which localviews are in use? */
                        for (; sl; sl = sl->next) {
                                if (sl->spacetype == SPACE_VIEW3D) {
                                        View3D *v3d = (View3D *) sl;
 -                                      lay |= v3d->lay;
 +                                      if (v3d->localvd) {
 +                                              local_view_bits |= v3d->local_view_uuid;
 +                                      }
                                }
                        }
                }
        }
  
 -      if ((lay & 0x01000000) == 0) return 0x01000000;
 -      if ((lay & 0x02000000) == 0) return 0x02000000;
 -      if ((lay & 0x04000000) == 0) return 0x04000000;
 -      if ((lay & 0x08000000) == 0) return 0x08000000;
 -      if ((lay & 0x10000000) == 0) return 0x10000000;
 -      if ((lay & 0x20000000) == 0) return 0x20000000;
 -      if ((lay & 0x40000000) == 0) return 0x40000000;
 -      if ((lay & 0x80000000) == 0) return 0x80000000;
 -
 -      return 0;
 -}
 -
 -int ED_view3d_scene_layer_set(int lay, const bool *values, int *active)
 -{
 -      int i, tot = 0;
 -
 -      /* ensure we always have some layer selected */
 -      for (i = 0; i < 20; i++)
 -              if (values[i])
 -                      tot++;
 -
 -      if (tot == 0)
 -              return lay;
 -
 -      for (i = 0; i < 20; i++) {
 -
 -              if (active) {
 -                      /* if this value has just been switched on, make that layer active */
 -                      if (values[i] && (lay & (1 << i)) == 0) {
 -                              *active = (1 << i);
 -                      }
 -              }
 -
 -              if (values[i]) lay |= (1 << i);
 -              else lay &= ~(1 << i);
 -      }
 -
 -      /* ensure always an active layer */
 -      if (active && (lay & *active) == 0) {
 -              for (i = 0; i < 20; i++) {
 -                      if (lay & (1 << i)) {
 -                              *active = 1 << i;
 -                              break;
 -                      }
 +      for (int i = 0; i < 16; i++) {
 +              if ((local_view_bits & (1 << i)) == 0) {
 +                      return (1 << i);
                }
        }
  
 -      return lay;
 +      return 0;
  }
  
  static bool view3d_localview_init(
 -        wmWindowManager *wm, wmWindow *win,
 -        Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx,
 +        const Depsgraph *depsgraph,
 +        wmWindowManager *wm,
 +        wmWindow *win,
 +        Main *bmain,
 +        ViewLayer *view_layer,
 +        ScrArea *sa,
 +        const int smooth_viewtx,
          ReportList *reports)
  {
        View3D *v3d = sa->spacedata.first;
        Base *base;
        float min[3], max[3], box[3], mid[3];
        float size = 0.0f;
 -      unsigned int locallay;
 +      unsigned int local_view_bit;
        bool ok = false;
  
        if (v3d->localvd) {
  
        INIT_MINMAX(min, max);
  
 -      locallay = free_localbit(bmain);
 +      local_view_bit = free_localbit(bmain);
  
 -      if (locallay == 0) {
 -              BKE_report(reports, RPT_ERROR, "No more than 8 local views");
 +      if (local_view_bit == 0) {
 +              /* TODO(dfelinto): We can kick one of the other 3D views out of local view
 +                 specially if it is not being used.  */
 +              BKE_report(reports, RPT_ERROR, "No more than 16 local views");
                ok = false;
        }
        else {
 -              if (scene->obedit) {
 -                      BKE_object_minmax(scene->obedit, min, max, false);
 -
 -                      ok = true;
 -
 -                      BASACT->lay |= locallay;
 -                      scene->obedit->lay = BASACT->lay;
 +              Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
 +              if (obedit) {
 +                      FOREACH_BASE_IN_EDIT_MODE_BEGIN(view_layer, v3d, base_iter) {
 +                              BKE_object_minmax(base_iter->object, min, max, false);
 +                              base_iter->local_view_bits |= local_view_bit;
 +                              ok = true;
 +                      } FOREACH_BASE_IN_EDIT_MODE_END;
                }
                else {
 -                      for (base = FIRSTBASE; base; base = base->next) {
 +                      for (base = FIRSTBASE(view_layer); base; base = base->next) {
                                if (TESTBASE(v3d, base)) {
                                        BKE_object_minmax(base->object, min, max, false);
 -                                      base->lay |= locallay;
 -                                      base->object->lay = base->lay;
 +                                      base->local_view_bits |= local_view_bit;
 +                                      /* Technically we should leave for Depsgraph to handle this.
 +                                         But it is harmless to do it here, and it seems to be necessary. */
 +                                      base->object->base_local_view_bits = base->local_view_bits;
                                        ok = true;
                                }
                        }
  
                mid_v3_v3v3(mid, min, max);
  
 -              copy_v3_v3(v3d->cursor, mid);
 -
                for (ar = sa->regionbase.first; ar; ar = ar->next) {
                        if (ar->regiontype == RGN_TYPE_WINDOW) {
                                RegionView3D *rv3d = ar->regiondata;
                                bool ok_dist = true;
  
 -                              /* new view values */
 +                              /* New view values. */
                                Object *camera_old = NULL;
                                float dist_new, ofs_new[3];
  
                                }
  
                                if (ok_dist) {
 -                                      dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
 +                                      dist_new = ED_view3d_radius_to_dist(v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
 +
                                        if (rv3d->persp == RV3D_PERSP) {
 -                                              /* don't zoom closer than the near clipping plane */
 +                                              /* Don't zoom closer than the near clipping plane. */
                                                dist_new = max_ff(dist_new, v3d->near * 1.5f);
                                        }
                                }
  
                                ED_view3d_smooth_view_ex(
 +                                      depsgraph,
                                        wm, win, sa, v3d, ar, smooth_viewtx,
                                            &(const V3D_SmoothParams) {
                                                .camera_old = camera_old,
                        }
                }
  
 -              v3d->lay = locallay;
 -      }
 -      else {
 -              /* clear flags */
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (base->lay & locallay) {
 -                              base->lay -= locallay;
 -                              if (base->lay == 0) base->lay = v3d->layact;
 -                              if (base->object != scene->obedit) base->flag |= SELECT;
 -                              base->object->lay = base->lay;
 -                      }
 -              }
 +              v3d->local_view_uuid = local_view_bit;
        }
  
 -      DAG_on_visible_update(bmain, false);
 -
 +      DEG_on_visible_update(bmain, false);
        return ok;
  }
  
 -static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, ScrArea *sa, const int smooth_viewtx)
 +static void restore_localviewdata(
 +        const Depsgraph *depsgraph,
 +        wmWindowManager *wm,
 +        wmWindow *win,
 +        Main *bmain,
 +        ScrArea *sa,
 +        const int smooth_viewtx)
  {
        const bool free = true;
        ARegion *ar;
        camera_old = v3d->camera;
        camera_new = v3d->localvd->camera;
  
 -      v3d->lay = v3d->localvd->lay;
 -      v3d->layact = v3d->localvd->layact;
 -      v3d->drawtype = v3d->localvd->drawtype;
 +      v3d->local_view_uuid = 0;
        v3d->camera = v3d->localvd->camera;
  
        if (free) {
                                rv3d->camzoom = rv3d->localvd->camzoom;
  
                                ED_view3d_smooth_view_ex(
 +                                      depsgraph,
                                        wm, win, sa,
                                        v3d, ar, smooth_viewtx,
                                        &(const V3D_SmoothParams) {
  }
  
  static bool view3d_localview_exit(
 -        wmWindowManager *wm, wmWindow *win,
 -        Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
 +        const Depsgraph *depsgraph,
 +        wmWindowManager *wm,
 +        wmWindow *win,
 +        Main *bmain,
 +        ViewLayer *view_layer,
 +        ScrArea *sa,
 +        const int smooth_viewtx)
  {
        View3D *v3d = sa->spacedata.first;
        struct Base *base;
 -      unsigned int locallay;
 +      unsigned int local_view_bit;
  
        if (v3d->localvd) {
  
 -              locallay = v3d->lay & 0xFF000000;
 -
 -              restore_localviewdata(wm, win, bmain, sa, smooth_viewtx);
 +              local_view_bit = v3d->local_view_uuid;
  
 -              /* for when in other window the layers have changed */
 -              if (v3d->scenelock) v3d->lay = scene->lay;
 +              restore_localviewdata(depsgraph, wm, win, bmain, sa, smooth_viewtx);
  
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (base->lay & locallay) {
 -                              base->lay -= locallay;
 -                              if (base->lay == 0) base->lay = v3d->layact;
 -                              if (base->object != scene->obedit) {
 -                                      base->flag |= SELECT;
 -                                      base->object->flag |= SELECT;
 +              Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
 +              for (base = FIRSTBASE(view_layer); base; base = base->next) {
 +                      if (base->local_view_bits & local_view_bit) {
 +                              base->local_view_bits &= ~local_view_bit;
 +                              if (base->object != obedit) {
 +                                      ED_object_base_select(base, BA_SELECT);
                                }
 -                              base->object->lay = base->lay;
                        }
                }
  
 -              DAG_on_visible_update(bmain, false);
 +              DEG_on_visible_update(bmain, false);
  
                return true;
        }
  
  static int localview_exec(bContext *C, wmOperator *op)
  {
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
        wmWindowManager *wm = CTX_wm_manager(C);
        wmWindow *win = CTX_wm_window(C);
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        ScrArea *sa = CTX_wm_area(C);
        View3D *v3d = CTX_wm_view3d(C);
        bool changed;
  
        if (v3d->localvd) {
 -              changed = view3d_localview_exit(wm, win, bmain, scene, sa, smooth_viewtx);
 +              changed = view3d_localview_exit(depsgraph, wm, win, bmain, view_layer, sa, smooth_viewtx);
        }
        else {
 -              changed = view3d_localview_init(wm, win, bmain, scene, sa, smooth_viewtx, op->reports);
 +              changed = view3d_localview_init(depsgraph, wm, win, bmain, view_layer, sa, smooth_viewtx, op->reports);
        }
  
        if (changed) {
 -              DAG_id_type_tag(bmain, ID_OB);
 +              DEG_id_type_tag(bmain, ID_OB);
                ED_area_tag_redraw(sa);
  
 -              /* unselected objects become selected when exiting */
 +              /* Unselected objects become selected when exiting. */
                if (v3d->localvd == NULL) {
 +                      DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
                        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
                }
 +              else {
 +                      DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
 +              }
  
                return OPERATOR_FINISHED;
        }
@@@ -1412,105 -1305,217 +1412,105 @@@ void VIEW3D_OT_localview(wmOperatorTyp
        ot->poll = ED_operator_view3d_active;
  }
  
 -/** \} */
 -
 -/* -------------------------------------------------------------------- */
 -/** \name Game Engine Operator
 - *
 - * Start the game engine (handles context switching).
 - * \{ */
 -
 -#ifdef WITH_GAMEENGINE
 -
 -static ListBase queue_back;
 -static void game_engine_save_state(bContext *C, wmWindow *win)
 +static int localview_remove_from_exec(bContext *C, wmOperator *op)
  {
 +      View3D *v3d = CTX_wm_view3d(C);
        Main *bmain = CTX_data_main(C);
 -      Object *obact = CTX_data_active_object(C);
 -
 -      glPushAttrib(GL_ALL_ATTRIB_BITS);
 +      Scene *scene = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      bool changed = false;
  
 -      if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
 -              GPU_paint_set_mipmap(bmain, 1);
 +      for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
 +              if (TESTBASE(v3d, base)) {
 +                      base->local_view_bits &= ~v3d->local_view_uuid;
 +                      ED_object_base_select(base, BA_DESELECT);
  
 -      queue_back = win->queue;
 +                      if (base == BASACT(view_layer)) {
 +                              view_layer->basact = NULL;
 +                      }
 +                      changed = true;
 +              }
 +      }
  
 -      BLI_listbase_clear(&win->queue);
 +      if (changed) {
 +              DEG_on_visible_update(bmain, false);
 +              DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
 +              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 +              WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 +              return OPERATOR_FINISHED;
 +      }
 +      else {
 +              BKE_report(op->reports, RPT_ERROR, "No object selected");
 +              return OPERATOR_CANCELLED;
 +      }
  }
  
 -static void game_engine_restore_state(bContext *C, wmWindow *win)
 +static bool localview_remove_from_poll(bContext *C)
  {
 -      Main *bmain = CTX_data_main(C);
 -      Object *obact = CTX_data_active_object(C);
 -
 -      if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
 -              GPU_paint_set_mipmap(bmain, 0);
 -
 -      /* check because closing win can set to NULL */
 -      if (win) {
 -              win->queue = queue_back;
 +      if (CTX_data_edit_object(C) != NULL) {
 +              return false;
        }
  
 -      GPU_state_init();
 -      GPU_set_tpage(NULL, 0, 0);
 -
 -      glPopAttrib();
 +      View3D *v3d = CTX_wm_view3d(C);
 +      return v3d && v3d->localvd;
  }
  
 -/* was space_set_commmandline_options in 2.4x */
 -static void game_set_commmandline_options(GameData *gm)
 +void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
  {
 -      SYS_SystemHandle syshandle;
 -      int test;
 -
 -      if ((syshandle = SYS_GetSystem())) {
 -              /* User defined settings */
 -              test = (U.gameflags & USER_DISABLE_MIPMAP);
 -              GPU_set_mipmap(G_MAIN, !test);
 -              SYS_WriteCommandLineInt(syshandle, "nomipmap", test);
 -
 -              /* File specific settings: */
 -              /* Only test the first one. These two are switched
 -               * simultaneously. */
 -              test = (gm->flag & GAME_SHOW_FRAMERATE);
 -              SYS_WriteCommandLineInt(syshandle, "show_framerate", test);
 -              SYS_WriteCommandLineInt(syshandle, "show_profile", test);
 -
 -              test = (gm->flag & GAME_SHOW_DEBUG_PROPS);
 -              SYS_WriteCommandLineInt(syshandle, "show_properties", test);
 -
 -              test = (gm->flag & GAME_SHOW_PHYSICS);
 -              SYS_WriteCommandLineInt(syshandle, "show_physics", test);
 -
 -              test = (gm->flag & GAME_ENABLE_ALL_FRAMES);
 -              SYS_WriteCommandLineInt(syshandle, "fixedtime", test);
 -
 -              test = (gm->flag & GAME_ENABLE_ANIMATION_RECORD);
 -              SYS_WriteCommandLineInt(syshandle, "animation_record", test);
 -
 -              test = (gm->flag & GAME_IGNORE_DEPRECATION_WARNINGS);
 -              SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", test);
 -
 -              test = (gm->matmode == GAME_MAT_MULTITEX);
 -              SYS_WriteCommandLineInt(syshandle, "blender_material", test);
 -              test = (gm->matmode == GAME_MAT_GLSL);
 -              SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", test);
 -              test = (gm->flag & GAME_DISPLAY_LISTS);
 -              SYS_WriteCommandLineInt(syshandle, "displaylists", test);
 -
 +      /* identifiers */
 +      ot->name = "Remove from Local View";
 +      ot->description = "Move selected objects out of local view";
 +      ot->idname = "VIEW3D_OT_localview_remove_from";
  
 -      }
 +      /* api callbacks */
 +      ot->exec = localview_remove_from_exec;
 +      ot->invoke = WM_operator_confirm;
 +      ot->poll = localview_remove_from_poll;
 +      ot->flag = OPTYPE_UNDO;
  }
  
 -#endif /* WITH_GAMEENGINE */
 -
 -static bool game_engine_poll(bContext *C)
 -{
 -      bScreen *screen;
 -      /* we need a context and area to launch BGE
 -       * it's a temporary solution to avoid crash at load time
 -       * if we try to auto run the BGE. Ideally we want the
 -       * context to be set as soon as we load the file. */
 -
 -      if (CTX_wm_window(C) == NULL) return 0;
 -      if ((screen = CTX_wm_screen(C)) == NULL) return 0;
 -
 -      if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)
 -              return 0;
 -
 -      if (!BKE_scene_uses_blender_game(screen->scene))
 -              return 0;
 +/** \} */
  
 -      return 1;
 -}
 +/* -------------------------------------------------------------------- */
 +/** \name View Layer Utilities
 + * \{ */
  
 -static int game_engine_exec(bContext *C, wmOperator *op)
 +int ED_view3d_view_layer_set(int lay, const bool *values, int *active)
  {
 -#ifdef WITH_GAMEENGINE
 -      Scene *startscene = CTX_data_scene(C);
 -      Main *bmain = CTX_data_main(C);
 -      ScrArea /* *sa, */ /* UNUSED */ *prevsa = CTX_wm_area(C);
 -      ARegion *ar, *prevar = CTX_wm_region(C);
 -      wmWindow *prevwin = CTX_wm_window(C);
 -      RegionView3D *rv3d;
 -      rcti cam_frame;
 -
 -      UNUSED_VARS(op);
 -
 -      /* bad context switch .. */
 -      if (!ED_view3d_context_activate(C))
 -              return OPERATOR_CANCELLED;
 -
 -      /* redraw to hide any menus/popups, we don't go back to
 -       * the window manager until after this operator exits */
 -      WM_redraw_windows(C);
 -
 -      BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_PRE);
 -
 -      rv3d = CTX_wm_region_view3d(C);
 -      /* sa = CTX_wm_area(C); */ /* UNUSED */
 -      ar = CTX_wm_region(C);
 -
 -      view3d_operator_needs_opengl(C);
 -
 -      game_set_commmandline_options(&startscene->gm);
 +      int i, tot = 0;
  
 -      if ((rv3d->persp == RV3D_CAMOB) &&
 -          (startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) &&
 -          (startscene->gm.stereoflag != STEREO_DOME))
 -      {
 -              /* Letterbox */
 -              rctf cam_framef;
 -              ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false);
 -              cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin;
 -              cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin;
 -              cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin;
 -              cam_frame.ymax = cam_framef.ymax + ar->winrct.ymin;
 -              BLI_rcti_isect(&ar->winrct, &cam_frame, &cam_frame);
 -      }
 -      else {
 -              cam_frame.xmin = ar->winrct.xmin;
 -              cam_frame.xmax = ar->winrct.xmax;
 -              cam_frame.ymin = ar->winrct.ymin;
 -              cam_frame.ymax = ar->winrct.ymax;
 -      }
 +      /* ensure we always have some layer selected */
 +      for (i = 0; i < 20; i++)
 +              if (values[i])
 +                      tot++;
  
 +      if (tot == 0)
 +              return lay;
  
 -      game_engine_save_state(C, prevwin);
 +      for (i = 0; i < 20; i++) {
  
 -      StartKetsjiShell(C, ar, &cam_frame, 1);
 +              if (active) {
 +                      /* if this value has just been switched on, make that layer active */
 +                      if (values[i] && (lay & (1 << i)) == 0) {
 +                              *active = (1 << i);
 +                      }
 +              }
  
 -      /* window wasnt closed while the BGE was running */
 -      if (BLI_findindex(&CTX_wm_manager(C)->windows, prevwin) == -1) {
 -              prevwin = NULL;
 -              CTX_wm_window_set(C, NULL);
 +              if (values[i]) lay |= (1 << i);
 +              else lay &= ~(1 << i);
        }
  
 -      ED_area_tag_redraw(CTX_wm_area(C));
 -
 -      if (prevwin) {
 -              /* restore context, in case it changed in the meantime, for
 -               * example by working in another window or closing it */
 -              CTX_wm_region_set(C, prevar);
 -              CTX_wm_window_set(C, prevwin);
 -              CTX_wm_area_set(C, prevsa);
 +      /* ensure always an active layer */
 +      if (active && (lay & *active) == 0) {
 +              for (i = 0; i < 20; i++) {
 +                      if (lay & (1 << i)) {
 +                              *active = 1 << i;
 +                              break;
 +                      }
 +              }
        }
  
 -      game_engine_restore_state(C, prevwin);
 -
 -      //XXX restore_all_scene_cfra(scene_cfra_store);
 -      BKE_scene_set_background(CTX_data_main(C), startscene);
 -      //XXX BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
 -
 -      BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
 -
 -      return OPERATOR_FINISHED;
 -#else
 -      UNUSED_VARS(C);
 -      BKE_report(op->reports, RPT_ERROR, "Game engine is disabled in this build");
 -      return OPERATOR_CANCELLED;
 -#endif
 -}
 -
 -void VIEW3D_OT_game_start(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Start Game Engine";
 -      ot->description = "Start game engine";
 -      ot->idname = "VIEW3D_OT_game_start";
 -
 -      /* api callbacks */
 -      ot->exec = game_engine_exec;
 -
 -      ot->poll = game_engine_poll;
 +      return lay;
  }
  
  /** \} */