Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Fri, 1 Jun 2018 15:26:36 +0000 (17:26 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Fri, 1 Jun 2018 15:26:36 +0000 (17:26 +0200)
 Conflicts:
source/blender/editors/io/io_collada.c
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_edit.c
source/blender/editors/render/render_internal.c
source/blender/makesrna/intern/rna_object_api.c
source/blenderplayer/bad_level_call_stubs/stubs.c

14 files changed:
1  2 
CMakeLists.txt
build_files/cmake/macros.cmake
build_files/cmake/platform/platform_win32.cmake
intern/cycles/blender/blender_mesh.cpp
source/blender/editors/include/ED_object.h
source/blender/editors/io/io_collada.c
source/blender/editors/object/object_bake_api.c
source/blender/editors/object/object_edit.c
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/util/ed_util.c
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/rna_object_api.c

diff --combined CMakeLists.txt
index 02aa3697d002a61916825e385e13e28b26321308,4543ca124bdf2922d6894d9e65c9ee9f013013e5..438201594564a7b993ffd122d766f976bc2d1902
@@@ -156,6 -156,7 +156,6 @@@ option_defaults_init
        _init_OPENCOLORIO
        _init_SDL
        _init_FFTW3
 -      _init_GAMEENGINE
        _init_OPENSUBDIV
  )
  
@@@ -225,10 -226,15 +225,10 @@@ 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})
  
 +option(WITH_CLAY_ENGINE    "Enable Clay engine" ON)
 +
  # Compositor
  option(WITH_COMPOSITOR         "Enable the tile based nodal compositor" ON)
  
@@@ -310,6 -316,7 +310,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)
@@@ -372,14 -379,10 +372,14 @@@ 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(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)
@@@ -460,16 -463,28 +460,16 @@@ endif(
  
  # OpenGL
  
 -option(WITH_GLEW_MX             "Support multiple GLEW contexts (experimental)"                                                                     OFF )
  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_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)
@@@ -495,10 -510,11 +495,10 @@@ if(APPLE
        set(WITH_CXX11 ON)
  elseif(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
        set(_c11_init ON)
 -      set(_cxx11_init ON)
  else()
        set(_c11_init OFF)
 -      set(_cxx11_init OFF)
  endif()
 +set(_cxx11_init ON)
  
  option(WITH_C11 "Build with C11 standard enabled, for development use only!" ${_c11_init})
  mark_as_advanced(WITH_C11)
@@@ -523,9 -539,7 +523,7 @@@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_C
  -fsanitize=enum \
  -fsanitize=float-cast-overflow \
  -fsanitize=float-divide-by-zero \
- -fsanitize=leak \
  -fsanitize=nonnull-attribute \
- -fsanitize=object-size \
  -fsanitize=returns-nonnull-attribute \
  -fsanitize=signed-integer-overflow \
  -fsanitize=undefined \
  -fno-sanitize=alignment \
  ")
  
+               if(NOT MSVC) # not all sanitizers are supported with clang-cl, these two however are very vocal about it
+                       set(_asan_defaults "${_asan_defaults} -fsanitize=leak -fsanitize=object-size" )
+               endif()
                set(COMPILER_ASAN_CFLAGS "${_asan_defaults}" CACHE STRING "C flags for address sanitizer")
                mark_as_advanced(COMPILER_ASAN_CFLAGS)
                set(COMPILER_ASAN_CXXFLAGS "${_asan_defaults}" CACHE STRING "C++ flags for address sanitizer")
  
                unset(_asan_defaults)
  
-               find_library(COMPILER_ASAN_LIBRARY asan ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
+               if(NOT MSVC)
+                       find_library(COMPILER_ASAN_LIBRARY asan ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
+               else()
+                       find_library( COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
+                               PATHS   [HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
+                                               [HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
+                                               )
+               endif() 
                mark_as_advanced(COMPILER_ASAN_LIBRARY)
        endif()
  endif()
  
@@@ -601,17 -624,15 +608,17 @@@ 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")
 +if(NOT WITH_CXX11)
 +      if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
 +              message(FATAL_ERROR "WITH_AUDASPACE requires WITH_CXX11")
 +      endif()
  endif()
  
  if(NOT WITH_AUDASPACE)
        if(WITH_JACK)
                message(FATAL_ERROR "WITH_JACK requires WITH_AUDASPACE")
        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()
@@@ -655,10 -683,15 +662,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()
@@@ -727,9 -760,30 +734,9 @@@ TEST_SHARED_PTR_SUPPORT(
  TEST_UNORDERED_MAP_SUPPORT()
  
  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()
  
@@@ -816,8 -870,12 +823,12 @@@ if(WITH_COMPILER_ASAN
  
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMPILER_ASAN_CXXFLAGS}")
        set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMPILER_ASAN_CXXFLAGS}")
-       set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY}")
+       if(MSVC)
+               set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6") 
+       endif()
+       set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
+       set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
+       set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}") 
  endif()
  
  #-----------------------------------------------------------------------------
@@@ -991,11 -1049,19 +1002,11 @@@ 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)
 -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)
@@@ -1145,6 -1214,10 +1156,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
@@@ -1509,15 -1589,10 +1520,15 @@@ if(WITH_PYTHON
                )
        endif()
  
 -      if(WIN32 OR APPLE)
 +      if(WIN32)
                # pass, we have this in an archive to extract
 -      elseif(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY)
 -              find_python_package(numpy)
 +      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)
@@@ -1607,7 -1682,7 +1618,7 @@@ if(WITH_GTESTS
        include(GTestTesting)
  endif()
  
 -if(WITH_BLENDER OR WITH_PLAYER)
 +if(WITH_BLENDER)
        add_subdirectory(intern)
        add_subdirectory(extern)
  
@@@ -1632,6 -1707,13 +1643,6 @@@ if(WITH_BLENDER
  endif()
  
  
 -#-----------------------------------------------------------------------------
 -# Blender Player
 -if(WITH_PLAYER)
 -      add_subdirectory(source/blenderplayer)
 -endif()
 -
 -
  #-----------------------------------------------------------------------------
  # Testing
  add_subdirectory(tests)
@@@ -1646,6 -1728,9 +1657,6 @@@ include(build_files/cmake/packaging.cma
  if(WITH_BLENDER)
        openmp_delayload(blender)
  endif()
 -if(WITH_PLAYER)
 -      openmp_delayload(blenderplayer)
 -endif()
  
  #-----------------------------------------------------------------------------
  # Print Final Configuration
@@@ -1679,6 -1764,8 +1690,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 a38a6805274d67589849a7057971fbeec7a6a908,11fc3e110c13d5af225a7f40b0858f19d7698de6..6157730af8edba9c0e2fa9ecf5cf446d8ac26b7c
@@@ -326,7 -326,7 +326,7 @@@ function(SETUP_LIBDIRS
                        link_directories(${JACK_LIBPATH})
                endif()
                if(WITH_CODEC_SNDFILE)
 -                      link_directories(${SNDFILE_LIBPATH})
 +                      link_directories(${LIBSNDFILE_LIBPATH})
                endif()
                if(WITH_FFTW3)
                        link_directories(${FFTW3_LIBPATH})
        endif()
  endfunction()
  
+ macro(setup_platform_linker_flags)
+       set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
+       set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+ endmacro()
  function(setup_liblinks
        target
        )
                target_link_libraries(${target} ${JACK_LIBRARIES})
        endif()
        if(WITH_CODEC_SNDFILE)
 -              target_link_libraries(${target} ${SNDFILE_LIBRARIES})
 +              target_link_libraries(${target} ${LIBSNDFILE_LIBRARIES})
        endif()
        if(WITH_SDL AND NOT WITH_SDL_DYNLOAD)
                target_link_libraries(${target} ${SDL_LIBRARY})
@@@ -555,12 -560,6 +560,12 @@@ function(SETUP_BLENDER_SORTED_LIBS
                endif()
        endif()
  
 +      if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
 +              list(APPEND BLENDER_LINK_LIBS
 +                      audaspace
 +                      audaspace-py)
 +      endif()
 +
        # Sort libraries
        set(BLENDER_SORTED_LIBS
                bf_windowmanager
                bf_editor_space_outliner
                bf_editor_space_script
                bf_editor_space_sequencer
 +              bf_editor_space_statusbar
                bf_editor_space_text
                bf_editor_space_time
 +              bf_editor_space_topbar
                bf_editor_space_userpref
                bf_editor_space_view3d
                bf_editor_space_clip
                bf_editor_curve
                bf_editor_gpencil
                bf_editor_interface
 +              bf_editor_manipulator_library
                bf_editor_mesh
                bf_editor_metaball
                bf_editor_object
                bf_editor_armature
                bf_editor_physics
                bf_editor_render
 +              bf_editor_scene
                bf_editor_screen
                bf_editor_sculpt_paint
                bf_editor_sound
                bf_python
                bf_python_ext
                bf_python_mathutils
 +              bf_python_gawain
                bf_python_bmesh
                bf_freestyle
                bf_ikplugin
                bf_alembic
                bf_bmesh
                bf_gpu
 +              bf_draw
                bf_blenloader
                bf_blenkernel
                bf_physics
                bf_nodes
                bf_rna
 +              bf_editor_manipulator_library  # rna -> manipulator bad-level calls
 +              bf_python
                bf_imbuf
                bf_blenlib
                bf_depsgraph
                bf_blenfont
                bf_blentranslation
                bf_intern_audaspace
 +              audaspace
 +              audaspace-py
                bf_intern_mikktspace
                bf_intern_dualcon
                bf_intern_cycles
                cycles_util
                cycles_subd
                bf_intern_opencolorio
 +              bf_intern_gawain
                bf_intern_eigen
                extern_rangetree
                extern_wcwidth
                list_insert_after(BLENDER_SORTED_LIBS "ge_logic_ngnetwork" "extern_bullet")
        endif()
  
 -      if(WITH_GAMEENGINE_DECKLINK)
 -              list(APPEND BLENDER_SORTED_LIBS bf_intern_decklink)
 -      endif()
 -
        if(WIN32)
                list(APPEND BLENDER_SORTED_LIBS bf_intern_gpudirect)
        endif()
@@@ -1523,7 -1515,6 +1528,7 @@@ function(find_python_packag
                  NAMES
                    ${package}
                  HINTS
 +                  "${PYTHON_LIBPATH}/"
                    "${PYTHON_LIBPATH}/python${PYTHON_VERSION}/"
                    "${PYTHON_LIBPATH}/python${_PY_VER_MAJOR}/"
                  PATH_SUFFIXES
index c14f6013394152cb5382cb3658f2b04033b2f6f0,6e049c0048f737b6b52c0cedbe3ccaaadddc92c0..f55178b89e205d23a825995a61f34579179ea2e0
@@@ -149,7 -149,7 +149,7 @@@ set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C
  set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
  set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
  
- set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ")
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO ")
  set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib ")
  
  # Ignore meaningless for us linker warnings.
@@@ -162,7 -162,7 +162,7 @@@ else(
        set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}")
  endif()
  
- set(PLATFORM_LINKFLAGS_DEBUG "/IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
+ set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib")
  
  if(NOT DEFINED LIBDIR)
  
@@@ -550,21 -550,22 +550,21 @@@ set(WINTAB_INC ${LIBDIR}/wintab/include
  if(WITH_OPENAL)
        set(OPENAL ${LIBDIR}/openal)
        set(OPENALDIR ${LIBDIR}/openal)
 -      set(OPENAL_INCLUDE_DIR ${OPENAL}/include)
 +      set(OPENAL_INCLUDE_DIR ${OPENAL}/include/AL)
        set(OPENAL_LIBPATH ${OPENAL}/lib)
        if(MSVC)
                set(OPENAL_LIBRARY ${OPENAL_LIBPATH}/openal32.lib)
        else()
                set(OPENAL_LIBRARY ${OPENAL_LIBPATH}/wrap_oal.lib)
        endif()
 -      
 +
  endif()
  
  if(WITH_CODEC_SNDFILE)
 -      set(SNDFILE ${LIBDIR}/sndfile)
 -      set(SNDFILE_INCLUDE_DIRS ${SNDFILE}/include)
 -      set(SNDFILE_LIBPATH ${SNDFILE}/lib) # TODO, deprecate
 -      set(SNDFILE_LIBRARIES ${SNDFILE_LIBPATH}/libsndfile-1.lib)
 -      
 +      set(LIBSNDFILE ${LIBDIR}/sndfile)
 +      set(LIBSNDFILE_INCLUDE_DIRS ${LIBSNDFILE}/include)
 +      set(LIBSNDFILE_LIBPATH ${LIBSNDFILE}/lib) # TODO, deprecate
 +      set(LIBSNDFILE_LIBRARIES ${LIBSNDFILE_LIBPATH}/libsndfile-1.lib)
  endif()
  
  if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD)
index 03d24c04e2ae7b6f50b7c1d916d20412ec7957c5,76d17bc1ae6c7a5c393d1799587e957426dc928e..6fe650f369941e3f05bea3e3dcf1a889fc7c183e
@@@ -561,7 -561,7 +561,7 @@@ static void attr_create_subd_uv_map(Sce
                int i = 0;
  
                for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
 -                      bool active_render = b_mesh.uv_textures[i].active_render();
 +                      bool active_render = l->active_render();
                        AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
                        ustring uv_name = ustring(l->name().c_str());
                        AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT
@@@ -1069,9 -1069,7 +1069,9 @@@ static void sync_mesh_fluid_motion(BL::
        }
  }
  
 -Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
 +Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
 +                             BL::Object& b_ob,
 +                             BL::Object& b_ob_instance,
                               bool object_updated,
                               bool hide_tris)
  {
  
        /* test if we can instance or if the object is modified */
        BL::ID b_ob_data = b_ob.data();
 -      BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
 -      BL::Material material_override = render_layer.material_override;
 +      BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data;
 +      BL::Material material_override = view_layer.material_override;
  
        /* find shader indices */
        vector<Shader*> used_shaders;
  
        /* test if we need to sync */
        int requested_geometry_flags = Mesh::GEOMETRY_NONE;
 -      if(render_layer.use_surfaces) {
 +      if(view_layer.use_surfaces) {
                requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
        }
 -      if(render_layer.use_hair) {
 +      if(view_layer.use_hair) {
                requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
        }
        Mesh *mesh;
                 * freed data from the blender side.
                 */
                if(preview && b_ob.type() != BL::Object::type_MESH)
-                       b_ob.update_from_editmode();
+                       b_ob.update_from_editmode(b_data);
  
                bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
  
  
                BL::Mesh b_mesh = object_to_mesh(b_data,
                                                 b_ob,
 -                                               b_scene,
 -                                               true,
 -                                               !preview,
 +                                               b_depsgraph,
 +                                               false,
                                                 need_undeformed,
                                                 mesh->subdivision_type);
  
                if(b_mesh) {
 -                      if(render_layer.use_surfaces && !hide_tris) {
 +                      if(view_layer.use_surfaces && !hide_tris) {
                                if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
                                        create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders,
                                                         dicing_rate, max_subdivisions);
                                create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
                        }
  
 -                      if(render_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
 +                      if(view_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
                                sync_curves(mesh, b_mesh, b_ob, false);
  
                        if(can_free_caches) {
        return mesh;
  }
  
 -void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
 +void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph,
 +                                   BL::Object& b_ob,
                                     Object *object,
                                     float motion_time)
  {
                /* get derived mesh */
                b_mesh = object_to_mesh(b_data,
                                        b_ob,
 -                                      b_scene,
 -                                      true,
 -                                      !preview,
 +                                      b_depsgraph,
 +                                      false,
                                        false,
                                        Mesh::SUBDIVISION_NONE);
        }
index b3a2f6f7ca657dd033f93705a32cc018ae38668d,75b98caaedb13c9f3f99e9bdd8a135dbf0361012..e3458bcb278846ff5ea09585341ce861d3ecef2d
@@@ -35,7 -35,6 +35,7 @@@
  extern "C" {
  #endif
  
 +struct bFaceMap;
  struct Base;
  struct EnumPropertyItem;
  struct ID;
@@@ -44,7 -43,6 +44,7 @@@ struct ModifierData
  struct Object;
  struct ReportList;
  struct Scene;
 +struct ViewLayer;
  struct bConstraint;
  struct bContext;
  struct bPoseChannel;
@@@ -52,12 -50,9 +52,12 @@@ struct wmKeyConfig
  struct wmKeyMap;
  struct wmOperator;
  struct wmOperatorType;
 +struct wmWindow;
 +struct wmWindowManager;
  struct PointerRNA;
  struct PropertyRNA;
  struct EnumPropertyItem;
 +struct Depsgraph;
  
  #include "DNA_object_enums.h"
  
@@@ -87,21 -82,16 +87,21 @@@ typedef enum eParentType 
        PAR_VERTEX_TRI,
  } eParentType;
  
 +typedef enum eObjectSelect_Mode {
 +      BA_DESELECT = 0,
 +      BA_SELECT = 1,
 +      BA_INVERT = 2,
 +} eObjectSelect_Mode;
 +
  #ifdef __RNA_TYPES_H__
  extern struct EnumPropertyItem prop_clear_parent_types[];
  extern struct EnumPropertyItem prop_make_parent_types[];
  #endif
  
 -bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
 +bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *ob,
                            struct Object *par, int partype, const bool xmirror, const bool keep_transform,
                            const int vert_par[3]);
  void ED_object_parent_clear(struct Object *ob, const int type);
 -struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
  
  void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
  void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@@ -109,12 -99,15 +109,12 @@@ void ED_keymap_proportional_maskmode(st
  void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap,
                                       const bool do_connected);
  
 -/* send your own notifier for select! */
 -void ED_base_object_select(struct Base *base, short mode);
 -/* includes notifier */
 -void ED_base_object_activate(struct bContext *C, struct Base *base);
 -
 -void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base);
 +void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode);
 +void ED_object_base_activate(struct bContext *C, struct Base *base);
 +void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
  
  /* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
 -struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
 +struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, int dupflag);
  
  void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
  
@@@ -123,25 -116,21 +123,25 @@@ enum 
        EM_FREEDATA         = (1 << 0),
        EM_WAITCURSOR       = (1 << 1),
        EM_IGNORE_LAYER     = (1 << 3),
 +      EM_NO_CONTEXT       = (1 << 4),
  };
 -bool ED_object_editmode_exit_ex(struct Scene *scene, struct Object *obedit, int flag);
 +bool ED_object_editmode_exit_ex(
 +        struct Scene *scene, struct Object *obedit, int flag);
  bool ED_object_editmode_exit(struct bContext *C, int flag);
- bool ED_object_editmode_enter_ex(struct Scene *scene, struct Object *ob, int flag);
 +
++bool ED_object_editmode_enter_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int flag);
  bool ED_object_editmode_enter(struct bContext *C, int flag);
- bool ED_object_editmode_load(struct Object *obedit);
+ bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit);
  
  bool ED_object_editmode_calc_active_center(struct Object *obedit, const bool select_only, float r_center[3]);
  
  
  void ED_object_vpaintmode_enter_ex(
 -        struct wmWindowManager *wm,
 +        struct Depsgraph *depsgraph, struct wmWindowManager *wm,
          struct Scene *scene, struct Object *ob);
  void ED_object_vpaintmode_enter(struct bContext *C);
  void ED_object_wpaintmode_enter_ex(
 -        struct wmWindowManager *wm,
 +        struct Depsgraph *depsgraph, struct wmWindowManager *wm,
          struct Scene *scene, struct Object *ob);
  void ED_object_wpaintmode_enter(struct bContext *C);
  
@@@ -151,12 -140,10 +151,12 @@@ void ED_object_wpaintmode_exit_ex(struc
  void ED_object_wpaintmode_exit(struct bContext *C);
  
  void ED_object_sculptmode_enter_ex(
 +        struct Depsgraph *depsgraph,
          struct Scene *scene, struct Object *ob,
          struct ReportList *reports);
  void ED_object_sculptmode_enter(struct bContext *C, struct ReportList *reports);
  void ED_object_sculptmode_exit_ex(
 +        struct Depsgraph *depsgraph,
          struct Scene *scene, struct Object *ob);
  void ED_object_sculptmode_exit(struct bContext *C);
  
@@@ -212,21 -199,6 +212,21 @@@ bool ED_object_mode_compat_set(struct b
  void ED_object_mode_toggle(struct bContext *C, eObjectMode mode);
  void ED_object_mode_set(struct bContext *C, eObjectMode mode);
  
 +bool ED_object_mode_generic_enter(
 +        struct bContext *C,
 +        eObjectMode object_mode);
 +void ED_object_mode_generic_exit(
 +        struct Main *bmain,
 +        struct Depsgraph *depsgraph,
 +        struct Scene *scene, struct Object *ob);
 +bool ED_object_mode_generic_has_data(
 +        struct Depsgraph *depsgraph,
 +        struct Object *ob);
 +
 +bool ED_object_mode_generic_exists(
 +        struct wmWindowManager *wm, struct Object *ob,
 +        eObjectMode object_mode);
 +
  /* object_modifier.c */
  enum {
        MODIFIER_APPLY_DATA = 1,
@@@ -243,10 -215,9 +243,10 @@@ int ED_object_modifier_move_down(struc
  int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
  int ED_object_modifier_convert(
          struct ReportList *reports, struct Main *bmain, struct Scene *scene,
 -        struct Object *ob, struct ModifierData *md);
 -int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
 -                             struct Object *ob, struct ModifierData *md, int mode);
 +        struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
 +int ED_object_modifier_apply(
 +        struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene,
 +        struct Object *ob, struct ModifierData *md, int mode);
  int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
  
  bool ED_object_iter_other(
@@@ -269,15 -240,8 +269,15 @@@ const struct EnumPropertyItem *ED_objec
  void ED_object_check_force_modifiers(
          struct Main *bmain, struct Scene *scene, struct Object *object);
  
 +/* object_facemap_ops.c */
 +void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
 +void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
 +
  #ifdef __cplusplus
  }
  #endif
  
 +/* Don't allow switching object-modes when selecting objects. */
 +#define USE_OBJECT_MODE_STRICT
 +
  #endif /* __ED_OBJECT_H__ */
index a3cbdb57fed89d605e7b25609b0875b6923d2f18,7e69aa62896b29a49b45a8524e252b84f6102c57..7fe252309dea2a172a22fe0bbc7111abe302a623
@@@ -28,7 -28,7 +28,7 @@@
   *  \ingroup collada
   */
  #ifdef WITH_COLLADA
 -#include "DNA_scene_types.h"
 +#include "DNA_space_types.h"
  
  #include "BLT_translation.h"
  
  #include "BLI_utildefines.h"
  
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_global.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_object.h"
  
 +#include "DEG_depsgraph.h"
 +
  #include "ED_screen.h"
  #include "ED_object.h"
  
@@@ -94,7 -93,7 +94,7 @@@ static int wm_collada_export_exec(bCont
        int sample_animations;
        int sampling_rate;
  
 -      int export_texture_type;
 +      int include_material_textures;
        int use_texture_copies;
        int active_uv_only;
  
  
        deform_bones_only        = RNA_boolean_get(op->ptr, "deform_bones_only");
  
 -      export_texture_type      = RNA_enum_get(op->ptr, "export_texture_type_selection");
 +      include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
        use_texture_copies       = RNA_boolean_get(op->ptr, "use_texture_copies");
        active_uv_only           = RNA_boolean_get(op->ptr, "active_uv_only");
  
        limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
        keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
  
+       Main *bmain = CTX_data_main(C);
        /* get editmode results */
-       ED_object_editmode_load(CTX_data_edit_object(C));
+       ED_object_editmode_load(bmain, CTX_data_edit_object(C));
  
 -      EvaluationContext *eval_ctx = bmain->eval_ctx;
        Scene *scene = CTX_data_scene(C);
 +
        ExportSettings export_settings;
  
        export_settings.filepath = filepath;
        export_settings.sampling_rate = sampling_rate;
  
        export_settings.active_uv_only = active_uv_only != 0;
 -      export_settings.export_texture_type = export_texture_type;
 +      export_settings.include_material_textures = include_material_textures != 0;
        export_settings.use_texture_copies = use_texture_copies != 0;
  
        export_settings.triangulate = triangulate != 0;
        if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
        if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
  
 -
 -      export_count = collada_export(eval_ctx,
 +      export_count = collada_export(CTX_data_depsgraph(C),
                scene,
                &export_settings
        );
@@@ -273,7 -275,7 +275,7 @@@ static void uiCollada_exportSettings(ui
        uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
  
        row = uiLayoutRow(box, false);
 -      uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE);
 +      uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE);
  
        row = uiLayoutRow(box, false);
        uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
@@@ -350,9 -352,15 +352,9 @@@ void WM_OT_collada_export(wmOperatorTyp
        };
  
        static const EnumPropertyItem prop_bc_export_transformation_type[] = {
 -              { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
 -              { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
 -              { 0, NULL, 0, NULL, NULL }
 -      };
 -
 -      static const EnumPropertyItem prop_bc_export_texture_type[] = {
 -              { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" },
 -              { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" },
 -              { 0, NULL, 0, NULL, NULL }
 +              {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
 +              {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
 +              {0, NULL, 0, NULL, NULL}
        };
  
        ot->name = "Export COLLADA";
        RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX,
                "Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX);
  
 +
        RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
                        "Export only the selected UV Map");
  
 +      RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures",
 +                      "Export textures assigned to the object Materials");
 +
        RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
                        "Copy textures to same folder where the .dae file is exported");
  
        RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
                        "Sort exported data by Object name");
  
 -
        RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
 -              "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
 +                  "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
  
        RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
 -              "Transform", "Transformation type for translation, scale and rotation");
 -
 -
 -      RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
 -              "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
 -
 -      RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0,
 -              "Texture Type", "Type for exported Textures (UV or MAT)");
 -
 +                   "Transform", "Transformation type for translation, scale and rotation");
  
        RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
                        "Compatibility mode for SL, OpenSim and other compatible online worlds");
@@@ -486,7 -499,6 +488,7 @@@ static int wm_collada_import_exec(bCont
        import_settings.keep_bind_info = keep_bind_info != 0;
  
        if (collada_import(C, &import_settings)) {
 +              DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_BASE_FLAGS_UPDATE);
                return OPERATOR_FINISHED;
        }
        else {
index 9af8169ae4192ac3e58af69d595d88bac106a902,d24fc96b007d38ad427f766cb05059a50d292d29..6dd6a76f129fc6950d6d49753678d20aef2373ff
  #include "BKE_report.h"
  #include "BKE_modifier.h"
  #include "BKE_mesh.h"
 +#include "BKE_scene.h"
  #include "BKE_screen.h"
 -#include "BKE_depsgraph.h"
 +
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
  
  #include "RE_engine.h"
  #include "RE_pipeline.h"
@@@ -87,7 -84,6 +87,7 @@@ typedef struct BakeAPIRender 
        Object *ob;
        Main *main;
        Scene *scene;
 +      ViewLayer *view_layer;
        ReportList *reports;
        ListBase selected_objects;
  
@@@ -276,7 -272,7 +276,7 @@@ static void refresh_images(BakeImages *
                Image *ima = bake_images->data[i].image;
                if (ima->ok == IMA_OK_LOADED) {
                        GPU_free_image(ima);
 -                      DAG_id_tag_update(&ima->id, 0);         
 +                      DEG_id_tag_update(&ima->id, 0);         
                }
        }
  }
@@@ -623,11 -619,11 +623,11 @@@ static size_t initialize_internal_image
  }
  
  /* create new mesh with edit mode changes and modifiers applied */
 -static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
 +static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
  {
-       ED_object_editmode_load(ob);
+       ED_object_editmode_load(bmain, ob);
  
 -      Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
 +      Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, 1, 0, 0);
        if (me->flag & ME_AUTOSMOOTH) {
                BKE_mesh_split_faces(me, true);
        }
  }
  
  static int bake(
 -        Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
 +        Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob_low, ListBase *selected_objects,
 +        ReportList *reports,
          const eScenePassType pass_type, const int pass_filter, const int margin,
          const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
          const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
          const char *custom_cage, const char *filepath, const int width, const int height,
          const char *identifier, ScrArea *sa, const char *uv_layer)
  {
 +      Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
 +
        int op_result = OPERATOR_CANCELLED;
        bool ok = false;
  
                }
        }
  
 +      /* Make sure depsgraph is up to date. */
 +      DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
 +      BKE_scene_graph_update_tagged(depsgraph, bmain);
 +
        /* get the mesh as it arrives in the renderer */
 -      me_low = bake_mesh_new_from_object(bmain, scene, ob_low);
 +      me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low);
  
        /* populate the pixel array with the face data */
        if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
  
                /* prepare cage mesh */
                if (ob_cage) {
 -                      me_cage = bake_mesh_new_from_object(bmain, scene, ob_cage);
 +                      me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage);
                        if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
                                BKE_report(reports, RPT_ERROR,
                                           "Invalid cage object, the cage mesh must have the same number "
                        ob_low->modifiers = modifiers_tmp;
  
                        /* get the cage mesh as it arrives in the renderer */
 -                      me_cage = bake_mesh_new_from_object(bmain, scene, ob_low);
 +                      me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low);
                        RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
                }
  
                        tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
                        tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
  
 -                      highpoly[i].me = bake_mesh_new_from_object(bmain, scene, highpoly[i].ob);
 +                      highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob);
                        highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
  
                        /* lowpoly to highpoly transformation matrix */
  
                /* the baking itself */
                for (i = 0; i < tot_highpoly; i++) {
 -                      ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high,
 +                      ok = RE_bake_engine(re, depsgraph, highpoly[i].ob, i, pixel_array_high,
                                            num_pixels, depth, pass_type, pass_filter, result);
                        if (!ok) {
                                BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
@@@ -920,7 -909,7 +920,7 @@@ cage_cleanup
                ob_low->restrictflag &= ~OB_RESTRICT_RENDER;
  
                if (RE_bake_has_engine(re)) {
 -                      ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
 +                      ok = RE_bake_engine(re, depsgraph, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
                }
                else {
                        BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
                                                md->mode &= ~eModifierMode_Render;
                                        }
  
 -                                      me_nores = bake_mesh_new_from_object(bmain, scene, ob_low);
 +                                      me_nores = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low);
                                        RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
  
                                        RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
@@@ -1120,8 -1109,6 +1120,8 @@@ cleanup
        if (me_cage)
                BKE_libblock_free(bmain, me_cage);
  
 +      DEG_graph_free(depsgraph);
 +
        return op_result;
  }
  
@@@ -1132,7 -1119,6 +1132,7 @@@ static void bake_init_api_data(wmOperat
  
        bkr->ob = CTX_data_active_object(C);
        bkr->main = CTX_data_main(C);
 +      bkr->view_layer = CTX_data_view_layer(C);
        bkr->scene = CTX_data_scene(C);
        bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
  
@@@ -1216,7 -1202,7 +1216,7 @@@ static int bake_exec(bContext *C, wmOpe
  
        if (bkr.is_selected_to_active) {
                result = bake(
 -                      bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
 +                      bkr.render, bkr.main, bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports,
                        bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
                        bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
                        bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
                for (link = bkr.selected_objects.first; link; link = link->next) {
                        Object *ob_iter = link->ptr.data;
                        result = bake(
 -                              bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
 +                              bkr.render, bkr.main, bkr.scene, bkr.view_layer, ob_iter, NULL, bkr.reports,
                                bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
                                is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
                                bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@@ -1274,7 -1260,7 +1274,7 @@@ static void bake_startjob(void *bkv, sh
  
        if (bkr->is_selected_to_active) {
                bkr->result = bake(
 -                      bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
 +                      bkr->render, bkr->main, bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports,
                        bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
                        bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
                        bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
                for (link = bkr->selected_objects.first; link; link = link->next) {
                        Object *ob_iter = link->ptr.data;
                        bkr->result = bake(
 -                              bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
 +                              bkr->render, bkr->main, bkr->scene, bkr->view_layer, ob_iter, NULL, bkr->reports,
                                bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
                                is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
                                bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
index b27e0c9666067c8934aa70033abf196c4bf448ca,d0429fc2bcffaa0d71510037334847502d1d4302..5c7c56f9b182dc4210e7db1c16d517b06a3e33c5
@@@ -51,6 -51,7 +51,6 @@@
  #include "DNA_group_types.h"
  #include "DNA_material_types.h"
  #include "DNA_meta_types.h"
 -#include "DNA_property_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_object_types.h"
  #include "DNA_object_force_types.h"
  #include "DNA_vfont_types.h"
  #include "DNA_mesh_types.h"
  #include "DNA_lattice_types.h"
 +#include "DNA_workspace_types.h"
  
  #include "IMB_imbuf_types.h"
  
  #include "BKE_anim.h"
 +#include "BKE_collection.h"
  #include "BKE_constraint.h"
  #include "BKE_context.h"
  #include "BKE_curve.h"
  #include "BKE_effect.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_global.h"
  #include "BKE_image.h"
  #include "BKE_lattice.h"
  #include "BKE_mball.h"
  #include "BKE_mesh.h"
  #include "BKE_object.h"
 +#include "BKE_paint.h"
  #include "BKE_pointcache.h"
 -#include "BKE_property.h"
 -#include "BKE_sca.h"
  #include "BKE_softbody.h"
  #include "BKE_modifier.h"
  #include "BKE_editlattice.h"
  #include "BKE_editmesh.h"
  #include "BKE_report.h"
 -#include "BKE_undo_system.h"
 +#include "BKE_workspace.h"
 +#include "BKE_layer.h"
 +
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
  
  #include "ED_armature.h"
  #include "ED_curve.h"
@@@ -96,7 -93,6 +96,7 @@@
  #include "ED_mball.h"
  #include "ED_lattice.h"
  #include "ED_object.h"
 +#include "ED_outliner.h"
  #include "ED_screen.h"
  #include "ED_undo.h"
  #include "ED_image.h"
  /* for menu/popup icons etc etc*/
  
  #include "UI_interface.h"
 +#include "UI_resources.h"
 +
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
 +#include "WM_toolsystem.h"
  
  #include "object_intern.h"  // own include
  
 +/* prototypes */
 +typedef struct MoveToCollectionData MoveToCollectionData;
 +static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu);
 +
  /* ************* XXX **************** */
  static void error(const char *UNUSED(arg)) {}
  static void waitcursor(int UNUSED(val)) {}
@@@ -147,15 -135,201 +147,15 @@@ Object *ED_object_active_context(bConte
  }
  
  
 -/* ********* clear/set restrict view *********/
 -static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
 -{
 -      Main *bmain = CTX_data_main(C);
 -      ScrArea *sa = CTX_wm_area(C);
 -      View3D *v3d = sa->spacedata.first;
 -      Scene *scene = CTX_data_scene(C);
 -      Base *base;
 -      bool changed = false;
 -      const bool select = RNA_boolean_get(op->ptr, "select");
 -      
 -      /* XXX need a context loop to handle such cases */
 -      for (base = FIRSTBASE; base; base = base->next) {
 -              if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
 -                      if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
 -                              SET_FLAG_FROM_TEST(base->flag, select, SELECT);
 -                      }
 -                      base->object->flag = base->flag;
 -                      base->object->restrictflag &= ~OB_RESTRICT_VIEW; 
 -                      changed = true;
 -              }
 -      }
 -      if (changed) {
 -              DAG_id_type_tag(bmain, ID_OB);
 -              DAG_relations_tag_update(bmain);
 -              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 -      }
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
 -{
 -      
 -      /* identifiers */
 -      ot->name = "Clear Restrict View";
 -      ot->description = "Reveal the object by setting the hide flag";
 -      ot->idname = "OBJECT_OT_hide_view_clear";
 -      
 -      /* api callbacks */
 -      ot->exec = object_hide_view_clear_exec;
 -      ot->poll = ED_operator_view3d_active;
 -      
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -
 -      RNA_def_boolean(ot->srna, "select", true, "Select", "");
 -}
 -
 -static int object_hide_view_set_exec(bContext *C, wmOperator *op)
 -{
 -      Main *bmain = CTX_data_main(C);
 -      Scene *scene = CTX_data_scene(C);
 -      bool changed = false;
 -      const bool unselected = RNA_boolean_get(op->ptr, "unselected");
 -      
 -      CTX_DATA_BEGIN(C, Base *, base, visible_bases)
 -      {
 -              if (!unselected) {
 -                      if (base->flag & SELECT) {
 -                              base->flag &= ~SELECT;
 -                              base->object->flag = base->flag;
 -                              base->object->restrictflag |= OB_RESTRICT_VIEW;
 -                              changed = true;
 -                              if (base == BASACT) {
 -                                      ED_base_object_activate(C, NULL);
 -                              }
 -                      }
 -              }
 -              else {
 -                      if (!(base->flag & SELECT)) {
 -                              base->object->restrictflag |= OB_RESTRICT_VIEW;
 -                              changed = true;
 -                              if (base == BASACT) {
 -                                      ED_base_object_activate(C, NULL);
 -                              }
 -                      }
 -              }
 -      }
 -      CTX_DATA_END;
 -
 -      if (changed) {
 -              DAG_id_type_tag(bmain, ID_OB);
 -              DAG_relations_tag_update(bmain);
 -              
 -              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 -              
 -      }
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void OBJECT_OT_hide_view_set(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Set Restrict View";
 -      ot->description = "Hide the object by setting the hide flag";
 -      ot->idname = "OBJECT_OT_hide_view_set";
 -      
 -      /* api callbacks */
 -      ot->exec = object_hide_view_set_exec;
 -      ot->poll = ED_operator_view3d_active;
 -      
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -      
 -      RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
 -      
 -}
 -
 -/* 99% same as above except no need for scene refreshing (TODO, update render preview) */
 -static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
 -{
 -      bool changed = false;
 -
 -      /* XXX need a context loop to handle such cases */
 -      CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
 -      {
 -              if (ob->restrictflag & OB_RESTRICT_RENDER) {
 -                      ob->restrictflag &= ~OB_RESTRICT_RENDER;
 -                      changed = true;
 -              }
 -      }
 -      CTX_DATA_END;
 -
 -      if (changed)
 -              WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
 -{
 -
 -      /* identifiers */
 -      ot->name = "Clear Restrict Render";
 -      ot->description = "Reveal the render object by setting the hide render flag";
 -      ot->idname = "OBJECT_OT_hide_render_clear";
 -
 -      /* api callbacks */
 -      ot->exec = object_hide_render_clear_exec;
 -      ot->poll = ED_operator_view3d_active;
 -
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -}
 -
 -static int object_hide_render_set_exec(bContext *C, wmOperator *op)
 -{
 -      const bool unselected = RNA_boolean_get(op->ptr, "unselected");
 -
 -      CTX_DATA_BEGIN(C, Base *, base, visible_bases)
 -      {
 -              if (!unselected) {
 -                      if (base->flag & SELECT) {
 -                              base->object->restrictflag |= OB_RESTRICT_RENDER;
 -                      }
 -              }
 -              else {
 -                      if (!(base->flag & SELECT)) {
 -                              base->object->restrictflag |= OB_RESTRICT_RENDER;
 -                      }
 -              }
 -      }
 -      CTX_DATA_END;
 -      WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
 -      return OPERATOR_FINISHED;
 -}
 -
 -void OBJECT_OT_hide_render_set(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Set Restrict Render";
 -      ot->description = "Hide the render object by setting the hide render flag";
 -      ot->idname = "OBJECT_OT_hide_render_set";
 -
 -      /* api callbacks */
 -      ot->exec = object_hide_render_set_exec;
 -      ot->poll = ED_operator_view3d_active;
 -
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -
 -      RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
 -}
 -
  /* ******************* toggle editmode operator  ***************** */
  
- static bool mesh_needs_keyindex(const Mesh *me)
+ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
  {
        if (me->key) {
                return false;  /* will be added */
        }
  
-       for (const Object *ob = G.main->object.first; ob; ob = ob->id.next) {
+       for (const Object *ob = bmain->object.first; ob; ob = ob->id.next) {
                if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
                        return true;
                }
@@@ -217,7 -391,7 +217,7 @@@ static bool ED_object_editmode_load_ex(
                 * to inform dependency graph about this. But is it really the
                 * best place to do this?
                 */
 -              DAG_relations_tag_update(bmain);
 +              DEG_relations_tag_update(bmain);
        }
        else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                const Curve *cu = obedit->data;
        return true;
  }
  
- bool ED_object_editmode_load(Object *obedit)
+ bool ED_object_editmode_load(Main *bmain, Object *obedit)
  {
-       /* TODO(sergey): use proper main here? */
-       return ED_object_editmode_load_ex(G.main, obedit, false);
+       return ED_object_editmode_load_ex(bmain, obedit, false);
  }
  
  /**
@@@ -282,8 -455,8 +281,8 @@@ bool ED_object_editmode_exit_ex(Scene *
        if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) {
                /* in rare cases (background mode) its possible active object
                 * is flagged for editmode, without 'obedit' being set [#35489] */
 -              if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) {
 -                      scene->basact->object->mode &= ~OB_MODE_EDIT;
 +              if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
 +                      obedit->mode &= ~OB_MODE_EDIT;
                }
                if (flag & EM_WAITCURSOR) waitcursor(0);
                return true;
                ListBase pidlist;
                PTCacheID *pid;
  
 -              /* for example; displist make is different in editmode */
 -              scene->obedit = NULL; // XXX for context
 -
                /* flag object caches as outdated */
                BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
                for (pid = pidlist.first; pid; pid = pid->next) {
                BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
  
                /* also flush ob recalc, doesn't take much overhead, but used for particles */
 -              DAG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA);
 +              DEG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA);
  
                WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
  
@@@ -324,14 -500,43 +323,14 @@@ bool ED_object_editmode_exit(bContext *
        return ED_object_editmode_exit_ex(scene, obedit, flag);
  }
  
- bool ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
 -bool ED_object_editmode_enter(bContext *C, int flag)
++bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
  {
 -      Main *bmain = CTX_data_main(C);
 -      Scene *scene = CTX_data_scene(C);
 -      Base *base = NULL;
 -      Object *ob;
 -      ScrArea *sa = CTX_wm_area(C);
 -      View3D *v3d = NULL;
        bool ok = false;
  
 -      if (ID_IS_LINKED(scene)) {
 -              return false;
 -      }
 -
 -      if (sa && sa->spacetype == SPACE_VIEW3D)
 -              v3d = sa->spacedata.first;
 -
 -      if ((flag & EM_IGNORE_LAYER) == 0) {
 -              base = CTX_data_active_base(C); /* active layer checked here for view3d */
 -
 -              if ((base == NULL) ||
 -                  (v3d && (base->lay & v3d->lay) == 0) ||
 -                  (!v3d && (base->lay & scene->lay) == 0))
 -              {
 -                      return false;
 -              }
 -      }
 -      else {
 -              base = scene->basact;
 -      }
 -
 -      if (ELEM(NULL, base, base->object, base->object->data)) {
 +      if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) {
                return false;
        }
  
 -      ob = base->object;
 -
        /* this checks actual object->data, for cases when other scenes have it in editmode context */
        if (BKE_object_is_in_editmode(ob)) {
                return true;
  
        ob->restore_mode = ob->mode;
  
 -      /* note, when switching scenes the object can have editmode data but
 -       * not be scene->obedit: bug 22954, this avoids calling self eternally */
 -      if ((ob->restore_mode & OB_MODE_EDIT) == 0)
 -              ED_object_mode_toggle(C, ob->mode);
 -
        ob->mode = OB_MODE_EDIT;
  
        if (ob->type == OB_MESH) {
                BMEditMesh *em;
                ok = 1;
-               const bool use_key_index = mesh_needs_keyindex(ob->data);
 -              scene->obedit = ob;  /* context sees this */
+               const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
  
                EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
  
                        BKE_editmesh_tessface_calc(em);
                }
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MESH, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
        }
        else if (ob->type == OB_ARMATURE) {
                ok = 1;
 -              scene->obedit = ob;
                ED_armature_to_edit(ob->data);
                /* to ensure all goes in restposition and without striding */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
 +              DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
        }
        else if (ob->type == OB_FONT) {
 -              scene->obedit = ob; /* XXX for context */
                ok = 1;
                ED_curve_editfont_make(ob);
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
        }
        else if (ob->type == OB_MBALL) {
 -              scene->obedit = ob; /* XXX for context */
                ok = 1;
                ED_mball_editmball_make(ob);
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
        }
        else if (ob->type == OB_LATTICE) {
 -              scene->obedit = ob; /* XXX for context */
                ok = 1;
                BKE_editlattice_make(ob);
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
        }
        else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
                ok = 1;
 -              scene->obedit = ob; /* XXX for context */
                ED_curve_editnurb_make(ob);
  
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
        }
  
        if (ok) {
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
        else {
 -              scene->obedit = NULL; /* XXX for context */
 -              ob->mode &= ~OB_MODE_EDIT;
 -              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
 +              if ((flag & EM_NO_CONTEXT) == 0) {
 +                      ob->mode &= ~OB_MODE_EDIT;
 +              }
 +              WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
        }
  
        if (flag & EM_WAITCURSOR) waitcursor(0);
        return (ob->mode & OB_MODE_EDIT) != 0;
  }
  
-       return ED_object_editmode_enter_ex(scene, ob, flag);
 +bool ED_object_editmode_enter(bContext *C, int flag)
 +{
++      Main *bmain = CTX_data_main(C);
 +      Scene *scene = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Object *ob;
 +
 +      if ((flag & EM_IGNORE_LAYER) == 0) {
 +              ob = CTX_data_active_object(C); /* active layer checked here for view3d */
 +      }
 +      else {
 +              ob = view_layer->basact->object;
 +      }
 +      if ((ob == NULL) || ID_IS_LINKED(ob)) {
 +              return false;
 +      }
++      return ED_object_editmode_enter_ex(bmain, scene, ob, flag);
 +}
 +
  static int editmode_toggle_exec(bContext *C, wmOperator *op)
  {
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
        const int mode_flag = OB_MODE_EDIT;
        const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
++      Main *bmain = CTX_data_main(C);
        Scene *scene =  CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Object *obact = OBACT(view_layer);
  
        if (!is_mode_set) {
 -              Object *ob = CTX_data_active_object(C);
 -              if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
 +              if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
                        return OPERATOR_CANCELLED;
                }
        }
  
        if (!is_mode_set) {
                ED_object_editmode_enter(C, EM_WAITCURSOR);
-                                       ED_object_editmode_enter_ex(scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
 +              if (obact->mode & mode_flag) {
 +                      FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
 +                      {
 +                              if ((ob != obact) && (ob->type == obact->type)) {
++                                      ED_object_editmode_enter_ex(bmain, scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
 +                              }
 +                      }
 +                      FOREACH_SELECTED_OBJECT_END;
 +              }
        }
        else {
                ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
 +              if ((obact->mode & mode_flag) == 0) {
 +                      FOREACH_OBJECT_BEGIN(view_layer, ob)
 +                      {
 +                              if ((ob != obact) && (ob->type == obact->type)) {
 +                                      ED_object_editmode_exit_ex(scene, ob, EM_FREEDATA | EM_WAITCURSOR);
 +                              }
 +                      }
 +                      FOREACH_OBJECT_END;
 +              }
        }
 +
        ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
  
 +      WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
 +
 +      WM_toolsystem_update_from_context_view3d(C);
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -488,9 -661,8 +490,9 @@@ static int editmode_toggle_poll(bContex
                return 0;
  
        /* if hidden but in edit mode, we still display */
 -      if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
 +      if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
                return 0;
 +      }
  
        return OB_TYPE_SUPPORT_EDITMODE(ob->type);
  }
@@@ -515,68 -687,34 +517,68 @@@ void OBJECT_OT_editmode_toggle(wmOperat
  
  static int posemode_exec(bContext *C, wmOperator *op)
  {
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
        Base *base = CTX_data_active_base(C);
 -      Object *ob = base->object;
 +      Object *obact = base->object;
        const int mode_flag = OB_MODE_POSE;
 -      bool is_mode_set = (ob->mode & mode_flag) != 0;
 +      bool is_mode_set = (obact->mode & mode_flag) != 0;
        
        if (!is_mode_set) {
 -              if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
 +              if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
                        return OPERATOR_CANCELLED;
                }
        }
  
 -      if (ob->type == OB_ARMATURE) {
 -              if (ob == CTX_data_edit_object(C)) {
 -                      ED_object_editmode_exit(C, EM_FREEDATA);
 -                      is_mode_set = false;
 -              }
 +      if (obact->type != OB_ARMATURE) {
 +              return OPERATOR_PASS_THROUGH;
 +      }
 +
 +      if (obact == CTX_data_edit_object(C)) {
 +              ED_object_editmode_exit(C, EM_FREEDATA);
 +              is_mode_set = false;
 +      }
  
 -              if (is_mode_set) {
 -                      ED_object_posemode_exit(C, ob);
 +      if (is_mode_set) {
 +              bool ok = ED_object_posemode_exit(C, obact);
 +              if (ok) {
 +                      struct Main *bmain = CTX_data_main(C);
 +                      ViewLayer *view_layer = CTX_data_view_layer(C);
 +                      FOREACH_OBJECT_BEGIN(view_layer, ob)
 +                      {
 +                              if ((ob != obact) &&
 +                                  (ob->type == OB_ARMATURE) &&
 +                                  (ob->mode & mode_flag))
 +                              {
 +                                      ED_object_posemode_exit_ex(bmain, ob);
 +                              }
 +                      }
 +                      FOREACH_OBJECT_END;
                }
 -              else {
 -                      ED_object_posemode_enter(C, ob);
 +      }
 +      else {
 +              bool ok = ED_object_posemode_enter(C, obact);
 +              if (ok) {
 +                      struct Main *bmain = CTX_data_main(C);
 +                      ViewLayer *view_layer = CTX_data_view_layer(C);
 +                      FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
 +                      {
 +                              if ((ob != obact) &&
 +                                  (ob->type == OB_ARMATURE) &&
 +                                  (ob->mode == OB_MODE_OBJECT) &&
 +                                  (!ID_IS_LINKED(ob)))
 +                              {
 +                                      ED_object_posemode_enter_ex(bmain, ob);
 +                              }
 +                      }
 +                      FOREACH_SELECTED_OBJECT_END;
                }
 -              
 -              return OPERATOR_FINISHED;
        }
 -      
 -      return OPERATOR_PASS_THROUGH;
 +
 +      WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
 +
 +      WM_toolsystem_update_from_context_view3d(C);
 +
 +      return OPERATOR_FINISHED;
  }
  
  void OBJECT_OT_posemode_toggle(wmOperatorType *ot) 
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  }
  
 -static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
 -{     
 -//XXX no longer used - to be removed - replaced by game_properties_copy_exec
 -      bProperty *prop;
 -      Base *base;
 -      int nr, tot = 0;
 -      char *str;
 -      
 -      prop = ob->prop.first;
 -      while (prop) {
 -              tot++;
 -              prop = prop->next;
 -      }
 -      
 -      str = MEM_callocN(50 + 33 * tot, "copymenu prop");
 -      
 -      if (tot)
 -              strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
 -      else
 -              strcpy(str, "Copy Property %t|Clear All (no properties on active)");
 -      
 -      tot = 0;
 -      prop = ob->prop.first;
 -      while (prop) {
 -              tot++;
 -              strcat(str, "|");
 -              strcat(str, prop->name);
 -              prop = prop->next;
 -      }
 -
 -      nr = pupmenu(str);
 -      
 -      if (nr == 1 || nr == 2) {
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
 -                              if (nr == 1) { /* replace */
 -                                      BKE_bproperty_copy_list(&base->object->prop, &ob->prop);
 -                              }
 -                              else {
 -                                      for (prop = ob->prop.first; prop; prop = prop->next) {
 -                                              BKE_bproperty_object_set(base->object, prop);
 -                                      }
 -                              }
 -                      }
 -              }
 -      }
 -      else if (nr > 0) {
 -              prop = BLI_findlink(&ob->prop, nr - 4); /* account for first 3 menu items & menu index starting at 1*/
 -              
 -              if (prop) {
 -                      for (base = FIRSTBASE; base; base = base->next) {
 -                              if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
 -                                      BKE_bproperty_object_set(base->object, prop);
 -                              }
 -                      }
 -              }
 -      }
 -      MEM_freeN(str);
 -      
 -}
 -
 -static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
 -{
 -//XXX no longer used - to be removed - replaced by logicbricks_copy_exec
 -      Base *base;
 -      
 -      for (base = FIRSTBASE; base; base = base->next) {
 -              if (base->object != ob) {
 -                      if (TESTBASELIB(v3d, base)) {
 -                              
 -                              /* first: free all logic */
 -                              free_sensors(&base->object->sensors);
 -                              unlink_controllers(&base->object->controllers);
 -                              free_controllers(&base->object->controllers);
 -                              unlink_actuators(&base->object->actuators);
 -                              free_actuators(&base->object->actuators);
 -                              
 -                              /* now copy it, this also works without logicbricks! */
 -                              clear_sca_new_poins_ob(ob);
 -                              copy_sensors(&base->object->sensors, &ob->sensors, 0);
 -                              copy_controllers(&base->object->controllers, &ob->controllers, 0);
 -                              copy_actuators(&base->object->actuators, &ob->actuators, 0);
 -                              set_sca_new_poins_ob(base->object);
 -                              
 -                              /* some menu settings */
 -                              base->object->scavisflag = ob->scavisflag;
 -                              base->object->scaflag = ob->scaflag;
 -                              
 -                              /* set the initial state */
 -                              base->object->state = ob->state;
 -                              base->object->init_state = ob->init_state;
 -                      }
 -              }
 -      }
 -}
 -
  /* both pointers should exist */
  static void copy_texture_space(Object *to, Object *ob)
  {
  }
  
  /* UNUSED, keep in case we want to copy functionality for use elsewhere */
 -static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
 +static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short event)
  {
        Object *ob;
        Base *base;
        
        if (ID_IS_LINKED(scene)) return;
  
 -      if (!(ob = OBACT)) return;
 +      if (!(ob = OBACT(view_layer))) return;
        
 -      if (scene->obedit) { // XXX get from context
 +      if (BKE_object_is_in_editmode(ob)) {
                /* obedit_copymenu(); */
                return;
        }
 -      if (event == 9) {
 -              copymenu_properties(scene, v3d, ob);
 -              return;
 -      }
 -      else if (event == 10) {
 -              copymenu_logicbricks(scene, v3d, ob);
 -              return;
 -      }
 -      else if (event == 24) {
 +
 +      if (event == 24) {
                /* moved to BKE_object_link_modifiers */
                /* copymenu_modifiers(bmain, scene, v3d, ob); */
                return;
        }
  
 -      for (base = FIRSTBASE; base; base = base->next) {
 -              if (base != BASACT) {
 -                      if (TESTBASELIB(v3d, base)) {
 -                              DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
 +      for (base = FIRSTBASE(view_layer); base; base = base->next) {
 +              if (base != BASACT(view_layer)) {
 +                      if (TESTBASELIB(base)) {
 +                              DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
                                
                                if (event == 1) {  /* loc */
                                        copy_v3_v3(base->object->loc, ob->loc);
                                        if (ob->dup_group)
                                                id_us_plus(&ob->dup_group->id);
                                }
 -                              else if (event == 7) {    /* mass */
 -                                      base->object->mass = ob->mass;
 -                              }
 -                              else if (event == 8) {    /* damping */
 -                                      base->object->damping = ob->damping;
 -                                      base->object->rdamping = ob->rdamping;
 -                              }
 -                              else if (event == 11) {   /* all physical attributes */
 -                                      base->object->gameflag = ob->gameflag;
 -                                      base->object->inertia = ob->inertia;
 -                                      base->object->formfactor = ob->formfactor;
 -                                      base->object->damping = ob->damping;
 -                                      base->object->rdamping = ob->rdamping;
 -                                      base->object->min_vel = ob->min_vel;
 -                                      base->object->max_vel = ob->max_vel;
 -                                      base->object->min_angvel = ob->min_angvel;
 -                                      base->object->max_angvel = ob->max_angvel;
 -                                      if (ob->gameflag & OB_BOUNDS) {
 -                                              base->object->collision_boundtype = ob->collision_boundtype;
 -                                      }
 -                                      base->object->margin = ob->margin;
 -                                      base->object->bsoft = copy_bulletsoftbody(ob->bsoft, 0);
 -
 -                              }
                                else if (event == 17) {   /* tex space */
                                        copy_texture_space(base->object, ob);
                                }
                                                
                                                BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
                                                
 -                                              DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
 +                                              DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
                                        }
                                }
                                else if (event == 19) {   /* bevel settings */
                                                cu1->ext1 = cu->ext1;
                                                cu1->ext2 = cu->ext2;
                                                
 -                                              DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
 +                                              DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
                                        }
                                }
                                else if (event == 25) {   /* curve resolution */
                                                        nu = nu->next;
                                                }
                                                
 -                                              DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
 +                                              DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
                                        }
                                }
                                else if (event == 21) {
                                                        }
  
                                                        modifier_copyData(md, tmd);
 -                                                      DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
 +                                                      DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
                                                }
                                        }
                                }
        }
        
        if (do_depgraph_update)
 -              DAG_relations_tag_update(bmain);
 +              DEG_relations_tag_update(bmain);
  }
  
 -static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d)
 +static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer, Object *obedit)
  {
        Object *ob;
        short event;
        char str[512];
        
 -      if (!(ob = OBACT)) return;
 +      if (!(ob = OBACT(view_layer))) return;
        
 -      if (scene->obedit) { /* XXX get from context */
 +      if (obedit) {
  /*            if (ob->type == OB_MESH) */
  /* XXX                        mesh_copy_menu(); */
                return;
        event = pupmenu(str);
        if (event <= 0) return;
        
 -      copy_attr(bmain, scene, v3d, event);
 +      copy_attr(bmain, scene, view_layer, event);
  }
  
  /* ******************* force field toggle operator ***************** */
@@@ -954,7 -1219,7 +956,7 @@@ static int forcefield_toggle_exec(bCont
                ob->pd->forcefield = PFIELD_FORCE;
        else
                ob->pd->forcefield = 0;
 -      
 +
        ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@@ -988,8 -1253,6 +990,8 @@@ void OBJECT_OT_forcefield_toggle(wmOper
   */
  void ED_objects_recalculate_paths(bContext *C, Scene *scene)
  {
 +      struct Main *bmain = CTX_data_main(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ListBase targets = {NULL, NULL};
        
        /* loop over objects in scene */
        CTX_DATA_END;
        
        /* recalculate paths, then free */
 -      animviz_calc_motionpaths(scene, &targets);
 +      animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
        BLI_freelistN(&targets);
 +      
 +      /* tag objects for copy on write - so paths will draw/redraw */
 +      CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
 +      {
 +              if (ob->mpath) {
 +                      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
 +              }
 +      }
 +      CTX_DATA_END;
  }
  
  
@@@ -1232,8 -1486,7 +1234,8 @@@ static int shade_smooth_exec(bContext *
                if (ob->type == OB_MESH) {
                        BKE_mesh_smooth_flag_set(ob, !clear);
  
 -                      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
 +                      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
  
                        done = true;
                                else nu->flag &= ~ME_SMOOTH;
                        }
  
 -                      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
  
                        done = true;
@@@ -1297,6 -1550,68 +1299,6 @@@ void OBJECT_OT_shade_smooth(wmOperatorT
  
  /* ********************** */
  
 -static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
 -{
 -      /* all selected objects with an image map: scale in image aspect */
 -      Base *base;
 -      Object *ob;
 -      Material *ma;
 -      Tex *tex;
 -      float x, y, space;
 -      int a, b, done;
 -      
 -      if (scene->obedit) return;  // XXX get from context
 -      if (ID_IS_LINKED(scene)) return;
 -      
 -      for (base = FIRSTBASE; base; base = base->next) {
 -              if (TESTBASELIB(v3d, base)) {
 -                      ob = base->object;
 -                      done = false;
 -                      
 -                      for (a = 1; a <= ob->totcol; a++) {
 -                              ma = give_current_material(ob, a);
 -                              if (ma) {
 -                                      for (b = 0; b < MAX_MTEX; b++) {
 -                                              if (ma->mtex[b] && ma->mtex[b]->tex) {
 -                                                      tex = ma->mtex[b]->tex;
 -                                                      if (tex->type == TEX_IMAGE && tex->ima) {
 -                                                              ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, NULL, NULL);
 -                                                              
 -                                                              /* texturespace */
 -                                                              space = 1.0;
 -                                                              if (ob->type == OB_MESH) {
 -                                                                      float size[3];
 -                                                                      BKE_mesh_texspace_get(ob->data, NULL, NULL, size);
 -                                                                      space = size[0] / size[1];
 -                                                              }
 -                                                              else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
 -                                                                      float size[3];
 -                                                                      BKE_curve_texspace_get(ob->data, NULL, NULL, size);
 -                                                                      space = size[0] / size[1];
 -                                                              }
 -                                                      
 -                                                              x = ibuf->x / space;
 -                                                              y = ibuf->y;
 -                                                              
 -                                                              if (x > y) ob->size[0] = ob->size[1] * x / y;
 -                                                              else ob->size[1] = ob->size[0] * y / x;
 -                                                              
 -                                                              done = true;
 -                                                              DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 -
 -                                                              BKE_image_release_ibuf(tex->ima, ibuf, NULL);
 -                                                      }
 -                                              }
 -                                              if (done) break;
 -                                      }
 -                              }
 -                              if (done) break;
 -                      }
 -              }
 -      }
 -      
 -}
 -
  static const EnumPropertyItem *object_mode_set_itemsf(
          bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
  {
@@@ -1362,28 -1677,12 +1364,28 @@@ static int object_mode_set_poll(bContex
  
  static int object_mode_set_exec(bContext *C, wmOperator *op)
  {
 +      bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode");
        Object *ob = CTX_data_active_object(C);
        bGPdata *gpd = CTX_data_gpencil_data(C);
        eObjectMode mode = RNA_enum_get(op->ptr, "mode");
        eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
        const bool toggle = RNA_boolean_get(op->ptr, "toggle");
 -      
 +
 +      if (use_submode) {
 +              /* When not changing modes use submodes, see: T55162. */
 +              if (toggle == false) {
 +                      if (mode == restore_mode) {
 +                              switch (mode) {
 +                                      case OB_MODE_EDIT:
 +                                              WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN);
 +                                              return OPERATOR_INTERFACE;
 +                                      default:
 +                                              break;
 +                              }
 +                      }
 +              }
 +      }
 +
        if (gpd) {
                /* GP Mode is not bound to a specific object. Therefore,
                 * we don't want it to be actually saved on any objects,
@@@ -1458,413 -1757,453 +1460,413 @@@ void OBJECT_OT_mode_set(wmOperatorType 
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
 -/************************ Game Properties ***********************/
 -
 -static int game_property_new_exec(bContext *C, wmOperator *op)
 +void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot)
  {
 -      Object *ob = CTX_data_active_object(C);
 -      bProperty *prop;
 -      char name[MAX_NAME];
 -      int type = RNA_enum_get(op->ptr, "type");
 -
 -      prop = BKE_bproperty_new(type);
 -      BLI_addtail(&ob->prop, prop);
 +      PropertyRNA *prop;
  
 -      RNA_string_get(op->ptr, "name", name);
 -      if (name[0] != '\0') {
 -              BLI_strncpy(prop->name, name, sizeof(prop->name));
 -      }
 -
 -      BLI_uniquename(&ob->prop, prop, DATA_("Property"), '.', offsetof(bProperty, name), sizeof(prop->name));
 -
 -      WM_event_add_notifier(C, NC_LOGIC, NULL);
 -      return OPERATOR_FINISHED;
 -}
 -
 -
 -void OBJECT_OT_game_property_new(wmOperatorType *ot)
 -{
        /* identifiers */
 -      ot->name = "New Game Property";
 -      ot->description = "Create a new property available to the game engine";
 -      ot->idname = "OBJECT_OT_game_property_new";
 +      ot->name = "Set Object Mode or Submode";
 +      ot->description = "Sets the object interaction mode";
 +      ot->idname = "OBJECT_OT_mode_set_or_submode";
  
        /* api callbacks */
 -      ot->exec = game_property_new_exec;
 -      ot->poll = ED_operator_object_active_editable;
 +      ot->exec = object_mode_set_exec;
 +
 +      ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
  
        /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +      ot->flag = 0; /* no register/undo here, leave it to operators being called */
  
 -      RNA_def_enum(ot->srna, "type", rna_enum_gameproperty_type_items, GPROP_FLOAT, "Type", "Type of game property to add");
 -      RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the game property to add");
 +      ot->prop = RNA_def_enum(ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
 +      RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
 +      RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
 +
 +      prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
  
 -static int game_property_remove_exec(bContext *C, wmOperator *op)
 +bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_only, float r_center[3])
  {
 -      Object *ob = CTX_data_active_object(C);
 -      bProperty *prop;
 -      int index = RNA_int_get(op->ptr, "index");
 -
 -      if (!ob)
 -              return OPERATOR_CANCELLED;
 +      switch (obedit->type) {
 +              case OB_MESH:
 +              {
 +                      BMEditMesh *em = BKE_editmesh_from_object(obedit);
 +                      BMEditSelection ese;
  
 -      prop = BLI_findlink(&ob->prop, index);
 +                      if (BM_select_history_active_get(em->bm, &ese)) {
 +                              BM_editselection_center(&ese, r_center);
 +                              return true;
 +                      }
 +                      break;
 +              }
 +              case OB_ARMATURE:
 +              {
 +                      bArmature *arm = obedit->data;
 +                      EditBone *ebo = arm->act_edbone;
  
 -      if (prop) {
 -              BLI_remlink(&ob->prop, prop);
 -              BKE_bproperty_free(prop);
 +                      if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
 +                              copy_v3_v3(r_center, ebo->head);
 +                              return true;
 +                      }
  
 -              WM_event_add_notifier(C, NC_LOGIC, NULL);
 -              return OPERATOR_FINISHED;
 -      }
 -      else {
 -              return OPERATOR_CANCELLED;
 -      }
 -}
 +                      break;
 +              }
 +              case OB_CURVE:
 +              case OB_SURF:
 +              {
 +                      Curve *cu = obedit->data;
  
 -void OBJECT_OT_game_property_remove(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Remove Game Property";
 -      ot->description = "Remove game property";
 -      ot->idname = "OBJECT_OT_game_property_remove";
 +                      if (ED_curve_active_center(cu, r_center)) {
 +                              return true;
 +                      }
 +                      break;
 +              }
 +              case OB_MBALL:
 +              {
 +                      MetaBall *mb = obedit->data;
 +                      MetaElem *ml_act = mb->lastelem;
  
 -      /* api callbacks */
 -      ot->exec = game_property_remove_exec;
 -      ot->poll = ED_operator_object_active_editable;
 +                      if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
 +                              copy_v3_v3(r_center, &ml_act->x);
 +                              return true;
 +                      }
 +                      break;
 +              }
 +              case OB_LATTICE:
 +              {
 +                      BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
  
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +                      if (actbp) {
 +                              copy_v3_v3(r_center, actbp->vec);
 +                              return true;
 +                      }
 +                      break;
 +              }
 +      }
  
 -      RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX);
 +      return false;
  }
  
 -#define GAME_PROPERTY_MOVE_UP    1
 -#define GAME_PROPERTY_MOVE_DOWN -1
 +#define COLLECTION_INVALID_INDEX -1
  
 -static int game_property_move(bContext *C, wmOperator *op)
 +static int move_to_collection_poll(bContext *C)
  {
 -      Object *ob = CTX_data_active_object(C);
 -      bProperty *prop;
 -      bProperty *otherprop = NULL;
 -      const int index = RNA_int_get(op->ptr, "index");
 -      const int dir = RNA_enum_get(op->ptr, "direction");
 +      if (CTX_wm_space_outliner(C) != NULL) {
 +              return ED_outliner_collections_editor_poll(C);
 +      }
 +      else {
 +              return ED_operator_object_active_editable(C);
 +      }
 +}
  
 -      if (ob == NULL)
 +static int move_to_collection_exec(bContext *C, wmOperator *op)
 +{
 +      Main *bmain = CTX_data_main(C);
 +      Scene *scene = CTX_data_scene(C);
 +      PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
 +      const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
 +      const bool is_new = RNA_boolean_get(op->ptr, "is_new");
 +      Collection *collection;
 +      ListBase objects = {NULL};
 +
 +      if (!RNA_property_is_set(op->ptr, prop)) {
 +              BKE_report(op->reports, RPT_ERROR, "No collection selected");
                return OPERATOR_CANCELLED;
 +      }
  
 -      prop = BLI_findlink(&ob->prop, index);
 -      /* invalid index */
 -      if (prop == NULL)
 +      int collection_index = RNA_property_int_get(op->ptr, prop);
 +      collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
 +      if (collection == NULL) {
 +              BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
                return OPERATOR_CANCELLED;
 -
 -      if (dir == GAME_PROPERTY_MOVE_UP) {
 -              otherprop = prop->prev;
        }
 -      else if (dir == GAME_PROPERTY_MOVE_DOWN) {
 -              otherprop = prop->next;
 +
 +      if (CTX_wm_space_outliner(C) != NULL) {
 +              ED_outliner_selected_objects_get(C, &objects);
        }
        else {
 -              BLI_assert(0);
 +              CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
 +              {
 +                      BLI_addtail(&objects, BLI_genericNodeN(ob));
 +              }
 +              CTX_DATA_END;
        }
  
 -      if (prop && otherprop) {
 -              BLI_listbase_swaplinks(&ob->prop, prop, otherprop);
 -
 -              WM_event_add_notifier(C, NC_LOGIC, NULL);
 -              return OPERATOR_FINISHED;
 +      if (is_new) {
 +              char new_collection_name[MAX_NAME];
 +              RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
 +              collection = BKE_collection_add(bmain, collection, new_collection_name);
        }
 -      else {
 +
 +      Object *single_object = BLI_listbase_is_single(&objects) ?
 +                                  ((LinkData *)objects.first)->data : NULL;
 +
 +      if ((single_object != NULL) &&
 +          is_link &&
 +          BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob)))
 +      {
 +              BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, collection->id.name + 2);
 +              BLI_freelistN(&objects);
                return OPERATOR_CANCELLED;
        }
 -}
  
 -void OBJECT_OT_game_property_move(wmOperatorType *ot)
 -{
 -      static const EnumPropertyItem direction_property_move[] = {
 -              {GAME_PROPERTY_MOVE_UP,   "UP",   0, "Up",   ""},
 -              {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""},
 -              {0, NULL, 0, NULL, NULL}
 -      };
 -      PropertyRNA *prop;
 +      for (LinkData *link = objects.first; link; link = link->next) {
 +              Object *ob = link->data;
  
 -      /* identifiers */
 -      ot->name = "Move Game Property";
 -      ot->description = "Move game property";
 -      ot->idname = "OBJECT_OT_game_property_move";
 -
 -      /* api callbacks */
 -      ot->exec = game_property_move;
 -      ot->poll = ED_operator_object_active_editable;
 +              if (!is_link) {
 +                      BKE_collection_object_move(bmain, scene, collection, NULL, ob);
 +              }
 +              else {
 +                      BKE_collection_object_add(bmain, collection, ob);
 +              }
 +      }
 +      BLI_freelistN(&objects);
  
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +      BKE_reportf(op->reports,
 +                  RPT_INFO,
 +                  "%s %s to %s",
 +                  (single_object != NULL) ? single_object->id.name + 2 : "Objects",
 +                  is_link ? "linked" : "moved",
 +                  collection->id.name + 2);
  
 -      /* properties */
 -      prop = RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX);
 -      RNA_def_property_flag(prop, PROP_HIDDEN);
 -      RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction",
 -                   "Direction for moving the property");
 -}
 +      DEG_relations_tag_update(CTX_data_main(C));
 +      DEG_id_tag_update(&scene->id, 0);
  
 -#undef GAME_PROPERTY_MOVE_UP
 -#undef GAME_PROPERTY_MOVE_DOWN
 +      WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
 +      WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 +      WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
  
 -#define COPY_PROPERTIES_REPLACE 1
 -#define COPY_PROPERTIES_MERGE   2
 -#define COPY_PROPERTIES_COPY    3
 +      return OPERATOR_FINISHED;
 +}
  
 -static const EnumPropertyItem game_properties_copy_operations[] = {
 -      {COPY_PROPERTIES_REPLACE, "REPLACE", 0, "Replace Properties", ""},
 -      {COPY_PROPERTIES_MERGE, "MERGE", 0, "Merge Properties", ""},
 -      {COPY_PROPERTIES_COPY, "COPY", 0, "Copy a Property", ""},
 -      {0, NULL, 0, NULL, NULL}
 +struct MoveToCollectionData {
 +      struct MoveToCollectionData *next, *prev;
 +      int index;
 +      struct Collection *collection;
 +      struct ListBase submenus;
 +      PointerRNA ptr;
 +      struct wmOperatorType *ot;
  };
  
 -static const EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
 -{     
 -      Object *ob = ED_object_active_context(C);
 -      EnumPropertyItem tmp = {0, "", 0, "", ""};
 -      EnumPropertyItem *item = NULL;
 -      bProperty *prop;
 -      int a, totitem = 0;
 -      
 -      if (!ob)
 -              return DummyRNA_NULL_items;
 +static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
 +{
 +      int index = menu->index;
 +      for (CollectionChild *child = menu->collection->children.first;
 +           child != NULL;
 +           child = child->next)
 +      {
 +              Collection *collection = child->collection;
 +              MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
 +                                                          "MoveToCollectionData submenu - expected memleak");
 +              BLI_addtail(&menu->submenus, submenu);
 +              submenu->collection = collection;
 +              submenu->index = ++index;
 +              index = move_to_collection_menus_create(op, submenu);
 +              submenu->ot = op->type;
 +      }
 +      return index;
 +}
  
 -      for (a = 1, prop = ob->prop.first; prop; prop = prop->next, a++) {
 -              tmp.value = a;
 -              tmp.identifier = prop->name;
 -              tmp.name = prop->name;
 -              RNA_enum_item_add(&item, &totitem, &tmp);
 +static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
 +{
 +      for (MoveToCollectionData *submenu = menu->submenus.first;
 +           submenu != NULL;
 +           submenu = submenu->next)
 +      {
 +              move_to_collection_menus_free_recursive(submenu);
        }
 +      BLI_freelistN(&menu->submenus);
 +}
  
 -      RNA_enum_item_end(&item, &totitem);
 -      *r_free = true;
 +static void move_to_collection_menus_free(MoveToCollectionData **menu)
 +{
 +      if (*menu == NULL) {
 +              return;
 +      }
  
 -      return item;
 +      move_to_collection_menus_free_recursive(*menu);
 +      MEM_freeN(*menu);
 +      *menu = NULL;
  }
  
 -static int game_property_copy_exec(bContext *C, wmOperator *op)
 +static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
  {
 -      Object *ob = ED_object_active_context(C);
 -      bProperty *prop;
 -      int type = RNA_enum_get(op->ptr, "operation");
 -      int propid = RNA_enum_get(op->ptr, "property");
 +      MoveToCollectionData *menu = menu_v;
 +      const char *name;
  
 -      if (propid > 0) { /* copy */
 -              prop = BLI_findlink(&ob->prop, propid - 1);
 -              
 -              if (prop) {
 -                      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 -                      {
 -                              if (ob != ob_iter)
 -                                      BKE_bproperty_object_set(ob_iter, prop);
 -                      } CTX_DATA_END;
 -              }
 +      if (menu->collection->flag & COLLECTION_IS_MASTER) {
 +              name = IFACE_("Scene Collection");
        }
 -
        else {
 -              CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 -              {
 -                      if (ob != ob_iter) {
 -                              if (type == COPY_PROPERTIES_REPLACE) {
 -                                      BKE_bproperty_copy_list(&ob_iter->prop, &ob->prop);
 -                              }
 -                              else {
 -                                      /* merge - the default when calling with no argument */
 -                                      for (prop = ob->prop.first; prop; prop = prop->next) {
 -                                              BKE_bproperty_object_set(ob_iter, prop);
 -                                      }
 -                              }
 -                      }
 -              }
 -              CTX_DATA_END;
 +              name = menu->collection->id.name + 2;
        }
  
 -      return OPERATOR_FINISHED;
 -}
 +      uiItemIntO(layout,
 +                 name,
 +                 ICON_NONE,
 +                 menu->ot->idname,
 +                 "collection_index",
 +                 menu->index);
 +      uiItemS(layout);
  
 -void OBJECT_OT_game_property_copy(wmOperatorType *ot)
 -{
 -      PropertyRNA *prop;
 -      /* identifiers */
 -      ot->name = "Copy Game Property";
 -      ot->idname = "OBJECT_OT_game_property_copy";
 -      ot->description = "Copy/merge/replace a game property from active object to all selected objects";
 +      for (MoveToCollectionData *submenu = menu->submenus.first;
 +           submenu != NULL;
 +           submenu = submenu->next)
 +      {
 +              move_to_collection_menus_items(layout, submenu);
 +      }
  
 -      /* api callbacks */
 -      ot->exec = game_property_copy_exec;
 -      ot->poll = ED_operator_object_active_editable;
 +      uiItemS(layout);
  
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +      WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
 +      RNA_int_set(&menu->ptr, "collection_index", menu->index);
 +      RNA_boolean_set(&menu->ptr, "is_new", true);
  
 -      RNA_def_enum(ot->srna, "operation", game_properties_copy_operations, 3, "Operation", "");
 -      prop = RNA_def_enum(ot->srna, "property", DummyRNA_NULL_items, 0, "Property", "Properties to copy");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_ENUM_NO_TRANSLATE);
 -      RNA_def_enum_funcs(prop, gameprops_itemf);
 -      ot->prop = prop;
 +      uiItemFullO_ptr(layout,
 +                      menu->ot,
 +                      "New Collection",
 +                      ICON_ZOOMIN,
 +                      menu->ptr.data,
 +                      WM_OP_INVOKE_DEFAULT,
 +                      0,
 +                      NULL);
  }
  
 -static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op))
 +static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
  {
 -      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 -      {
 -              BKE_bproperty_free_list(&ob_iter->prop);
 +      if (BLI_listbase_is_empty(&menu->submenus)) {
 +              uiItemIntO(layout,
 +                         menu->collection->id.name + 2,
 +                         ICON_NONE,
 +                         menu->ot->idname,
 +                         "collection_index",
 +                         menu->index);
 +      }
 +      else {
 +              uiItemMenuF(layout,
 +                          menu->collection->id.name + 2,
 +                          ICON_NONE,
 +                          move_to_collection_menu_create,
 +                          menu);
        }
 -      CTX_DATA_END;
 -
 -      WM_event_add_notifier(C, NC_LOGIC, NULL);
 -      return OPERATOR_FINISHED;
  }
 -void OBJECT_OT_game_property_clear(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Clear Game Properties";
 -      ot->idname = "OBJECT_OT_game_property_clear";
 -      ot->description = "Remove all game properties from all selected objects";
  
 -      /* api callbacks */
 -      ot->exec = game_property_clear_exec;
 -      ot->poll = ED_operator_object_active_editable;
 +/* This is allocated statically because we need this available for the menus creation callback. */
 +static MoveToCollectionData *master_collection_menu = NULL;
  
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -}
 +static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 +{
 +      Scene *scene = CTX_data_scene(C);
  
 -/************************ Copy Logic Bricks ***********************/
 +      /* Reset the menus data for the current master collection, and free previously allocated data. */
 +      move_to_collection_menus_free(&master_collection_menu);
  
 -static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op))
 -{
 -      Object *ob = ED_object_active_context(C);
 +      PropertyRNA *prop;
 +      prop = RNA_struct_find_property(op->ptr, "collection_index");
 +      if (RNA_property_is_set(op->ptr, prop)) {
 +              int collection_index = RNA_property_int_get(op->ptr, prop);
  
 -      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 -      {
 -              if (ob != ob_iter) {
 -                      /* first: free all logic */
 -                      free_sensors(&ob_iter->sensors);
 -                      unlink_controllers(&ob_iter->controllers);
 -                      free_controllers(&ob_iter->controllers);
 -                      unlink_actuators(&ob_iter->actuators);
 -                      free_actuators(&ob_iter->actuators);
 -              
 -                      /* now copy it, this also works without logicbricks! */
 -                      clear_sca_new_poins_ob(ob);
 -                      copy_sensors(&ob_iter->sensors, &ob->sensors, 0);
 -                      copy_controllers(&ob_iter->controllers, &ob->controllers, 0);
 -                      copy_actuators(&ob_iter->actuators, &ob->actuators, 0);
 -                      set_sca_new_poins_ob(ob_iter);
 -              
 -                      /* some menu settings */
 -                      ob_iter->scavisflag = ob->scavisflag;
 -                      ob_iter->scaflag = ob->scaflag;
 -              
 -                      /* set the initial state */
 -                      ob_iter->state = ob->state;
 -                      ob_iter->init_state = ob->init_state;
 +              if (RNA_boolean_get(op->ptr, "is_new")) {
 +                      prop = RNA_struct_find_property(op->ptr, "new_collection_name");
 +                      if (!RNA_property_is_set(op->ptr, prop)) {
 +                              char name[MAX_NAME];
 +                              Collection *collection;
 +
 +                              collection = BKE_collection_from_index(scene, collection_index);
 +                              BKE_collection_new_name_get(collection, name);
  
 -                      if (ob_iter->totcol == ob->totcol) {
 -                              ob_iter->actcol = ob->actcol;
 -                              WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
 +                              RNA_property_string_set(op->ptr, prop, name);
 +                              return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
                        }
                }
 +              return move_to_collection_exec(C, op);
        }
 -      CTX_DATA_END;
  
 -      WM_event_add_notifier(C, NC_LOGIC, NULL);
 +      Collection *master_collection = BKE_collection_master(scene);
  
 -      return OPERATOR_FINISHED;
 -}
 +      /* We need the data to be allocated so it's available during menu drawing.
 +       * Technically we could use wmOperator->customdata. However there is no free callback
 +       * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
 +       *
 +       * So we are left with a memory that will necessarily leak. It's a small leak though.*/
 +      if (master_collection_menu == NULL) {
 +              master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
 +                                                   "MoveToCollectionData menu - expected eventual memleak");
 +      }
  
 -void OBJECT_OT_logic_bricks_copy(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Copy Logic Bricks to Selected";
 -      ot->description = "Copy logic bricks to other selected objects";
 -      ot->idname = "OBJECT_OT_logic_bricks_copy";
 +      master_collection_menu->collection = master_collection;
 +      master_collection_menu->ot = op->type;
 +      move_to_collection_menus_create(op, master_collection_menu);
  
 -      /* api callbacks */
 -      ot->exec = logicbricks_copy_exec;
 -      ot->poll = ED_operator_object_active_editable;
 +      uiPopupMenu *pup;
 +      uiLayout *layout;
  
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -}
 +      /* Build the menus. */
 +      const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
 +      pup = UI_popup_menu_begin(C, title, ICON_NONE);
 +      layout = UI_popup_menu_layout(pup);
  
 -static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
 -{
 -      Object *ob = ED_object_active_context(C);
 -      
 -      CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
 -      {
 -              if (ob != ob_iter) {
 -                      ob_iter->gameflag = ob->gameflag;
 -                      ob_iter->gameflag2 = ob->gameflag2;
 -                      ob_iter->inertia = ob->inertia;
 -                      ob_iter->formfactor = ob->formfactor;
 -                      ob_iter->damping = ob->damping;
 -                      ob_iter->rdamping = ob->rdamping;
 -                      ob_iter->min_vel = ob->min_vel;
 -                      ob_iter->max_vel = ob->max_vel;
 -                      ob_iter->min_angvel = ob->min_angvel;
 -                      ob_iter->max_angvel = ob->max_angvel;
 -                      ob_iter->obstacleRad = ob->obstacleRad;
 -                      ob_iter->mass = ob->mass;
 -                      copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction);
 -                      ob_iter->collision_boundtype = ob->collision_boundtype;
 -                      ob_iter->margin = ob->margin;
 -                      ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft, 0);
 -                      if (ob->restrictflag & OB_RESTRICT_RENDER) 
 -                              ob_iter->restrictflag |= OB_RESTRICT_RENDER;
 -                      else
 -                              ob_iter->restrictflag &= ~OB_RESTRICT_RENDER;
 -
 -                      ob_iter->col_group = ob->col_group;
 -                      ob_iter->col_mask = ob->col_mask;
 -              }
 -      }
 -      CTX_DATA_END;
 -      
 -      return OPERATOR_FINISHED;
 +      uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
 +
 +      move_to_collection_menu_create(C, layout, master_collection_menu);
 +
 +      UI_popup_menu_end(C, pup);
 +
 +      return OPERATOR_INTERFACE;
  }
  
 -void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
 +void OBJECT_OT_move_to_collection(wmOperatorType *ot)
  {
 +      PropertyRNA *prop;
 +
        /* identifiers */
 -      ot->name = "Copy Game Physics Properties to Selected";
 -      ot->description = "Copy game physics properties to other selected objects";
 -      ot->idname = "OBJECT_OT_game_physics_copy";
 -      
 +      ot->name = "Move to Collection";
 +      ot->description = "Move objects to a scene collection";
 +      ot->idname = "OBJECT_OT_move_to_collection";
 +
        /* api callbacks */
 -      ot->exec = game_physics_copy_exec;
 -      ot->poll = ED_operator_object_active_editable;
 -      
 +      ot->exec = move_to_collection_exec;
 +      ot->invoke = move_to_collection_invoke;
 +      ot->poll = move_to_collection_poll;
 +
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -}
  
 -/* generic utility function */
 +      prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
 +                         "Collection Index", "Index of the collection to move to", 0, INT_MAX);
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 +      prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 +      prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
 +                            "Name of the newly added collection");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 +}
  
 -bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_only, float r_center[3])
 +void OBJECT_OT_link_to_collection(wmOperatorType *ot)
  {
 -      switch (obedit->type) {
 -              case OB_MESH:
 -              {
 -                      BMEditMesh *em = BKE_editmesh_from_object(obedit);
 -                      BMEditSelection ese;
 -
 -                      if (BM_select_history_active_get(em->bm, &ese)) {
 -                              BM_editselection_center(&ese, r_center);
 -                              return true;
 -                      }
 -                      break;
 -              }
 -              case OB_ARMATURE:
 -              {
 -                      bArmature *arm = obedit->data;
 -                      EditBone *ebo = arm->act_edbone;
 -
 -                      if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
 -                              copy_v3_v3(r_center, ebo->head);
 -                              return true;
 -                      }
 -
 -                      break;
 -              }
 -              case OB_CURVE:
 -              case OB_SURF:
 -              {
 -                      Curve *cu = obedit->data;
 +      PropertyRNA *prop;
  
 -                      if (ED_curve_active_center(cu, r_center)) {
 -                              return true;
 -                      }
 -                      break;
 -              }
 -              case OB_MBALL:
 -              {
 -                      MetaBall *mb = obedit->data;
 -                      MetaElem *ml_act = mb->lastelem;
 +      /* identifiers */
 +      ot->name = "Link to Collection";
 +      ot->description = "Link objects to a collection";
 +      ot->idname = "OBJECT_OT_link_to_collection";
  
 -                      if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
 -                              copy_v3_v3(r_center, &ml_act->x);
 -                              return true;
 -                      }
 -                      break;
 -              }
 -              case OB_LATTICE:
 -              {
 -                      BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
 +      /* api callbacks */
 +      ot->exec = move_to_collection_exec;
 +      ot->invoke = move_to_collection_invoke;
 +      ot->poll = move_to_collection_poll;
  
 -                      if (actbp) {
 -                              copy_v3_v3(r_center, actbp->vec);
 -                              return true;
 -                      }
 -                      break;
 -              }
 -      }
 +      /* flags */
 +      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  
 -      return false;
 +      prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
 +                         "Collection Index", "Index of the collection to move to", 0, INT_MAX);
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 +      prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 +      prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
 +                            "Name of the newly added collection");
 +      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
  }
 +
 +#undef COLLECTION_INVALID_INDEX
index 0e30c43998eb20a0f2ce4e9076759198d298dbe7,9c3b9c7b17996711412532c1524fb20d09cb52d8..5ad107c5d3b925e0acce503a2698d9160d118023
  #include "BLI_utildefines.h"
  #include "BLI_listbase.h"
  
 +#include "BKE_armature.h"
 +#include "BKE_collection.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
 +#include "BKE_layer.h"
  #include "BKE_object.h"
  #include "BKE_scene.h"
  #include "BKE_sequencer.h"
 -#include "BKE_armature.h"
 +#include "BKE_workspace.h"
 +
 +#include "DEG_depsgraph.h"
  
  #include "ED_armature.h"
  #include "ED_object.h"
  
  #include "outliner_intern.h"
  
 -/* ****************************************************** */
 -/* Outliner Selection (gray-blue highlight for rows) */
 -
 -static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
 +static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *view_layer, Base *base)
  {
 -      TreeElement *te;
 -      TreeStoreElem *tselem;
 -      bool changed = false;
 -      
 -      for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) {
 -              tselem = TREESTORE(te);
 -              
 -              /* if we've encountered the right item, set its 'Outliner' selection status */
 -              if (*index == 0) {
 -                      /* this should be the last one, so no need to do anything with index */
 -                      if ((te->flag & TE_ICONROW) == 0) {
 -                              /* -1 value means toggle testing for now... */
 -                              if (*selecting == -1) {
 -                                      if (tselem->flag & TSE_SELECTED) 
 -                                              *selecting = 0;
 -                                      else 
 -                                              *selecting = 1;
 -                              }
 -                              
 -                              /* set selection */
 -                              if (*selecting) 
 -                                      tselem->flag |= TSE_SELECTED;
 -                              else 
 -                                      tselem->flag &= ~TSE_SELECTED;
 -
 -                              changed |= true;
 +      Object *obact = OBACT(view_layer);
 +      bool use_all = false;
 +
 +      if (obact == NULL) {
 +              ED_object_base_activate(C, base);
 +              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 +              obact = base->object;
 +              use_all = true;
 +      }
 +      else if (obact->data == base->object->data) {
 +              use_all = true;
 +      }
 +
 +      if (use_all) {
 +              WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
 +      }
 +      else {
 +              Object *ob = base->object;
 +              if (ob->type == obact->type) {
 +                      bool ok;
 +                      if (BKE_object_is_in_editmode(ob)) {
 +                              ok = ED_object_editmode_exit_ex(scene, ob, EM_FREEDATA | EM_WAITCURSOR);
 +                      }
 +                      else {
-                               ok = ED_object_editmode_enter_ex(scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
++                              ok = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
 +                      }
 +                      if (ok) {
 +                              ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT);
 +                              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
                        }
 -              }
 -              else if (TSELEM_OPEN(tselem, soops)) {
 -                      /* Only try selecting sub-elements if we haven't hit the right element yet
 -                       *
 -                       * Hack warning:
 -                       *  Index must be reduced before supplying it to the sub-tree to try to do
 -                       *  selection, however, we need to increment it again for the next loop to
 -                       *  function correctly
 -                       */
 -                      (*index)--;
 -                      changed |= outliner_select(soops, &te->subtree, index, selecting);
 -                      (*index)++;
                }
        }
 +}
  
 -      return changed;
 +static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base *base)
 +{
 +      Object *obact = OBACT(view_layer);
 +      bool use_all = false;
 +
 +      if (obact == NULL) {
 +              ED_object_base_activate(C, base);
 +              Scene *scene = CTX_data_scene(C);
 +              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 +              obact = base->object;
 +              use_all = true;
 +      }
 +      else if (obact->data == base->object->data) {
 +              use_all = true;
 +      }
 +
 +      if (use_all) {
 +              WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
 +      }
 +      else {
 +              Object *ob = base->object;
 +              if (ob->type == obact->type) {
 +                      struct Main *bmain = CTX_data_main(C);
 +                      bool ok = false;
 +                      if (ob->mode & OB_MODE_POSE) {
 +                              ok = ED_object_posemode_exit_ex(bmain, ob);
 +                      }
 +                      else {
 +                              ok = ED_object_posemode_enter_ex(bmain, ob);
 +                      }
 +                      if (ok) {
 +                              ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT);
 +
 +                              Scene *scene = CTX_data_scene(C);
 +                              WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
 +                              WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 +                      }
 +              }
 +      }
  }
  
  /* ****************************************************** */
  /* Outliner Element Selection/Activation on Click */
  
 -static eOLDrawState tree_element_active_renderlayer(
 -        bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
 +static eOLDrawState active_viewlayer(
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
  {
        Scene *sce;
        
                return OL_DRAWSEL_NONE;
        sce = (Scene *)tselem->id;
        
 +      WorkSpace *workspace = CTX_wm_workspace(C);
 +      ViewLayer *view_layer = te->directdata;
 +
        if (set != OL_SETSEL_NONE) {
 -              sce->r.actlay = tselem->nr;
 -              WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, sce);
 +              BKE_workspace_view_layer_set(workspace, view_layer, sce);
 +              WM_event_add_notifier(C, NC_SCREEN | ND_LAYER, NULL);
        }
        else {
 -              return sce->r.actlay == tselem->nr;
 +              return BKE_workspace_view_layer_get(workspace, sce) == view_layer;
        }
        return OL_DRAWSEL_NONE;
  }
   * CTRL+LMB: Select/Deselect object and all children.
   * CTRL+SHIFT+LMB: Add/Remove object and all children.
   */
 -static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select)
 +static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, bool select)
  {
        Base *base;
  
 -      for (base = FIRSTBASE; base; base = base->next) {
 +      for (base = FIRSTBASE(view_layer); base; base = base->next) {
                Object *ob = base->object;
 -              if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
 -                      ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
 +              if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
 +                      ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
                }
        }
  }
@@@ -218,7 -184,7 +218,7 @@@ static void do_outliner_ebone_select_re
  }
  
  static eOLDrawState tree_element_set_active_object(
 -        bContext *C, Scene *scene, SpaceOops *soops,
 +        bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
          TreeElement *te, const eOLSetState set, bool recursive)
  {
        TreeStoreElem *tselem = TREESTORE(te);
        }
        else {
                ob = (Object *)outliner_search_back(soops, te, ID_OB);
 -              if (ob == OBACT) {
 +              if (ob == OBACT(view_layer)) {
                        return OL_DRAWSEL_NONE;
                }
        }
        
        sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
        if (sce && scene != sce) {
 -              ED_screen_set_scene(C, CTX_wm_screen(C), sce);
 +              WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
                scene = sce;
        }
        
        /* find associated base in current scene */
 -      base = BKE_scene_base_find(scene, ob);
 +      base = BKE_view_layer_base_find(view_layer, ob);
 +
 +#ifdef USE_OBJECT_MODE_STRICT
 +      if (base != NULL) {
 +              Object *obact = OBACT(view_layer);
 +              const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
 +              if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
 +                      if (object_mode == OB_MODE_OBJECT) {
 +                              struct Main *bmain = CTX_data_main(C);
 +                              Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                              ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object);
 +                      }
 +                      if (!BKE_object_is_mode_compat(base->object, object_mode)) {
 +                              base = NULL;
 +                      }
 +              }
 +      }
 +#endif
  
        if (base) {
                if (set == OL_SETSEL_EXTEND) {
                        /* swap select */
 -                      if (base->flag & SELECT)
 -                              ED_base_object_select(base, BA_DESELECT);
 +                      if (base->flag & BASE_SELECTED)
 +                              ED_object_base_select(base, BA_DESELECT);
                        else 
 -                              ED_base_object_select(base, BA_SELECT);
 +                              ED_object_base_select(base, BA_SELECT);
                }
                else {
                        /* deleselect all */
 -                      BKE_scene_base_deselect_all(scene);
 -                      ED_base_object_select(base, BA_SELECT);
 +#ifdef USE_OBJECT_MODE_STRICT
 +                      /* Only in object mode so we can switch the active object,
 +                       * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode.
 +                       * This keeps the convention that all objects in the current mode are also selected. see T55246. */
 +                      if (ob->mode == OB_MODE_OBJECT)
 +#endif
 +                      {
 +                              BKE_view_layer_base_deselect_all(view_layer);
 +                      }
 +                      ED_object_base_select(base, BA_SELECT);
                }
  
                if (recursive) {
                        /* Recursive select/deselect for Object hierarchies */
 -                      do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0);
 +                      do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0);
                }
  
 -              if (C) {
 -                      ED_base_object_activate(C, base); /* adds notifier */
 +              if (set != OL_SETSEL_NONE) {
 +                      ED_object_base_activate(C, base); /* adds notifier */
                        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
                }
 -      }
 -      
 -      if (ob != scene->obedit)
 -              ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
                
 +              if (ob != OBEDIT_FROM_VIEW_LAYER(view_layer)) {
 +                      ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
 +              }
 +      }
        return OL_DRAWSEL_NORMAL;
  }
  
  static eOLDrawState tree_element_active_material(
 -        bContext *C, Scene *scene, SpaceOops *soops,
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOops *soops,
          TreeElement *te, const eOLSetState set)
  {
        TreeElement *tes;
        /* we search for the object parent */
        ob = (Object *)outliner_search_back(soops, te, ID_OB);
        // note: ob->matbits can be NULL when a local object points to a library mesh.
 -      if (ob == NULL || ob != OBACT || ob->matbits == NULL) {
 +      if (ob == NULL || ob != OBACT(view_layer) || ob->matbits == NULL) {
                return OL_DRAWSEL_NONE;  /* just paranoia */
        }
        
                /* Tagging object for update seems a bit stupid here, but looks like we have to do it
                 * for render views to update. See T42973.
                 * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
 -              DAG_id_tag_update((ID *)ob, OB_RECALC_OB);
 +              DEG_id_tag_update((ID *)ob, OB_RECALC_OB);
                WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
        }
        return OL_DRAWSEL_NONE;
  }
  
 -static eOLDrawState tree_element_active_texture(
 -        bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
 -        TreeElement *te, const eOLSetState set)
 -{
 -      TreeElement *tep;
 -      TreeStoreElem /* *tselem,*/ *tselemp;
 -      Object *ob = OBACT;
 -      SpaceButs *sbuts = NULL;
 -      
 -      if (ob == NULL) {
 -              /* no active object */
 -              return OL_DRAWSEL_NONE;
 -      }
 -      
 -      /*tselem = TREESTORE(te);*/ /*UNUSED*/
 -      
 -      /* find buttons region (note, this is undefined really still, needs recode in blender) */
 -      /* XXX removed finding sbuts */
 -      
 -      /* where is texture linked to? */
 -      tep = te->parent;
 -      tselemp = TREESTORE(tep);
 -      
 -      if (tep->idcode == ID_WO) {
 -              World *wrld = (World *)tselemp->id;
 -
 -              if (set != OL_SETSEL_NONE) {
 -                      if (sbuts) {
 -                              // XXX sbuts->tabo = TAB_SHADING_TEX;   // hack from header_buttonswin.c
 -                              // XXX sbuts->texfrom = 1;
 -                      }
 -// XXX                        extern_set_butspace(F6KEY, 0);  // force shading buttons texture
 -                      wrld->texact = te->index;
 -              }
 -              else if (tselemp->id == (ID *)(scene->world)) {
 -                      if (wrld->texact == te->index) {
 -                              return OL_DRAWSEL_NORMAL;
 -                      }
 -              }
 -      }
 -      else if (tep->idcode == ID_LA) {
 -              Lamp *la = (Lamp *)tselemp->id;
 -              if (set != OL_SETSEL_NONE) {
 -                      if (sbuts) {
 -                              // XXX sbuts->tabo = TAB_SHADING_TEX;   // hack from header_buttonswin.c
 -                              // XXX sbuts->texfrom = 2;
 -                      }
 -// XXX                        extern_set_butspace(F6KEY, 0);  // force shading buttons texture
 -                      la->texact = te->index;
 -              }
 -              else {
 -                      if (tselemp->id == ob->data) {
 -                              if (la->texact == te->index) {
 -                                      return OL_DRAWSEL_NORMAL;
 -                              }
 -                      }
 -              }
 -      }
 -      else if (tep->idcode == ID_MA) {
 -              Material *ma = (Material *)tselemp->id;
 -              if (set != OL_SETSEL_NONE) {
 -                      if (sbuts) {
 -                              //sbuts->tabo = TAB_SHADING_TEX;        // hack from header_buttonswin.c
 -                              // XXX sbuts->texfrom = 0;
 -                      }
 -// XXX                        extern_set_butspace(F6KEY, 0);  // force shading buttons texture
 -                      ma->texact = (char)te->index;
 -                      
 -                      /* also set active material */
 -                      ob->actcol = tep->index + 1;
 -              }
 -              else if (tep->flag & TE_ACTIVE) {   // this is active material
 -                      if (ma->texact == te->index) {
 -                              return OL_DRAWSEL_NORMAL;
 -                      }
 -              }
 -      }
 -      
 -      if (set != OL_SETSEL_NONE) {
 -              WM_event_add_notifier(C, NC_TEXTURE, NULL);
 -      }
 -
 -      /* no active object */
 -      return OL_DRAWSEL_NONE;
 -}
 -
 -
  static eOLDrawState tree_element_active_lamp(
 -        bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
 +        bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOops *soops,
          TreeElement *te, const eOLSetState set)
  {
        Object *ob;
        
        /* we search for the object parent */
        ob = (Object *)outliner_search_back(soops, te, ID_OB);
 -      if (ob == NULL || ob != OBACT) {
 +      if (ob == NULL || ob != OBACT(view_layer)) {
                /* just paranoia */
                return OL_DRAWSEL_NONE;
        }
  }
  
  static eOLDrawState tree_element_active_camera(
 -        bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
 +        bContext *UNUSED(C), Scene *scene, ViewLayer *UNUSED(sl), SpaceOops *soops,
          TreeElement *te, const eOLSetState set)
  {
        Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
  }
  
  static eOLDrawState tree_element_active_world(
 -        bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
 +        bContext *C, Scene *scene, ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
          TreeElement *te, const eOLSetState set)
  {
        TreeElement *tep;
        if (set != OL_SETSEL_NONE) {
                /* make new scene active */
                if (sce && scene != sce) {
 -                      ED_screen_set_scene(C, CTX_wm_screen(C), sce);
 +                      WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
                }
        }
        
  }
  
  static eOLDrawState tree_element_active_defgroup(
 -        bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
 +        bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
  {
        Object *ob;
        
                BLI_assert(te->index + 1 >= 0);
                ob->actdef = te->index + 1;
  
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
        }
        else {
 -              if (ob == OBACT) {
 +              if (ob == OBACT(view_layer))
                        if (ob->actdef == te->index + 1) {
                                return OL_DRAWSEL_NORMAL;
                        }
 -              }
        }
        return OL_DRAWSEL_NONE;
  }
  
  static eOLDrawState tree_element_active_posegroup(
 -        bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
  {
        Object *ob = (Object *)tselem->id;
        
                }
        }
        else {
 -              if (ob == OBACT && ob->pose) {
 +              if (ob == OBACT(view_layer) && ob->pose) {
                        if (ob->pose->active_group == te->index + 1) {
                                return OL_DRAWSEL_NORMAL;
                        }
  }
  
  static eOLDrawState tree_element_active_posechannel(
 -        bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
  {
        Object *ob = (Object *)tselem->id;
        bArmature *arm = ob->data;
                }
        }
        else {
 -              if (ob == OBACT && ob->pose) {
 +              if (ob == OBACT(view_layer) && ob->pose) {
                        if (pchan->bone->flag & BONE_SELECTED) {
                                return OL_DRAWSEL_NORMAL;
                        }
  }
  
  static eOLDrawState tree_element_active_bone(
 -        bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
 +        bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
  {
        bArmature *arm = (bArmature *)tselem->id;
        Bone *bone = te->directdata;
        
        if (set != OL_SETSEL_NONE) {
                if (!(bone->flag & BONE_HIDDEN_P)) {
 -                      Object *ob = OBACT;
 +                      Object *ob = OBACT(view_layer);
                        if (ob) {
                                if (set != OL_SETSEL_EXTEND) {
                                        /* single select forces all other bones to get unselected */
                }
        }
        else {
 -              Object *ob = OBACT;
 +              Object *ob = OBACT(view_layer);
                
                if (ob && ob->data == arm) {
                        if (bone->flag & BONE_SELECTED) {
  
  
  /* ebones only draw in editmode armature */
 -static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature *arm, EditBone *ebone, short sel)
 +static void tree_element_active_ebone__sel(bContext *C, Object *obedit, bArmature *arm, EditBone *ebone, short sel)
  {
        if (sel) {
                ebone->flag |= BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL;
                if (ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag &= ~BONE_TIPSEL;
        }
  
 -      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, scene->obedit);
 +      WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, obedit);
  }
  static eOLDrawState tree_element_active_ebone(
 -        bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set, bool recursive)
 +        bContext *C, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set, bool recursive)
  {
 -      BLI_assert(scene->obedit != NULL);
 -
 -      bArmature *arm = scene->obedit->data;
 +      Object *obedit = CTX_data_edit_object(C);
 +      BLI_assert(obedit != NULL);
 +      bArmature *arm = obedit->data;
        EditBone *ebone = te->directdata;
        eOLDrawState status = OL_DRAWSEL_NONE;
  
        if (set != OL_SETSEL_NONE) {
                if (set == OL_SETSEL_NORMAL) {
                        if (!(ebone->flag & BONE_HIDDEN_A)) {
 -                              ED_armature_edit_deselect_all(scene->obedit);
 -                              tree_element_active_ebone__sel(C, scene, arm, ebone, true);
 +                              ED_armature_edit_deselect_all(obedit);
 +                              tree_element_active_ebone__sel(C, obedit, arm, ebone, true);
                                status = OL_DRAWSEL_NORMAL;
                        }
                }
                else if (set == OL_SETSEL_EXTEND) {
                        if (!(ebone->flag & BONE_HIDDEN_A)) {
                                if (!(ebone->flag & BONE_SELECTED)) {
 -                                      tree_element_active_ebone__sel(C, scene, arm, ebone, true);
 +                                      tree_element_active_ebone__sel(C, obedit, arm, ebone, true);
                                        status = OL_DRAWSEL_NORMAL;
                                }
                                else {
                                        /* entirely selected, so de-select */
 -                                      tree_element_active_ebone__sel(C, scene, arm, ebone, false);
 +                                      tree_element_active_ebone__sel(C, obedit, arm, ebone, false);
                                        status = OL_DRAWSEL_NONE;
                                }
                        }
  }
  
  static eOLDrawState tree_element_active_modifier(
 -        bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
  {
        if (set != OL_SETSEL_NONE) {
                Object *ob = (Object *)tselem->id;
@@@ -653,7 -682,7 +653,7 @@@ static eOLDrawState tree_element_active
  }
  
  static int tree_element_active_constraint(
 -        bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
 +        bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
  {
        if (set != OL_SETSEL_NONE) {
                Object *ob = (Object *)tselem->id;
  }
  
  static eOLDrawState tree_element_active_text(
 -        bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops),
 +        bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
          TreeElement *UNUSED(te), int UNUSED(set))
  {
        // XXX removed
  }
  
  static eOLDrawState tree_element_active_pose(
 -        bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
 +        bContext *C, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
  {
        Object *ob = (Object *)tselem->id;
 -      Base *base = BKE_scene_base_find(scene, ob);
 +      Base *base = BKE_view_layer_base_find(view_layer, ob);
  
        if (base == NULL) {
                /* Armature not instantiated in current scene (e.g. inside an appended group...). */
        }
  
        if (set != OL_SETSEL_NONE) {
 -              if (scene->obedit) {
 -                      ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
 -              }
 -              
 -              if (ob->mode & OB_MODE_POSE) {
 -                      ED_object_posemode_exit(C, ob);
 -              }
 -              else {
 -                      ED_object_posemode_enter(C, ob);
 -              }
 +              do_outliner_activate_pose(C, view_layer, base);
        }
        else {
                if (ob->mode & OB_MODE_POSE) {
@@@ -757,7 -795,7 +757,7 @@@ static eOLDrawState tree_element_active
  }
  
  static eOLDrawState tree_element_active_keymap_item(
 -        bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
 +        bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
  {
        wmKeyMapItem *kmi = te->directdata;
        
        return OL_DRAWSEL_NONE;
  }
  
 +static eOLDrawState tree_element_active_master_collection(
 +        bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
 +{
 +      if (set == OL_SETSEL_NONE) {
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              LayerCollection *active = CTX_data_layer_collection(C);
 +
 +              if (active == view_layer->layer_collections.first) {
 +                      return OL_DRAWSEL_NORMAL;
 +              }
 +      }
 +      else {
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              LayerCollection *layer_collection = view_layer->layer_collections.first;
 +              BKE_layer_collection_activate(view_layer, layer_collection);
 +              WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
 +      }
 +
 +      return OL_DRAWSEL_NONE;
 +}
 +
 +static eOLDrawState tree_element_active_layer_collection(
 +        bContext *C, TreeElement *te, const eOLSetState set)
 +{
 +      if (set == OL_SETSEL_NONE) {
 +              LayerCollection *active = CTX_data_layer_collection(C);
 +
 +              if (active == te->directdata) {
 +                      return OL_DRAWSEL_NORMAL;
 +              }
 +      }
 +      else {
 +              Scene *scene = CTX_data_scene(C);
 +              LayerCollection *layer_collection = te->directdata;
 +              ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
 +              BKE_layer_collection_activate(view_layer, layer_collection);
 +              WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
 +      }
 +
 +      return OL_DRAWSEL_NONE;
 +}
 +
  /* ---------------------------------------------- */
  
  /* generic call for ID data check or make/check active in UI */
 -eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te,
 +eOLDrawState tree_element_active(bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, TreeElement *te,
                                   const eOLSetState set, const bool handle_all_types)
  {
        switch (te->idcode) {
                /* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
 -               * selection. See do_outliner_item_activate_from_cursor. */
 +               * selection. See do_outliner_item_activate. */
                case ID_OB:
                        if (handle_all_types) {
 -                              return tree_element_set_active_object(C, scene, soops, te, set, false);
 +                              return tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
                        }
                        break;
                case ID_MA:
 -                      return tree_element_active_material(C, scene, soops, te, set);
 +                      return tree_element_active_material(C, scene, view_layer, soops, te, set);
                case ID_WO:
 -                      return tree_element_active_world(C, scene, soops, te, set);
 +                      return tree_element_active_world(C, scene, view_layer, soops, te, set);
                case ID_LA:
 -                      return tree_element_active_lamp(C, scene, soops, te, set);
 -              case ID_TE:
 -                      return tree_element_active_texture(C, scene, soops, te, set);
 +                      return tree_element_active_lamp(C, scene, view_layer, soops, te, set);
                case ID_TXT:
 -                      return tree_element_active_text(C, scene, soops, te, set);
 +                      return tree_element_active_text(C, scene, view_layer, soops, te, set);
                case ID_CA:
 -                      return tree_element_active_camera(C, scene, soops, te, set);
 +                      return tree_element_active_camera(C, scene, view_layer, soops, te, set);
        }
        return OL_DRAWSEL_NONE;
  }
  
  /**
   * Generic call for non-id data to make/check active in UI
 - *
 - * \note Context can be NULL when ``(set == OL_SETSEL_NONE)``
   */
  eOLDrawState tree_element_type_active(
 -        bContext *C, Scene *scene, SpaceOops *soops,
 +        bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
          TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
  {
        switch (tselem->type) {
                case TSE_DEFGROUP:
 -                      return tree_element_active_defgroup(C, scene, te, tselem, set);
 +                      return tree_element_active_defgroup(C, view_layer, te, tselem, set);
                case TSE_BONE:
 -                      return tree_element_active_bone(C, scene, te, tselem, set, recursive);
 +                      return tree_element_active_bone(C, view_layer, te, tselem, set, recursive);
                case TSE_EBONE:
 -                      return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
 +                      return tree_element_active_ebone(C, te, tselem, set, recursive);
                case TSE_MODIFIER:
 -                      return tree_element_active_modifier(C, te, tselem, set);
 +                      return tree_element_active_modifier(C, scene, view_layer, te, tselem, set);
                case TSE_LINKED_OB:
                        if (set != OL_SETSEL_NONE) {
 -                              tree_element_set_active_object(C, scene, soops, te, set, false);
 +                              tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
                        }
 -                      else if (tselem->id == (ID *)OBACT) {
 +                      else if (tselem->id == (ID *)OBACT(view_layer)) {
                                return OL_DRAWSEL_NORMAL;
                        }
                        break;
                case TSE_LINKED_PSYS:
                        return tree_element_active_psys(C, scene, te, tselem, set);
                case TSE_POSE_BASE:
 -                      return tree_element_active_pose(C, scene, te, tselem, set);
 +                      return tree_element_active_pose(C, view_layer, te, tselem, set);
                case TSE_POSE_CHANNEL:
 -                      return tree_element_active_posechannel(C, scene, te, tselem, set, recursive);
 +                      return tree_element_active_posechannel(C, scene, view_layer, te, tselem, set, recursive);
                case TSE_CONSTRAINT:
 -                      return tree_element_active_constraint(C, te, tselem, set);
 +                      return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
                case TSE_R_LAYER:
 -                      return tree_element_active_renderlayer(C, te, tselem, set);
 +                      return active_viewlayer(C, scene, view_layer, te, tselem, set);
                case TSE_POSEGRP:
 -                      return tree_element_active_posegroup(C, scene, te, tselem, set);
 +                      return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
                case TSE_SEQUENCE:
                        return tree_element_active_sequence(C, scene, te, tselem, set);
                case TSE_SEQUENCE_DUP:
                        return tree_element_active_sequence_dup(scene, te, tselem, set);
                case TSE_KEYMAP_ITEM:
 -                      return tree_element_active_keymap_item(C, te, tselem, set);
 +                      return tree_element_active_keymap_item(C, scene, view_layer, te, tselem, set);
                case TSE_GP_LAYER:
 -                      //return tree_element_active_gplayer(C, scene, te, tselem, set);
 +                      //return tree_element_active_gplayer(C, scene, s, te, tselem, set);
                        break;
 -                      
 +              case TSE_VIEW_COLLECTION_BASE:
 +                      return tree_element_active_master_collection(C, te, set);
 +              case TSE_LAYER_COLLECTION:
 +                      return tree_element_active_layer_collection(C, te, set);
        }
        return OL_DRAWSEL_NONE;
  }
   * Needed to run from operators accessed from a menu.
   */
  static void do_outliner_item_activate_tree_element(
 -        bContext *C, Scene *scene, SpaceOops *soops,
 +        bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
          TreeElement *te, TreeStoreElem *tselem,
 -        bool extend, bool recursive)
 +        const bool extend, const bool recursive)
  {
 -      /* always makes active object, except for some specific types.
 -       * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
 -       * to switch out of edit mode (see T48328 for details). */
 -      if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
 +      /* Always makes active object, except for some specific types. */
 +      if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
 +              /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
 +               * to switch out of edit mode (see T48328 for details). */
 +      }
 +      else if (tselem->id && OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
 +              /* Support edit-mode toggle, keeping the active object as is. */
 +      }
 +      else if (tselem->type == TSE_POSE_BASE) {
 +              /* Support pose mode toggle, keeping the active object as is. */
 +      }
 +      else {
                tree_element_set_active_object(
 -                      C, scene, soops, te,
 +                      C, scene, view_layer, soops, te,
                        (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
                        recursive && tselem->type == 0);
        }
                /* editmode? */
                if (te->idcode == ID_SCE) {
                        if (scene != (Scene *)tselem->id) {
 -                              ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
 +                              WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
                        }
                }
                else if (te->idcode == ID_GR) {
 -                      Group *gr = (Group *)tselem->id;
 -                      GroupObject *gob;
 +                      Collection *gr = (Collection *)tselem->id;
  
                        if (extend) {
                                int sel = BA_SELECT;
 -                              for (gob = gr->gobject.first; gob; gob = gob->next) {
 -                                      if (gob->ob->flag & SELECT) {
 +                              FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(gr, base)
 +                              {
 +                                      if (base->flag & BASE_SELECTED) {
                                                sel = BA_DESELECT;
                                                break;
                                        }
                                }
 +                              FOREACH_COLLECTION_BASE_RECURSIVE_END
  
 -                              for (gob = gr->gobject.first; gob; gob = gob->next) {
 -                                      ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
 +                              FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
 +                              {
 +                                      ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
                                }
 +                              FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
                        }
                        else {
 -                              BKE_scene_base_deselect_all(scene);
 -
 -                              for (gob = gr->gobject.first; gob; gob = gob->next) {
 -                                      if ((gob->ob->flag & SELECT) == 0)
 -                                              ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
 +                              BKE_view_layer_base_deselect_all(view_layer);
 +
 +                              FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
 +                              {
 +                                      Base *base = BKE_view_layer_base_find(view_layer, object);
 +                                      /* Object may not be in this scene */
 +                                      if (base != NULL) {
 +                                              if ((base->flag & BASE_SELECTED) == 0) {
 +                                                      ED_object_base_select(base, BA_SELECT);
 +                                              }
 +                                      }
                                }
 +                              FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
                        }
 -
 +                      
                        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
                }
                else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
 -                      WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
 +                      Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
 +                      if ((ob != NULL) && (ob->data == tselem->id)) {
 +                              Base *base = BKE_view_layer_base_find(view_layer, ob);
 +                              if ((base != NULL) && (base->flag & BASE_VISIBLED)) {
 +                                      do_outliner_activate_obdata(C, scene, view_layer, base);
 +                              }
 +                      }
                }
                else {  // rest of types
 -                      tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
 +                      tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
                }
  
        }
        else {
 -              tree_element_type_active(
 -                      C, scene, soops, te, tselem,
 -                      extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
 -                      recursive);
 +              tree_element_type_active(C, scene, view_layer, soops, te, tselem,
 +                                       extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
 +                                       recursive);
        }
  }
  
  /**
 - * Activates tree items, also handles clicking on arrows.
 + * \param extend: Don't deselect other items, only modify \a te.
 + * \param toggle: Select \a te when not selected, deselect when selected.
   */
 -static bool do_outliner_item_activate_from_cursor(
 -        bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
 -        TreeElement *te, bool extend, bool recursive, const float mval[2])
 +void outliner_item_select(SpaceOops *soops, const TreeElement *te, const bool extend, const bool toggle)
  {
 -      if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
 -              TreeStoreElem *tselem = TREESTORE(te);
 -              bool openclose = false;
 -              
 -              /* open close icon */
 -              if ((te->flag & TE_ICONROW) == 0) {               // hidden icon, no open/close
 -                      if (mval[0] > te->xs && mval[0] < te->xs + UI_UNIT_X)
 -                              openclose = true;
 -              }
 -              
 -              if (openclose) {
 -                      /* all below close/open? */
 -                      if (extend) {
 -                              tselem->flag &= ~TSE_CLOSED;
 -                              outliner_set_flag(&te->subtree, TSE_CLOSED, !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1));
 -                      }
 -                      else {
 -                              if (tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
 -                              else tselem->flag |= TSE_CLOSED;
 -                              
 -                      }
 -                      
 -                      return true;
 -              }
 -              /* name and first icon */
 -              else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
 -                      do_outliner_item_activate_tree_element(
 -                              C, scene, soops,
 -                              te, tselem,
 -                              extend, recursive);
 -                      return true;
 -              }
 +      TreeStoreElem *tselem = TREESTORE(te);
 +      const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
 +
 +      if (extend == false) {
 +              outliner_set_flag(&soops->tree, TSE_SELECTED, false);
        }
 -      
 -      for (te = te->subtree.first; te; te = te->next) {
 -              if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) {
 -                      return true;
 -              }
 +      tselem->flag = new_flag;
 +}
 +
 +static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
 +{
 +      TreeStoreElem *tselem = TREESTORE(te);
 +      if (toggle_children) {
 +              tselem->flag &= ~TSE_CLOSED;
 +
 +              const bool all_opened = !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1);
 +              outliner_set_flag(&te->subtree, TSE_CLOSED, all_opened);
 +      }
 +      else {
 +              tselem->flag ^= TSE_CLOSED;
        }
 -      return false;
 +}
 +
 +static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
 +{
 +      return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
 +}
 +
 +static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
 +{
 +      return ((soops->outlinevis != SO_DATA_API) &&
 +              !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
 +              (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
  }
  
  /**
@@@ -1045,11 -1027,10 +1045,11 @@@ void outliner_item_do_activate_from_tre
          bool extend, bool recursive)
  {
        Scene *scene = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        SpaceOops *soops = CTX_wm_space_outliner(C);
  
        do_outliner_item_activate_tree_element(
 -              C, scene, soops,
 +              C, scene, view_layer, soops,
                te, tselem,
                extend, recursive);
  }
@@@ -1063,53 -1044,56 +1063,53 @@@ int outliner_item_do_activate_from_curs
          bContext *C, const int mval[2],
          bool extend, bool recursive)
  {
 -      Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
        SpaceOops *soops = CTX_wm_space_outliner(C);
        TreeElement *te;
 -      float fmval[2];
 +      float view_mval[2];
 +      bool changed = false, rebuild_tree = false;
  
 -      UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]);
 +      UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
  
 -      if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
 -          !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
 -          (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX))
 -      {
 +      if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
                return OPERATOR_CANCELLED;
        }
  
 -      for (te = soops->tree.first; te; te = te->next) {
 -              if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) {
 -                      break;
 -              }
 +      if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
 +              /* skip */
        }
 -      
 -      if (te) {
 -              ED_undo_push(C, "Outliner click event");
 +      else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
 +              outliner_item_toggle_closed(te, extend);
 +              changed = true;
 +              rebuild_tree = true;
        }
        else {
 -              short selecting = -1;
 -              int row;
 -              
 -              /* get row number - 100 here is just a dummy value since we don't need the column */
 -              UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET, 
 -                                              fmval[0], fmval[1], NULL, &row);
 -              
 -              /* select relevant row */
 -              if (outliner_select(soops, &soops->tree, &row, &selecting)) {
 -              
 -                      soops->storeflag |= SO_TREESTORE_REDRAW;
 -              
 -                      /* no need for undo push here, only changing outliner data which is
 -                       * scene level - campbell */
 -                      /* ED_undo_push(C, "Outliner selection event"); */
 +              Scene *scene = CTX_data_scene(C);
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              /* the row may also contain children, if one is hovered we want this instead of current te */
 +              TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
 +              TreeStoreElem *activate_tselem = TREESTORE(activate_te);
 +
 +              outliner_item_select(soops, activate_te, extend, extend);
 +              do_outliner_item_activate_tree_element(C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
 +              changed = true;
 +      }
 +
 +      if (changed) {
 +              if (rebuild_tree) {
 +                      ED_region_tag_redraw(ar);
                }
 +              else {
 +                      ED_region_tag_redraw_no_rebuild(ar);
 +              }
 +              ED_undo_push(C, "Outliner selection change");
        }
 -      
 -      ED_region_tag_redraw(ar);
  
        return OPERATOR_FINISHED;
  }
  
  /* event can enterkey, then it opens/closes */
 -static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event)
 +static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
  {
        bool extend    = RNA_boolean_get(op->ptr, "extend");
        bool recursive = RNA_boolean_get(op->ptr, "recursive");
@@@ -1122,7 -1106,7 +1122,7 @@@ void OUTLINER_OT_item_activate(wmOperat
        ot->idname = "OUTLINER_OT_item_activate";
        ot->description = "Handle mouse clicks to activate/select items";
        
 -      ot->invoke = outliner_item_activate;
 +      ot->invoke = outliner_item_activate_invoke;
        
        ot->poll = ED_operator_outliner_active;
        
index caa3ba593fb8d8e202810b25181c8fd0d67ae144,8315a0eab3d717d797121ce9d38ce8da16d72e04..6968702b9582c26e14921a7c93340c0daf00e9f3
@@@ -69,7 -69,7 +69,7 @@@
  #include "BKE_sound.h"
  
  #ifdef WITH_AUDASPACE
 -#  include AUD_SEQUENCE_H
 +#  include <AUD_Sequence.h>
  #endif
  
  /* own include */
@@@ -114,9 -114,10 +114,10 @@@ static void sequencer_generic_invoke_pa
                Scene *scene = CTX_data_scene(C);
                Sequence *last_seq = BKE_sequencer_active_get(scene);
                if (last_seq && last_seq->strip && SEQ_HAS_PATH(last_seq)) {
+                       Main *bmain = CTX_data_main(C);
                        char path[FILE_MAX];
                        BLI_strncpy(path, last_seq->strip->dir, sizeof(path));
-                       BLI_path_abs(path, G.main->name);
+                       BLI_path_abs(path, bmain->name);
                        RNA_string_set(op->ptr, identifier, path);
                }
        }
@@@ -173,8 -174,10 +174,10 @@@ static void sequencer_generic_invoke_xy
        }
  }
  
- static void seq_load_operator_info(SeqLoadInfo *seq_load, wmOperator *op)
+ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperator *op)
  {
+       Main *bmain = CTX_data_main(C);
        PropertyRNA *prop;
        const bool relative = (prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop);
        int is_file = -1;
        }
  
        if ((is_file != -1) && relative)
-               BLI_path_rel(seq_load->path, G.main->name);
+               BLI_path_rel(seq_load->path, bmain->name);
  
        
        if ((prop = RNA_struct_find_property(op->ptr, "frame_end"))) {
@@@ -545,7 -548,7 +548,7 @@@ static int sequencer_add_generic_strip_
        SeqLoadInfo seq_load;
        int tot_files;
  
-       seq_load_operator_info(&seq_load, op);
+       seq_load_operator_info(&seq_load, C, op);
  
        if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
                ED_sequencer_deselect_all(scene);
@@@ -690,7 -693,7 +693,7 @@@ static void sequencer_add_draw(bContex
  
        /* main draw call */
        RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
 -      uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, '\0');
 +      uiDefAutoButsRNA(layout, &ptr, sequencer_add_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
  
        /* image template */
        RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
@@@ -855,7 -858,7 +858,7 @@@ static int sequencer_add_image_strip_ex
        StripElem *se;
        const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
  
-       seq_load_operator_info(&seq_load, op);
+       seq_load_operator_info(&seq_load, C, op);
  
        /* images are unique in how they handle this - 1 per strip elem */
        if (use_placeholders) {
index d82028ef2c9ba914c0e7933e4e34de747bddcb33,a052b76e85347541e532584b7c190fc036172216..999e0fbf2a4d51b53628549c5b977fd13566e80b
@@@ -71,6 -71,7 +71,6 @@@
  #include "UI_view2d.h"
  #include "UI_interface.h"
  
 -
  /* own include */
  #include "sequencer_intern.h"
  
@@@ -128,9 -129,8 +128,9 @@@ typedef struct TransSeq 
  /* ***************** proxy job manager ********************** */
  
  typedef struct ProxyBuildJob {
 -      Scene *scene; 
        struct Main *main;
 +      struct Depsgraph *depsgraph;
 +      Scene *scene; 
        ListBase queue;
        int stop;
  } ProxyJob;
@@@ -182,7 -182,6 +182,7 @@@ static void seq_proxy_build_job(const b
  {
        wmJob *wm_job;
        ProxyJob *pj;
 +      struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Editing *ed = BKE_sequencer_editing_get(scene, false);
        ScrArea *sa = CTX_wm_area(C);
        if (!pj) {
                pj = MEM_callocN(sizeof(ProxyJob), "proxy rebuild job");
        
 +              pj->depsgraph = depsgraph;
                pj->scene = scene;
                pj->main = CTX_data_main(C);
  
        SEQP_BEGIN (ed, seq)
        {
                if ((seq->flag & SELECT)) {
 -                      BKE_sequencer_proxy_rebuild_context(pj->main, pj->scene, seq, file_list, &pj->queue);
 +                      BKE_sequencer_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
                }
        }
        SEQ_END
@@@ -1290,6 -1288,7 +1290,6 @@@ typedef struct SlipData 
        int num_seq;
        bool slow;
        int slow_offset; /* offset at the point where offset was turned on */
 -      void *draw_handle;
        NumInput num_input;
  } SlipData;
  
@@@ -1324,6 -1323,21 +1324,6 @@@ static void transseq_restore(TransSeq *
        seq->len = ts->len;
  }
  
 -static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
 -{
 -      Scene *scene = CTX_data_scene(C);
 -      SlipData *td = data;
 -      int i;
 -
 -      for (i = 0; i < td->num_seq; i++) {
 -              Sequence *seq = td->seq_array[i];
 -
 -              if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
 -                      draw_sequence_extensions(scene, ar, seq);
 -              }
 -      }
 -}
 -
  static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
  {
        Sequence *seq;
@@@ -1372,6 -1386,7 +1372,6 @@@ static int sequencer_slip_invoke(bConte
        SlipData *data;
        Scene *scene = CTX_data_scene(C);
        Editing *ed = BKE_sequencer_editing_get(scene, false);
 -      ARegion *ar = CTX_wm_region(C);
        float mouseloc[2];
        int num_seq, i;
        View2D *v2d = UI_view2d_fromcontext(C);
                transseq_backup(data->ts + i, data->seq_array[i]);
        }
  
 -      data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
 -
        UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
  
        copy_v2_v2_int(data->init_mouse, event->mval);
@@@ -1542,6 -1559,7 +1542,6 @@@ static int sequencer_slip_modal(bContex
        Scene *scene = CTX_data_scene(C);
        SlipData *data = (SlipData *)op->customdata;
        ScrArea *sa = CTX_wm_area(C);
 -      ARegion *ar = CTX_wm_region(C);
        const bool has_numInput = hasNumInput(&data->num_input);
        bool handled = true;
  
                case RETKEY:
                case SPACEKEY:
                {
 -                      ED_region_draw_cb_exit(ar->type, data->draw_handle);
                        MEM_freeN(data->seq_array);
                        MEM_freeN(data->trim);
                        MEM_freeN(data->ts);
                                BKE_sequence_calc(scene, seq);
                        }
  
 -                      ED_region_draw_cb_exit(ar->type, data->draw_handle);
 -
                        MEM_freeN(data->seq_array);
                        MEM_freeN(data->ts);
                        MEM_freeN(data->trim);
@@@ -3459,7 -3480,6 +3459,7 @@@ static int sequencer_rebuild_proxy_invo
  static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
  {
        Main *bmain = CTX_data_main(C);
 +      struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Editing *ed = BKE_sequencer_editing_get(scene, false);
        Sequence *seq;
                        short stop = 0, do_update;
                        float progress;
  
 -                      BKE_sequencer_proxy_rebuild_context(bmain, scene, seq, file_list, &queue);
 +                      BKE_sequencer_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue);
  
                        for (link = queue.first; link; link = link->next) {
                                struct SeqIndexBuildContext *context = link->data;
@@@ -3865,13 -3885,14 +3865,14 @@@ void SEQUENCER_OT_change_path(struct wm
  
  static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
  {
+       Main *bmain = CTX_data_main(C);
        if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
                char filepath[FILE_MAX];
  
-               if (G.main->name[0] == 0)
+               if (bmain->name[0] == '\0')
                        BLI_strncpy(filepath, "untitled", sizeof(filepath));
                else
-                       BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+                       BLI_strncpy(filepath, bmain->name, sizeof(filepath));
  
                BLI_replace_extension(filepath, sizeof(filepath), ".srt");
                RNA_string_set(op->ptr, "filepath", filepath);
index 6751577bfda7c095cce529704727a5edf70e7b45,ee552e53d9701eaa2249fd40e9ee4fdac991cb40..0672a8ab7636a04a10b4bc3f59ce384b77e6a54d
@@@ -35,7 -35,6 +35,7 @@@
  
  #include "MEM_guardedalloc.h"
  
 +#include "DNA_armature_types.h"
  #include "DNA_mesh_types.h"
  #include "DNA_object_types.h"
  #include "DNA_screen_types.h"
  #include "BKE_global.h"
  #include "BKE_main.h"
  #include "BKE_multires.h"
 +#include "BKE_object.h"
  #include "BKE_packedFile.h"
  #include "BKE_paint.h"
  #include "BKE_screen.h"
 +#include "BKE_workspace.h"
 +#include "BKE_layer.h"
  #include "BKE_undo_system.h"
  
  #include "ED_armature.h"
@@@ -75,8 -71,6 +75,8 @@@
  #include "ED_space_api.h"
  #include "ED_util.h"
  
 +#include "GPU_immediate.h"
 +
  #include "UI_interface.h"
  #include "UI_resources.h"
  
  
  void ED_editors_init(bContext *C)
  {
 -      wmWindowManager *wm = CTX_wm_manager(C);
        Main *bmain = CTX_data_main(C);
 -      Scene *sce = CTX_data_scene(C);
 -      Object *ob, *obact = (sce && sce->basact) ? sce->basact->object : NULL;
 -      ID *data;
 +      wmWindowManager *wm = CTX_wm_manager(C);
  
        if (wm->undo_stack == NULL) {
                wm->undo_stack = BKE_undosys_stack_create();
        /* toggle on modes for objects that were saved with these enabled. for
         * e.g. linked objects we have to ensure that they are actually the
         * active object in this scene. */
 -      for (ob = bmain->object.first; ob; ob = ob->id.next) {
 -              int mode = ob->mode;
 -
 -              if (!ELEM(mode, OB_MODE_OBJECT, OB_MODE_POSE)) {
 -                      ob->mode = OB_MODE_OBJECT;
 -                      data = ob->data;
 +      Object *obact = CTX_data_active_object(C);
 +      if (obact != NULL) {
 +              for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
 +                      int mode = ob->mode;
  
 -                      if (ob == obact && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data)))
 -                              ED_object_mode_toggle(C, mode);
 +                      if (mode == OB_MODE_OBJECT) {
 +                              /* pass */
 +                      }
 +                      else if (!BKE_object_has_mode_data(ob, mode)) {
 +                              /* For multi-edit mode we may already have mode data. */
 +                              ID *data = ob->data;
 +                              ob->mode = OB_MODE_OBJECT;
 +                              if ((ob == obact) && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) {
 +                                      ED_object_mode_toggle(C, mode);
 +                              }
 +                      }
                }
        }
  
        /* image editor paint mode */
 -      if (sce) {
 -              ED_space_image_paint_update(wm, sce);
 +      {
 +              Scene *sce = CTX_data_scene(C);
 +              if (sce) {
 +                      ED_space_image_paint_update(wm, sce);
 +              }
        }
  
        SWAP(int, reports->flag, reports_flag_prev);
  void ED_editors_exit(bContext *C)
  {
        Main *bmain = CTX_data_main(C);
 -      Scene *sce;
  
        if (!bmain)
                return;
 -      
 +
        /* frees all editmode undos */
        if (G.main->wm.first) {
                wmWindowManager *wm = G.main->wm.first;
                }
        }
  
 -      for (sce = bmain->scene.first; sce; sce = sce->id.next) {
 -              if (sce->obedit) {
 -                      Object *ob = sce->obedit;
 -              
 -                      if (ob) {
 -                              if (ob->type == OB_MESH) {
 -                                      Mesh *me = ob->data;
 -                                      if (me->edit_btmesh) {
 -                                              EDBM_mesh_free(me->edit_btmesh);
 -                                              MEM_freeN(me->edit_btmesh);
 -                                              me->edit_btmesh = NULL;
 -                                      }
 -                              }
 -                              else if (ob->type == OB_ARMATURE) {
 -                                      ED_armature_edit_free(ob->data);
 -                              }
 +      for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
 +              if (ob->type == OB_MESH) {
 +                      Mesh *me = ob->data;
 +                      if (me->edit_btmesh) {
 +                              EDBM_mesh_free(me->edit_btmesh);
 +                              MEM_freeN(me->edit_btmesh);
 +                              me->edit_btmesh = NULL;
 +                      }
 +              }
 +              else if (ob->type == OB_ARMATURE) {
 +                      bArmature *arm = ob->data;
 +                      if (arm->edbo) {
 +                              ED_armature_edit_free(ob->data);
                        }
                }
        }
@@@ -210,7 -201,7 +210,7 @@@ bool ED_editors_flush_edits(const bCont
                else if (ob->mode & OB_MODE_EDIT) {
                        /* get editmode results */
                        has_edited = true;
-                       ED_object_editmode_load(ob);
+                       ED_object_editmode_load(bmain, ob);
                }
        }
  
@@@ -338,28 -329,16 +338,28 @@@ void ED_region_draw_mouse_line_cb(cons
  {
        wmWindow *win = CTX_wm_window(C);
        const float *mval_src = (float *)arg_info;
 -      const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
 -                               win->eventstate->y - ar->winrct.ymin};
 -
 -      UI_ThemeColor(TH_VIEW_OVERLAY);
 -      setlinestyle(3);
 -      glBegin(GL_LINES);
 -      glVertex2iv(mval_dst);
 -      glVertex2fv(mval_src);
 -      glEnd();
 -      setlinestyle(0);
 +      const float mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
 +                                 win->eventstate->y - ar->winrct.ymin};
 +
 +      const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
 +
 +      float viewport_size[4];
 +      glGetFloatv(GL_VIEWPORT, viewport_size);
 +      immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
 +
 +      immUniform1i("num_colors", 0);  /* "simple" mode */
 +      immUniformThemeColor(TH_VIEW_OVERLAY);
 +      immUniform1f("dash_width", 6.0f);
 +      immUniform1f("dash_factor", 0.5f);
 +
 +      immBegin(GWN_PRIM_LINES, 2);
 +      immVertex2fv(shdr_pos, mval_src);
 +      immVertex2fv(shdr_pos, mval_dst);
 +      immEnd();
 +
 +      immUnbindProgram();
  }
  
  /**
index c62e8ed4da8ea7ae7fe2abc31c3d668637e43b0c,5e7438ce4ee1b232aeedd78d96f68a1e2419de5b..134ec2cc17088c4697831e87797e1ff0080cf0e9
@@@ -32,6 -32,7 +32,6 @@@ endif(
  set(DEFSRC
        rna_ID.c
        rna_action.c
 -      rna_actuator.c
        rna_animation.c
        rna_animviz.c
        rna_armature.c
@@@ -43,6 -44,7 +43,6 @@@
        rna_color.c
        rna_constraint.c
        rna_context.c
 -      rna_controller.c
        rna_curve.c
        rna_depsgraph.c
        rna_dynamicpaint.c
@@@ -54,7 -56,6 +54,7 @@@
        rna_key.c
        rna_lamp.c
        rna_lattice.c
 +      rna_layer.c
        rna_linestyle.c
        rna_main.c
        rna_mask.c
        rna_palette.c
        rna_particle.c
        rna_pose.c
 -      rna_property.c
 +      rna_lightprobe.c
        rna_render.c
        rna_rigidbody.c
        rna_rna.c
        rna_scene.c
        rna_screen.c
        rna_sculpt_paint.c
 -      rna_sensor.c
        rna_sequencer.c
        rna_smoke.c
        rna_sound.c
        rna_userdef.c
        rna_vfont.c
        rna_wm.c
 +      rna_wm_manipulator.c
 +      rna_workspace.c
        rna_world.c
  )
  
  set(APISRC
        rna_action_api.c
 -      rna_actuator_api.c
        rna_animation_api.c
        rna_armature_api.c
        rna_camera_api.c
 -      rna_controller_api.c
        rna_curve_api.c
        rna_fcurve_api.c
        rna_image_api.c
        rna_object_api.c
        rna_pose_api.c
        rna_scene_api.c
 -      rna_sensor_api.c
        rna_sequencer_api.c
        rna_sound_api.c
        rna_space_api.c
        rna_ui_api.c
        rna_vfont_api.c
        rna_wm_api.c
 +      rna_wm_manipulator_api.c
 +      rna_workspace_api.c
  )
  
  string(REGEX REPLACE "rna_([a-zA-Z0-9_-]*).c" "${CMAKE_CURRENT_BINARY_DIR}/rna_\\1_gen.c" GENSRC "${DEFSRC}")
@@@ -187,8 -188,8 +187,8 @@@ if(WITH_PYTHON
        )
  endif()
  
 -if(WITH_GAMEENGINE)
 -      add_definitions(-DWITH_GAMEENGINE)
 +if(WITH_CLAY_ENGINE)
 +      add_definitions(-DWITH_CLAY_ENGINE)
  endif()
  
  if(WITH_IMAGE_OPENEXR)
@@@ -219,8 -220,12 +219,8 @@@ if(WITH_IMAGE_HDR
        add_definitions(-DWITH_HDR)
  endif()
  
 -if(WITH_IMAGE_FRAMESERVER)
 -      add_definitions(-DWITH_FRAMESERVER)
 -endif()
 -
  if(WITH_AUDASPACE)
 -      add_definitions(${AUDASPACE_DEFINITIONS})
 +      add_definitions(-DWITH_AUDASPACE)
  
        list(APPEND INC_SYS
                ${AUDASPACE_C_INCLUDE_DIRS}
@@@ -329,7 -334,6 +329,7 @@@ blender_include_dirs
        ../../bmesh
        ../../blentranslation
        ../../depsgraph
 +      ../../draw
        ../../gpu
        ../../imbuf
        ../../ikplugin
@@@ -352,6 -356,7 +352,7 @@@ blender_include_dirs_sys
  )
  
  add_cc_flags_custom_test(makesrna)
+ setup_platform_linker_flags()
  
  add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC})
  
index a01192dad68cba2c79762d416e49c8289515a2a8,7571194b2fd71b1005516b6c87b22471da5ae032..a837a2ff0320710a3a6d5134c6d3ce696be0e5ed
  #include "RNA_define.h"
  
  #include "DNA_constraint_types.h"
 +#include "DNA_layer_types.h"
  #include "DNA_modifier_types.h"
  #include "DNA_object_types.h"
  
 -#include "BKE_depsgraph.h"
 +#include "BKE_layer.h"
 +
 +#include "DEG_depsgraph.h"
  
  #include "rna_internal.h"  /* own include */
  
@@@ -89,65 -86,9 +89,65 @@@ static const EnumPropertyItem space_ite
  #include "DNA_scene_types.h"
  #include "DNA_view3d_types.h"
  
 +#include "DEG_depsgraph_query.h"
 +
  #include "MEM_guardedalloc.h"
  
 -#include "DEG_depsgraph.h"
 +static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action)
 +{
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Base *base = BKE_view_layer_base_find(view_layer, ob);
 +
 +      if (!base) {
 +              BKE_reportf(reports, RPT_ERROR, "Object '%s' not in View Layer '%s'!", ob->id.name + 2, view_layer->name);
 +              return;
 +      }
 +
 +      if (action == 2) { /* TOGGLE */
 +              if ((base->flag & BASE_SELECTED) != 0) {
 +                      action = 1; /* DESELECT */
 +              }
 +              else {
 +                      action = 0; /* SELECT */
 +              }
 +      }
 +
 +      switch (action) {
 +              case 1: /* DESELECT */
 +                      base->flag &= ~BASE_SELECTED;
 +                      break;
 +              case 0: /* SELECT */
 +              default:
 +                      BKE_view_layer_base_select(view_layer, base);
 +                      break;
 +      }
 +}
 +
 +static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports)
 +{
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Base *base = BKE_view_layer_base_find(view_layer, ob);
 +
 +      if (!base) {
 +              BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
 +              return -1;
 +      }
 +
 +      return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0;
 +}
 +
 +static int rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
 +{
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Base *base = BKE_view_layer_base_find(view_layer, ob);
 +
 +      if (!base) {
 +              BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
 +              return -1;
 +      }
 +
 +      return ((base->flag & BASE_VISIBLED) != 0) ? 1 : 0;
 +}
  
  /* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
  static void rna_Object_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
  }
  
  static void rna_Object_calc_matrix_camera(
 -        Object *ob, float mat_ret[16], int width, int height, float scalex, float scaley)
 +        Object *ob, Depsgraph *depsgraph, float mat_ret[16], int width, int height, float scalex, float scaley)
  {
 +      const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        CameraParams params;
  
        /* setup parameters */
        BKE_camera_params_init(&params);
 -      BKE_camera_params_from_object(&params, ob);
 +      BKE_camera_params_from_object(&params, ob_eval);
  
        /* compute matrix, viewplane, .. */
        BKE_camera_params_compute_viewplane(&params, width, height, scalex, scaley);
  }
  
  static void rna_Object_camera_fit_coords(
 -        Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret)
 +        Object *ob, Depsgraph *depsgraph, int num_cos, float *cos, float co_ret[3], float *scale_ret)
  {
 -      BKE_camera_view_frame_fit_to_coords(scene, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret);
 +      BKE_camera_view_frame_fit_to_coords(depsgraph, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret);
  }
  
  /* copied from Mesh_getFromObject and adapted to RNA interface */
  /* settings: 0 - preview, 1 - render */
  static Mesh *rna_Object_to_mesh(
 -        Object *ob, Main *bmain, ReportList *reports, Scene *sce,
 -        int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
 -{
 -      return rna_Main_meshes_new_from_object(bmain, reports, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
 -}
 -
 -/* mostly a copy from convertblender.c */
 -static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int enable)
 +        Object *ob, bContext *C, ReportList *reports, Depsgraph *depsgraph,
 +        int apply_modifiers, int calc_tessface, int calc_undeformed)
  {
 -      /* ugly function, but we need to set particle systems to their render
 -       * settings before calling object_duplilist, to get render level duplis */
 -      Group *group;
 -      GroupObject *go;
 -      ParticleSystem *psys;
 -      DerivedMesh *dm;
 -      float mat[4][4];
 -
 -      unit_m4(mat);
 -
 -      if (level >= MAX_DUPLI_RECUR)
 -              return;
 -      
 -      if (ob->transflag & OB_DUPLIPARTS) {
 -              for (psys = ob->particlesystem.first; psys; psys = psys->next) {
 -                      if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
 -                              if (enable)
 -                                      psys_render_set(ob, psys, mat, mat, 1, 1, 0.f);
 -                              else
 -                                      psys_render_restore(ob, psys);
 -                      }
 -              }
 -
 -              if (enable) {
 -                      /* this is to make sure we get render level duplis in groups:
 -                       * the derivedmesh must be created before init_render_mesh,
 -                       * since object_duplilist does dupliparticles before that */
 -                      dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
 -                      dm->release(dm);
 -
 -                      for (psys = ob->particlesystem.first; psys; psys = psys->next)
 -                              psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
 -              }
 -      }
 +      Main *bmain = CTX_data_main(C);
  
 -      if (ob->dup_group == NULL) return;
 -      group = ob->dup_group;
 -
 -      for (go = group->gobject.first; go; go = go->next)
 -              dupli_render_particle_set(scene, go->ob, level + 1, enable);
 -}
 -/* When no longer needed, duplilist should be freed with Object.free_duplilist */
 -static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
 -{
 -      bool for_render = (settings == DAG_EVAL_RENDER);
 -      EvaluationContext eval_ctx;
 -      DEG_evaluation_context_init(&eval_ctx, settings);
 -
 -      if (!(ob->transflag & OB_DUPLI)) {
 -              BKE_report(reports, RPT_ERROR, "Object does not have duplis");
 -              return;
 -      }
 -
 -      /* free duplilist if a user forgets to */
 -      if (ob->duplilist) {
 -              BKE_report(reports, RPT_WARNING, "Object.dupli_list has not been freed");
 -
 -              free_object_duplilist(ob->duplilist);
 -              ob->duplilist = NULL;
 -      }
 -      if (for_render)
 -              dupli_render_particle_set(sce, ob, 0, 1);
 -      ob->duplilist = object_duplilist(&eval_ctx, sce, ob);
 -      if (for_render)
 -              dupli_render_particle_set(sce, ob, 0, 0);
 -      /* ob->duplilist should now be freed with Object.free_duplilist */
 -}
 -
 -static void rna_Object_free_duplilist(Object *ob)
 -{
 -      if (ob->duplilist) {
 -              free_object_duplilist(ob->duplilist);
 -              ob->duplilist = NULL;
 -      }
 +      return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_tessface, calc_undeformed);
  }
  
  static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
@@@ -244,12 -261,17 +244,12 @@@ static void rna_Object_shape_key_remove
                return;
        }
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
  
        RNA_POINTER_INVALIDATE(kb_ptr);
  }
  
 -static int rna_Object_is_visible(Object *ob, Scene *sce)
 -{
 -      return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay);
 -}
 -
  #if 0
  static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int *indices, int totindex,
                                             float weight, int assignmode)
@@@ -397,6 -419,13 +397,6 @@@ finally
        free_bvhtree_from_mesh(&treeData);
  }
  
 -/* ObjectBase */
 -
 -static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d)
 -{
 -      base->lay = base->object->lay = v3d->lay;
 -}
 -
  static int rna_Object_is_modified(Object *ob, Scene *scene, int settings)
  {
        return BKE_object_is_modified(scene, ob) & settings;
@@@ -445,10 -474,9 +445,10 @@@ void rna_Object_dm_info(struct Object *
  }
  #endif /* NDEBUG */
  
- static int rna_Object_update_from_editmode(Object *ob)
+ static int rna_Object_update_from_editmode(Object *ob, Main *bmain)
  {
-       return ED_object_editmode_load(ob);
 +      /* fail gracefully if we aren't in edit-mode. */
+       return ED_object_editmode_load(bmain, ob);
  }
  #else /* RNA_RUNTIME */
  
@@@ -463,6 -491,13 +463,6 @@@ void RNA_api_object(StructRNA *srna
                {0, NULL, 0, NULL, NULL}
        };
  
 -      static const EnumPropertyItem dupli_eval_mode_items[] = {
 -              {DAG_EVAL_VIEWPORT, "VIEWPORT", 0, "Viewport", "Generate duplis using viewport settings"},
 -              {DAG_EVAL_PREVIEW, "PREVIEW", 0, "Preview", "Generate duplis using preview settings"},
 -              {DAG_EVAL_RENDER, "RENDER", 0, "Render", "Generate duplis using render settings"},
 -              {0, NULL, 0, NULL, NULL}
 -      };
 -
  #ifndef NDEBUG
        static const EnumPropertyItem mesh_dm_info_items[] = {
                {0, "SOURCE", 0, "Source", "Source mesh"},
        };
  #endif
  
 +      static EnumPropertyItem object_select_items[] = {
 +          {0, "SELECT", 0, "Select", "Select object from the active render layer"},
 +          {1, "DESELECT", 0, "Deselect", "Deselect object from the active render layer"},
 +          {2, "TOGGLE", 0, "Toggle", "Toggle object selection from the active render layer"},
 +          {0, NULL, 0, NULL, NULL}
 +      };
 +
 +      /* Special wrapper to access the base selection value */
 +      func = RNA_def_function(srna, "select_set", "rna_Object_select_set");
 +      RNA_def_function_ui_description(func, "Select the object (for the active render layer)");
 +      RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
 +      parm = RNA_def_enum(func, "action", object_select_items, 0, "Action", "Select mode");
 +      RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 +
 +      func = RNA_def_function(srna, "select_get", "rna_Object_select_get");
 +      RNA_def_function_ui_description(func, "Get the object selection for the active render layer");
 +      RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
 +      parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
 +      RNA_def_function_return(func, parm);
 +
 +      func = RNA_def_function(srna, "visible_get", "rna_Object_visible_get");
 +      RNA_def_function_ui_description(func, "Get the object visibility for the active render layer");
 +      RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
 +      parm = RNA_def_boolean(func, "result", 0, "", "Object visible");
 +      RNA_def_function_return(func, parm);
 +
        /* Matrix space conversion */
        func = RNA_def_function(srna, "convert_space", "rna_Object_mat_convert_space");
        RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
        func = RNA_def_function(srna, "calc_matrix_camera", "rna_Object_calc_matrix_camera");
        RNA_def_function_ui_description(func, "Generate the camera projection matrix of this object "
                                              "(mostly useful for Camera and Lamp types)");
 +      parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "",
 +                             "Depsgraph to get evaluated data from");
 +      RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
        parm = RNA_def_property(func, "result", PROP_FLOAT, PROP_MATRIX);
        RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
        RNA_def_property_ui_text(parm, "", "The camera projection matrix");
        func = RNA_def_function(srna, "camera_fit_coords", "rna_Object_camera_fit_coords");
        RNA_def_function_ui_description(func, "Compute the coordinate (and scale for ortho cameras) "
                                              "given object should be to 'see' all given coordinates");
 -      parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to get render size information from, if available");
 +      parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "",
 +                             "Depsgraph to get evaluated data from");
        RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
        parm = RNA_def_float_array(func, "coordinates", 1, NULL, -FLT_MAX, FLT_MAX, "", "Coordinates to fit in",
                                   -FLT_MAX, FLT_MAX);
        /* mesh */
        func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
        RNA_def_function_ui_description(func, "Create a Mesh data-block with modifiers applied");
 -      RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
 -      parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
 +      RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
 +      parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "Dependency Graph", "Evaluated dependency graph within wich to evaluate modifiers");
        RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
        parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
        RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 -      parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
 -      RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
        RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
        RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
        parm = RNA_def_pointer(func, "mesh", "Mesh", "",
                               "Mesh created from object, remove it if it is only used for export");
        RNA_def_function_return(func, parm);
  
 -      /* duplis */
 -      func = RNA_def_function(srna, "dupli_list_create", "rna_Object_create_duplilist");
 -      RNA_def_function_ui_description(func, "Create a list of dupli objects for this object, needs to "
 -                                      "be freed manually with free_dupli_list to restore the "
 -                                      "objects real matrix and layers");
 -      parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis");
 -      RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 -      RNA_def_enum(func, "settings", dupli_eval_mode_items, 0, "", "Generate texture coordinates for rendering");
 -      RNA_def_function_flag(func, FUNC_USE_REPORTS);
 -
 -      func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");
 -      RNA_def_function_ui_description(func, "Free the list of dupli objects");
 -
        /* Armature */
        func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature");
        RNA_def_function_ui_description(func, "Find armature influencing this object as a parent or via a modifier");
        RNA_def_function_output(func, parm);
  
        /* View */
 -      func = RNA_def_function(srna, "is_visible", "rna_Object_is_visible");
 -      RNA_def_function_ui_description(func, "Determine if object is visible in a given scene");
 -      parm = RNA_def_pointer(func, "scene", "Scene", "", "");
 -      RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 -      parm = RNA_def_boolean(func, "result", 0, "", "Object visibility");
 -      RNA_def_function_return(func, parm);
  
        /* utility function for checking if the object is modified */
        func = RNA_def_function(srna, "is_modified", "rna_Object_is_modified");
  
        func = RNA_def_function(srna, "update_from_editmode", "rna_Object_update_from_editmode");
        RNA_def_function_ui_description(func, "Load the objects edit-mode data into the object data");
+       RNA_def_function_flag(func, FUNC_USE_MAIN);
        parm = RNA_def_boolean(func, "result", 0, "", "Success");
        RNA_def_function_return(func, parm);
  
        RNA_def_function_ui_description(func, "Release memory used by caches associated with this object. Intended to be used by render engines only");
  }
  
 -
 -void RNA_api_object_base(StructRNA *srna)
 -{
 -      FunctionRNA *func;
 -      PropertyRNA *parm;
 -
 -      func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBase_layers_from_view");
 -      RNA_def_function_ui_description(func,
 -                                      "Sets the object layers from a 3D View (use when adding an object in local view)");
 -      parm = RNA_def_pointer(func, "view", "SpaceView3D", "", "");
 -      RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 -}
 -
  #endif /* RNA_RUNTIME */