Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Sun, 27 May 2018 09:06:29 +0000 (11:06 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 27 May 2018 09:06:29 +0000 (11:06 +0200)
22 files changed:
1  2 
build_files/cmake/platform/platform_win32.cmake
intern/cycles/blender/blender_shader.cpp
intern/cycles/blender/blender_util.h
intern/cycles/kernel/kernel_light.h
intern/cycles/render/light.cpp
intern/cycles/render/light.h
make.bat
release/scripts/startup/bl_ui/properties_data_modifier.py
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/bpath.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/pointcache.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_shader.h
source/blender/nodes/NOD_static_types.h

index 7e978a71ad44a225afdf54e945c982d00b6f1002,3520ac9c075ed33cc9102c185ff57b7d03679a87..606e4e595716a41fc22e86293264e33563e2a2d9
@@@ -119,6 -119,8 +119,8 @@@ set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WI
  set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
  include(InstallRequiredSystemLibraries)
  
+ remove_cc_flag("/MDd" "/MD")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
  set(CMAKE_C_FLAGS     "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
  
@@@ -532,21 -534,22 +534,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 cc2a6824190181a491e369b5139a9f350bd38e85,c6144cef1bf846b9048f424a8607b9aeda4ae42a..15d633b5c9ae5f3d441d6bbb86ce9141010d5398
@@@ -231,11 -231,18 +231,11 @@@ static void get_tex_mapping(TextureMapp
                mapping->max = get_float3(b_mapping.max());
  }
  
 -static bool is_output_node(BL::Node& b_node)
 -{
 -      return (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
 -                  || b_node.is_a(&RNA_ShaderNodeOutputWorld)
 -                  || b_node.is_a(&RNA_ShaderNodeOutputLamp));
 -}
 -
  static ShaderNode *add_node(Scene *scene,
                              BL::RenderEngine& b_engine,
                              BL::BlendData& b_data,
 +                            BL::Depsgraph& b_depsgraph,
                              BL::Scene& b_scene,
 -                            const bool background,
                              ShaderGraph *graph,
                              BL::ShaderNodeTree& b_ntree,
                              BL::ShaderNode& b_node)
                get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
                node = sky;
        }
+       else if(b_node.is_a(&RNA_ShaderNodeTexIES)) {
+               BL::ShaderNodeTexIES b_ies_node(b_node);
+               IESLightNode *ies = new IESLightNode();
+               switch(b_ies_node.mode()) {
+                       case BL::ShaderNodeTexIES::mode_EXTERNAL:
+                               ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
+                               break;
+                       case BL::ShaderNodeTexIES::mode_INTERNAL:
+                               ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
+                               break;
+               }
+               node = ies;
+       }
        else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
                BL::ShaderNodeNormalMap b_normal_map_node(b_node);
                NormalMapNode *nmap = new NormalMapNode();
                point_density->interpolation = get_image_interpolation(b_point_density_node);
                point_density->builtin_data = b_point_density_node.ptr.data;
  
 -              /* 1 - render settings, 0 - vewport settings. */
 -              int settings = background ? 1 : 0;
 -
                /* TODO(sergey): Use more proper update flag. */
                if(true) {
 -                      b_point_density_node.cache_point_density(b_scene, settings);
 +                      b_point_density_node.cache_point_density(b_depsgraph);
                        scene->image_manager->tag_reload_image(
                                point_density->filename.string(),
                                point_density->builtin_data,
                BL::Object b_ob(b_point_density_node.object());
                if(b_ob) {
                        float3 loc, size;
 -                      point_density_texture_space(b_scene,
 +                      point_density_texture_space(b_depsgraph,
                                                    b_point_density_node,
 -                                                  settings,
                                                    loc,
                                                    size);
                        point_density->tfm =
@@@ -972,36 -996,11 +985,36 @@@ static ShaderOutput *node_find_output_b
        return node->output(name.c_str());
  }
  
 +static BL::ShaderNode find_output_node(BL::ShaderNodeTree& b_ntree)
 +{
 +      BL::ShaderNodeTree::nodes_iterator b_node;
 +      BL::ShaderNode output_node(PointerRNA_NULL);
 +
 +      for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
 +              BL::ShaderNodeOutputMaterial b_output_node(*b_node);
 +
 +              if (b_output_node.is_a(&RNA_ShaderNodeOutputMaterial) ||
 +                  b_output_node.is_a(&RNA_ShaderNodeOutputWorld) ||
 +                  b_output_node.is_a(&RNA_ShaderNodeOutputLamp)) {
 +                      /* regular Cycles output node */
 +                      if(b_output_node.is_active_output()) {
 +                              output_node = b_output_node;
 +                              break;
 +                      }
 +                      else if(!output_node.ptr.data) {
 +                              output_node = b_output_node;
 +                      }
 +              }
 +      }
 +
 +      return output_node;
 +}
 +
  static void add_nodes(Scene *scene,
                        BL::RenderEngine& b_engine,
                        BL::BlendData& b_data,
 +                      BL::Depsgraph& b_depsgraph,
                        BL::Scene& b_scene,
 -                      const bool background,
                        ShaderGraph *graph,
                        BL::ShaderNodeTree& b_ntree,
                        const ProxyMap &proxy_input_map,
        BL::Node::outputs_iterator b_output;
  
        /* find the node to use for output if there are multiple */
 -      bool found_active_output = false;
 -      BL::ShaderNode output_node(PointerRNA_NULL);
 -
 -      for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
 -              if(is_output_node(*b_node)) {
 -                      BL::ShaderNodeOutputMaterial b_output_node(*b_node);
 -
 -                      if(b_output_node.is_active_output()) {
 -                              output_node = b_output_node;
 -                              found_active_output = true;
 -                              break;
 -                      }
 -                      else if(!output_node.ptr.data && !found_active_output) {
 -                              output_node = b_output_node;
 -                      }
 -              }
 -      }
 +      BL::ShaderNode output_node = find_output_node(b_ntree);
  
        /* add nodes */
        for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
                                add_nodes(scene,
                                          b_engine,
                                          b_data,
 +                                        b_depsgraph,
                                          b_scene,
 -                                        background,
                                          graph,
                                          b_group_ntree,
                                          group_proxy_input_map,
                else {
                        ShaderNode *node = NULL;
  
 -                      if(is_output_node(*b_node)) {
 -                              if(b_node->ptr.data == output_node.ptr.data) {
 -                                      node = graph->output();
 -                              }
 +                      if(b_node->ptr.data == output_node.ptr.data) {
 +                              node = graph->output();
                        }
                        else {
                                BL::ShaderNode b_shader_node(*b_node);
                                node = add_node(scene,
                                                b_engine,
                                                b_data,
 +                                              b_depsgraph,
                                                b_scene,
 -                                              background,
                                                graph,
                                                b_ntree,
                                                b_shader_node);
  static void add_nodes(Scene *scene,
                        BL::RenderEngine& b_engine,
                        BL::BlendData& b_data,
 +                      BL::Depsgraph& b_depsgraph,
                        BL::Scene& b_scene,
 -                      const bool background,
                        ShaderGraph *graph,
                        BL::ShaderNodeTree& b_ntree)
  {
        add_nodes(scene,
                  b_engine,
                  b_data,
 +                b_depsgraph,
                  b_scene,
 -                background,
                  graph,
                  b_ntree,
                  empty_proxy_map,
  
  /* Sync Materials */
  
 -void BlenderSync::sync_materials(bool update_all)
 +void BlenderSync::sync_materials(BL::Depsgraph& b_depsgraph, bool update_all)
  {
        shader_map.set_default(scene->default_surface);
  
 -      /* material loop */
 -      BL::BlendData::materials_iterator b_mat;
 -
        TaskPool pool;
        set<Shader*> updated_shaders;
  
 -      for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
 +      /* material loop */
 +      BL::BlendData::materials_iterator b_mat_orig;
 +      for(b_data.materials.begin(b_mat_orig);
 +          b_mat_orig != b_data.materials.end();
 +          ++b_mat_orig)
 +      {
 +              /* TODO(sergey): Iterate over evaluated data rather than using mapping. */
 +              BL::Material b_mat_(b_depsgraph.id_eval_get(*b_mat_orig));
 +              BL::Material *b_mat = &b_mat_;
                Shader *shader;
  
                /* test if we need to sync */
                        if(b_mat->use_nodes() && b_mat->node_tree()) {
                                BL::ShaderNodeTree b_ntree(b_mat->node_tree());
  
 -                              add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
 +                              add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
                        }
                        else {
                                DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
  
  /* Sync World */
  
 -void BlenderSync::sync_world(bool update_all)
 +void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
  {
        Background *background = scene->background;
        Background prevbackground = *background;
                if(b_world && b_world.use_nodes() && b_world.node_tree()) {
                        BL::ShaderNodeTree b_ntree(b_world.node_tree());
  
 -                      add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
 +                      add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
  
                        /* volume */
                        PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
                background->transparent_roughness_threshold = 0.0f;
        }
  
 -      background->use_shader = render_layer.use_background_shader;
 -      background->use_ao = background->use_ao && render_layer.use_background_ao;
 +      background->use_shader = view_layer.use_background_shader;
 +      background->use_ao = background->use_ao && view_layer.use_background_ao;
  
        if(background->modified(prevbackground))
                background->tag_update(scene);
  
  /* Sync Lamps */
  
 -void BlenderSync::sync_lamps(bool update_all)
 +void BlenderSync::sync_lamps(BL::Depsgraph& b_depsgraph, bool update_all)
  {
        shader_map.set_default(scene->default_light);
  
        /* lamp loop */
 -      BL::BlendData::lamps_iterator b_lamp;
 -
 -      for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
 +      BL::BlendData::lamps_iterator b_lamp_orig;
 +      for(b_data.lamps.begin(b_lamp_orig);
 +          b_lamp_orig != b_data.lamps.end();
 +          ++b_lamp_orig)
 +      {
 +              /* TODO(sergey): Iterate over evaluated data rather than using mapping. */
 +              BL::Lamp b_lamp_(b_depsgraph.id_eval_get(*b_lamp_orig));
 +              BL::Lamp *b_lamp = &b_lamp_;
                Shader *shader;
  
                /* test if we need to sync */
  
                                BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
  
 -                              add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
 +                              add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
                        }
                        else {
                                float strength = 1.0f;
        }
  }
  
 -void BlenderSync::sync_shaders()
 +void BlenderSync::sync_shaders(BL::Depsgraph& b_depsgraph)
  {
        /* for auto refresh images */
        bool auto_refresh_update = false;
  
        shader_map.pre_sync();
  
 -      sync_world(auto_refresh_update);
 -      sync_lamps(auto_refresh_update);
 -      sync_materials(auto_refresh_update);
 +      sync_world(b_depsgraph, auto_refresh_update);
 +      sync_lamps(b_depsgraph, auto_refresh_update);
 +      sync_materials(b_depsgraph, auto_refresh_update);
  
        /* false = don't delete unused shaders, not supported */
        shader_map.post_sync(false);
index a8379914b834a535ecc362a8aece30de6ca75ccc,87d6c7eba8abbf9aeae7c16d8a354b0263ed84c0..983988f4e361c5e98a734a00d365f0bae50b0204
@@@ -45,15 -45,15 +45,15 @@@ void python_thread_state_restore(void *
  
  static inline BL::Mesh object_to_mesh(BL::BlendData& data,
                                        BL::Object& object,
 -                                      BL::Scene& scene,
 +                                      BL::Depsgraph& depsgraph,
                                        bool apply_modifiers,
 -                                      bool render,
                                        bool calc_undeformed,
                                        Mesh::SubdivisionType subdivision_type)
  {
        bool subsurf_mod_show_render = false;
        bool subsurf_mod_show_viewport = false;
  
 +      /* TODO: make this work with copy-on-write, modifiers are already evaluated. */
        if(subdivision_type != Mesh::SUBDIVISION_NONE) {
                BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
  
@@@ -64,7 -64,7 +64,7 @@@
                subsurf_mod.show_viewport(false);
        }
  
 -      BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
 +      BL::Mesh me = data.meshes.new_from_object(depsgraph, object, apply_modifiers, false, calc_undeformed);
  
        if(subdivision_type != Mesh::SUBDIVISION_NONE) {
                BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
@@@ -307,7 -307,7 +307,7 @@@ static inline uint get_layer(const BL::
  static inline uint get_layer(const BL::Array<int, 20>& array,
                               const BL::Array<int, 8>& local_array,
                               bool is_light = false,
 -                             uint scene_layers = (1 << 20) - 1)
 +                             uint view_layers = (1 << 20) - 1)
  {
        uint layer = 0;
  
                /* Consider light is visible if it was visible without layer
                 * override, which matches behavior of Blender Internal.
                 */
 -              if(layer & scene_layers) {
 +              if(layer & view_layers) {
                        for(uint i = 0; i < 8; i++)
                                layer |= (1 << (20+i));
                }
@@@ -468,6 -468,21 +468,21 @@@ static inline string blender_absolute_p
        return path;
  }
  
+ static inline string get_text_datablock_content(const PointerRNA&& ptr)
+ {
+       if(ptr.data == NULL) {
+               return "";
+       }
+       string content;
+       BL::Text::lines_iterator iter;
+       for(iter.begin(ptr); iter; ++iter) {
+               content += iter->body() + "\n";
+       }
+       return content;
+ }
  /* Texture Space */
  
  static inline void mesh_texture_space(BL::Mesh& b_mesh,
index cd879e27e728df739ee8efb2e436906956c5ea2d,ec7203d36eb1a570a23bc8202e2e7d57a741dda1..b1be0b2155ac3c772d77ea90ba1aa7fce66c3bfc
@@@ -44,7 -44,7 +44,7 @@@ typedef struct LightSample 
   *
   * Note: light_p is modified when sample_coord is true.
   */
 -ccl_device_inline float area_light_sample(float3 P,
 +ccl_device_inline float rect_light_sample(float3 P,
                                            float3 *light_p,
                                            float3 axisu, float3 axisv,
                                            float randu, float randv,
                return 0.0f;
  }
  
 +ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
 +{
 +      to_unit_disk(&randu, &randv);
 +      return ru*randu + rv*randv;
 +}
 +
 +ccl_device float3 disk_light_sample(float3 v, float randu, float randv)
 +{
 +      float3 ru, rv;
 +
 +      make_orthonormals(v, &ru, &rv);
 +
 +      return ellipse_sample(ru, rv, randu, randv);
 +}
 +
 +ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
 +{
 +      return normalize(D + disk_light_sample(D, randu, randv)*radius);
 +}
 +
 +ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
 +{
 +      return disk_light_sample(normalize(P - center), randu, randv)*radius;
 +}
 +
 +ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls)
 +{
 +      float3 I = ls->Ng;
 +
 +      float attenuation = dot(dir, I);
 +
 +      if(attenuation <= spot_angle) {
 +              attenuation = 0.0f;
 +      }
 +      else {
 +              float t = attenuation - spot_angle;
 +
 +              if(t < spot_smooth && spot_smooth != 0.0f)
 +                      attenuation *= smoothstepf(t/spot_smooth);
 +      }
 +
 +      return attenuation;
 +}
 +
 +ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
 +{
 +      float cos_pi = dot(Ng, I);
 +
 +      if(cos_pi <= 0.0f)
 +              return 0.0f;
 +
 +      return t*t/cos_pi;
 +}
 +
  /* Background Light */
  
  #ifdef __BACKGROUND_MIS__
@@@ -224,7 -170,7 +224,7 @@@ float3 background_map_sample(KernelGlob
        float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res);
  
        /* importance-sampled V direction */
-       float dv = (randv - cdf_v.y) / (cdf_next_v.y - cdf_v.y);
+       float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
        float v = (index_v + dv) / res;
  
        /* this is basically std::lower_bound as used by pbrt */
        float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res);
  
        /* importance-sampled U direction */
-       float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y);
+       float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
        float u = (index_u + du) / res;
  
        /* compute pdf */
@@@ -349,19 -295,11 +349,19 @@@ ccl_device_inline float background_port
                const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
                float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
                float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
 +              bool is_round = (klight->area.invarea < 0.0f);
  
 -              if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL))
 +              if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL, is_round))
                        continue;
  
 -              portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
 +              if(is_round) {
 +                      float t;
 +                      float3 D = normalize_len(lightpos - P, &t);
 +                      portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
 +              }
 +              else {
 +                      portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
 +              }
        }
  
        if(ignore_portal >= 0) {
@@@ -411,26 -349,15 +411,26 @@@ ccl_device float3 background_portal_sam
                        const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
                        float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
                        float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
 -
 -                      *pdf = area_light_sample(P, &lightpos,
 -                                               axisu, axisv,
 -                                               randu, randv,
 -                                               true);
 +                      bool is_round = (klight->area.invarea < 0.0f);
 +
 +                      float3 D;
 +                      if(is_round) {
 +                              lightpos += ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv);
 +                              float t;
 +                              D = normalize_len(lightpos - P, &t);
 +                              *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
 +                      }
 +                      else {
 +                              *pdf = rect_light_sample(P, &lightpos,
 +                                                       axisu, axisv,
 +                                                       randu, randv,
 +                                                       true);
 +                              D = normalize(lightpos - P);
 +                      }
  
                        *pdf /= num_possible;
                        *sampled_portal = p;
 -                      return normalize(lightpos - P);
 +                      return D;
                }
  
                portal--;
@@@ -531,6 -458,55 +531,6 @@@ ccl_device float background_light_pdf(K
  
  /* Regular Light */
  
 -ccl_device float3 disk_light_sample(float3 v, float randu, float randv)
 -{
 -      float3 ru, rv;
 -
 -      make_orthonormals(v, &ru, &rv);
 -      to_unit_disk(&randu, &randv);
 -
 -      return ru*randu + rv*randv;
 -}
 -
 -ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
 -{
 -      return normalize(D + disk_light_sample(D, randu, randv)*radius);
 -}
 -
 -ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
 -{
 -      return disk_light_sample(normalize(P - center), randu, randv)*radius;
 -}
 -
 -ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls)
 -{
 -      float3 I = ls->Ng;
 -
 -      float attenuation = dot(dir, I);
 -
 -      if(attenuation <= spot_angle) {
 -              attenuation = 0.0f;
 -      }
 -      else {
 -              float t = attenuation - spot_angle;
 -
 -              if(t < spot_smooth && spot_smooth != 0.0f)
 -                      attenuation *= smoothstepf(t/spot_smooth);
 -      }
 -
 -      return attenuation;
 -}
 -
 -ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
 -{
 -      float cos_pi = dot(Ng, I);
 -
 -      if(cos_pi <= 0.0f)
 -              return 0.0f;
 -      
 -      return t*t/cos_pi;
 -}
 -
  ccl_device_inline bool lamp_light_sample(KernelGlobals *kg,
                                           int lamp,
                                           float randu, float randv,
                        float3 D = make_float3(klight->area.dir[0],
                                               klight->area.dir[1],
                                               klight->area.dir[2]);
 +                      float invarea = fabsf(klight->area.invarea);
 +                      bool is_round = (klight->area.invarea < 0.0f);
  
                        if(dot(ls->P - P, D) > 0.0f) {
                                return false;
                        }
  
 -                      float3 inplane = ls->P;
 -                      ls->pdf = area_light_sample(P, &ls->P,
 -                                                axisu, axisv,
 -                                                randu, randv,
 -                                                true);
 +                      float3 inplane;
 +
 +                      if(is_round) {
 +                              inplane = ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv);
 +                              ls->P += inplane;
 +                              ls->pdf = invarea;
 +                      }
 +                      else {
 +                              inplane = ls->P;
 +                              ls->pdf = rect_light_sample(P, &ls->P,
 +                                                          axisu, axisv,
 +                                                          randu, randv,
 +                                                          true);
 +                              inplane = ls->P - inplane;
 +                      }
  
 -                      inplane = ls->P - inplane;
                        ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
                        ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
  
                        ls->Ng = D;
                        ls->D = normalize_len(ls->P - P, &ls->t);
  
 -                      float invarea = klight->area.invarea;
                        ls->eval_fac = 0.25f*invarea;
 +                      if(is_round) {
 +                              ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
 +                      }
                }
        }
  
@@@ -768,8 -731,7 +768,8 @@@ ccl_device bool lamp_light_eval(KernelG
        }
        else if(type == LIGHT_AREA) {
                /* area light */
 -              float invarea = klight->area.invarea;
 +              float invarea = fabsf(klight->area.invarea);
 +              bool is_round = (klight->area.invarea < 0.0f);
                if(invarea == 0.0f)
                        return false;
  
                if(!ray_quad_intersect(P, D, 0.0f, t, light_P,
                                       axisu, axisv, Ng,
                                       &ls->P, &ls->t,
 -                                     &ls->u, &ls->v))
 +                                     &ls->u, &ls->v,
 +                                     is_round))
                {
                        return false;
                }
  
                ls->D = D;
                ls->Ng = Ng;
 -              ls->pdf = area_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
 +              if(is_round) {
 +                      ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
 +              }
 +              else {
 +                      ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
 +              }
                ls->eval_fac = 0.25f*invarea;
        }
        else {
index 01a8b50cb21d65e49db17ac9ac527c307f9e5c28,f0824ef4319b51c4832b542bf42725b9c8a5e332..91f9b4e3bec6a0950a1bf79073abd71714c72928
@@@ -25,6 -25,8 +25,8 @@@
  #include "render/shader.h"
  
  #include "util/util_foreach.h"
+ #include "util/util_hash.h"
+ #include "util/util_path.h"
  #include "util/util_progress.h"
  #include "util/util_logging.h"
  
@@@ -117,7 -119,6 +119,7 @@@ NODE_DEFINE(Light
        SOCKET_FLOAT(sizeu, "Size U", 1.0f);
        SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
        SOCKET_FLOAT(sizev, "Size V", 1.0f);
 +      SOCKET_BOOLEAN(round, "Round", false);
  
        SOCKET_INT(map_resolution, "Map Resolution", 512);
  
@@@ -176,6 -177,9 +178,9 @@@ LightManager::LightManager(
  
  LightManager::~LightManager()
  {
+       foreach(IESSlot *slot, ies_slots) {
+               delete slot;
+       }
  }
  
  bool LightManager::has_background_light(Scene *scene)
@@@ -731,15 -735,12 +736,15 @@@ void LightManager::device_update_points
                        float3 axisu = light->axisu*(light->sizeu*light->size);
                        float3 axisv = light->axisv*(light->sizev*light->size);
                        float area = len(axisu)*len(axisv);
 -                      float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
 +                      if(light->round) {
 +                              area *= -M_PI_4_F;
 +                      }
 +                      float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
                        float3 dir = light->dir;
                        
                        dir = safe_normalize(dir);
  
 -                      if(light->use_mis && area > 0.0f)
 +                      if(light->use_mis && area != 0.0f)
                                shader_id |= SHADER_USE_MIS;
  
                        klights[light_index].co[0] = co.x;
                float3 axisu = light->axisu*(light->sizeu*light->size);
                float3 axisv = light->axisv*(light->sizev*light->size);
                float area = len(axisu)*len(axisv);
 -              float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
 +              if(light->round) {
 +                      area *= -M_PI_4_F;
 +              }
 +              float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
                float3 dir = light->dir;
  
                dir = safe_normalize(dir);
@@@ -865,6 -863,9 +870,9 @@@ void LightManager::device_update(Devic
        device_update_background(device, dscene, scene, progress);
        if(progress.get_cancel()) return;
  
+       device_update_ies(dscene);
+       if(progress.get_cancel()) return;
        if(use_light_visibility != scene->film->use_light_visibility) {
                scene->film->use_light_visibility = use_light_visibility;
                scene->film->tag_update(scene);
@@@ -879,6 -880,7 +887,7 @@@ void LightManager::device_free(Device *
        dscene->lights.free();
        dscene->light_background_marginal_cdf.free();
        dscene->light_background_conditional_cdf.free();
+       dscene->ies_lights.free();
  }
  
  void LightManager::tag_update(Scene * /*scene*/)
        need_update = true;
  }
  
+ int LightManager::add_ies_from_file(ustring filename)
+ {
+       string content;
+       /* If the file can't be opened, call with an empty string */
+       path_read_text(filename.c_str(), content);
+       return add_ies(ustring(content));
+ }
+ int LightManager::add_ies(ustring content)
+ {
+       uint hash = hash_string(content.c_str());
+       thread_scoped_lock ies_lock(ies_mutex);
+       /* Check whether this IES already has a slot. */
+       size_t slot;
+       for(slot = 0; slot < ies_slots.size(); slot++) {
+               if(ies_slots[slot]->hash == hash) {
+                       ies_slots[slot]->users++;
+                       return slot;
+               }
+       }
+       /* Try to find an empty slot for the new IES. */
+       for(slot = 0; slot < ies_slots.size(); slot++) {
+               if(ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
+                       break;
+               }
+       }
+       /* If there's no free slot, add one. */
+       if(slot == ies_slots.size()) {
+               ies_slots.push_back(new IESSlot());
+       }
+       ies_slots[slot]->ies.load(content);
+       ies_slots[slot]->users = 1;
+       ies_slots[slot]->hash = hash;
+       need_update = true;
+       return slot;
+ }
+ void LightManager::remove_ies(int slot)
+ {
+       thread_scoped_lock ies_lock(ies_mutex);
+       if(slot < 0 || slot >= ies_slots.size()) {
+               assert(false);
+               return;
+       }
+       assert(ies_slots[slot]->users > 0);
+       ies_slots[slot]->users--;
+       /* If the slot has no more users, update the device to remove it. */
+       need_update |= (ies_slots[slot]->users == 0);
+ }
+ void LightManager::device_update_ies(DeviceScene *dscene)
+ {
+       /* Clear empty slots. */
+       foreach(IESSlot *slot, ies_slots) {
+               if(slot->users == 0) {
+                       slot->hash = 0;
+                       slot->ies.clear();
+               }
+       }
+       /* Shrink the slot table by removing empty slots at the end. */
+       int slot_end;
+       for(slot_end = ies_slots.size(); slot_end; slot_end--) {
+               if(ies_slots[slot_end-1]->users > 0) {
+                       /* If the preceding slot has users, we found the new end of the table. */
+                       break;
+               }
+               else {
+                       /* The slot will be past the new end of the table, so free it. */
+                       delete ies_slots[slot_end-1];
+               }
+       }
+       ies_slots.resize(slot_end);
+       if(ies_slots.size() > 0) {
+               int packed_size = 0;
+               foreach(IESSlot *slot, ies_slots) {
+                       packed_size += slot->ies.packed_size();
+               }
+               /* ies_lights starts with an offset table that contains the offset of every slot,
+                * or -1 if the slot is invalid.
+                * Following that table, the packed valid IES lights are stored. */
+               float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
+               int offset = ies_slots.size();
+               for(int i = 0; i < ies_slots.size(); i++) {
+                       int size = ies_slots[i]->ies.packed_size();
+                       if(size > 0) {
+                               data[i] = __int_as_float(offset);
+                               ies_slots[i]->ies.pack(data + offset);
+                               offset += size;
+                       }
+                       else {
+                               data[i] = __int_as_float(-1);
+                       }
+               }
+               dscene->ies_lights.copy_to_device();
+       }
+ }
  CCL_NAMESPACE_END
  
index 539a33f4e410730c7e417d3e2ffc11b78275e17d,5f8677ee2f24ffb484a001e4d2ef8185a33f20b8..acbbdd15ddf69afd6237ed57ecb99e45baf96535
@@@ -21,6 -21,8 +21,8 @@@
  
  #include "graph/node.h"
  
+ #include "util/util_ies.h"
+ #include "util/util_thread.h"
  #include "util/util_types.h"
  #include "util/util_vector.h"
  
@@@ -49,7 -51,6 +51,7 @@@ public
        float sizeu;
        float3 axisv;
        float sizev;
 +      bool round;
  
        Transform tfm;
  
@@@ -87,6 -88,11 +89,11 @@@ public
        LightManager();
        ~LightManager();
  
+       /* IES texture management */
+       int add_ies(ustring ies);
+       int add_ies_from_file(ustring filename);
+       void remove_ies(int slot);
        void device_update(Device *device,
                           DeviceScene *dscene,
                           Scene *scene,
@@@ -116,9 -122,19 +123,19 @@@ protected
                                      DeviceScene *dscene,
                                      Scene *scene,
                                      Progress& progress);
+       void device_update_ies(DeviceScene *dscene);
  
        /* Check whether light manager can use the object as a light-emissive. */
        bool object_usable_as_light(Object *object);
+       struct IESSlot {
+               IESFile ies;
+               uint hash;
+               int users;
+       };
+       vector<IESSlot*> ies_slots;
+       thread_mutex ies_mutex;
  };
  
  CCL_NAMESPACE_END
diff --combined make.bat
index d00a9ecf711f2dab7b6b0f4cdf06f4339943d7a3,577f820438b5af535b530d749bb58b246a02f813..3e2217d010a22bdc0879a821d4eea3748b999a5e
+++ b/make.bat
@@@ -4,359 -4,66 +4,66 @@@ REM This is for users who like to confi
  setlocal EnableDelayedExpansion
  setlocal ENABLEEXTENSIONS
  set BLENDER_DIR=%~dp0
- set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
- for %%X in (svn.exe) do (set HAS_SVN=%%~$PATH:X)
- if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
-       echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
-       goto EOF
- )
- set BUILD_DIR=%BLENDER_DIR%..\build_windows
- set BUILD_TYPE=Release
- rem reset all variables so they do not get accidentally get carried over from previous builds
- set BUILD_DIR_OVERRRIDE=
- set BUILD_CMAKE_ARGS=
- set BUILD_ARCH=
- set BUILD_VS_VER=
- set BUILD_VS_YEAR=
- set BUILD_VS_LIBDIRPOST=
- set BUILD_VS_LIBDIR=
- set BUILD_VS_SVNDIR=
- set BUILD_NGE=
- set KEY_NAME=
- set MSBUILD_PLATFORM=
- set MUST_CLEAN=
- set NOBUILD=
- set TARGET=
- set WINDOWS_ARCH=
- set TESTS_CMAKE_ARGS=
- :argv_loop
- if NOT "%1" == "" (
  
-       REM Help Message
-       if "%1" == "help" (
-               goto HELP
-       )
+ call "%BLENDER_DIR%\build_files\windows\reset_variables.cmd"
  
-       REM Build Types
-       if "%1" == "debug" (
-               set BUILD_TYPE=Debug
-       REM Build Configurations
-       ) else if "%1" == "noge" (
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF
-               set BUILD_NGE=_noge
-       ) else if "%1" == "builddir" (
-               set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2"
-               shift /1
-       ) else if "%1" == "with_tests" (
-               set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On
-       ) else if "%1" == "full" (
-               set TARGET=Full
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-                   -C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake"
-       ) else if "%1" == "lite" (
-               set TARGET=Lite
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-                   -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake"
-       ) else if "%1" == "cycles" (
-               set TARGET=Cycles
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-                   -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake"
-       ) else if "%1" == "headless" (
-               set TARGET=Headless
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-                   -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake"
-       ) else if "%1" == "bpy" (
-               set TARGET=Bpy
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-                   -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
-       ) else if "%1" == "release" (
-               set TARGET=Release
-       ) else if "%1" == "x86" (
-               set BUILD_ARCH=x86
-       ) else if "%1" == "x64" (
-               set BUILD_ARCH=x64
-       ) else if "%1" == "2017" (
-               set BUILD_VS_VER=15
-               set BUILD_VS_YEAR=2017
-               set BUILD_VS_LIBDIRPOST=vc14
-       ) else if "%1" == "2015" (
-               set BUILD_VS_VER=14
-               set BUILD_VS_YEAR=2015
-               set BUILD_VS_LIBDIRPOST=vc14
-       ) else if "%1" == "2013" (
-               set BUILD_VS_VER=12
-               set BUILD_VS_YEAR=2013
-               set BUILD_VS_LIBDIRPOST=vc12
-       ) else if "%1" == "packagename" (
-               set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
-               shift /1
-       ) else if "%1" == "nobuild" (
-               set NOBUILD=1
-       ) else if "%1" == "showhash" (
-               for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
-               cd release/datafiles/locale
-               for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
-               cd %~dp0
-               cd release/scripts/addons
-               for /f "delims=" %%i in ('git rev-parse HEAD') do echo Addons_Hash=%%i
-               cd %~dp0
-               goto EOF
-       REM Non-Build Commands
-       ) else if "%1" == "update" (
-               svn up ../lib/*
-               git pull --rebase
-               git submodule update --remote
-               goto EOF
-       ) else if "%1" == "clean" (
-               set MUST_CLEAN=1
-       ) else (
-               echo Command "%1" unknown, aborting!
-               goto EOF
-       )
+ call "%BLENDER_DIR%\build_files\windows\check_spaces_in_path.cmd"
+ if errorlevel 1 goto EOF
  
-       shift /1
-       goto argv_loop
- )
- if "%BUILD_ARCH%"=="" (
-       if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
-               set WINDOWS_ARCH= Win64
-               set BUILD_ARCH=x64
-       ) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
-               set WINDOWS_ARCH= Win64
-               set BUILD_ARCH=x64
-       ) else (
-               set WINDOWS_ARCH=
-               set BUILD_ARCH=x86
-       )
- ) else if "%BUILD_ARCH%"=="x64" (
-       set WINDOWS_ARCH= Win64
- ) else if "%BUILD_ARCH%"=="x86" (
-       set WINDOWS_ARCH=
- )
+ call "%BLENDER_DIR%\build_files\windows\parse_arguments.cmd" %*
+ if errorlevel 1 goto EOF
  
- if "%BUILD_VS_VER%"=="" (
-       set BUILD_VS_VER=12
-       set BUILD_VS_YEAR=2013
-       set BUILD_VS_LIBDIRPOST=vc12
- )
+ call "%BLENDER_DIR%\build_files\windows\find_dependencies.cmd"
+ if errorlevel 1 goto EOF
  
- if "%BUILD_ARCH%"=="x64" (
-       set MSBUILD_PLATFORM=x64
- ) else if "%BUILD_ARCH%"=="x86" (
-       set MSBUILD_PLATFORM=win32
+ if "%SHOW_HELP%" == "1" (
+       call "%BLENDER_DIR%\build_files\windows\show_help.cmd"
+       goto EOF
  )
  
- if "%target%"=="Release" (
-       rem for vc12 check for both cuda 7.5 and 8
-       if "%CUDA_PATH%"=="" (
-               echo Cuda Not found, aborting!
-               goto EOF
-       )
-       set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-       -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
+ if "%BUILD_UPDATE%" == "1" (
+       call "%BLENDER_DIR%\build_files\windows\update_sources.cmd"
+       goto EOF
  )
  
- :DetectMSVC
- REM Detect MSVC Installation for 2013-2015
- if DEFINED VisualStudioVersion goto msvc_detect_finally
- set VALUE_NAME=ProductDir
- REM Check 64 bits
- set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
- for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
- if DEFINED MSVC_VC_DIR goto msvc_detect_finally
- REM Check 32 bits
- set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
- for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
- if DEFINED MSVC_VC_DIR goto msvc_detect_finally
- :msvc_detect_finally
- if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
- if DEFINED MSVC_VC_DIR goto sanity_checks
- rem MSVC Build environment 2017 and up.
- for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
- if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
- REM Check 32 bits
- for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\sxs\vs7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
- if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
- :msvc_detect_finally_2017
- if DEFINED MSVC_VS_DIR call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat"
+ call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd" 
  
- :sanity_checks
- REM Sanity Checks
- where /Q msbuild
- if %ERRORLEVEL% NEQ 0 (
-       if "%BUILD_VS_VER%"=="12" (
-               rem vs12 not found, try vs14
-               echo Visual Studio 2013 not found, trying Visual Studio 2015.
-               set BUILD_VS_VER=14
-               set BUILD_VS_YEAR=2015
-               set BUILD_VS_LIBDIRPOST=vc14
-               goto DetectMSVC
-       ) else (
-               echo Error: "MSBuild" command not in the PATH.
-               echo You must have MSVC installed and run this from the "Developer Command Prompt"
-               echo ^(available from Visual Studio's Start menu entry^), aborting!
+ if "%BUILD_VS_YEAR%" == "" (
+       call "%BLENDER_DIR%\build_files\windows\autodetect_msvc.cmd"
+       if errorlevel 1 (
+               echo Visual Studio not found ^(try with the 'verbose' switch for more information^)
                goto EOF
        )
- )
- set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE%
- if NOT "%BUILD_DIR_OVERRRIDE%"=="" (
-       set BUILD_DIR=%BUILD_DIR_OVERRRIDE%
- )
- where /Q cmake
- if %ERRORLEVEL% NEQ 0 (
-       echo Error: "CMake" command not in the PATH.
-       echo You must have CMake installed and added to your PATH, aborting!
-       goto EOF
- )
- if "%BUILD_ARCH%"=="x64" (
-       set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
- ) else if "%BUILD_ARCH%"=="x86" (
-       set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
- )
- set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
- if NOT EXIST %BUILD_VS_LIBDIR% (
-       rem libs not found, but svn is on the system
-       if not "%HAS_SVN%"=="" (
-               echo.
-               echo The required external libraries in %BUILD_VS_LIBDIR% are missing
-               echo.
-               set /p GetLibs= "Would you like to download them? (y/n)"
-               if /I "!GetLibs!"=="Y" (
-                       echo.
-                       echo Downloading %BUILD_VS_SVNDIR% libraries, please wait.
-                       echo.
-                       svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR%
-               )
+ ) else (
+       call "%BLENDER_DIR%\build_files\windows\detect_msvc%BUILD_VS_YEAR%.cmd"
+       if errorlevel 1 (
+               echo Visual Studio %BUILD_VS_YEAR% not found ^(try with the 'verbose' switch for more information^)
+               goto EOF
        )
  )
  
- if NOT EXIST %BUILD_VS_LIBDIR% (
-       echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%"
-       echo This is needed for building, aborting!
-       goto EOF
- )
+ call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" 
  
- if "%TARGET%"=="" (
-       echo Error: Convenience target not set
-       echo This is required for building, aborting!
-       echo .
-       goto HELP
- )
+ echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR%
  
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS%
- if NOT EXIST %BUILD_DIR%\nul (
-       mkdir %BUILD_DIR%
- )
- if "%MUST_CLEAN%"=="1" (
-       echo Cleaning %BUILD_DIR%
-       msbuild ^
-               %BUILD_DIR%\Blender.sln ^
-               /target:clean ^
-               /property:Configuration=%BUILD_TYPE% ^
-               /verbosity:minimal ^
-               /p:platform=%MSBUILD_PLATFORM%
+ call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" 
+ if errorlevel 1 goto EOF
  
-       if %ERRORLEVEL% NEQ 0 (
-               echo Cleaned "%BUILD_DIR%"
-       )
-       goto EOF
- )
- REM Only configure on first run or when called with nobuild
- if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
- if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
- if "%MUST_CONFIGURE%"=="1" (
-       cmake ^
-               %BUILD_CMAKE_ARGS% ^
-               -H%BLENDER_DIR% ^
-               -B%BUILD_DIR% ^
-               %BUILD_CMAKE_ARGS%
-       if %ERRORLEVEL% NEQ 0 (
-               echo "Configuration Failed"
-               goto EOF
-       )
- )
- if DEFINED MSVC_VC_DIR echo call "%MSVC_VC_DIR%\vcvarsall.bat" > %BUILD_DIR%\rebuild.cmd
- if DEFINED MSVC_VS_DIR echo call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat" > %BUILD_DIR%\rebuild.cmd
- echo cmake . >> %BUILD_DIR%\rebuild.cmd
- echo msbuild ^
-       %BUILD_DIR%\Blender.sln ^
-       /target:build ^
-       /property:Configuration=%BUILD_TYPE% ^
-       /maxcpucount:2 ^
-       /verbosity:minimal ^
-       /p:platform=%MSBUILD_PLATFORM% ^
-       /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd
- echo msbuild ^
-       %BUILD_DIR%\INSTALL.vcxproj ^
-       /property:Configuration=%BUILD_TYPE% ^
-       /verbosity:minimal ^
-       /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd
+ call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd" 
+ if errorlevel 1 goto EOF
  
- if "%NOBUILD%"=="1" goto EOF
+ if "%BUILD_WITH_NINJA%" == "" (
+       call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd" 
+       if errorlevel 1 goto EOF
  
- msbuild ^
-       %BUILD_DIR%\Blender.sln ^
-       /target:build ^
-       /property:Configuration=%BUILD_TYPE% ^
-       /maxcpucount:2 ^
-       /verbosity:minimal ^
-       /p:platform=%MSBUILD_PLATFORM% ^
-       /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log
+       call "%BLENDER_DIR%\build_files\windows\build_msbuild.cmd" 
+       if errorlevel 1 goto EOF
+ ) else (
+       call "%BLENDER_DIR%\build_files\windows\configure_ninja.cmd" 
+       if errorlevel 1 goto EOF
  
- if %ERRORLEVEL% NEQ 0 (
-       echo "Build Failed"
-       goto EOF
+       call "%BLENDER_DIR%\build_files\windows\build_ninja.cmd" 
+       if errorlevel 1 goto EOF
  )
  
- msbuild ^
-       %BUILD_DIR%\INSTALL.vcxproj ^
-       /property:Configuration=%BUILD_TYPE% ^
-       /verbosity:minimal ^
-       /p:platform=%MSBUILD_PLATFORM%
- echo.
- echo At any point you can optionally modify your build configuration by editing:
- echo "%BUILD_DIR%\CMakeCache.txt", then run "rebuild.cmd" in the build folder to build with the changes applied.
- echo.
- echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender.exe"
- echo.
- goto EOF
- :HELP
-       echo.
-       echo Convenience targets
-       echo - release ^(identical to the official blender.org builds^)
-       echo - full ^(same as release minus the cuda kernels^)
-       echo - lite
-       echo - headless
-       echo - cycles
-       echo - bpy
-       echo.
-       echo Utilities ^(not associated with building^)
-       echo - clean ^(Target must be set^)
-       echo - update
-       echo - nobuild ^(only generate project files^)
-       echo - showhash ^(Show git hashes of source tree^)
-       echo.
-       echo Configuration options
-       echo - with_tests ^(enable building unit tests^)
-       echo - noge ^(disable building game enginge and player^)
-       echo - debug ^(Build an unoptimized debuggable build^)
-       echo - packagename [newname] ^(override default cpack package name^)
-       echo - buildir [newdir] ^(override default build folder^)
-       echo - x86 ^(override host auto-detect and build 32 bit code^)
-       echo - x64 ^(override host auto-detect and build 64 bit code^)
-       echo - 2013 ^(build with visual studio 2013^)
-       echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
-       echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL]
-       echo.
 -:EOF
 +:EOF
index 28e39959c7e5b1a037b8b8a044a05e03e96da1ef,5bcf188c683cd0c30a25360003d6e35ac136faa9..466e7dfa3256a8dbca99cf274512f44f279a1510
@@@ -328,7 -328,8 +328,8 @@@ class DATA_PT_modifiers(ModifierButtons
              row.prop(md, "delimit")
              layout_info = layout
  
-         layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False)
+         layout_info.label(text=iface_("Face Count: {:,}".format(md.face_count)),
+                      translate=False)
  
      def DISPLACE(self, layout, ob, md):
          has_texture = (md.texture is not None)
              col.prop(md, "texture_coords_object", text="")
          elif md.texture_coords == 'UV' and ob.type == 'MESH':
              col.label(text="UV Map:")
 -            col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
 +            col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
  
          layout.separator()
  
          sub.active = bool(md.vertex_group)
          sub.prop(md, "protect")
          col.label(text="Particle UV")
 -        col.prop_search(md, "particle_uv", ob.data, "uv_textures", text="")
 +        col.prop_search(md, "particle_uv", ob.data, "uv_layers", text="")
  
          col = split.column()
          col.prop(md, "use_edge_cut")
          col = split.column()
  
          scene = context.scene
 -        engine = scene.render.engine
 +        engine = context.engine
          show_adaptive_options = (
              engine == 'CYCLES' and md == ob.modifiers[-1] and
              scene.cycles.feature_set == 'EXPERIMENTAL'
  
      def UV_PROJECT(self, layout, ob, md):
          split = layout.split()
 -
 -        col = split.column()
 -        col.label(text="Image:")
 -        col.prop(md, "image", text="")
 -
          col = split.column()
 -        col.label(text="UV Map:")
 -        col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
 +        col.prop_search(md, "uv_layer", ob.data, "uv_layers")
 +        col.separator()
  
 -        split = layout.split()
 -        col = split.column()
 -        col.prop(md, "use_image_override")
          col.prop(md, "projector_count", text="Projectors")
          for proj in md.projectors:
              col.prop(proj, "object", text="")
          if md.texture_coords == 'OBJECT':
              layout.prop(md, "texture_coords_object", text="Object")
          elif md.texture_coords == 'UV' and ob.type == 'MESH':
 -            layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
 +            layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
  
      def WAVE(self, layout, ob, md):
          split = layout.split()
          col.template_ID(md, "texture", new="texture.new")
          layout.prop(md, "texture_coords")
          if md.texture_coords == 'UV' and ob.type == 'MESH':
 -            layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
 +            layout.prop_search(md, "uv_layer", ob.data, "uv_layers")
          elif md.texture_coords == 'OBJECT':
              layout.prop(md, "texture_coords_object")
  
                  if md.mask_tex_mapping == 'OBJECT':
                      layout.prop(md, "mask_tex_map_object", text="Object")
                  elif md.mask_tex_mapping == 'UV' and ob.type == 'MESH':
 -                    layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_textures")
 +                    layout.prop_search(md, "mask_tex_uv_layer", ob.data, "uv_layers")
  
      def VERTEX_WEIGHT_EDIT(self, layout, ob, md):
          split = layout.split()
  
          col = split.column()
          col.label(text="UV Map:")
 -        col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
 +        col.prop_search(md, "uv_layer", ob.data, "uv_layers", text="")
  
      def WIREFRAME(self, layout, ob, md):
          has_vgroup = bool(md.vertex_group)
index 591180f08b41e1c0f04f3ec2458e62eadd74a1ae,60a8471ca3b3ae8ee260377cf266a12adf26931c..d60710db4aa07c1452aba0b46282cf290354a662
@@@ -43,10 -43,18 +43,10 @@@ class CompositorNodeCategory(SortedNode
          return (context.space_data.tree_type == 'CompositorNodeTree')
  
  
 -class ShaderNewNodeCategory(SortedNodeCategory):
 +class ShaderNodeCategory(SortedNodeCategory):
      @classmethod
      def poll(cls, context):
 -        return (context.space_data.tree_type == 'ShaderNodeTree' and
 -                context.scene.render.use_shading_nodes)
 -
 -
 -class ShaderOldNodeCategory(SortedNodeCategory):
 -    @classmethod
 -    def poll(cls, context):
 -        return (context.space_data.tree_type == 'ShaderNodeTree' and
 -                not context.scene.render.use_shading_nodes)
 +        return (context.space_data.tree_type == 'ShaderNodeTree')
  
  
  class TextureNodeCategory(SortedNodeCategory):
@@@ -133,39 -141,62 +133,39 @@@ def object_shader_nodes_poll(context)
              snode.shader_type == 'OBJECT')
  
  
 +def cycles_shader_nodes_poll(context):
 +    return context.engine == 'CYCLES'
 +
 +
 +def eevee_shader_nodes_poll(context):
 +    return context.engine == 'BLENDER_EEVEE'
 +
 +
 +def eevee_cycles_shader_nodes_poll(context):
 +    return (cycles_shader_nodes_poll(context) or
 +            eevee_shader_nodes_poll(context))
 +
 +
 +def object_cycles_shader_nodes_poll(context):
 +    return (object_shader_nodes_poll(context) and
 +            cycles_shader_nodes_poll(context))
 +
 +
 +def object_eevee_shader_nodes_poll(context):
 +    return (object_shader_nodes_poll(context) and
 +            eevee_shader_nodes_poll(context))
 +
 +
 +def object_eevee_cycles_shader_nodes_poll(context):
 +    return (object_shader_nodes_poll(context) and
 +            eevee_cycles_shader_nodes_poll(context))
 +
 +
  # All standard node categories currently used in nodes.
  
  shader_node_categories = [
 -    # Shader Nodes
 -    ShaderOldNodeCategory("SH_INPUT", "Input", items=[
 -        NodeItem("ShaderNodeMaterial"),
 -        NodeItem("ShaderNodeCameraData"),
 -        NodeItem("ShaderNodeFresnel"),
 -        NodeItem("ShaderNodeLayerWeight"),
 -        NodeItem("ShaderNodeLampData"),
 -        NodeItem("ShaderNodeValue"),
 -        NodeItem("ShaderNodeRGB"),
 -        NodeItem("ShaderNodeTexture"),
 -        NodeItem("ShaderNodeGeometry"),
 -        NodeItem("ShaderNodeExtendedMaterial"),
 -        NodeItem("ShaderNodeParticleInfo"),
 -        NodeItem("ShaderNodeObjectInfo"),
 -        NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
 -        ]),
 -    ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
 -        NodeItem("ShaderNodeOutput"),
 -        NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
 -        ]),
 -    ShaderOldNodeCategory("SH_OP_COLOR", "Color", items=[
 -        NodeItem("ShaderNodeMixRGB"),
 -        NodeItem("ShaderNodeRGBCurve"),
 -        NodeItem("ShaderNodeInvert"),
 -        NodeItem("ShaderNodeHueSaturation"),
 -        NodeItem("ShaderNodeGamma"),
 -        ]),
 -    ShaderOldNodeCategory("SH_OP_VECTOR", "Vector", items=[
 -        NodeItem("ShaderNodeNormal"),
 -        NodeItem("ShaderNodeMapping"),
 -        NodeItem("ShaderNodeVectorCurve"),
 -        NodeItem("ShaderNodeVectorTransform"),
 -        NodeItem("ShaderNodeNormalMap"),
 -        ]),
 -    ShaderOldNodeCategory("SH_CONVERTOR", "Converter", items=[
 -        NodeItem("ShaderNodeValToRGB"),
 -        NodeItem("ShaderNodeRGBToBW"),
 -        NodeItem("ShaderNodeMath"),
 -        NodeItem("ShaderNodeVectorMath"),
 -        NodeItem("ShaderNodeSqueeze"),
 -        NodeItem("ShaderNodeSeparateRGB"),
 -        NodeItem("ShaderNodeCombineRGB"),
 -        NodeItem("ShaderNodeSeparateHSV"),
 -        NodeItem("ShaderNodeCombineHSV"),
 -        ]),
 -    ShaderOldNodeCategory("SH_GROUP", "Group", items=node_group_items),
 -    ShaderOldNodeCategory("SH_LAYOUT", "Layout", items=[
 -        NodeItem("NodeFrame"),
 -        NodeItem("NodeReroute"),
 -        ]),
 -
 -    # New Shader Nodes (Cycles)
 -    ShaderNewNodeCategory("SH_NEW_INPUT", "Input", items=[
 +    # Shader Nodes (Cycles and Eevee)
 +    ShaderNodeCategory("SH_NEW_INPUT", "Input", items=[
          NodeItem("ShaderNodeTexCoord"),
          NodeItem("ShaderNodeAttribute"),
          NodeItem("ShaderNodeLightPath"),
          NodeItem("ShaderNodeUVAlongStroke", poll=line_style_shader_nodes_poll),
          NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
 -        NodeItem("ShaderNodeOutputMaterial", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeOutputLamp", poll=object_shader_nodes_poll),
 +    ShaderNodeCategory("SH_NEW_OUTPUT", "Output", items=[
 +        NodeItem("ShaderNodeOutputMaterial", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeOutputLamp", poll=object_cycles_shader_nodes_poll),
          NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll),
          NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll),
          NodeItem("NodeGroupOutput", poll=group_input_output_item_poll),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[
 -        NodeItem("ShaderNodeMixShader"),
 -        NodeItem("ShaderNodeAddShader"),
 -        NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfPrincipled", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfGlass", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfTranslucent", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfAnisotropic", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfVelvet", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfToon", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeSubsurfaceScattering", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeEmission", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeBsdfHair", poll=object_shader_nodes_poll),
 +    ShaderNodeCategory("SH_NEW_SHADER", "Shader", items=[
 +        NodeItem("ShaderNodeMixShader", poll=eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeAddShader", poll=eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfDiffuse", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfPrincipled", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfGlossy", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfTransparent", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfRefraction", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfGlass", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfTranslucent", poll=object_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfAnisotropic", poll=object_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfVelvet", poll=object_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfToon", poll=object_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeSubsurfaceScattering", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeEmission", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeBsdfHair", poll=object_cycles_shader_nodes_poll),
          NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll),
 -        NodeItem("ShaderNodeAmbientOcclusion", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeHoldout", poll=object_shader_nodes_poll),
 -        NodeItem("ShaderNodeVolumeAbsorption"),
 -        NodeItem("ShaderNodeVolumeScatter"),
 +        NodeItem("ShaderNodeAmbientOcclusion", poll=object_eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeHoldout", poll=object_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeVolumeAbsorption", poll=eevee_cycles_shader_nodes_poll),
 +        NodeItem("ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll),
          NodeItem("ShaderNodeVolumePrincipled"),
 +        NodeItem("ShaderNodeEeveeSpecular", poll=object_eevee_shader_nodes_poll),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
 +    ShaderNodeCategory("SH_NEW_TEXTURE", "Texture", items=[
          NodeItem("ShaderNodeTexImage"),
          NodeItem("ShaderNodeTexEnvironment"),
          NodeItem("ShaderNodeTexSky"),
          NodeItem("ShaderNodeTexChecker"),
          NodeItem("ShaderNodeTexBrick"),
          NodeItem("ShaderNodeTexPointDensity"),
+         NodeItem("ShaderNodeTexIES"),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
 +    ShaderNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
          NodeItem("ShaderNodeMixRGB"),
          NodeItem("ShaderNodeRGBCurve"),
          NodeItem("ShaderNodeInvert"),
          NodeItem("ShaderNodeGamma"),
          NodeItem("ShaderNodeBrightContrast"),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_OP_VECTOR", "Vector", items=[
 +    ShaderNodeCategory("SH_NEW_OP_VECTOR", "Vector", items=[
          NodeItem("ShaderNodeMapping"),
          NodeItem("ShaderNodeBump"),
          NodeItem("ShaderNodeDisplacement"),
          NodeItem("ShaderNodeVectorCurve"),
          NodeItem("ShaderNodeVectorTransform"),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
 +    ShaderNodeCategory("SH_NEW_CONVERTOR", "Converter", items=[
          NodeItem("ShaderNodeMath"),
          NodeItem("ShaderNodeValToRGB"),
          NodeItem("ShaderNodeRGBToBW"),
 +        NodeItem("ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll),
          NodeItem("ShaderNodeVectorMath"),
          NodeItem("ShaderNodeSeparateRGB"),
          NodeItem("ShaderNodeCombineRGB"),
          NodeItem("ShaderNodeWavelength"),
          NodeItem("ShaderNodeBlackbody"),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_SCRIPT", "Script", items=[
 +    ShaderNodeCategory("SH_NEW_SCRIPT", "Script", items=[
          NodeItem("ShaderNodeScript"),
          ]),
 -    ShaderNewNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
 -    ShaderNewNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
 +    ShaderNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
 +    ShaderNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
          NodeItem("NodeFrame"),
          NodeItem("NodeReroute"),
          ]),
index f3cbcd7b99ff288f880ee163ac08d21c258efc89,150f0818cb8b25b9d5ce8a730c4968e7f6688ecb..c654dd51e2ad6283ab02a9f1a57c96e491d0b5f1
@@@ -74,7 -74,6 +74,7 @@@ struct PointerRNA
  struct RenderData;
  struct Scene;
  struct Tex;
 +struct ViewRender;
  struct SpaceNode;
  struct ARegion;
  struct ColorManagedViewSettings;
@@@ -252,9 -251,8 +252,9 @@@ typedef struct bNodeType 
  #define NODE_CLASS_LAYOUT                     100
  
  /* nodetype->compatibility */
 -#define NODE_OLD_SHADING      1
 -#define NODE_NEW_SHADING      2
 +#define NODE_OLD_SHADING      (1 << 0)
 +#define NODE_NEW_SHADING      (1 << 1)
 +#define NODE_NEWER_SHADING    (1 << 2)
  
  /* node resize directions */
  #define NODE_RESIZE_TOP               1
@@@ -498,6 -496,7 +498,6 @@@ struct bNode   *nodeGetActiveTexture(st
  void            nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
  bool            nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
  void            nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
 -void            nodeSynchronizeID(struct bNode *node, bool copy_to_id);
  
  int             nodeSocketIsHidden(struct bNodeSocket *sock);
  void            ntreeTagUsedSockets(struct bNodeTree *ntree);
@@@ -691,33 -690,27 +691,33 @@@ bool BKE_node_tree_iter_step(struct Nod
  }
  /** \} */
  
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Node Tree
 + */
 +
 +void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
 +
  /* -------------------------------------------------------------------- */
  /** \name Shader Nodes
   * \{ */
 -struct ShadeInput;
 -struct ShadeResult;
  
  /* note: types are needed to restore callbacks, don't change values */
  /* range 1 - 100 is reserved for common nodes */
  /* using toolbox, we add node groups by assuming the values below don't exceed NODE_GROUP_MENU for now */
  
 -#define SH_NODE_OUTPUT                1
 +//#define SH_NODE_OUTPUT              1
  
 -#define SH_NODE_MATERIAL      100
 +//#define SH_NODE_MATERIAL    100
  #define SH_NODE_RGB                   101
  #define SH_NODE_VALUE         102
  #define SH_NODE_MIX_RGB               103
  #define SH_NODE_VALTORGB      104
  #define SH_NODE_RGBTOBW               105
 -#define SH_NODE_TEXTURE               106
 +#define SH_NODE_SHADERTORGB   106
 +//#define SH_NODE_TEXTURE             106
  #define SH_NODE_NORMAL                107
 -#define SH_NODE_GEOMETRY      108
 +//#define SH_NODE_GEOMETRY    108
  #define SH_NODE_MAPPING               109
  #define SH_NODE_CURVE_VEC     110
  #define SH_NODE_CURVE_RGB     111
  #define SH_NODE_MATH          115
  #define SH_NODE_VECT_MATH     116
  #define SH_NODE_SQUEEZE               117
 -#define SH_NODE_MATERIAL_EXT  118
 +//#define SH_NODE_MATERIAL_EXT        118
  #define SH_NODE_INVERT                119
  #define SH_NODE_SEPRGB                120
  #define SH_NODE_COMBRGB               121
  #define SH_NODE_UVALONGSTROKE                 191
  #define SH_NODE_TEX_POINTDENSITY              192
  #define SH_NODE_BSDF_PRINCIPLED         193
+ #define SH_NODE_TEX_IES                 194
 +#define SH_NODE_EEVEE_SPECULAR                        195
  #define SH_NODE_BEVEL                   197
  #define SH_NODE_DISPLACEMENT            198
  #define SH_NODE_VECTOR_DISPLACEMENT     199
  
  struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
  void            ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
 -bool            ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
 -void            ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
 -
 -/* switch material render loop */
 -extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
 -void            set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
 +bool            ntreeShaderExecTree(struct bNodeTree *ntree, int thread);
  
  void            ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility);
 +void            ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output);
  
  /** \} */
  
@@@ -985,7 -982,7 +986,7 @@@ void ntreeCompositTagRender(struct Scen
  int ntreeCompositTagAnimated(struct bNodeTree *ntree);
  void ntreeCompositTagGenerators(struct bNodeTree *ntree);
  void ntreeCompositUpdateRLayers(struct bNodeTree *ntree);
 -void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
 +void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int type);
  void ntreeCompositClearTags(struct bNodeTree *ntree);
  
  struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node,
@@@ -1044,22 -1041,10 +1045,22 @@@ struct bNodeTreeExec *ntreeTexBeginExec
  void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
  int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
                       float coord[3], float dxt[3], float dyt[3], int osatex, const short thread,
 -                     struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
 +                     struct Tex *tex, short which_output, int cfra, int preview, struct MTex *mtex);
  /** \} */
  
  void init_nodesystem(void);
  void free_nodesystem(void);
  
 +/* -------------------------------------------------------------------- */
 +/* evaluation support, */
 +
 +struct Depsgraph;
 +
 +void BKE_nodetree_copy_default_values(struct bNodeTree *ntree_dst,
 +                                      const struct bNodeTree *ntree_src);
 +
 +void BKE_nodetree_shading_params_eval(struct Depsgraph *depsgraph,
 +                                      struct bNodeTree *ntree_dst,
 +                                      const struct bNodeTree *ntree_src);
 +
  #endif  /* __BKE_NODE_H__ */
index 259c51898968121377d0884e10a7af71b6f31c86,cc4c28e8016666d1f1c1a8df3cccf9ffdc5a2eee..dbaf3f2ee9e88feb7eff23f54b3bb71d0bb8a00e
@@@ -560,6 -560,10 +560,10 @@@ void BKE_bpath_traverse_id(Main *bmain
                                                NodeShaderScript *nss = (NodeShaderScript *)node->storage;
                                                rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
                                        }
+                                       else if (node->type == SH_NODE_TEX_IES) {
+                                               NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
+                                               rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
+                                       }
                                }
                        }
                        break;
                                                NodeShaderScript *nss = (NodeShaderScript *)node->storage;
                                                rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
                                        }
+                                       else if (node->type == SH_NODE_TEX_IES) {
+                                               NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
+                                               rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
+                                       }
                                }
                        }
                        break;
                }
 -              case ID_TE:
 -              {
 -                      Tex *tex = (Tex *)id;
 -                      if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) {
 -                              rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data);
 -                      }
 -                      break;
 -              }
                case ID_SCE:
                {
                        Scene *scene = (Scene *)id;
index d86b73ab1a9bb4c742f03488605564c5b143cccd,521874bb14f3d84c5ec1aaf7a5b39cc8524b865f..a25b21a995a8fb88acccd1023dca0441245caa6f
@@@ -75,8 -75,6 +75,8 @@@
  #include "NOD_shader.h"
  #include "NOD_texture.h"
  
 +#include "DEG_depsgraph.h"
 +
  #define NODE_DEFAULT_MAX_WIDTH 700
  
  /* Fallback types for undefined tree, nodes, sockets */
@@@ -1989,6 -1987,9 +1989,6 @@@ bNodeTree *ntreeLocalize(bNodeTree *ntr
        if (ntree) {
                bNodeTree *ltree;
                bNode *node;
 -              AnimData *adt;
 -
 -              bAction *action_backup = NULL, *tmpact_backup = NULL;
  
                BLI_spin_lock(&spin);
                if (!ntree->duplilock) {
  
                BLI_mutex_lock(ntree->duplilock);
  
 -              /* Workaround for copying an action on each render!
 -               * set action to NULL so animdata actions don't get copied */
 -              adt = BKE_animdata_from_id(&ntree->id);
 -
 -              if (adt) {
 -                      action_backup = adt->action;
 -                      tmpact_backup = adt->tmpact;
 -
 -                      adt->action = NULL;
 -                      adt->tmpact = NULL;
 -              }
 -
                /* Make full copy outside of Main database.
                 * Note: previews are not copied here.
                 */
 -              BKE_id_copy_ex(G.main, (ID *)ntree, (ID **)&ltree,
 -                             LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_COPY_NO_PREVIEW, false);
 +              BKE_id_copy_ex(
 +                      NULL, &ntree->id, (ID **)&ltree,
 +                      (LIB_ID_CREATE_NO_MAIN |
 +                       LIB_ID_CREATE_NO_USER_REFCOUNT |
 +                       LIB_ID_COPY_NO_PREVIEW |
 +                       LIB_ID_COPY_NO_ANIMDATA),
 +                      false);
                ltree->flag |= NTREE_IS_LOCALIZED;
  
                for (node = ltree->nodes.first; node; node = node->next) {
                        }
                }
  
 -              if (adt) {
 -                      AnimData *ladt = BKE_animdata_from_id(&ltree->id);
 -
 -                      adt->action = ladt->action = action_backup;
 -                      adt->tmpact = ladt->tmpact = tmpact_backup;
 -
 -                      if (action_backup)
 -                              id_us_plus(&action_backup->id);
 -                      if (tmpact_backup)
 -                              id_us_plus(&tmpact_backup->id);
 -
 -              }
 -              /* end animdata uglyness */
 -
                /* ensures only a single output node is enabled */
                ntreeSetOutput(ntree);
  
                for (node = ntree->nodes.first; node; node = node->next) {
                        /* store new_node pointer to original */
 -                      node->new_node->new_node = node;
 +                      node->new_node->original = node;
                }
  
                if (ntree->typeinfo->localize)
                        ntree->typeinfo->localize(ltree, ntree);
  
 +              ltree->id.tag |= LIB_TAG_LOCALIZED;
 +
                BLI_mutex_unlock(ntree->duplilock);
  
                return ltree;
@@@ -3098,6 -3118,77 +3098,6 @@@ void nodeUpdateInternalLinks(bNodeTree 
  }
  
  
 -/* nodes that use ID data get synced with local data */
 -void nodeSynchronizeID(bNode *node, bool copy_to_id)
 -{
 -      if (node->id == NULL) return;
 -      
 -      if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
 -              bNodeSocket *sock;
 -              Material *ma = (Material *)node->id;
 -              int a;
 -              short check_flags = SOCK_UNAVAIL;
 -
 -              if (!copy_to_id)
 -                      check_flags |= SOCK_HIDDEN;
 -              
 -              /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */
 -              for (a = 0, sock = node->inputs.first; sock; sock = sock->next, a++) {
 -                      if (!(sock->flag & check_flags)) {
 -                              if (copy_to_id) {
 -                                      switch (a) {
 -                                              case MAT_IN_COLOR:
 -                                                      copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 -                                              case MAT_IN_SPEC:
 -                                                      copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 -                                              case MAT_IN_REFL:
 -                                                      ma->ref = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_MIR:
 -                                                      copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
 -                                              case MAT_IN_AMB:
 -                                                      ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_EMIT:
 -                                                      ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_SPECTRA:
 -                                                      ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_RAY_MIRROR:
 -                                                      ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_ALPHA:
 -                                                      ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                              case MAT_IN_TRANSLUCENCY:
 -                                                      ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
 -                                      }
 -                              }
 -                              else {
 -                                      switch (a) {
 -                                              case MAT_IN_COLOR:
 -                                                      copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break;
 -                                              case MAT_IN_SPEC:
 -                                                      copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break;
 -                                              case MAT_IN_REFL:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ref; break;
 -                                              case MAT_IN_MIR:
 -                                                      copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break;
 -                                              case MAT_IN_AMB:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break;
 -                                              case MAT_IN_EMIT:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break;
 -                                              case MAT_IN_SPECTRA:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break;
 -                                              case MAT_IN_RAY_MIRROR:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break;
 -                                              case MAT_IN_ALPHA:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break;
 -                                              case MAT_IN_TRANSLUCENCY:
 -                                                      ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break;
 -                                      }
 -                              }
 -                      }
 -              }
 -      }
 -}
 -
 -
  /* ************* node type access ********** */
  
  void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen)
@@@ -3462,7 -3553,10 +3462,7 @@@ static void registerShaderNodes(void
  {
        register_node_type_sh_group();
  
 -      register_node_type_sh_output();
 -      register_node_type_sh_material();
        register_node_type_sh_camera();
 -      register_node_type_sh_lamp();
        register_node_type_sh_gamma();
        register_node_type_sh_brightcontrast();
        register_node_type_sh_value();
        register_node_type_sh_mix_rgb();
        register_node_type_sh_valtorgb();
        register_node_type_sh_rgbtobw();
 -      register_node_type_sh_texture();
 +      register_node_type_sh_shadertorgb();
        register_node_type_sh_normal();
 -      register_node_type_sh_geom();
        register_node_type_sh_mapping();
        register_node_type_sh_curve_vec();
        register_node_type_sh_curve_rgb();
        register_node_type_sh_vect_math();
        register_node_type_sh_vect_transform();
        register_node_type_sh_squeeze();
 -      register_node_type_sh_material_ext();
        register_node_type_sh_invert();
        register_node_type_sh_seprgb();
        register_node_type_sh_combrgb();
        register_node_type_sh_add_shader();
        register_node_type_sh_uvmap();
        register_node_type_sh_uvalongstroke();
 +      register_node_type_sh_eevee_specular();
  
        register_node_type_sh_output_lamp();
        register_node_type_sh_output_material();
        register_node_type_sh_tex_checker();
        register_node_type_sh_tex_brick();
        register_node_type_sh_tex_pointdensity();
+       register_node_type_sh_tex_ies();
  }
  
  static void registerTextureNodes(void)
@@@ -3719,62 -3815,3 +3720,62 @@@ bool BKE_node_tree_iter_step(struct Nod
  
        return true;
  }
 +
 +/* -------------------------------------------------------------------- */
 +/* NodeTree kernel functions */
 +
 +void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
 +{
 +      BLI_assert(layer_index != -1);
 +      for (bNode *node = ntree->nodes.first; node; node = node->next) {
 +              if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
 +                      if (node->custom1 == layer_index) {
 +                              node->custom1 = 0;
 +                      }
 +                      else if (node->custom1 > layer_index) {
 +                              node->custom1--;
 +                      }
 +              }
 +      }
 +}
 +
 +static void node_copy_default_values_list(ListBase *sockets_dst,
 +                                          const ListBase *sockets_src)
 +{
 +      bNodeSocket *sock_dst = sockets_dst->first;
 +      const bNodeSocket *sock_src = sockets_src->first;
 +      while (sock_dst != NULL) {
 +              node_socket_copy_default_value(sock_dst, sock_src);
 +              sock_dst = sock_dst->next;
 +              sock_src = sock_src->next;
 +      }
 +}
 +
 +static void node_copy_default_values(bNode *node_dst, const bNode *node_src)
 +{
 +      node_copy_default_values_list(&node_dst->inputs, &node_src->inputs);
 +      node_copy_default_values_list(&node_dst->outputs, &node_src->outputs);
 +}
 +
 +void BKE_nodetree_copy_default_values(bNodeTree *ntree_dst,
 +                                      const bNodeTree *ntree_src)
 +{
 +      if (ntree_dst == ntree_src) {
 +              return;
 +      }
 +      bNode *node_dst = ntree_dst->nodes.first;
 +      const bNode *node_src = ntree_src->nodes.first;
 +      while (node_dst != NULL) {
 +              node_copy_default_values(node_dst, node_src);
 +              node_dst = node_dst->next;
 +              node_src = node_src->next;
 +      }
 +}
 +
 +void BKE_nodetree_shading_params_eval(struct Depsgraph *depsgraph,
 +                                      bNodeTree *ntree_dst,
 +                                      const bNodeTree *ntree_src)
 +{
 +      DEG_debug_print_eval(depsgraph, __func__, ntree_src->id.name, ntree_dst);
 +      BKE_nodetree_copy_default_values(ntree_dst, ntree_src);
 +}
index 7fd7b791a3f66d3a02167e3bf42bcede0d90b79b,3d1cdba1cddb25a232387ca08fefcd93181989b5..a99057ac0ad3c9a302d3417f738d392ceb6fe8c1
@@@ -38,7 -38,6 +38,7 @@@
  
  #include "DNA_ID.h"
  #include "DNA_dynamicpaint_types.h"
 +#include "DNA_group_types.h"
  #include "DNA_modifier_types.h"
  #include "DNA_object_types.h"
  #include "DNA_object_force_types.h"
@@@ -50,6 -49,7 +50,7 @@@
  #include "BLI_blenlib.h"
  #include "BLI_threads.h"
  #include "BLI_math.h"
+ #include "BLI_string.h"
  #include "BLI_utildefines.h"
  
  #include "BLT_translation.h"
@@@ -59,7 -59,6 +60,7 @@@
  #include "BKE_appdir.h"
  #include "BKE_anim.h"
  #include "BKE_cloth.h"
 +#include "BKE_collection.h"
  #include "BKE_dynamicpaint.h"
  #include "BKE_global.h"
  #include "BKE_main.h"
@@@ -73,8 -72,6 +74,8 @@@
  
  #include "BIK_api.h"
  
 +#include "DEG_depsgraph.h"
 +
  #ifdef WITH_BULLET
  #  include "RBI_api.h"
  #endif
@@@ -1651,25 -1648,6 +1652,25 @@@ void BKE_ptcache_id_from_rigidbody(PTCa
        pid->file_type = PTCACHE_FILE_PTCACHE;
  }
  
 +PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
 +{
 +      PTCacheID result = {0};
 +
 +      ListBase pidlist;
 +      BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
 +
 +      for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
 +              if (pid->cache == cache) {
 +                      result = *pid;
 +                      break;
 +              }
 +      }
 +
 +      BLI_freelistN(&pidlist);
 +
 +      return result;
 +}
 +
  void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
  {
        PTCacheID *pid;
                BLI_addtail(lb, pid);
        }
  
 -      if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
 -              ListBase *lb_dupli_ob;
 -              /* don't update the dupli groups, we only want their pid's */
 -              if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, false))) {
 -                      DupliObject *dob;
 -                      for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
 -                              if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
 -                                      ListBase lb_dupli_pid;
 -                                      BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
 -                                      BLI_movelisttolist(lb, &lb_dupli_pid);
 -                                      if (lb_dupli_pid.first)
 -                                              printf("Adding Dupli\n");
 -                              }
 -                      }
 +      /* Consider all object in dupli groups to be part of the same object,
 +       * for baking with linking dupligroups. Once we have better overrides
 +       * this can be revisited so users select the local objects directly. */
 +      if (scene && (duplis-- > 0) && (ob->dup_group)) {
 +              Collection *collection = ob->dup_group;
 +              Base *base = BKE_collection_object_cache_get(collection).first;
  
 -                      free_object_duplilist(lb_dupli_ob);     /* does restore */
 +              for (; base; base = base->next) {
 +                      if (base->object != ob) {
 +                              ListBase lb_dupli_pid;
 +                              BKE_ptcache_ids_from_object(&lb_dupli_pid, base->object, scene, duplis);
 +                              BLI_movelisttolist(lb, &lb_dupli_pid);
 +                      }
                }
        }
  }
@@@ -3376,7 -3357,6 +3377,7 @@@ int  BKE_ptcache_object_reset(Scene *sc
        if (ob->type == OB_ARMATURE)
                BIK_clear_cache(ob->pose);
  
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
        return reset;
  }
  
@@@ -3531,14 -3511,13 +3532,14 @@@ PointCache *BKE_ptcache_copy_list(ListB
   * every user action changing stuff, and then it runs a complete bake??? (ton) */
  
  /* Baking */
 -void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
 +void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
  {
        PTCacheBaker baker;
  
        memset(&baker, 0, sizeof(baker));
        baker.main = bmain;
        baker.scene = scene;
 +      baker.view_layer = view_layer;
        baker.bake = 0;
        baker.render = 0;
        baker.anim_init = 0;
@@@ -3564,8 -3543,6 +3565,8 @@@ void BKE_ptcache_bake(PTCacheBaker *bak
  {
        Main *bmain = baker->main;
        Scene *scene = baker->scene;
 +      ViewLayer *view_layer = baker->view_layer;
 +      struct Depsgraph *depsgraph = baker->depsgraph;
        Scene *sce_iter; /* SETLOOPER macro only */
        Base *base;
        ListBase pidlist;
                }
        }
        else {
 -              for (SETLOOPER(scene, sce_iter, base)) {
 +              for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
                        /* cache/bake everything in the scene */
                        BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
  
        stime = ptime = PIL_check_seconds_timer();
  
        for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
 -              BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay);
 +              BKE_scene_graph_update_for_newframe(depsgraph, bmain);
  
                if (baker->update_progress) {
                        float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
                }
        }
        else {
 -              for (SETLOOPER(scene, sce_iter, base)) {
 +              for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
                        BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
  
                        for (pid=pidlist.first; pid; pid=pid->next) {
        CFRA = cfrao;
        
        if (bake) { /* already on cfra unless baking */
 -              BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
 +              BKE_scene_graph_update_for_newframe(depsgraph, bmain);
        }
  
        /* TODO: call redraw all windows somehow */
@@@ -4071,9 -4048,11 +4072,11 @@@ void BKE_ptcache_update_info(PTCacheID 
        }
        else {
                PTCacheMem *pm = cache->mem_cache.first;
-               float bytes = 0.0f;
-               int i, mb;
-               
+               char formatted_tot[16];
+               char formatted_mem[15];
+               long long int bytes = 0.0f;
+               int i;
                for (; pm; pm=pm->next) {
                        for (i=0; i<BPHYS_TOT_DATA; i++)
                                bytes += MEM_allocN_len(pm->data[i]);
                        totframes++;
                }
  
-               mb = (bytes > 1024.0f * 1024.0f);
+               BLI_str_format_int_grouped(formatted_tot, totframes);
+               BLI_str_format_byte_unit(formatted_mem, bytes, true);
  
-               BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"),
-                            totframes,
-                            bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
-                            mb ? IFACE_("Mb") : IFACE_("kb"));
+               BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%s frames in memory (%s)"), formatted_tot, formatted_mem);
        }
  
        if (cache->flag & PTCACHE_OUTDATED) {
index dfcf5fd5d8d4cb9e00c9ac16459dcec3cc190ab3,10b5eded8d4dc629f79926289eebeeab491b1544..d2bfcfa76df63631b7e187634aa84c5b3006d956
@@@ -37,7 -37,6 +37,7 @@@
  #include "DNA_meta_types.h"
  #include "DNA_scene_types.h"
  
 +#include "BLI_listbase.h"
  #include "BLI_math.h"
  #include "BLI_string.h"
  #include "BLI_utildefines.h"
  #include "BKE_displist.h"
  #include "BKE_DerivedMesh.h"
  #include "BKE_key.h"
 +#include "BKE_layer.h"
  #include "BKE_paint.h"
  #include "BKE_particle.h"
  #include "BKE_editmesh.h"
 +#include "BKE_object.h"
  
  #include "ED_info.h"
  #include "ED_armature.h"
@@@ -272,32 -269,9 +272,32 @@@ static void stats_object_sculpt_dynamic
        stats->tottri = ob->sculpt->bm->totface;
  }
  
 +static void stats_dupli_object_group_count(Collection *collection, int *count)
 +{
 +      *count += BLI_listbase_count(&collection->gobject);
 +
 +      for (CollectionChild *child = collection->children.first; child; child = child->next) {
 +              stats_dupli_object_group_count(child->collection, count);
 +      }
 +}
 +
 +static void stats_dupli_object_group_doit(Collection *collection, SceneStats *stats, ParticleSystem *psys,
 +                                          const int totgroup, int *cur)
 +{
 +      for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
 +              int tot = count_particles_mod(psys, totgroup, *cur);
 +              stats_object(cob->ob, 0, tot, stats);
 +              (*cur)++;
 +      }
 +
 +      for (CollectionChild *child = collection->children.first; child; child = child->next) {
 +              stats_dupli_object_group_doit(child->collection, stats, psys, totgroup, cur);
 +      }
 +}
 +
  static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
  {
 -      if (base->flag & SELECT) stats->totobjsel++;
 +      if (base->flag & BASE_SELECTED) stats->totobjsel++;
  
        if (ob->transflag & OB_DUPLIPARTS) {
                /* Dupli Particles */
                                stats_object(part->dup_ob, 0, tot, stats);
                        }
                        else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
 -                              GroupObject *go;
 -                              int tot, totgroup = 0, cur = 0;
 -                              
 -                              for (go = part->dup_group->gobject.first; go; go = go->next)
 -                                      totgroup++;
 -
 -                              for (go = part->dup_group->gobject.first; go; go = go->next) {
 -                                      tot = count_particles_mod(psys, totgroup, cur);
 -                                      stats_object(go->ob, 0, tot, stats);
 -                                      cur++;
 -                              }
 +                              int totgroup = 0, cur = 0;
 +
 +                              Collection *collection = part->dup_group;
 +                              stats_dupli_object_group_count(collection, &totgroup);
 +                              stats_dupli_object_group_doit(collection, stats, psys, totgroup, &cur);
                        }
                }
                
 -              stats_object(ob, base->flag & SELECT, 1, stats);
 +              stats_object(ob, base->flag & BASE_SELECTED, 1, stats);
                stats->totobj++;
        }
        else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
                }
  
                stats->totobj += tot;
 -              stats_object(ob, base->flag & SELECT, tot, stats);
 +              stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
        }
        else if (ob->transflag & OB_DUPLIFRAMES) {
                /* Dupli Frames */
                int tot = count_duplilist(ob);
                stats->totobj += tot;
 -              stats_object(ob, base->flag & SELECT, tot, stats);
 +              stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
        }
 -      else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
 +      else if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group) {
                /* Dupli Group */
                int tot = count_duplilist(ob);
                stats->totobj += tot;
 -              stats_object(ob, base->flag & SELECT, tot, stats);
 +              stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
        }
        else {
                /* No Dupli */
 -              stats_object(ob, base->flag & SELECT, 1, stats);
 +              stats_object(ob, base->flag & BASE_SELECTED, 1, stats);
                stats->totobj++;
        }
  }
  
 -static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
 +static bool stats_is_object_dynamic_topology_sculpt(Object *ob, const eObjectMode object_mode)
  {
 -      return (ob && (ob->mode & OB_MODE_SCULPT) &&
 +      return (ob &&
 +              (object_mode & OB_MODE_SCULPT) &&
                ob->sculpt && ob->sculpt->bm);
  }
  
  /* Statistics displayed in info header. Called regularly on scene changes. */
 -static void stats_update(Scene *scene)
 +static void stats_update(ViewLayer *view_layer)
  {
        SceneStats stats = {0};
 -      Object *ob = (scene->basact) ? scene->basact->object : NULL;
 +      Object *ob = OBACT(view_layer);
 +      Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
        Base *base;
 -      
 -      if (scene->obedit) {
 +
 +      if (obedit) {
                /* Edit Mode */
 -              stats_object_edit(scene->obedit, &stats);
 +              stats_object_edit(ob, &stats);
        }
        else if (ob && (ob->mode & OB_MODE_POSE)) {
                /* Pose Mode */
                stats_object_pose(ob, &stats);
        }
 -      else if (stats_is_object_dynamic_topology_sculpt(ob)) {
 +      else if (ob && stats_is_object_dynamic_topology_sculpt(ob, ob->mode)) {
                /* Dynamic-topology sculpt mode */
                stats_object_sculpt_dynamic_topology(ob, &stats);
        }
        else {
                /* Objects */
 -              for (base = scene->base.first; base; base = base->next)
 -                      if (scene->lay & base->lay)
 +              for (base = view_layer->object_bases.first; base; base = base->next)
 +                      if (base->flag & BASE_VISIBLED) {
                                stats_dupli_object(base, base->object, &stats);
 +                      }
        }
  
 -      if (!scene->stats)
 -              scene->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
 +      if (!view_layer->stats) {
 +              view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
 +      }
  
 -      *(scene->stats) = stats;
 +      *(view_layer->stats) = stats;
  }
  
 -static void stats_string(Scene *scene)
 +static void stats_string(ViewLayer *view_layer)
  {
  #define MAX_INFO_MEM_LEN  64
 -      SceneStats *stats = scene->stats;
 +      SceneStats *stats = view_layer->stats;
        SceneStatsFmt stats_fmt;
 -      Object *ob = (scene->basact) ? scene->basact->object : NULL;
 +      Object *ob = OBACT(view_layer);
 +      Object *obedit = OBEDIT_FROM_OBACT(ob);
 +      eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT;
        uintptr_t mem_in_use, mmap_in_use;
        char memstr[MAX_INFO_MEM_LEN];
        char gpumemstr[MAX_INFO_MEM_LEN] = "";
+       char formatted_mem[15];
        char *s;
        size_t ofs = 0;
  
  
  
        /* get memory statistics */
-       ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
-                           (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
-       if (mmap_in_use)
-               BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+       BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true);
+       ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem);
+       if (mmap_in_use) {
+               BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true);
+               BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%s)"), formatted_mem);
+       }
  
        if (GPU_mem_stats_supported()) {
                int gpu_free_mem, gpu_tot_memory;
  
                GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
  
-               ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
+               BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, true);
+               ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem);
  
                if (gpu_tot_memory) {
-                       BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
+                       BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true);
+                       BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem);
                }
        }
  
  
        ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", versionstr);
  
 -      if (scene->obedit) {
 -              if (BKE_keyblock_from_object(scene->obedit))
 +      if (obedit) {
 +              if (BKE_keyblock_from_object(obedit))
                        ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs);
  
 -              if (scene->obedit->type == OB_MESH) {
 +              if (obedit->type == OB_MESH) {
                        ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
                                            IFACE_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"),
                                            stats_fmt.totvertsel, stats_fmt.totvert, stats_fmt.totedgesel, stats_fmt.totedge,
                                            stats_fmt.totfacesel, stats_fmt.totface, stats_fmt.tottri);
                }
 -              else if (scene->obedit->type == OB_ARMATURE) {
 +              else if (obedit->type == OB_ARMATURE) {
                        ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s/%s | Bones:%s/%s"), stats_fmt.totvertsel,
                                            stats_fmt.totvert, stats_fmt.totbonesel, stats_fmt.totbone);
                }
                ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
                ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
        }
 -      else if (ob && (ob->mode & OB_MODE_POSE)) {
 +      else if (ob && (object_mode & OB_MODE_POSE)) {
                ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"),
                                    stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
        }
 -      else if (stats_is_object_dynamic_topology_sculpt(ob)) {
 +      else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
                ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
                                    stats_fmt.tottri, gpumemstr);
        }
  
  #undef MAX_INFO_LEN
  
 -void ED_info_stats_clear(Scene *scene)
 +void ED_info_stats_clear(ViewLayer *view_layer)
  {
 -      if (scene->stats) {
 -              MEM_freeN(scene->stats);
 -              scene->stats = NULL;
 +      if (view_layer->stats) {
 +              MEM_freeN(view_layer->stats);
 +              view_layer->stats = NULL;
        }
  }
  
 -const char *ED_info_stats_string(Scene *scene)
 +const char *ED_info_stats_string(Scene *UNUSED(scene), ViewLayer *view_layer)
  {
 -      if (!scene->stats)
 -              stats_update(scene);
 -      stats_string(scene);
 -
 -      return scene->stats->infostr;
 +      if (!view_layer->stats) {
 +              stats_update(view_layer);
 +      }
 +      stats_string(view_layer);
 +      return view_layer->stats->infostr;
  }
index ca6ae5955a98616d4d1eaf1159d4d69f800b1129,ea8d4b36d3b5a73f26c68e85027af509f43a75d2..19e2ae9808aae144891251b8d4d6e193d099a33f
  #include "BLF_api.h"
  #include "BLT_translation.h"
  
 -#include "BIF_gl.h"
  #include "BIF_glutil.h"
  
 +#include "GPU_draw.h"
 +#include "GPU_batch.h"
 +#include "GPU_immediate.h"
 +#include "GPU_matrix.h"
 +
  #include "RNA_access.h"
  #include "RNA_define.h"
  
@@@ -66,7 -62,6 +66,7 @@@
  #include "WM_types.h"
  
  #include "UI_resources.h"
 +#include "UI_view2d.h"
  
  #include "IMB_colormanagement.h"
  #include "IMB_imbuf_types.h"
@@@ -85,6 -80,49 +85,6 @@@ static void node_socket_button_label(bC
        uiItemL(layout, text, 0);
  }
  
 -
 -/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
 -
 -#if 0 /* UNUSED */
 -static void node_draw_socket_new(bNodeSocket *sock, float size)
 -{
 -      float x = sock->locx, y = sock->locy;
 -      
 -      /* 16 values of sin function */
 -      static float si[16] = {
 -              0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
 -              0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
 -              -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
 -              -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
 -      };
 -      /* 16 values of cos function */
 -      static float co[16] = {
 -              1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
 -              -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
 -              -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
 -              0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
 -      };
 -      int a;
 -      
 -      glColor3ub(180, 180, 180);
 -      
 -      glBegin(GL_POLYGON);
 -      for (a = 0; a < 16; a++)
 -              glVertex2f(x + size * si[a], y + size * co[a]);
 -      glEnd();
 -      
 -      glColor4ub(0, 0, 0, 150);
 -      glEnable(GL_BLEND);
 -      glEnable(GL_LINE_SMOOTH);
 -      glBegin(GL_LINE_LOOP);
 -      for (a = 0; a < 16; a++)
 -              glVertex2f(x + size * si[a], y + size * co[a]);
 -      glEnd();
 -      glDisable(GL_LINE_SMOOTH);
 -      glDisable(GL_BLEND);
 -}
 -#endif
 -
  /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
  
  static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@@ -354,7 -392,6 +354,7 @@@ static void node_draw_frame_label(bNode
        const int font_size = data->label_size / aspect;
        const float margin = (float)(NODE_DY / 4);
        int label_height;
 +      unsigned char color[3];
  
        nodeLabel(ntree, node, label, sizeof(label));
  
        BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */
        
        /* title color */
 -      UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
 +      UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
 +      BLF_color3ubv(fontid, color);
  
        width = BLF_width(fontid, label, sizeof(label));
        ascender = BLF_ascender(fontid);
@@@ -429,7 -465,7 +429,7 @@@ static void node_draw_frame(const bCont
  {
        rctf *rct = &node->totr;
        int color_id = node_get_colorid(node);
 -      unsigned char color[4];
 +      float color[4];
        float alpha;
        
        /* skip if out of view */
                return;
        }
  
 -      UI_GetThemeColor4ubv(TH_NODE_FRAME, color);
 -      alpha = (float)(color[3]) / 255.0f;
 +      UI_GetThemeColor4fv(TH_NODE_FRAME, color);
 +      alpha = color[3];
        
        /* shadow */
        node_draw_shadow(snode, node, BASIS_RAD, alpha);
        
        /* body */
 -      if (node->flag & NODE_CUSTOM_COLOR)
 -              glColor4f(node->color[0], node->color[1], node->color[2], alpha);
 +      if (node->flag & NODE_CUSTOM_COLOR) {
 +              rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha);
 +      }
        else
 -              UI_ThemeColor4(TH_NODE_FRAME);
 -      glEnable(GL_BLEND);
 +              UI_GetThemeColor4fv(TH_NODE_FRAME, color);
 +
        UI_draw_roundbox_corner_set(UI_CNR_ALL);
 -      UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
 -      glDisable(GL_BLEND);
 +      UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
  
        /* outline active and selected emphasis */
        if (node->flag & SELECT) {
 -              glEnable(GL_BLEND);
 -              glEnable(GL_LINE_SMOOTH);
 -              
                if (node->flag & NODE_ACTIVE)
 -                      UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
 +                      UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
                else
 -                      UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
 -              UI_draw_roundbox_corner_set(UI_CNR_ALL);
 -              UI_draw_roundbox_gl_mode(GL_LINE_LOOP,
 -                        rct->xmin, rct->ymin,
 -                        rct->xmax, rct->ymax, BASIS_RAD);
 -              
 -              glDisable(GL_LINE_SMOOTH);
 -              glDisable(GL_BLEND);
 +                      UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
 +
 +              UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
        }
 -      
 +
        /* label */
        node_draw_frame_label(ntree, node, snode->aspect);
        
@@@ -536,9 -580,15 +536,9 @@@ static void node_draw_reroute_prepare(c
  static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
                                bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
  {
 -      bNodeSocket *sock;
        char showname[128]; /* 128 used below */
        rctf *rct = &node->totr;
  
 -#if 0   /* UNUSED */
 -      float size = NODE_REROUTE_SIZE;
 -#endif
 -      float socket_size = NODE_SOCKSIZE;
 -
        /* skip if out of view */
        if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
            node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax)
         * selection state is indicated by socket outline below!
         */
  #if 0
 +      float size = NODE_REROUTE_SIZE;
 +
        /* body */
 +      float debug_color[4];
        UI_draw_roundbox_corner_set(UI_CNR_ALL);
 -      UI_ThemeColor4(TH_NODE);
 -      glEnable(GL_BLEND);
 -      UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
 -      glDisable(GL_BLEND);
 +      UI_GetThemeColor4fv(TH_NODE, debug_color);
 +      UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
  
        /* outline active and selected emphasis */
        if (node->flag & SELECT) {
                glEnable(GL_BLEND);
                glEnable(GL_LINE_SMOOTH);
                /* using different shades of TH_TEXT_HI for the empasis, like triangle */
 -              if (node->flag & NODE_ACTIVE)
 -                      UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
 -              else
 -                      UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
 -              UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
 +              if (node->flag & NODE_ACTIVE) {
 +                      UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color);
 +              }
 +              else {
 +                      UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color);
 +              }
 +              UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
  
                glDisable(GL_LINE_SMOOTH);
                glDisable(GL_BLEND);
        /* only draw input socket. as they all are placed on the same position.
         * highlight also if node itself is selected, since we don't display the node body separately!
         */
 -      for (sock = node->inputs.first; sock; sock = sock->next) {
 -              node_socket_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
 -      }
 +      node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT);
  
        UI_block_end(C, node->block);
        UI_block_draw(C, node->block);
@@@ -679,6 -728,21 +679,6 @@@ static void node_buts_image_user(uiLayo
        }
  }
  
 -static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
 -{
 -      bNode *node = ptr->data;
 -      uiLayout *col;
 -      
 -      uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL);
 -      
 -      if (!node->id) return;
 -      
 -      col = uiLayoutColumn(layout, false);
 -      uiItemR(col, ptr, "use_diffuse", 0, NULL, ICON_NONE);
 -      uiItemR(col, ptr, "use_specular", 0, NULL, ICON_NONE);
 -      uiItemR(col, ptr, "invert_normal", 0, NULL, ICON_NONE);
 -}
 -
  static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
  {
        uiLayout *row, *col, *sub;
@@@ -726,6 -790,30 +726,6 @@@ static void node_shader_buts_vect_trans
        uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE);
  }
  
 -static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA *ptr)
 -{
 -      PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
 -      uiLayout *col;
 -
 -      col = uiLayoutColumn(layout, false);
 -
 -      if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
 -              PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
 -
 -              uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE);
 -              uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE);
 -      }
 -      else {
 -              uiItemR(col, ptr, "uv_layer", 0, IFACE_("UV"), ICON_NONE);
 -              uiItemR(col, ptr, "color_layer", 0, IFACE_("VCol"), ICON_NONE);
 -      }
 -}
 -
 -static void node_shader_buts_lamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 -{
 -      uiItemR(layout, ptr, "lamp_object", 0, IFACE_("Lamp Object"), ICON_NONE);
 -}
 -
  static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
  {
        uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE);
@@@ -934,7 -1022,7 +934,7 @@@ static void node_shader_buts_uvmap(uiLa
  
                if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
                        PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
 -                      uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
 +                      uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
                }
        }
  }
@@@ -953,7 -1041,7 +953,7 @@@ static void node_shader_buts_normal_map
  
                if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
                        PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
 -                      uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
 +                      uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
                }
                else
                        uiItemR(layout, ptr, "uv_map", 0, "", 0);
@@@ -980,7 -1068,7 +980,7 @@@ static void node_shader_buts_tangent(ui
  
                if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
                        PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
 -                      uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
 +                      uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
                }
                else
                        uiItemR(row, ptr, "uv_map", 0, "", 0);
@@@ -1021,6 -1109,21 +1021,21 @@@ static void node_shader_buts_hair(uiLay
        uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
  }
  
+ static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+ {
+       uiLayout *row;
+       row = uiLayoutRow(layout, false);
+       uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+       row = uiLayoutRow(layout, true);
+       if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL)
+               uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
+       else
+               uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+ }
  static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
  {
        uiLayout *row;
@@@ -1069,6 -1172,13 +1084,6 @@@ static void node_shader_buts_bevel(uiLa
  static void node_shader_set_butfunc(bNodeType *ntype)
  {
        switch (ntype->type) {
 -              case SH_NODE_MATERIAL:
 -              case SH_NODE_MATERIAL_EXT:
 -                      ntype->draw_buttons = node_shader_buts_material;
 -                      break;
 -              case SH_NODE_TEXTURE:
 -                      ntype->draw_buttons = node_buts_texture;
 -                      break;
                case SH_NODE_NORMAL:
                        ntype->draw_buttons = node_buts_normal;
                        break;
                case SH_NODE_VECT_TRANSFORM: 
                        ntype->draw_buttons = node_shader_buts_vect_transform;
                        break; 
 -              case SH_NODE_GEOMETRY:
 -                      ntype->draw_buttons = node_shader_buts_geometry;
 -                      break;
 -              case SH_NODE_LAMP:
 -                      ntype->draw_buttons = node_shader_buts_lamp;
 -                      break;
                case SH_NODE_ATTRIBUTE:
                        ntype->draw_buttons = node_shader_buts_attribute;
                        break;
                case SH_NODE_OUTPUT_LINESTYLE:
                        ntype->draw_buttons = node_buts_output_linestyle;
                        break;
+               case SH_NODE_TEX_IES:
+                       ntype->draw_buttons = node_shader_buts_ies;
+                       break;
                case SH_NODE_BEVEL:
                        ntype->draw_buttons = node_shader_buts_bevel;
                        break;
@@@ -1244,7 -1363,7 +1262,7 @@@ static void node_composit_buts_image_ex
        uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
  }
  
 -static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
 +static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
  {
        bNode *node = ptr->data;
        uiLayout *col, *row;
@@@ -2142,21 -2261,14 +2160,21 @@@ static void node_composit_backdrop_view
                const float cy = y + snode->zoom * backdropHeight * node->custom4;
                const float cross_size = 12 * U.pixelsize;
  
 -              glColor3f(1.0, 1.0, 1.0);
 +              Gwn_VertFormat *format = immVertexFormat();
 +              unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
 +              immUniformColor3f(1.0f, 1.0f, 1.0f);
  
 -              glBegin(GL_LINES);
 -              glVertex2f(cx - cross_size, cy - cross_size);
 -              glVertex2f(cx + cross_size, cy + cross_size);
 -              glVertex2f(cx + cross_size, cy - cross_size);
 -              glVertex2f(cx - cross_size, cy + cross_size);
 -              glEnd();
 +              immBegin(GWN_PRIM_LINES, 4);
 +              immVertex2f(pos, cx - cross_size, cy - cross_size);
 +              immVertex2f(pos, cx + cross_size, cy + cross_size);
 +              immVertex2f(pos, cx + cross_size, cy - cross_size);
 +              immVertex2f(pos, cx - cross_size, cy + cross_size);
 +              immEnd();
 +
 +              immUnbindProgram();
        }
  }
  
@@@ -2175,6 -2287,9 +2193,6 @@@ static void node_composit_backdrop_boxm
        float cx, cy, x1, x2, x3, x4;
        float y1, y2, y3, y4;
  
 -
 -      glColor3f(1.0, 1.0, 1.0);
 -
        cx  = x + snode->zoom * backdropWidth * boxmask->x;
        cy = y + snode->zoom * backdropHeight * boxmask->y;
  
        y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
        y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
  
 -      glBegin(GL_LINE_LOOP);
 -      glVertex2f(x1, y1);
 -      glVertex2f(x2, y2);
 -      glVertex2f(x3, y3);
 -      glVertex2f(x4, y4);
 -      glEnd();
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
 +      immUniformColor3f(1.0f, 1.0f, 1.0f);
 +
 +      immBegin(GWN_PRIM_LINE_LOOP, 4);
 +      immVertex2f(pos, x1, y1);
 +      immVertex2f(pos, x2, y2);
 +      immVertex2f(pos, x3, y3);
 +      immVertex2f(pos, x4, y4);
 +      immEnd();
 +
 +      immUnbindProgram();
  }
  
  static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
        float cx, cy, x1, x2, x3, x4;
        float y1, y2, y3, y4;
  
 -
 -      glColor3f(1.0, 1.0, 1.0);
 -
        cx  = x + snode->zoom * backdropWidth * ellipsemask->x;
        cy = y + snode->zoom * backdropHeight * ellipsemask->y;
  
        y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
        y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
  
 -      glBegin(GL_LINE_LOOP);
 +      Gwn_VertFormat *format = immVertexFormat();
 +      unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
  
 -      glVertex2f(x1, y1);
 -      glVertex2f(x2, y2);
 -      glVertex2f(x3, y3);
 -      glVertex2f(x4, y4);
 -      glEnd();
 +      immUniformColor3f(1.0f, 1.0f, 1.0f);
 +
 +      immBegin(GWN_PRIM_LINE_LOOP, 4);
 +      immVertex2f(pos, x1, y1);
 +      immVertex2f(pos, x2, y2);
 +      immVertex2f(pos, x3, y3);
 +      immVertex2f(pos, x4, y4);
 +      immEnd();
 +
 +      immUnbindProgram();
  }
  
  static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@@ -2445,7 -2546,7 +2463,7 @@@ static void node_composit_set_butfunc(b
                        ntype->draw_buttons_ex = node_composit_buts_image_ex;
                        break;
                case CMP_NODE_R_LAYERS:
 -                      ntype->draw_buttons = node_composit_buts_renderlayers;
 +                      ntype->draw_buttons = node_composit_buts_viewlayers;
                        break;
                case CMP_NODE_NORMAL:
                        ntype->draw_buttons = node_buts_normal;
@@@ -3134,7 -3235,6 +3152,7 @@@ void ED_init_node_socket_type_virtual(b
  void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key)
  {
        bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE);
 +      float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
        Image *ima;
        void *lock;
        ImBuf *ibuf;
        ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
        if (ibuf) {
                float x, y; 
 -              
 -              glMatrixMode(GL_PROJECTION);
 -              glPushMatrix();
 -              glMatrixMode(GL_MODELVIEW);
 -              glPushMatrix();
 -              
 +
 +              gpuPushProjectionMatrix();
 +              gpuPushMatrix();
 +
                /* somehow the offset has to be calculated inverse */
 -              
 -              glaDefine2DArea(&ar->winrct);
                wmOrtho2_region_pixelspace(ar);
                
                x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
                        unsigned char *display_buffer = NULL;
                        void *cache_handle = NULL;
                        
 -                      if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) {
 -                              int ofs;
 +                      if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
                                
                                display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
 -                              
 -#ifdef __BIG_ENDIAN__
 -                              if      (snode->flag & SNODE_SHOW_R) ofs = 0;
 -                              else if (snode->flag & SNODE_SHOW_G) ofs = 1;
 -                              else                                 ofs = 2;
 -#else
 -                              if      (snode->flag & SNODE_SHOW_R) ofs = 1;
 -                              else if (snode->flag & SNODE_SHOW_G) ofs = 2;
 -                              else                                 ofs = 3;
 -#endif
 -                              
 -                              glPixelZoom(snode->zoom, snode->zoom);
 -                              /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
 -                              
 -                              glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
 -                                                display_buffer - (4 - ofs));
 -                              
 -                              glPixelZoom(1.0f, 1.0f);
 -                      }
 -                      else if (snode->flag & SNODE_SHOW_ALPHA) {
 -                              display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
 -                              
 -                              glPixelZoom(snode->zoom, snode->zoom);
 -                              /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
 -#ifdef __BIG_ENDIAN__
 -                              glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
 -#endif
 -                              glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer);
 -                              
 -#ifdef __BIG_ENDIAN__
 -                              glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
 -#endif
 -                              glPixelZoom(1.0f, 1.0f);
 +
 +                              if (snode->flag & SNODE_SHOW_R)
 +                                      shuffle[0] = 1.0f;
 +                              else if (snode->flag & SNODE_SHOW_G)
 +                                      shuffle[1] = 1.0f;
 +                              else if (snode->flag & SNODE_SHOW_B)
 +                                      shuffle[2] = 1.0f;
 +                              else
 +                                      shuffle[3] = 1.0f;
 +
 +                              IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
 +                              GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
 +
 +                              immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
 +                                               display_buffer, snode->zoom, snode->zoom, NULL);
 +
 +                              GPU_shader_unbind();
                        }
                        else if (snode->flag & SNODE_USE_ALPHA) {
                                glEnable(GL_BLEND);
 -                              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 -                              glPixelZoom(snode->zoom, snode->zoom);
 -                              
 -                              glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
 -                              
 -                              glPixelZoom(1.0f, 1.0f);
 +                              glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 +
 +                              glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
 +
                                glDisable(GL_BLEND);
                        }
                        else {
 -                              glPixelZoom(snode->zoom, snode->zoom);
 -                              
 -                              glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
 -                              
 -                              glPixelZoom(1.0f, 1.0f);
 +                              glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
                        }
                        
                        if (cache_handle)
                            viewer_border->ymin < viewer_border->ymax)
                        {
                                rcti pixel_border;
 -                              UI_ThemeColor(TH_ACTIVE);
                                BLI_rcti_init(&pixel_border,
                                              x + snode->zoom * viewer_border->xmin * ibuf->x,
                                              x + snode->zoom * viewer_border->xmax * ibuf->x,
                                              y + snode->zoom * viewer_border->ymin * ibuf->y,
                                              y + snode->zoom * viewer_border->ymax * ibuf->y);
 -                              glaDrawBorderCorners(&pixel_border, 1.0f, 1.0f);
 +
 +                              unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +                              immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +                              immUniformThemeColor(TH_ACTIVE);
 +
 +                              immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
 +
 +                              immUnbindProgram();
                        }
                }
 -              
 -              glMatrixMode(GL_PROJECTION);
 -              glPopMatrix();
 -              glMatrixMode(GL_MODELVIEW);
 -              glPopMatrix();
 +
 +              gpuPopProjectionMatrix();
 +              gpuPopMatrix();
        }
        
        BKE_image_release_ibuf(ima, ibuf, lock);
  }
  
 -
 -/* if v2d not NULL, it clips and returns 0 if not visible */
 -bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
 +/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */
 +static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *link, float vec[4][2])
  {
 -      float dist, vec[4][2];
 +      float dist;
        float deltax, deltay;
        float cursor[2] = {0.0f, 0.0f};
        int toreroute, fromreroute;
                vec[2][0] = vec[3][0] - dist;
                vec[2][1] = vec[3][1];
        }
 +
        if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
 -              /* clipped */
 +              return 0; /* clipped */
        }
        else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
 -              /* clipped */
 +              return 0; /* clipped */
        }
 -      else {
 +
 +      return 1;
 +}
 +
 +/* if v2d not NULL, it clips and returns 0 if not visible */
 +bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
 +{
 +      float vec[4][2];
 +
 +      if (node_link_bezier_handles(v2d, snode, link, vec)) {
                /* always do all three, to prevent data hanging around */
                BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0],
                                              coord_array[0] + 0, resol, sizeof(float) * 2);
        return 0;
  }
  
 +#define NODELINK_GROUP_SIZE 256
  #define LINK_RESOL  24
 -#define LINK_ARROW  12  /* position of arrow on the link, LINK_RESOL/2 */
 -#define ARROW_SIZE (7 * UI_DPI_FAC)
 -void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
 -                           int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3)
 -{
 -      float coord_array[LINK_RESOL + 1][2];
 -      
 -      if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
 -              float dist, spline_step = 0.0f;
 -              int i;
 -              int drawarrow;
 -              /* store current linewidth */
 -              float linew;
 -              float arrow[2], arrow1[2], arrow2[2];
 -              glGetFloatv(GL_LINE_WIDTH, &linew);
 -              
 -              /* we can reuse the dist variable here to increment the GL curve eval amount*/
 -              dist = 1.0f / (float)LINK_RESOL;
 -              
 -              glEnable(GL_LINE_SMOOTH);
 -              
 -              drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
 -                           (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
 -
 -              if (drawarrow) {
 -                      /* draw arrow in line segment LINK_ARROW */
 -                      float d_xy[2], len;
 -
 -                      sub_v2_v2v2(d_xy, coord_array[LINK_ARROW], coord_array[LINK_ARROW - 1]);
 -                      len = len_v2(d_xy);
 -                      mul_v2_fl(d_xy, ARROW_SIZE / len);
 -                      arrow1[0] = coord_array[LINK_ARROW][0] - d_xy[0] + d_xy[1];
 -                      arrow1[1] = coord_array[LINK_ARROW][1] - d_xy[1] - d_xy[0];
 -                      arrow2[0] = coord_array[LINK_ARROW][0] - d_xy[0] - d_xy[1];
 -                      arrow2[1] = coord_array[LINK_ARROW][1] - d_xy[1] + d_xy[0];
 -                      arrow[0] = coord_array[LINK_ARROW][0];
 -                      arrow[1] = coord_array[LINK_ARROW][1];
 +#define LINK_WIDTH  (2.5f * UI_DPI_FAC)
 +#define ARROW_SIZE  (7 * UI_DPI_FAC)
 +
 +static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
 +static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
 +
 +struct {
 +      Gwn_Batch *batch; /* for batching line together */
 +      Gwn_Batch *batch_single; /* for single line */
 +      Gwn_VertBuf *inst_vbo;
 +      unsigned int p0_id, p1_id, p2_id, p3_id;
 +      unsigned int colid_id;
 +      Gwn_VertBufRaw p0_step, p1_step, p2_step, p3_step;
 +      Gwn_VertBufRaw colid_step;
 +      unsigned int count;
 +      bool enabled;
 +} g_batch_link = {0};
 +
 +static void nodelink_batch_reset(void)
 +{
 +      GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
 +      GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
 +      GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
 +      GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
 +      GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
 +      g_batch_link.count = 0;
 +}
 +
 +static void set_nodelink_vertex(
 +        Gwn_VertBuf *vbo,
 +        unsigned int uv_id, unsigned int pos_id, unsigned int exp_id, unsigned int v,
 +        const unsigned char uv[2], const float pos[2], const float exp[2])
 +{
 +      GWN_vertbuf_attr_set(vbo, uv_id, v, uv);
 +      GWN_vertbuf_attr_set(vbo, pos_id, v, pos);
 +      GWN_vertbuf_attr_set(vbo, exp_id, v, exp);
 +}
 +
 +static void nodelink_batch_init(void)
 +{
 +      Gwn_VertFormat format = {0};
 +      unsigned int uv_id = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
 +      unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      unsigned int expand_id = GWN_vertformat_attr_add(&format, "expand", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
 +      int vcount = LINK_RESOL * 2; /* curve */
 +      vcount += 2; /* restart strip */
 +      vcount += 3 * 2; /* arrow */
 +      vcount *= 2; /* shadow */
 +      vcount += 2; /* restart strip */
 +      GWN_vertbuf_data_alloc(vbo, vcount);
 +      int v = 0;
 +
 +      for (int k = 0; k < 2; ++k) {
 +              unsigned char uv[2] = {0, 0};
 +              float pos[2] = {0.0f, 0.0f};
 +              float exp[2] = {0.0f, 1.0f};
 +
 +              /* restart */
 +              if (k == 1)
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
 +
 +              /* curve strip */
 +              for (int i = 0; i < LINK_RESOL; ++i) {
 +                      uv[0] = 255 * (i / (float)(LINK_RESOL - 1));
 +                      uv[1] = 0;
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
 +                      uv[1] = 255;
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
                }
 -              if (do_triple) {
 -                      UI_ThemeColorShadeAlpha(th_col3, -80, -120);
 -                      glLineWidth(4.0f);
 -                      
 -                      glBegin(GL_LINE_STRIP);
 -                      for (i = 0; i <= LINK_RESOL; i++) {
 -                              glVertex2fv(coord_array[i]);
 -                      }
 -                      glEnd();
 -                      if (drawarrow) {
 -                              glBegin(GL_LINE_STRIP);
 -                              glVertex2fv(arrow1);
 -                              glVertex2fv(arrow);
 -                              glVertex2fv(arrow2);
 -                              glEnd();
 -                      }
 +              /* restart */
 +              set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
 +
 +              uv[0] = 127;
 +              uv[1] = 0;
 +              copy_v2_v2(pos, arrow_verts[0]);
 +              copy_v2_v2(exp, arrow_expand_axis[0]);
 +              set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
 +              /* arrow */
 +              for (int i = 0; i < 3; ++i) {
 +                      uv[1] = 0;
 +                      copy_v2_v2(pos, arrow_verts[i]);
 +                      copy_v2_v2(exp, arrow_expand_axis[i]);
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
 +
 +                      uv[1] = 255;
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
                }
 -              
 -              /* XXX using GL_LINES for shaded node lines is a workaround
 -               * for Intel hardware, this breaks with GL_LINE_STRIP and
 -               * changing color in begin/end blocks.
 -               */
 -              glLineWidth(1.5f);
 -              if (do_shaded) {
 -                      glBegin(GL_LINES);
 -                      for (i = 0; i < LINK_RESOL; i++) {
 -                              UI_ThemeColorBlend(th_col1, th_col2, spline_step);
 -                              glVertex2fv(coord_array[i]);
 -                              
 -                              UI_ThemeColorBlend(th_col1, th_col2, spline_step + dist);
 -                              glVertex2fv(coord_array[i + 1]);
 -                              
 -                              spline_step += dist;
 -                      }
 -                      glEnd();
 -              }
 -              else {
 -                      UI_ThemeColor(th_col1);
 -                      glBegin(GL_LINE_STRIP);
 -                      for (i = 0; i <= LINK_RESOL; i++) {
 -                              glVertex2fv(coord_array[i]);
 -                      }
 -                      glEnd();
 -              }
 -              
 -              if (drawarrow) {
 -                      glBegin(GL_LINE_STRIP);
 -                      glVertex2fv(arrow1);
 -                      glVertex2fv(arrow);
 -                      glVertex2fv(arrow2);
 -                      glEnd();
 -              }
 -              
 -              glDisable(GL_LINE_SMOOTH);
 +
 +              /* restart */
 +              if (k == 0)
 +                      set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
        }
 +
 +      g_batch_link.batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
 +      gpu_batch_presets_register(g_batch_link.batch);
 +
 +      g_batch_link.batch_single = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, 0);
 +      gpu_batch_presets_register(g_batch_link.batch_single);
 +
 +      /* Instances data */
 +      Gwn_VertFormat format_inst = {0};
 +      g_batch_link.p0_id = GWN_vertformat_attr_add(&format_inst, "P0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      g_batch_link.p1_id = GWN_vertformat_attr_add(&format_inst, "P1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      g_batch_link.p2_id = GWN_vertformat_attr_add(&format_inst, "P2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      g_batch_link.p3_id = GWN_vertformat_attr_add(&format_inst, "P3", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +      g_batch_link.colid_id = GWN_vertformat_attr_add(&format_inst, "colid_doarrow", GWN_COMP_U8, 4, GWN_FETCH_INT);
 +      g_batch_link.inst_vbo = GWN_vertbuf_create_with_format_ex(&format_inst, GWN_USAGE_STREAM);
 +      GWN_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */
 +
 +      GWN_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
 +
 +      nodelink_batch_reset();
  }
  
 -#if 0 /* not used in 2.5x yet */
 -static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2])
 +static char nodelink_get_color_id(int th_col)
  {
 -      if (link->fromsock) {
 -              coord_array[0][0] = link->fromsock->locx;
 -              coord_array[0][1] = link->fromsock->locy;
 -      }
 -      else {
 -              if (snode == NULL) return;
 -              coord_array[0][0] = snode->mx;
 -              coord_array[0][1] = snode->my;
 -      }
 -      if (link->tosock) {
 -              coord_array[1][0] = link->tosock->locx;
 -              coord_array[1][1] = link->tosock->locy;
 -      }
 -      else {
 -              if (snode == NULL) return;
 -              coord_array[1][0] = snode->mx;
 -              coord_array[1][1] = snode->my;
 +      switch (th_col) {
 +              case TH_WIRE:        return 1;
 +              case TH_WIRE_INNER:  return 2;
 +              case TH_ACTIVE:      return 3;
 +              case TH_EDGE_SELECT: return 4;
 +              case TH_REDALERT:    return 5;
        }
 +      return 0;
  }
  
 -void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link,
 -                             int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3)
 +static void nodelink_batch_draw(SpaceNode *snode)
  {
 -      float coord_array[2][2];
 -      int i;
 -      
 -      node_link_straight_points(v2d, snode, link, coord_array);
 -      
 -      glEnable(GL_LINE_SMOOTH);
 -      
 -      if (do_triple) {
 -              UI_ThemeColorShadeAlpha(th_col3, -80, -120);
 -              glLineWidth(4.0f);
 -              
 -              glBegin(GL_LINES);
 -              glVertex2fv(coord_array[0]);
 -              glVertex2fv(coord_array[1]);
 -              glEnd();
 +      if (g_batch_link.count == 0)
 +              return;
 +
 +      glEnable(GL_BLEND);
 +
 +      float colors[6][4] = {{0.0f}};
 +      UI_GetThemeColor4fv(TH_WIRE_INNER,  colors[nodelink_get_color_id(TH_WIRE_INNER)]);
 +      UI_GetThemeColor4fv(TH_WIRE,        colors[nodelink_get_color_id(TH_WIRE)]);
 +      UI_GetThemeColor4fv(TH_ACTIVE,      colors[nodelink_get_color_id(TH_ACTIVE)]);
 +      UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
 +      UI_GetThemeColor4fv(TH_REDALERT,    colors[nodelink_get_color_id(TH_REDALERT)]);
 +
 +      GWN_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count);
 +      GWN_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
 +
 +      GWN_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
 +      GWN_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
 +      GWN_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
 +      GWN_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE);
 +      GWN_batch_draw(g_batch_link.batch);
 +
 +      nodelink_batch_reset();
 +
 +      glDisable(GL_BLEND);
 +}
 +
 +void nodelink_batch_start(SpaceNode *UNUSED(snode))
 +{
 +      g_batch_link.enabled = true;
 +}
 +
 +void nodelink_batch_end(SpaceNode *snode)
 +{
 +      nodelink_batch_draw(snode);
 +      g_batch_link.enabled = false;
 +}
 +
 +static void nodelink_batch_add_link(
 +        SpaceNode *snode,
 +        const float p0[2], const float p1[2], const float p2[2], const float p3[2],
 +        int th_col1, int th_col2, int th_col3, bool drawarrow)
 +{
 +      /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
 +      BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
 +      BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
 +      BLI_assert(ELEM(th_col3, TH_WIRE, -1));
 +
 +      g_batch_link.count++;
 +      copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p0_step), p0);
 +      copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p1_step), p1);
 +      copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p2_step), p2);
 +      copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p3_step), p3);
 +      char *colid = GWN_vertbuf_raw_step(&g_batch_link.colid_step);
 +      colid[0] = nodelink_get_color_id(th_col1);
 +      colid[1] = nodelink_get_color_id(th_col2);
 +      colid[2] = nodelink_get_color_id(th_col3);
 +      colid[3] = drawarrow;
 +
 +      if (g_batch_link.count == NODELINK_GROUP_SIZE) {
 +              nodelink_batch_draw(snode);
        }
 -      
 -      UI_ThemeColor(th_col1);
 -      glLineWidth(1.5f);
 -      
 -      /* XXX using GL_LINES for shaded node lines is a workaround
 -       * for Intel hardware, this breaks with GL_LINE_STRIP and
 -       * changing color in begin/end blocks.
 -       */
 -      if (do_shaded) {
 -              glBegin(GL_LINES);
 -              for (i = 0; i < LINK_RESOL - 1; ++i) {
 -                      float t = (float)i / (float)(LINK_RESOL - 1);
 -                      UI_ThemeColorBlend(th_col1, th_col2, t);
 -                      glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
 -                                 (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
 -                      
 -                      t = (float)(i + 1) / (float)(LINK_RESOL - 1);
 -                      UI_ThemeColorBlend(th_col1, th_col2, t);
 -                      glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
 -                                 (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
 +}
 +
 +/* don't do shadows if th_col3 is -1. */
 +void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
 +                           int th_col1, int th_col2, int th_col3)
 +{
 +      float vec[4][2];
 +
 +      if (node_link_bezier_handles(v2d, snode, link, vec)) {
 +              int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
 +                               (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
 +
 +              if (g_batch_link.batch == NULL) {
 +                      nodelink_batch_init();
                }
 -              glEnd();
 -      }
 -      else {
 -              glBegin(GL_LINE_STRIP);
 -              for (i = 0; i < LINK_RESOL; ++i) {
 -                      float t = (float)i / (float)(LINK_RESOL - 1);
 -                      glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
 -                                 (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
 +
 +              if (g_batch_link.enabled) {
 +                      /* Add link to batch. */
 +                      nodelink_batch_add_link(snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow);
 +              }
 +              else {
 +                      /* Draw single link. */
 +                      float colors[3][4] = {{0.0f}};
 +                      if (th_col3 != -1) {
 +                              UI_GetThemeColor4fv(th_col3, colors[0]);
 +                      }
 +                      UI_GetThemeColor4fv(th_col1, colors[1]);
 +                      UI_GetThemeColor4fv(th_col2, colors[2]);
 +
 +                      Gwn_Batch *batch = g_batch_link.batch_single;
 +                      GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
 +                      GWN_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
 +                      GWN_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
 +                      GWN_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
 +                      GWN_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE);
 +                      GWN_batch_uniform_1i(batch, "doArrow", drawarrow);
 +                      GWN_batch_draw(batch);
                }
 -              glEnd();
        }
 -      
 -      glDisable(GL_LINE_SMOOTH);
  }
 -#endif
  
  /* note; this is used for fake links in groups too */
  void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
  {
 -      bool do_shaded = false;
 -      bool do_triple = false;
        int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
        
        if (link->fromsock == NULL && link->tosock == NULL)
        
        /* new connection */
        if (!link->fromsock || !link->tosock) {
 -              th_col1 = TH_ACTIVE;
 -              do_triple = true;
 +              th_col1 = th_col2 = TH_ACTIVE;
        }
        else {
                /* going to give issues once... */
                                if (link->tonode && link->tonode->flag & SELECT)
                                        th_col2 = TH_EDGE_SELECT;
                        }
 -                      do_shaded = true;
 -                      do_triple = true;
                }
                else {
 -                      th_col1 = TH_REDALERT;
 +                      th_col1 = th_col2 = TH_REDALERT;
 +                      // th_col3 = -1; /* no shadow */
                }
        }
  
 -      node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
 +      node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
  //    node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
  }
  
 -void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border)
 +void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned pos)
  {
 -      glBegin(GL_LINES);
 +      immBegin(GWN_PRIM_LINES, 4);
        
        if (border & (NODE_LEFT | NODE_RIGHT)) {
 -              glVertex2f(cent[0], v2d->cur.ymin);
 -              glVertex2f(cent[0], v2d->cur.ymax);
 +              immVertex2f(pos, cent[0], v2d->cur.ymin);
 +              immVertex2f(pos, cent[0], v2d->cur.ymax);
        }
        else {
 -              glVertex2f(cent[0], cent[1] - size);
 -              glVertex2f(cent[0], cent[1] + size);
 +              immVertex2f(pos, cent[0], cent[1] - size);
 +              immVertex2f(pos, cent[0], cent[1] + size);
        }
        
        if (border & (NODE_TOP | NODE_BOTTOM)) {
 -              glVertex2f(v2d->cur.xmin, cent[1]);
 -              glVertex2f(v2d->cur.xmax, cent[1]);
 +              immVertex2f(pos, v2d->cur.xmin, cent[1]);
 +              immVertex2f(pos, v2d->cur.xmax, cent[1]);
        }
        else {
 -              glVertex2f(cent[0] - size, cent[1]);
 -              glVertex2f(cent[0] + size, cent[1]);
 +              immVertex2f(pos, cent[0] - size, cent[1]);
 +              immVertex2f(pos, cent[0] + size, cent[1]);
        }
        
 -      glEnd();
 +      immEnd();
  }
index 66eaf34865f080a612bdc6fb65f44e254cc2c53d,8573bb3457aa6a6b399eb9a78031e358b3416b0f..cd8a49fd697c1b6cd017388fa5fe38336bcd9a78
@@@ -36,7 -36,6 +36,7 @@@
  #include <float.h>
  
  #include "DNA_armature_types.h"
 +#include "DNA_camera_types.h"
  #include "DNA_curve_types.h"
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h"
  #include "BLI_utildefines.h"
  
  #include "BKE_armature.h"
 +#include "BKE_camera.h"
  #include "BKE_context.h"
  #include "BKE_font.h"
 +#include "BKE_layer.h"
  #include "BKE_library.h"
  #include "BKE_object.h"
  #include "BKE_paint.h"
  #include "BKE_screen.h"
  #include "BKE_action.h"
  
 -
 -#include "BIF_gl.h"
 -#include "BIF_glutil.h"
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
  
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
  
  #include "RNA_access.h"
  #include "RNA_define.h"
@@@ -78,7 -75,6 +78,7 @@@
  #include "ED_mesh.h"
  #include "ED_gpencil.h"
  #include "ED_view3d.h"
 +#include "ED_transform_snap_object_context.h"
  
  #include "UI_resources.h"
  
@@@ -135,7 -131,6 +135,7 @@@ typedef struct ViewOpsData 
        ARegion *ar;
        View3D *v3d;
        RegionView3D *rv3d;
 +      Depsgraph *depsgraph;
  
        /** Needed for continuous zoom. */
        wmTimer *timer;
@@@ -220,7 -215,6 +220,7 @@@ static void viewops_data_alloc(bContex
  
        /* store data */
        op->customdata = vod;
 +      vod->depsgraph = CTX_data_depsgraph(C);
        vod->scene = CTX_data_scene(C);
        vod->sa = CTX_wm_area(C);
        vod->ar = CTX_wm_region(C);
@@@ -248,11 -242,8 +248,11 @@@ static bool view3d_orbit_calc_center(bC
        static float lastofs[3] = {0, 0, 0};
        bool is_set = false;
  
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
 -      Object *ob_act = OBACT;
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
 +      Object *ob_act_eval = OBACT(view_layer_eval);
 +      Object *ob_act = DEG_get_original_object(ob_act_eval);
  
        if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
            /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
                 */
                if (ob_act->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
                        float stroke[3];
 -                      BKE_paint_stroke_get_average(scene, ob_act, stroke);
 +                      BKE_paint_stroke_get_average(scene, ob_act_eval, stroke);
                        copy_v3_v3(lastofs, stroke);
                }
                else {
 -                      copy_v3_v3(lastofs, ob_act->obmat[3]);
 +                      copy_v3_v3(lastofs, ob_act_eval->obmat[3]);
                }
                is_set = true;
        }
        else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) {
 -              Curve *cu = ob_act->data;
 +              Curve *cu = ob_act_eval->data;
                EditFont *ef = cu->editfont;
                int i;
  
                }
                mul_v2_fl(lastofs, 1.0f / 4.0f);
  
 -              mul_m4_v3(ob_act->obmat, lastofs);
 +              mul_m4_v3(ob_act_eval->obmat, lastofs);
  
                is_set = true;
        }
        else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
                /* object mode use boundbox centers */
 -              View3D *v3d = CTX_wm_view3d(C);
 -              Base *base;
 +              Base *base_eval;
                unsigned int tot = 0;
                float select_center[3];
  
                zero_v3(select_center);
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (TESTBASE(v3d, base)) {
 +              for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASE(base_eval)) {
                                /* use the boundbox if we can */
 -                              Object *ob = base->object;
 +                              Object *ob_eval = base_eval->object;
  
 -                              if (ob->bb && !(ob->bb->flag & BOUNDBOX_DIRTY)) {
 +                              if (ob_eval->bb && !(ob_eval->bb->flag & BOUNDBOX_DIRTY)) {
                                        float cent[3];
  
 -                                      BKE_boundbox_calc_center_aabb(ob->bb, cent);
 +                                      BKE_boundbox_calc_center_aabb(ob_eval->bb, cent);
  
 -                                      mul_m4_v3(ob->obmat, cent);
 +                                      mul_m4_v3(ob_eval->obmat, cent);
                                        add_v3_v3(select_center, cent);
                                }
                                else {
 -                                      add_v3_v3(select_center, ob->obmat[3]);
 +                                      add_v3_v3(select_center, ob_eval->obmat[3]);
                                }
                                tot++;
                        }
@@@ -371,7 -363,6 +371,7 @@@ static void viewops_data_create
          bContext *C, wmOperator *op, const wmEvent *event,
          enum eViewOpsFlag viewops_flag)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ViewOpsData *vod = op->customdata;
        RegionView3D *rv3d = vod->rv3d;
  
                negate_v3_v3(fallback_depth_pt, rv3d->ofs);
  
                vod->use_dyn_ofs = ED_view3d_autodist(
 -                      vod->scene, vod->ar, vod->v3d,
 +                      depsgraph, vod->ar, vod->v3d,
                        event->mval, vod->dyn_ofs, true, fallback_depth_pt);
        }
        else {
        }
  
        if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
 -              if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
 +              if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
                        /* If we're switching from camera view to the perspective one,
                         * need to tag viewport update, so camera vuew and borders
                         * are properly updated.
  
        /* set the view from the camera, if view locking is enabled.
         * we may want to make this optional but for now its needed always */
 -      ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
  
        vod->init.dist = rv3d->dist;
        vod->init.camzoom = rv3d->camzoom;
  static void viewops_data_free(bContext *C, wmOperator *op)
  {
        ARegion *ar;
 +#if 0
        Paint *p = BKE_paint_get_active_from_context(C);
 -
 +#endif
        if (op->customdata) {
                ViewOpsData *vod = op->customdata;
                ar = vod->ar;
                ar = CTX_wm_region(C);
        }
  
 +#if 0
        if (p && (p->flags & PAINT_FAST_NAVIGATE))
 +#endif
                ED_region_tag_redraw(ar);
  }
  
@@@ -811,7 -799,7 +811,7 @@@ static void viewrotate_apply(ViewOpsDat
        vod->prev.event_xy[0] = event_xy[0];
        vod->prev.event_xy[1] = event_xy[1];
  
 -      ED_view3d_camera_lock_sync(vod->v3d, rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -1110,7 -1098,7 +1110,7 @@@ static void view3d_ndof_pan_zoom
  static void view3d_ndof_orbit(
          const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
          /* optional, can be NULL*/
-         ViewOpsData *vod)
+         ViewOpsData *vod, const bool apply_dyn_ofs)
  {
        View3D *v3d = sa->spacedata.first;
        RegionView3D *rv3d = ar->regiondata;
  
        BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
  
 -      ED_view3d_persp_ensure(v3d, ar);
 +      ED_view3d_persp_ensure(vod->depsgraph, v3d, ar);
  
        rv3d->view = RV3D_VIEW_USER;
  
                mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
        }
  
-       if (vod) {
+       if (apply_dyn_ofs) {
                viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
        }
  }
@@@ -1308,7 -1296,6 +1308,7 @@@ static int ndof_orbit_invoke(bContext *
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                ViewOpsData *vod;
                View3D *v3d;
                RegionView3D *rv3d;
                /* off by default, until changed later this function */
                rv3d->rot_angle = 0.0f;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress != P_FINISHING) {
                        const bool has_rotation = NDOF_HAS_ROTATE;
                        }
  
                        if (has_rotation) {
-                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
                        }
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(vod->ar);
  
@@@ -1377,7 -1364,6 +1377,7 @@@ static int ndof_orbit_zoom_invoke(bCont
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                ViewOpsData *vod;
                View3D *v3d;
                RegionView3D *rv3d;
                /* off by default, until changed later this function */
                rv3d->rot_angle = 0.0f;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress == P_FINISHING) {
                        /* pass */
                        }
  
                        if (has_rotation) {
-                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
                        }
                }
                else {  /* free/explore (like fly mode) */
                        ED_view3d_distance_set(rv3d, 0.0f);
  
                        if (has_rotation) {
-                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL);
+                               view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false);
                        }
  
                        ED_view3d_distance_set(rv3d, dist_backup);
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(vod->ar);
  
@@@ -1482,7 -1468,6 +1482,7 @@@ static int ndof_pan_invoke(bContext *C
                return OPERATOR_CANCELLED;
        }
        else {
 +              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
                View3D *v3d = CTX_wm_view3d(C);
                RegionView3D *rv3d = CTX_wm_region_view3d(C);
                const wmNDOFMotionData *ndof = event->customdata;
                if (!(has_translate || has_zoom))
                        return OPERATOR_CANCELLED;
  
 -              ED_view3d_camera_lock_init_ex(v3d, rv3d, false);
 +              ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
  
                if (ndof->progress != P_FINISHING) {
                        ScrArea *sa = CTX_wm_area(C);
                        }
                }
  
 -              ED_view3d_camera_lock_sync(v3d, rv3d);
 +              ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
  
                ED_region_tag_redraw(CTX_wm_region(C));
  
@@@ -1640,7 -1625,7 +1640,7 @@@ static void viewmove_apply(ViewOpsData 
        vod->prev.event_xy[0] = x;
        vod->prev.event_xy[1] = y;
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -1804,7 -1789,7 +1804,7 @@@ void viewzoom_modal_keymap(wmKeyConfig 
   * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
   */
  static void view_zoom_to_window_xy_camera(
 -        Scene *scene, View3D *v3d,
 +        Scene *scene, Depsgraph *depsgraph, View3D *v3d,
          ARegion *ar, float dfac, const int zoom_xy[2])
  {
        RegionView3D *rv3d = ar->regiondata;
                float pt_dst[2];
                float delta_px[2];
  
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false);
                BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
  
                rv3d->camzoom = camzoom_new;
                CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
  
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false);
                BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
  
                BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
@@@ -2001,7 -1986,7 +2001,7 @@@ static void viewzoom_apply_camera
                /* calculate inverted, then invert again (needed because of camera zoom scaling) */
                zfac = 1.0f / zfac;
                view_zoom_to_window_xy_camera(
 -                      vod->scene, vod->v3d,
 +                      vod->scene, vod->depsgraph, vod->v3d,
                        vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
        }
  
@@@ -2039,7 -2024,7 +2039,7 @@@ static void viewzoom_apply_3d
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -2121,7 -2106,6 +2121,7 @@@ static int viewzoom_modal(bContext *C, 
  
  static int viewzoom_exec(bContext *C, wmOperator *op)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d;
        RegionView3D *rv3d;
                const float step = 1.2f;
                /* this min and max is also in viewmove() */
                if (use_cam_zoom) {
 -                      view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
 +                      view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
                }
                else {
                        if (rv3d->dist < dist_range[1]) {
        else {
                const float step = 1.0f / 1.2f;
                if (use_cam_zoom) {
 -                      view_zoom_to_window_xy_camera(scene, v3d, ar, step, zoom_xy);
 +                      view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
                }
                else {
                        if (rv3d->dist > dist_range[0]) {
  
        ED_view3d_depth_tag_update(rv3d);
  
 -      ED_view3d_camera_lock_sync(v3d, rv3d);
 +      ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
        ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
  
        ED_region_tag_redraw(ar);
@@@ -2384,7 -2368,7 +2384,7 @@@ static void viewdolly_apply(ViewOpsDat
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -2485,7 -2469,7 +2485,7 @@@ static int viewdolly_exec(bContext *C, 
  
        ED_view3d_depth_tag_update(rv3d);
  
 -      ED_view3d_camera_lock_sync(v3d, rv3d);
 +      ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d);
  
        ED_region_tag_redraw(ar);
  
@@@ -2519,8 -2503,7 +2519,8 @@@ static int viewdolly_invoke(bContext *C
        if (vod->rv3d->persp != RV3D_PERSP) {
                if (vod->rv3d->persp == RV3D_CAMOB) {
                        /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
 -                      ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
 +                      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                      ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
                }
                else {
                        vod->rv3d->persp = RV3D_PERSP;
@@@ -2654,7 -2637,7 +2654,7 @@@ static void view3d_from_minmax
                }
  
                if (ok_dist) {
 -                      new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN);
 +                      new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), persp, true, (size / 2) * VIEW3D_MARGIN);
                        if (rv3d->is_persp) {
                                /* don't zoom closer than the near clipping plane */
                                new_dist = max_ff(new_dist, v3d->near * 1.5f);
@@@ -2709,9 -2692,8 +2709,9 @@@ static int view3d_all_exec(bContext *C
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        Scene *scene = CTX_data_scene(C);
 -      Base *base;
 -      float *curs;
 +      const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
 +      Base *base_eval;
        const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
        const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
                                  /* any one of the regions may be locked */
  
        if (center) {
                /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
 -              curs = ED_view3d_cursor3d_get(scene, v3d);
 +              View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
                zero_v3(min);
                zero_v3(max);
 -              zero_v3(curs);
 +              zero_v3(cursor->location);
 +              unit_qt(cursor->rotation);
        }
        else {
                INIT_MINMAX(min, max);
        }
  
 -      for (base = scene->base.first; base; base = base->next) {
 -              if (BASE_VISIBLE(v3d, base)) {
 +      for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
 +              if (BASE_VISIBLE(base_eval)) {
                        changed = true;
  
 -                      if (skip_camera && base->object == v3d->camera) {
 +                      Object *ob = DEG_get_original_object(base_eval->object);
 +                      if (skip_camera && ob == v3d->camera) {
                                continue;
                        }
  
 -                      BKE_object_minmax(base->object, min, max, false);
 +                      BKE_object_minmax(base_eval->object, min, max, false);
                }
        }
        if (!changed) {
@@@ -2802,13 -2782,9 +2802,13 @@@ static int viewselected_exec(bContext *
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        Scene *scene = CTX_data_scene(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
        bGPdata *gpd = CTX_data_gpencil_data(C);
        const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
 -      Object *ob = OBACT;
 +      const bool is_face_map = ((is_gp_edit == false) && ar->manipulator_map &&
 +                                WM_manipulatormap_is_any_selected(ar->manipulator_map));
 +      Object *ob_eval = OBACT(view_layer_eval);
        Object *obedit = CTX_data_edit_object(C);
        float min[3], max[3];
        bool ok = false, ok_dist = true;
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
        INIT_MINMAX(min, max);
 -
 -      if (is_gp_edit) {
 -              ob = NULL;
 +      if (is_gp_edit || is_face_map) {
 +              ob_eval = NULL;
        }
  
 -      if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
 +      if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) {
                /* hard-coded exception, we look for the one selected armature */
                /* this is weak code this way, we should make a generic active/selection callback interface once... */
 -              Base *base;
 -              for (base = scene->base.first; base; base = base->next) {
 -                      if (TESTBASELIB(v3d, base)) {
 -                              if (base->object->type == OB_ARMATURE)
 -                                      if (base->object->mode & OB_MODE_POSE)
 +              Base *base_eval;
 +              for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASELIB(base_eval)) {
 +                              if (base_eval->object->type == OB_ARMATURE)
 +                                      if (base_eval->object->mode & OB_MODE_POSE)
                                                break;
                        }
                }
 -              if (base)
 -                      ob = base->object;
 +              if (base_eval)
 +                      ob_eval = base_eval->object;
        }
  
 -
        if (is_gp_edit) {
 +              /* TODO(sergey): Check on this after gpencil merge. */
                CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
                {
                        /* we're only interested in selected points here... */
                }
                CTX_DATA_END;
        }
 +      else if (is_face_map) {
 +              ok = WM_manipulatormap_minmax(ar->manipulator_map, true, true, min, max);
 +      }
        else if (obedit) {
 -              ok = ED_view3d_minmax_verts(obedit, min, max);    /* only selected */
 +              /* only selected */
 +              FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, obedit->mode, ob_eval_iter) {
 +                      ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max);
 +              }
 +              FOREACH_OBJECT_IN_MODE_END;
        }
 -      else if (ob && (ob->mode & OB_MODE_POSE)) {
 -              ok = BKE_pose_minmax(ob, min, max, true, true);
 +      else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) {
 +              FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, ob_eval->mode, ob_eval_iter) {
 +                      ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true);
 +              }
 +              FOREACH_OBJECT_IN_MODE_END;
        }
 -      else if (BKE_paint_select_face_test(ob)) {
 -              ok = paintface_minmax(ob, min, max);
 +      else if (BKE_paint_select_face_test(ob_eval)) {
 +              ok = paintface_minmax(ob_eval, min, max);
        }
 -      else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
 -              ok = PE_minmax(scene, min, max);
 +      else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) {
 +              ok = PE_minmax(scene, view_layer_eval, min, max);
        }
 -      else if (ob &&
 -               (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
 +      else if (ob_eval &&
 +               (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
        {
 -              BKE_paint_stroke_get_average(scene, ob, min);
 +              BKE_paint_stroke_get_average(scene, ob_eval, min);
                copy_v3_v3(max, min);
                ok = true;
                ok_dist = 0; /* don't zoom */
        }
        else {
 -              Base *base;
 -              for (base = FIRSTBASE; base; base = base->next) {
 -                      if (TESTBASE(v3d, base)) {
 +              Base *base_eval;
 +              for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) {
 +                      if (TESTBASE(base_eval)) {
  
 -                              if (skip_camera && base->object == v3d->camera) {
 +                              if (skip_camera && base_eval->object == v3d->camera) {
                                        continue;
                                }
  
                                /* account for duplis */
 -                              if (BKE_object_minmax_dupli(scene, base->object, min, max, false) == 0)
 -                                      BKE_object_minmax(base->object, min, max, false);  /* use if duplis not found */
 +                              if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0)
 +                                      BKE_object_minmax(base_eval->object, min, max, false);  /* use if duplis not found */
  
                                ok = 1;
                        }
@@@ -2981,14 -2948,14 +2981,14 @@@ static int view_lock_to_active_exec(bCo
        Object *obact = CTX_data_active_object(C);
  
        if (v3d) {
 -
                ED_view3d_lock_clear(v3d);
  
                v3d->ob_centre = obact; /* can be NULL */
  
                if (obact && obact->type == OB_ARMATURE) {
                        if (obact->mode & OB_MODE_POSE) {
 -                              bPoseChannel *pcham_act = BKE_pose_channel_active(obact);
 +                              Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), obact);
 +                              bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval);
                                if (pcham_act) {
                                        BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone));
                                }
@@@ -3046,7 -3013,7 +3046,7 @@@ static int viewcenter_cursor_exec(bCont
  
                /* non camera center */
                float new_ofs[3];
 -              negate_v3_v3(new_ofs, ED_view3d_cursor3d_get(scene, v3d));
 +              negate_v3_v3(new_ofs, ED_view3d_cursor3d_get(scene, v3d)->location);
                ED_view3d_smooth_view(
                        C, v3d, ar, smooth_viewtx,
                        &(const V3D_SmoothParams) {.ofs = new_ofs});
@@@ -3082,10 -3049,10 +3082,10 @@@ static int viewcenter_pick_invoke(bCont
  {
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
  
        if (rv3d) {
 +              struct Depsgraph *graph = CTX_data_depsgraph(C);
                float new_ofs[3];
                const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
  
                view3d_operator_needs_opengl(C);
  
 -              if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false, NULL)) {
 +              if (ED_view3d_autodist(graph, ar, v3d, event->mval, new_ofs, false, NULL)) {
                        /* pass */
                }
                else {
@@@ -3133,7 -3100,6 +3133,7 @@@ void VIEW3D_OT_view_center_pick(wmOpera
  
  static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        float xfac, yfac;
        float size[2];
  
        rv3d->camdx = rv3d->camdy = 0.0f;
  
 -      ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
 +      ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
  
        /* 4px is just a little room from the edge of the area */
        xfac = (float)ar->winx / (float)(size[0] + 4);
@@@ -3217,7 -3183,6 +3217,7 @@@ void VIEW3D_OT_view_center_lock(wmOpera
  
  static int render_border_exec(bContext *C, wmOperator *op)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        View3D *v3d = CTX_wm_view3d(C);
        ARegion *ar = CTX_wm_region(C);
        RegionView3D *rv3d = ED_view3d_context_rv3d(C);
        /* calculate range */
  
        if (rv3d->persp == RV3D_CAMOB) {
 -              ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
 +              ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
        }
        else {
                vb.xmin = 0;
                        v3d->flag2 |= V3D_RENDER_BORDER;
        }
  
 +      if (rv3d->persp == RV3D_CAMOB) {
 +              DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
 +      }
        return OPERATOR_FINISHED;
  }
  
@@@ -3349,9 -3311,6 +3349,9 @@@ static int clear_render_border_exec(bCo
        border->xmax = 1.0f;
        border->ymax = 1.0f;
  
 +      if (rv3d->persp == RV3D_CAMOB) {
 +              DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
 +      }
        return OPERATOR_FINISHED;
  }
  
@@@ -3381,6 -3340,7 +3381,6 @@@ static int view3d_zoom_border_exec(bCon
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      Scene *scene = CTX_data_scene(C);
        const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
  
        /* Zooms in on a border drawn by the user */
        float new_ofs[3];
  
        /* ZBuffer depth vars */
 -      bglMats mats;
        float depth_close = FLT_MAX;
 -      double cent[2],  p[3];
 +      float cent[2],  p[3];
  
        /* note; otherwise opengl won't work */
        view3d_operator_needs_opengl(C);
        ED_view3d_dist_range_get(v3d, dist_range);
  
        /* Get Z Depths, needed for perspective, nice for ortho */
 -      bgl_get_mats(&mats);
 -      ED_view3d_draw_depth(scene, ar, v3d, true);
 +      ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, v3d, true);
  
        {
                /* avoid allocating the whole depth buffer */
                MEM_SAFE_FREE(depth_temp.depths);
        }
  
 -      cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2;
 -      cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2;
 +      cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
 +      cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
  
        if (rv3d->is_persp) {
 -              double p_corner[3];
 +              float p_corner[3];
  
                /* no depths to use, we cant do anything! */
                if (depth_close == FLT_MAX) {
                        return OPERATOR_CANCELLED;
                }
                /* convert border to 3d coordinates */
 -              if ((!gluUnProject(cent[0], cent[1], depth_close,
 -                                 mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                 &p[0], &p[1], &p[2])) ||
 -                  (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close,
 -                                 mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                 &p_corner[0], &p_corner[1], &p_corner[2])))
 +              if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) ||
 +                  (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
                {
                        return OPERATOR_CANCELLED;
                }
  
 -              dvec[0] = p[0] - p_corner[0];
 -              dvec[1] = p[1] - p_corner[1];
 -              dvec[2] = p[2] - p_corner[2];
 -
 -              new_ofs[0] = -p[0];
 -              new_ofs[1] = -p[1];
 -              new_ofs[2] = -p[2];
 +              sub_v3_v3v3(dvec, p, p_corner);
 +              negate_v3_v3(new_ofs, p);
  
                new_dist = len_v3(dvec);
  
                new_dist = rv3d->dist;
  
                /* convert the drawn rectangle into 3d space */
 -              if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close,
 -                                                         mats.modelview, mats.projection, (GLint *)mats.viewport,
 -                                                         &p[0], &p[1], &p[2]))
 -              {
 -                      new_ofs[0] = -p[0];
 -                      new_ofs[1] = -p[1];
 -                      new_ofs[2] = -p[2];
 +              if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) {
 +                      negate_v3_v3(new_ofs, p);
                }
                else {
                        float mval_f[2];
@@@ -3548,13 -3524,13 +3548,13 @@@ void VIEW3D_OT_zoom_border(wmOperatorTy
   * Sets the view to 1:1 camera/render-pixel.
   * \{ */
  
 -static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
 +static void view3d_set_1_to_1_viewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
  {
        RegionView3D *rv3d = ar->regiondata;
        float size[2];
        int im_width = (scene->r.size * scene->r.xsch) / 100;
  
 -      ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
 +      ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
  
        rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
        CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
  
  static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
  
        View3D *v3d;
        /* no NULL check is needed, poll checks */
        ED_view3d_context_user_region(C, &v3d, &ar);
  
 -      view3d_set_1_to_1_viewborder(scene, ar, v3d);
 +      view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
  
        WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
  
@@@ -3678,8 -3653,7 +3678,8 @@@ static void axis_set_view
                dist = rv3d->dist;
  
                /* so we animate _from_ the camera location */
 -              ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL);
 +              Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera);
 +              ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL);
  
                ED_view3d_smooth_view(
                        C, v3d, ar, smooth_viewtx,
@@@ -3709,6 -3683,7 +3709,6 @@@ static int viewnumpad_exec(bContext *C
        View3D *v3d;
        ARegion *ar;
        RegionView3D *rv3d;
 -      Scene *scene = CTX_data_scene(C);
        static int perspo = RV3D_PERSP;
        int viewnum, nextperspo;
        bool align_active;
                if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
                        /* lastview -  */
  
 +                      ViewLayer *view_layer = CTX_data_view_layer(C);
 +                      Scene *scene = CTX_data_scene(C);
 +
                        if (rv3d->persp != RV3D_CAMOB) {
 -                              Object *ob = OBACT;
 +                              Object *ob = OBACT(view_layer);
  
                                if (!rv3d->smooth_timer) {
                                        /* store settings of current view before allowing overwriting with camera view
                                        v3d->camera = ob;
  
                                if (v3d->camera == NULL)
 -                                      v3d->camera = BKE_scene_camera_find(scene);
 +                                      v3d->camera = BKE_view_layer_camera_find(view_layer);
  
                                /* couldnt find any useful camera, bail out */
                                if (v3d->camera == NULL)
@@@ -3889,8 -3861,7 +3889,8 @@@ static int vieworbit_exec(bContext *C, 
                        float quat_new[4];
  
                        if (view_opposite == RV3D_VIEW_USER) {
 -                              ED_view3d_persp_ensure(v3d, ar);
 +                              const Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +                              ED_view3d_persp_ensure(depsgraph, v3d, ar);
                        }
  
                        if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@@ -4015,7 -3986,7 +4015,7 @@@ static void viewroll_apply(ViewOpsData 
                view3d_boxview_sync(vod->sa, vod->ar);
        }
  
 -      ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
 +      ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
  
        ED_region_tag_redraw(vod->ar);
  }
@@@ -4348,11 -4319,11 +4348,11 @@@ void VIEW3D_OT_navigate(wmOperatorType 
  /** \name Background Image Add Operator
   * \{ */
  
 -static BGpic *background_image_add(bContext *C)
 +static CameraBGImage *background_image_add(bContext *C)
  {
 -      View3D *v3d = CTX_wm_view3d(C);
 +      Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
  
 -      return ED_view3d_background_image_new(v3d);
 +      return BKE_camera_background_image_new(cam);
  }
  
  static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
  
  static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
  {
 -      View3D *v3d = CTX_wm_view3d(C);
 +      Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
        Image *ima;
 -      BGpic *bgpic;
 +      CameraBGImage *bgpic;
  
        ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
        /* may be NULL, continue anyway */
        bgpic = background_image_add(C);
        bgpic->ima = ima;
  
 -      v3d->flag |= V3D_DISPBGPICS;
 +      cam->flag |= CAM_SHOW_BG_IMAGE;
  
 -      WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 +      WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
  
        return OPERATOR_FINISHED;
  }
@@@ -4393,7 -4364,7 +4393,7 @@@ void VIEW3D_OT_background_image_add(wmO
        /* api callbacks */
        ot->invoke = background_image_add_invoke;
        ot->exec   = background_image_add_exec;
 -      ot->poll   = ED_operator_view3d_active;
 +      ot->poll   = ED_operator_camera;
  
        /* flags */
        ot->flag   = OPTYPE_UNDO;
  
  static int background_image_remove_exec(bContext *C, wmOperator *op)
  {
 -      View3D *v3d = CTX_wm_view3d(C);
 +      Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
        const int index = RNA_int_get(op->ptr, "index");
 -      BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index);
 +      CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index);
  
        if (bgpic_rem) {
 -              if (bgpic_rem->source == V3D_BGPIC_IMAGE) {
 +              if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) {
                        id_us_min((ID *)bgpic_rem->ima);
                }
 -              else if (bgpic_rem->source == V3D_BGPIC_MOVIE) {
 +              else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) {
                        id_us_min((ID *)bgpic_rem->clip);
                }
  
 -              ED_view3d_background_image_remove(v3d, bgpic_rem);
 +              BKE_camera_background_image_remove(cam, bgpic_rem);
  
 -              WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 +              WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
                return OPERATOR_FINISHED;
        }
        else {
@@@ -4444,7 -4415,7 +4444,7 @@@ void VIEW3D_OT_background_image_remove(
  
        /* api callbacks */
        ot->exec   = background_image_remove_exec;
 -      ot->poll   = ED_operator_view3d_active;
 +      ot->poll   = ED_operator_camera;
  
        /* flags */
        ot->flag   = 0;
@@@ -4484,8 -4455,9 +4484,8 @@@ void ED_view3d_clipping_local(RegionVie
  
  static int view3d_clipping_exec(bContext *C, wmOperator *op)
  {
 +      ARegion *ar = CTX_wm_region(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
 -      ViewContext vc;
 -      bglMats mats;
        rcti rect;
  
        WM_operator_properties_border_to_rcti(op, &rect);
        rv3d->rflag |= RV3D_CLIPPING;
        rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
  
 -      /* note; otherwise opengl won't work */
 -      view3d_operator_needs_opengl(C);
 -
 -      ED_view3d_viewcontext_init(C, &vc);
 -      view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
 -      ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect);
 +      /* NULL object because we don't want it in object space */
 +      ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
  
        return OPERATOR_FINISHED;
  }
@@@ -4549,6 -4525,7 +4549,6 @@@ void VIEW3D_OT_clip_border(wmOperatorTy
  /* note: cannot use event->mval here (called by object_add() */
  void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
  {
 -      Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = ar->regiondata;
        }
  
        if (U.uiflag & USER_DEPTH_CURSOR) {  /* maybe this should be accessed some other way */
 +              struct Depsgraph *graph = CTX_data_depsgraph(C);
 +
                view3d_operator_needs_opengl(C);
 -              if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true, NULL))
 +              if (ED_view3d_autodist(graph, ar, v3d, mval, fp, true, NULL)) {
                        depth_used = true;
 +              }
        }
  
        if (depth_used == false) {
@@@ -4589,74 -4563,25 +4589,74 @@@ void ED_view3d_cursor3d_update(bContex
  {
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
 +      ARegion *ar = CTX_wm_region(C);
 +      RegionView3D *rv3d = ar->regiondata;
 +
 +      View3DCursor *cursor_curr = ED_view3d_cursor3d_get(scene, v3d);
 +      View3DCursor  cursor_prev = *cursor_curr;
  
 -      float *fp_curr = ED_view3d_cursor3d_get(scene, v3d);
 -      float  fp_prev[3];
 +      ED_view3d_cursor3d_position(C, cursor_curr->location, mval);
 +      copy_qt_qt(cursor_curr->rotation, rv3d->viewquat);
 +      cursor_curr->rotation[0] *= -1.0f;
  
 -      copy_v3_v3(fp_prev, fp_curr);
 +      {
 +              const float mval_fl[2] = {UNPACK2(mval)};
 +              float ray_no[3];
 +
 +              struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
 +                      scene, CTX_data_depsgraph(C), 0, ar, v3d);
 +
 +              float obmat[4][4];
 +              Object *ob_dummy = NULL;
 +              float dist_px = 0;
 +              if (ED_transform_snap_object_project_view3d_ex(
 +                      snap_context,
 +                      SCE_SNAP_MODE_FACE,
 +                      &(const struct SnapObjectParams){
 +                          .snap_select = SNAP_ALL,
 +                          .use_object_edit_cage = false,
 +                      },
 +                      mval_fl, &dist_px,
 +                      cursor_curr->location, ray_no, NULL,
 +                      &ob_dummy, obmat))
 +              {
 +                      float tquat[4];
 +                      /* Math normal (Z). */
 +                      {
 +                              float z_src[3] = {0, 0, 1};
 +                              mul_qt_v3(cursor_curr->rotation, z_src);
 +                              rotation_between_vecs_to_quat(tquat, z_src, ray_no);
 +                              mul_qt_qtqt(cursor_curr->rotation, tquat, cursor_curr->rotation);
 +                      }
  
 -      ED_view3d_cursor3d_position(C, fp_curr, mval);
 +                      /* Match object matrix (X). */
 +                      {
 +                              const float ortho_axis_dot[3] = {
 +                                      dot_v3v3(ray_no, obmat[0]),
 +                                      dot_v3v3(ray_no, obmat[1]),
 +                                      dot_v3v3(ray_no, obmat[2]),
 +                              };
 +                              const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
 +                              float x_src[3] = {1, 0, 0};
 +                              float x_dst[3];
 +                              mul_qt_v3(cursor_curr->rotation, x_src);
 +                              project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
 +                              normalize_v3(x_dst);
 +                              rotation_between_vecs_to_quat(tquat, x_src, x_dst);
 +                              mul_qt_qtqt(cursor_curr->rotation, tquat, cursor_curr->rotation);
 +                      }
 +              }
 +              ED_transform_snap_object_context_destroy(snap_context);
 +      }
  
        /* offset the cursor lock to avoid jumping to new offset */
        if (v3d->ob_centre_cursor) {
 -              ARegion *ar = CTX_wm_region(C);
 -              RegionView3D *rv3d = ar->regiondata;
 -
                if (U.uiflag & USER_LOCK_CURSOR_ADJUST) {
  
                        float co_curr[2], co_prev[2];
  
 -                      if ((ED_view3d_project_float_global(ar, fp_prev, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
 -                          (ED_view3d_project_float_global(ar, fp_curr, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
 +                      if ((ED_view3d_project_float_global(ar, cursor_prev.location, co_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
 +                          (ED_view3d_project_float_global(ar, cursor_curr->location, co_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
                        {
                                rv3d->ofs_lock[0] += (co_curr[0] - co_prev[0]) / (ar->winx * 0.5f);
                                rv3d->ofs_lock[1] += (co_curr[1] - co_prev[1]) / (ar->winy * 0.5f);
                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
        else
                WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
 +
 +      {
 +              struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +              WM_msg_publish_rna_prop(
 +                      mbus, &scene->id, scene, Scene, cursor_location);
 +      }
 +
 +      DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
@@@ -4708,6 -4625,96 +4708,6 @@@ void VIEW3D_OT_cursor3d(wmOperatorType 
  
  /** \} */
  
 -/* -------------------------------------------------------------------- */
 -/** \name Transform Manipulator Operator
 - * \{ */
 -
 -static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 -{
 -      View3D *v3d = CTX_wm_view3d(C);
 -
 -      if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
 -      if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
 -
 -      /* note; otherwise opengl won't work */
 -      view3d_operator_needs_opengl(C);
 -
 -      if (BIF_do_manipulator(C, event, op) == 0)
 -              return OPERATOR_PASS_THROUGH;
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void VIEW3D_OT_manipulator(wmOperatorType *ot)
 -{
 -      PropertyRNA *prop;
 -
 -      /* identifiers */
 -      ot->name = "3D Manipulator";
 -      ot->description = "Manipulate selected item by axis";
 -      ot->idname = "VIEW3D_OT_manipulator";
 -
 -      /* api callbacks */
 -      ot->invoke = manipulator_invoke;
 -
 -      ot->poll = ED_operator_view3d_active;
 -
 -      /* properties to pass to transform */
 -      Transform_Properties(ot, P_CONSTRAINT);
 -
 -      prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the "
 -                             "two axes that have not been clicked (translate/scale only)");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
 -}
 -
 -/** \} */
 -
 -/* -------------------------------------------------------------------- */
 -/** \name Enable Transform Manipulator Operator
 - * \{ */
 -
 -static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 -{
 -      View3D *v3d = CTX_wm_view3d(C);
 -
 -      v3d->twtype = 0;
 -
 -      if (RNA_boolean_get(op->ptr, "translate"))
 -              v3d->twtype |= V3D_MANIP_TRANSLATE;
 -      if (RNA_boolean_get(op->ptr, "rotate"))
 -              v3d->twtype |= V3D_MANIP_ROTATE;
 -      if (RNA_boolean_get(op->ptr, "scale"))
 -              v3d->twtype |= V3D_MANIP_SCALE;
 -
 -      WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
 -{
 -      PropertyRNA *prop;
 -
 -      /* identifiers */
 -      ot->name = "Enable 3D Manipulator";
 -      ot->description = "Enable the transform manipulator for use";
 -      ot->idname = "VIEW3D_OT_enable_manipulator";
 -
 -      /* api callbacks */
 -      ot->invoke = enable_manipulator_invoke;
 -      ot->poll = ED_operator_view3d_active;
 -
 -      /* properties */
 -      prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 -      prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 -      prop = RNA_def_boolean(ot->srna, "scale", 0, "Scale", "Enable the scale manipulator");
 -      RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 -}
 -
 -/** \} */
 -
  /* -------------------------------------------------------------------- */
  /** \name Toggle Render Shading Operator
   * \{ */
index 613830bac8d4a80f409b420f1527149eb2b4ccda,95101ac1e510afaee6e12b5e0bda8eb6f43b011d..af1045ee0593411c6b6a2680bc2fbedb79b64970
@@@ -221,11 -221,8 +221,11 @@@ typedef struct bNode 
         * and replacing all uses with per-instance data.
         */
        short preview_xsize, preview_ysize;     /* reserved size of the preview rect */
 -      int pad2;
 +      short pad2[2];
        struct uiBlock *block;  /* runtime during drawing */
 +
 +      float ssr_id; /* XXX: eevee only, id of screen space reflection layer, needs to be a float to feed GPU_uniform. */
 +      float sss_id; /* XXX: eevee only, id of screen subsurface scatter layer, needs to be a float to feed GPU_uniform. */
  } bNode;
  
  /* node->flag */
@@@ -653,6 -650,11 +653,6 @@@ typedef struct NodeTwoFloats 
        float x, y;
  } NodeTwoFloats;
  
 -typedef struct NodeGeometry {
 -      char uvname[64];        /* MAX_CUSTOMDATA_LAYER_NAME */
 -      char colname[64];
 -} NodeGeometry;
 -
  typedef struct NodeVertexCol {
        char name[64];
  } NodeVertexCol;
@@@ -891,6 -893,12 +891,12 @@@ typedef struct NodeShaderUVMap 
        char uv_map[64];
  } NodeShaderUVMap;
  
+ typedef struct NodeShaderTexIES {
+       int mode;
+       char filepath[1024]; /* 1024 = FILE_MAX */
+ } NodeShaderTexIES;
  typedef struct NodeSunBeams {
        float source[2];
  
  /* script node flag */
  #define NODE_SCRIPT_AUTO_UPDATE               1
  
+ /* ies node mode */
+ #define NODE_IES_INTERNAL             0
+ #define NODE_IES_EXTERNAL             1
  
  /* frame node flags */
  #define NODE_FRAME_SHRINK             1       /* keep the bounding box minimal */
index 4744b2e33dfff23885870ce4aa2187ad967e9ce4,73beee51a8b7863009c957fce84f7269ec29d42b..1cd907aeb914a2872688525f1ef619ee68d14a29
@@@ -39,9 -39,6 +39,9 @@@ extern "C" 
  
  struct bContext;
  struct ID;
 +struct IDOverrideStatic;
 +struct IDOverrideStaticProperty;
 +struct IDOverrideStaticPropertyOperation;
  struct ListBase;
  struct Main;
  struct ReportList;
@@@ -109,8 -106,6 +109,8 @@@ extern StructRNA RNA_ClothCollisionSett
  extern StructRNA RNA_ClothModifier;
  extern StructRNA RNA_ClothSettings;
  extern StructRNA RNA_CloudsTexture;
 +extern StructRNA RNA_Collection;
 +extern StructRNA RNA_CollectionEngineSettings;
  extern StructRNA RNA_CollectionProperty;
  extern StructRNA RNA_CollisionModifier;
  extern StructRNA RNA_CollisionSensor;
@@@ -209,15 -204,12 +209,15 @@@ extern StructRNA RNA_CurveMapPoint
  extern StructRNA RNA_CurveMapping;
  extern StructRNA RNA_CurveModifier;
  extern StructRNA RNA_CurvePoint;
 +extern StructRNA RNA_Depsgraph;
 +extern StructRNA RNA_DepsgraphIter;
  extern StructRNA RNA_DampedTrackConstraint;
  extern StructRNA RNA_DataTransferModifier;
  extern StructRNA RNA_DecimateModifier;
  extern StructRNA RNA_DelaySensor;
  extern StructRNA RNA_CorrectiveSmoothModifier;
  extern StructRNA RNA_DisplaceModifier;
 +extern StructRNA RNA_SceneDisplay;
  extern StructRNA RNA_DisplaySafeAreas;
  extern StructRNA RNA_DistortedNoiseTexture;
  extern StructRNA RNA_DomainFluidSettings;
@@@ -236,10 -228,11 +236,10 @@@ extern StructRNA RNA_EffectSequence
  extern StructRNA RNA_EffectorWeights;
  extern StructRNA RNA_EnumProperty;
  extern StructRNA RNA_EnumPropertyItem;
 -extern StructRNA RNA_EnvironmentMap;
 -extern StructRNA RNA_EnvironmentMapTexture;
  extern StructRNA RNA_Event;
  extern StructRNA RNA_ExplodeModifier;
  extern StructRNA RNA_ExpressionController;
 +extern StructRNA RNA_FaceMap;
  extern StructRNA RNA_FCurve;
  extern StructRNA RNA_FCurveSample;
  extern StructRNA RNA_FFmpegSettings;
@@@ -277,16 -270,23 +277,16 @@@ extern StructRNA RNA_GPencilStroke
  extern StructRNA RNA_GPencilStrokePoint;
  extern StructRNA RNA_GPencilSculptSettings;
  extern StructRNA RNA_GPencilSculptBrush;
 -extern StructRNA RNA_GameBooleanProperty;
 -extern StructRNA RNA_GameFloatProperty;
 -extern StructRNA RNA_GameIntProperty;
 -extern StructRNA RNA_GameObjectSettings;
 -extern StructRNA RNA_GameProperty;
 -extern StructRNA RNA_GameSoftBodySettings;
 -extern StructRNA RNA_GameStringProperty;
 -extern StructRNA RNA_GameTimerProperty;
  extern StructRNA RNA_GaussianBlurSequence;
  extern StructRNA RNA_GlowSequence;
  extern StructRNA RNA_GreasePencil;
 -extern StructRNA RNA_Group;
  extern StructRNA RNA_Header;
  extern StructRNA RNA_HemiLamp;
  extern StructRNA RNA_Histogram;
  extern StructRNA RNA_HookModifier;
  extern StructRNA RNA_ID;
 +extern StructRNA RNA_IDOverrideStatic;
 +extern StructRNA RNA_IDOverrideStaticProperty;
  extern StructRNA RNA_IKParam;
  extern StructRNA RNA_Image;
  extern StructRNA RNA_ImageFormatSettings;
@@@ -320,7 -320,6 +320,7 @@@ extern StructRNA RNA_LaplacianSmoothMod
  extern StructRNA RNA_Lattice;
  extern StructRNA RNA_LatticeModifier;
  extern StructRNA RNA_LatticePoint;
 +extern StructRNA RNA_LayerCollection;
  extern StructRNA RNA_Library;
  extern StructRNA RNA_LimitDistanceConstraint;
  extern StructRNA RNA_LimitLocationConstraint;
@@@ -374,14 -373,19 +374,14 @@@ extern StructRNA RNA_LineStyleThickness
  extern StructRNA RNA_LockedTrackConstraint;
  extern StructRNA RNA_Macro;
  extern StructRNA RNA_MagicTexture;
 +extern StructRNA RNA_Manipulator;
 +extern StructRNA RNA_ManipulatorProperties;
  extern StructRNA RNA_MarbleTexture;
  extern StructRNA RNA_MaskModifier;
  extern StructRNA RNA_MaskSequence;
  extern StructRNA RNA_Material;
 -extern StructRNA RNA_MaterialHalo;
 -extern StructRNA RNA_MaterialPhysics;
  extern StructRNA RNA_MaterialRaytraceMirror;
 -extern StructRNA RNA_MaterialRaytraceTransparency;
  extern StructRNA RNA_MaterialSlot;
 -extern StructRNA RNA_MaterialStrand;
 -extern StructRNA RNA_MaterialSubsurfaceScattering;
 -extern StructRNA RNA_MaterialTextureSlot;
 -extern StructRNA RNA_MaterialVolume;
  extern StructRNA RNA_Mask;
  extern StructRNA RNA_MaskLayer;
  extern StructRNA RNA_Menu;
@@@ -442,7 -446,6 +442,7 @@@ extern StructRNA RNA_NoiseTexture
  extern StructRNA RNA_NorController;
  extern StructRNA RNA_Object;
  extern StructRNA RNA_ObjectBase;
 +extern StructRNA RNA_ObjectDisplay;
  extern StructRNA RNA_ObstacleFluidSettings;
  extern StructRNA RNA_OceanModifier;
  extern StructRNA RNA_OceanTexData;
@@@ -476,11 -479,12 +476,11 @@@ extern StructRNA RNA_ParticleSystemModi
  extern StructRNA RNA_ParticleTarget;
  extern StructRNA RNA_PivotConstraint;
  extern StructRNA RNA_PointCache;
 -extern StructRNA RNA_PointDensity;
 -extern StructRNA RNA_PointDensityTexture;
  extern StructRNA RNA_PointLamp;
  extern StructRNA RNA_PointerProperty;
  extern StructRNA RNA_Pose;
  extern StructRNA RNA_PoseBone;
 +extern StructRNA RNA_LightProbe;
  extern StructRNA RNA_Property;
  extern StructRNA RNA_PropertyGroup;
  extern StructRNA RNA_PropertyGroupItem;
@@@ -496,17 -500,15 +496,17 @@@ extern StructRNA RNA_RenderLayer
  extern StructRNA RNA_RenderPass;
  extern StructRNA RNA_RenderResult;
  extern StructRNA RNA_RenderSettings;
 +extern StructRNA RNA_RenderEngineSettings;
 +extern StructRNA RNA_RenderEngineSettingsClay;
  extern StructRNA RNA_RigidBodyWorld;
  extern StructRNA RNA_RigidBodyObject;
  extern StructRNA RNA_RigidBodyJointConstraint;
  extern StructRNA RNA_SPHFluidSettings;
  extern StructRNA RNA_Scene;
 -extern StructRNA RNA_SceneGameData;
 +extern StructRNA RNA_SceneEEVEE;
 +extern StructRNA RNA_SceneObjects;
  extern StructRNA RNA_SceneRenderLayer;
  extern StructRNA RNA_SceneSequence;
 -extern StructRNA RNA_SceneObjects;
  extern StructRNA RNA_Scopes;
  extern StructRNA RNA_Screen;
  extern StructRNA RNA_ScrewModifier;
@@@ -527,6 -529,7 +527,7 @@@ extern StructRNA RNA_ShaderNodeCombineR
  extern StructRNA RNA_ShaderNodeExtendedMaterial;
  extern StructRNA RNA_ShaderNodeGeometry;
  extern StructRNA RNA_ShaderNodeHueSaturation;
+ extern StructRNA RNA_ShaderNodeIESLight;
  extern StructRNA RNA_ShaderNodeInvert;
  extern StructRNA RNA_ShaderNodeLampData;
  extern StructRNA RNA_ShaderNodeMapping;
@@@ -573,12 -576,14 +574,12 @@@ extern StructRNA RNA_SpaceFileBrowser
  extern StructRNA RNA_SpaceGraphEditor;
  extern StructRNA RNA_SpaceImageEditor;
  extern StructRNA RNA_SpaceInfo;
 -extern StructRNA RNA_SpaceLogicEditor;
  extern StructRNA RNA_SpaceNLA;
  extern StructRNA RNA_SpaceNodeEditor;
  extern StructRNA RNA_SpaceOutliner;
  extern StructRNA RNA_SpaceProperties;
  extern StructRNA RNA_SpaceSequenceEditor;
  extern StructRNA RNA_SpaceTextEditor;
 -extern StructRNA RNA_SpaceTimeline;
  extern StructRNA RNA_SpaceUVEditor;
  extern StructRNA RNA_SpaceUserPreferences;
  extern StructRNA RNA_SpaceView3D;
@@@ -652,6 -657,7 +653,6 @@@ extern StructRNA RNA_ThemeSpaceGradient
  extern StructRNA RNA_ThemeSpaceListGeneric;
  extern StructRNA RNA_ThemeStyle;
  extern StructRNA RNA_ThemeTextEditor;
 -extern StructRNA RNA_ThemeTimeline;
  extern StructRNA RNA_ThemeUserInterface;
  extern StructRNA RNA_ThemeUserPreferences;
  extern StructRNA RNA_ThemeView3D;
@@@ -666,7 -672,6 +667,7 @@@ extern StructRNA RNA_TransformSequence
  extern StructRNA RNA_UILayout;
  extern StructRNA RNA_UIList;
  extern StructRNA RNA_UIPieMenu;
 +extern StructRNA RNA_uiPopover;
  extern StructRNA RNA_UIPopupMenu;
  extern StructRNA RNA_UVWarpModifier;
  extern StructRNA RNA_UVProjectModifier;
@@@ -686,21 -691,18 +687,21 @@@ extern StructRNA RNA_VertexGroup
  extern StructRNA RNA_VertexGroupElement;
  extern StructRNA RNA_VertexPaint;
  extern StructRNA RNA_VoronoiTexture;
 -extern StructRNA RNA_VoxelData;
 -extern StructRNA RNA_VoxelDataTexture;
  extern StructRNA RNA_WarpModifier;
  extern StructRNA RNA_WaveModifier;
  extern StructRNA RNA_VertexWeightEditModifier;
  extern StructRNA RNA_VertexWeightMixModifier;
  extern StructRNA RNA_VertexWeightProximityModifier;
 +extern StructRNA RNA_View3DOverlay;
 +extern StructRNA RNA_View3DShading;
 +extern StructRNA RNA_ViewLayer;
  extern StructRNA RNA_Window;
  extern StructRNA RNA_WindowManager;
  extern StructRNA RNA_WipeSequence;
  extern StructRNA RNA_WireframeModifier;
  extern StructRNA RNA_WoodTexture;
 +extern StructRNA RNA_WorkSpace;
 +extern StructRNA RNA_wmOwnerIDs;
  extern StructRNA RNA_World;
  extern StructRNA RNA_WorldAmbientOcclusion;
  extern StructRNA RNA_WorldLighting;
@@@ -879,10 -881,6 +880,10 @@@ bool RNA_property_editable_index(Pointe
  bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */
  bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop);
  bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop);
 +bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop);
 +bool RNA_property_overridable_static_set(PointerRNA *ptr, PropertyRNA *prop, const bool is_overridable);
 +bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop);
 +bool RNA_property_comparable(PointerRNA *ptr, PropertyRNA *prop);
  bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */
  
  void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop);
@@@ -1034,7 -1032,7 +1035,7 @@@ char *RNA_path_property_py(struct Point
   * call RNA_struct_find_property. The names have to exist as RNA properties
   * for the type in the pointer, if they do not exist an error will be printed.
   *
 - * There is no support for pointers and collections here yet, these can be 
 + * There is no support for pointers and collections here yet, these can be
   * added when ID properties support them. */
  
  int  RNA_boolean_get(PointerRNA *ptr, const char *name);
@@@ -1226,77 -1224,17 +1227,77 @@@ StructRNA *ID_code_to_RNA_type(short id
  
  void _RNA_warning(const char *format, ...) ATTR_PRINTF_FORMAT(1, 2);
  
 -/* Equals test (skips pointers and collections)
 - * is_strict false assumes uninitialized properties are equal */
 -
 -typedef enum eRNAEqualsMode {
 -      RNA_EQ_STRICT,          /* set/unset ignored */
 -      RNA_EQ_UNSET_MATCH_ANY, /* unset property matches anything */
 -      RNA_EQ_UNSET_MATCH_NONE /* unset property never matches set property */
 -} eRNAEqualsMode;
 +/* Equals test. */
 +
 +/* Note: In practice, EQ_STRICT and EQ_COMPARE have same behavior currently, and will yield same result. */
 +typedef enum eRNACompareMode {
 +      /* Only care about equality, not full comparison. */
 +      RNA_EQ_STRICT,           /* set/unset ignored */
 +      RNA_EQ_UNSET_MATCH_ANY,  /* unset property matches anything */
 +      RNA_EQ_UNSET_MATCH_NONE, /* unset property never matches set property */
 +      /* Full comparison. */
 +      RNA_EQ_COMPARE,
 +} eRNACompareMode;
 +
 +bool RNA_property_equals(struct PointerRNA *ptr_a, struct PointerRNA *ptr_b, struct PropertyRNA *prop, eRNACompareMode mode);
 +bool RNA_struct_equals(struct PointerRNA *ptr_a, struct PointerRNA *ptr_b, eRNACompareMode mode);
 +
 +/* Override. */
 +
 +/* flags for RNA_struct_override_matches. */
 +typedef enum eRNAOverrideMatch {
 +      /* Do not compare properties that are not overridable. */
 +      RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE = 1 << 0,
 +      /* Do not compare properties that are already overridden. */
 +      RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN = 1 << 1,
 +
 +      /* Create new property override if needed and possible. */
 +      RNA_OVERRIDE_COMPARE_CREATE = 1 << 16,
 +      /* Restore property's value(s) to reference ones if needed and possible. */
 +      RNA_OVERRIDE_COMPARE_RESTORE = 1 << 17,
 +} eRNAOverrideMatch;
 +
 +typedef enum eRNAOverrideMatchResult {
 +      /* Some new property overrides were created to take into account differences between local and reference. */
 +      RNA_OVERRIDE_MATCH_RESULT_CREATED = 1 << 0,
 +      /* Some properties were reset to reference values. */
 +      RNA_OVERRIDE_MATCH_RESULT_RESTORED = 1 << 1,
 +} eRNAOverrideMatchResult;
 +
 +typedef enum eRNAOverrideStatus {
 +      RNA_OVERRIDE_STATUS_OVERRIDABLE = 1 << 0,  /* The property is overridable. */
 +      RNA_OVERRIDE_STATUS_OVERRIDDEN = 1 << 1,  /* The property is overridden. */
 +      RNA_OVERRIDE_STATUS_MANDATORY = 1 << 2,  /* Overriding this property is mandatory when creating an override. */
 +      RNA_OVERRIDE_STATUS_LOCKED = 1 << 3,  /* The override status of this property is locked. */
 +} eRNAOverrideStatus;
 +
 +bool RNA_struct_override_matches(
 +        struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, const char *root_path,
 +        struct IDOverrideStatic *override, const eRNAOverrideMatch flags,
 +        eRNAOverrideMatchResult *r_report_flags);
 +
 +bool RNA_struct_override_store(
 +        struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, PointerRNA *ptr_storage,
 +        struct IDOverrideStatic *override);
 +
 +void RNA_struct_override_apply(
 +        struct PointerRNA *ptr_local, struct PointerRNA *ptr_override, struct PointerRNA *ptr_storage,
 +        struct IDOverrideStatic *override);
 +
 +struct IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop);
 +struct IDOverrideStaticProperty *RNA_property_override_property_get(PointerRNA *ptr, PropertyRNA *prop, bool *r_created);
 +
 +struct IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_find(
 +        PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict);
 +struct IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_get(
 +        PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index,
 +        const bool strict, bool *r_strict, bool *r_created);
 +
 +eRNAOverrideStatus RNA_property_static_override_status(PointerRNA *ptr, PropertyRNA *prop, const int index);
 +
 +void        RNA_struct_state_owner_set(const char *name);
 +const char *RNA_struct_state_owner_get(void);
  
 -bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, eRNAEqualsMode mode);
 -bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNAEqualsMode mode);
  
  #ifdef __cplusplus
  }
index e05e9d32277c7f6f26114bf1413518d6d25d7b45,8dbb133a8ac1dc729a50f44ff35172478cf2dc8f..182e606a3572b6877fb57fb759e441fe2c1933ab
@@@ -66,9 -66,6 +66,9 @@@
  
  #include "NOD_composite.h"
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
 +
  const EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
        { SOCK_IN, "IN", 0, "Input", "" },
        { SOCK_OUT, "OUT", 0, "Output", "" },
@@@ -191,8 -188,6 +191,8 @@@ static const EnumPropertyItem node_samp
  #include "ED_node.h"
  #include "ED_render.h"
  
 +#include "GPU_material.h"
 +
  #include "NOD_common.h"
  #include "NOD_socket.h"
  
@@@ -2305,31 -2300,13 +2305,31 @@@ static void rna_NodeSocketStandard_vect
        *softmax = dval->max;
  }
  
 +static void rna_NodeSocket_value_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 +{
 +      bNodeTree *ntree = (bNodeTree *)ptr->id.data;
 +      bNodeSocket *sock = ptr->data;
 +
 +      if (ntree->type == NTREE_SHADER) {
 +              DEG_id_tag_update_ex(bmain, &ntree->id, DEG_TAG_SHADING_UPDATE);
 +              WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
 +
 +              if (sock->type == SOCK_STRING) {
 +                      rna_NodeSocket_update(bmain, scene, ptr);
 +              }
 +      }
 +      else {
 +              rna_NodeSocket_update(bmain, scene, ptr);
 +      }
 +}
 +
  /* using a context update function here, to avoid searching the node if possible */
  static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
  {
        bNode *node;
        
        /* default update */
 -      rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr);
 +      rna_NodeSocket_value_update(CTX_data_main(C), CTX_data_scene(C), ptr);
        
        /* try to use node from context, faster */
        node = CTX_data_pointer_get(C, "node").data;
                /* fall back to searching node in the tree */
                nodeFindNode(ntree, sock, &node, NULL);
        }
 -      
 -      if (node) {
 -              nodeSynchronizeID(node, true);
 -
 -              /* extra update for sockets that get synced to material */
 -              if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT))
 -                      WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, node->id);
 -      }
  }
  
  
@@@ -2495,6 -2480,17 +2495,6 @@@ static void rna_Node_tex_image_update(M
        WM_main_add_notifier(NC_IMAGE, NULL);
  }
  
 -static void rna_Node_material_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
 -{
 -      bNodeTree *ntree = (bNodeTree *)ptr->id.data;
 -      bNode *node = (bNode *)ptr->data;
 -
 -      if (node->id)
 -              nodeSetActive(ntree, node);
 -
 -      ED_node_tag_update_nodetree(bmain, ntree, node);
 -}
 -
  static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
  {
        bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@@ -2756,7 -2752,7 +2756,7 @@@ static const EnumPropertyItem *rna_Node
        return item;
  }
  
 -static const EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr,
 +static const EnumPropertyItem *rna_Node_view_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr,
                                                      PropertyRNA *UNUSED(prop), bool *r_free)
  {
        bNode *node = (bNode *)ptr->data;
                return DummyRNA_NULL_items;
        }
  
 -      rl = sce->r.layers.first;
 +      rl = sce->view_layers.first;
        item = renderresult_layers_add_enum(rl);
  
        *r_free = true;
        return item;
  }
  
 -static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 +static void rna_Node_view_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
  {
        rna_Node_update(bmain, scene, ptr);
        if (scene->nodetree != NULL) {
@@@ -2950,6 -2946,30 +2950,30 @@@ static bNodeSocket *rna_NodeOutputFile_
        return sock;
  }
  
+ static void rna_ShaderNodeTexIES_mode_set(PointerRNA *ptr, int value)
+ {
+       bNode *node = (bNode *)ptr->data;
+       NodeShaderTexIES *nss = node->storage;
+       if (nss->mode != value) {
+               nss->mode = value;
+               nss->filepath[0] = '\0';
+               /* replace text datablock by filepath */
+               if (node->id) {
+                       Text *text = (Text *)node->id;
+                       if (value == NODE_IES_EXTERNAL && text->name) {
+                               BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
+                               BLI_path_rel(nss->filepath, G.main->name);
+                       }
+                       id_us_min(node->id);
+                       node->id = NULL;
+               }
+       }
+ }
  static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
  {
        bNode *node = (bNode *)ptr->data;
@@@ -3117,12 -3137,12 +3141,12 @@@ static int point_density_vertex_color_s
  }
  
  void rna_ShaderNodePointDensity_density_cache(bNode *self,
 -                                              Scene *scene,
 -                                              int settings)
 +                                              Depsgraph *depsgraph)
  {
        NodeShaderTexPointDensity *shader_point_density = self->storage;
        PointDensity *pd = &shader_point_density->pd;
 -      if (scene == NULL) {
 +
 +      if (depsgraph == NULL) {
                return;
        }
  
        shader_point_density->cached_resolution = shader_point_density->resolution;
  
        /* Single-threaded sampling of the voxel domain. */
 -      RE_point_density_cache(scene,
 -                             pd,
 -                             settings == 1);
 +      RE_point_density_cache(depsgraph, pd);
  }
  
  void rna_ShaderNodePointDensity_density_calc(bNode *self,
 -                                             Scene *scene,
 -                                             int settings,
 +                                             Depsgraph *depsgraph,
                                               int *length,
                                               float **values)
  {
        PointDensity *pd = &shader_point_density->pd;
        const int resolution = shader_point_density->cached_resolution;
  
 -      if (scene == NULL) {
 +      if (depsgraph == NULL) {
                *length = 0;
                return;
        }
        }
  
        /* Single-threaded sampling of the voxel domain. */
 -      RE_point_density_sample(scene, pd,
 -                              resolution,
 -                              settings == 1,
 -                              *values);
 +      RE_point_density_sample(depsgraph, pd, resolution, *values);
  
        /* We're done, time to clean up. */
        BKE_texture_pointdensity_free_data(pd);
  }
  
  void rna_ShaderNodePointDensity_density_minmax(bNode *self,
 -                                               Scene *scene,
 -                                               int settings,
 +                                               Depsgraph *depsgraph,
                                                 float r_min[3],
                                                 float r_max[3])
  {
        NodeShaderTexPointDensity *shader_point_density = self->storage;
        PointDensity *pd = &shader_point_density->pd;
 -      if (scene == NULL) {
 +
 +      if (depsgraph == NULL) {
                zero_v3(r_min);
                zero_v3(r_max);
                return;
        }
 -      RE_point_density_minmax(scene, pd, settings == 1, r_min, r_max);
 +
 +      RE_point_density_minmax(depsgraph, pd, r_min, r_max);
  }
  
  #else
@@@ -3216,7 -3241,7 +3240,7 @@@ static const EnumPropertyItem prop_imag
        {0, NULL, 0, NULL, NULL}
  };
  
 -static const EnumPropertyItem prop_scene_layer_items[] = {
 +static const EnumPropertyItem prop_view_layer_items[] = {
        { 0, "PLACEHOLDER",          0, "Placeholder",          ""},
        {0, NULL, 0, NULL, NULL}
  };
@@@ -3292,6 -3317,12 +3316,12 @@@ static const EnumPropertyItem node_scri
        {0, NULL, 0, NULL, NULL}
  };
  
+ static EnumPropertyItem node_ies_mode_items[] = {
+       {NODE_IES_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"},
+       {NODE_IES_EXTERNAL, "EXTERNAL", 0, "External", "Use external .ies file"},
+       {0, NULL, 0, NULL, NULL}
+ };
  static const EnumPropertyItem node_principled_distribution_items[] = {
        {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
        {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
@@@ -3530,6 -3561,33 +3560,6 @@@ static void def_sh_output_linestyle(Str
        def_mix_rgb(srna);
  }
  
 -static void def_sh_material(StructRNA *srna)
 -{
 -      PropertyRNA *prop;
 -
 -      prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
 -      RNA_def_property_pointer_sdna(prop, NULL, "id");
 -      RNA_def_property_struct_type(prop, "Material");
 -      RNA_def_property_flag(prop, PROP_EDITABLE);
 -      RNA_def_property_ui_text(prop, "Material", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_material_update");
 -
 -      prop = RNA_def_property(srna, "use_diffuse", PROP_BOOLEAN, PROP_NONE);
 -      RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_DIFF);
 -      RNA_def_property_ui_text(prop, "Diffuse", "Material Node outputs Diffuse");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -
 -      prop = RNA_def_property(srna, "use_specular", PROP_BOOLEAN, PROP_NONE);
 -      RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_SPEC);
 -      RNA_def_property_ui_text(prop, "Specular", "Material Node outputs Specular");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -      
 -      prop = RNA_def_property(srna, "invert_normal", PROP_BOOLEAN, PROP_NONE);
 -      RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_NEG);
 -      RNA_def_property_ui_text(prop, "Invert Normal", "Material Node uses inverted normal");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -}
 -
  static void def_sh_mapping(StructRNA *srna)
  {
        static const EnumPropertyItem prop_vect_type_items[] = {
        RNA_def_property_update(prop, 0, "rna_Mapping_Node_update");
  }
  
 -static void def_sh_geometry(StructRNA *srna)
 -{
 -      PropertyRNA *prop;
 -      
 -      RNA_def_struct_sdna_from(srna, "NodeGeometry", "storage");
 -      
 -      prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
 -      RNA_def_property_string_sdna(prop, NULL, "uvname");
 -      RNA_def_property_ui_text(prop, "UV Map", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -      
 -      prop = RNA_def_property(srna, "color_layer", PROP_STRING, PROP_NONE);
 -      RNA_def_property_string_sdna(prop, NULL, "colname");
 -      RNA_def_property_ui_text(prop, "Vertex Color Layer", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -}
 -
 -static void def_sh_lamp(StructRNA *srna)
 -{
 -      PropertyRNA *prop;
 -      
 -      prop = RNA_def_property(srna, "lamp_object", PROP_POINTER, PROP_NONE);
 -      RNA_def_property_pointer_sdna(prop, NULL, "id");
 -      RNA_def_property_struct_type(prop, "Object");
 -      RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
 -      RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Lamp_object_poll");
 -      RNA_def_property_ui_text(prop, "Lamp Object", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 -}
 -
  static void def_sh_attribute(StructRNA *srna)
  {
        PropertyRNA *prop;
@@@ -4066,6 -4154,13 +4096,6 @@@ static void def_sh_tex_pointdensity(Str
                {0, NULL, 0, NULL, NULL}
        };
  
 -      /* TODO(sergey): Use some mnemonic names for the hardcoded values here. */
 -      static const EnumPropertyItem calc_mode_items[] = {
 -              {0, "VIEWPORT", 0, "Viewport", "Canculate density using viewport settings"},
 -              {1, "RENDER", 0, "Render", "Canculate duplis using render settings"},
 -              {0, NULL, 0, NULL, NULL}
 -      };
 -
        prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "id");
        RNA_def_property_struct_type(prop, "Object");
  
        func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
        RNA_def_function_ui_description(func, "Cache point density data for later calculation");
 -      RNA_def_pointer(func, "scene", "Scene", "", "");
 -      RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
 +      RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
  
        func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
        RNA_def_function_ui_description(func, "Calculate point density");
 -      RNA_def_pointer(func, "scene", "Scene", "", "");
 -      RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
 +      RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
        /* TODO, See how array size of 0 works, this shouldnt be used. */
        parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
        RNA_def_parameter_flags(parm, PROP_DYNAMIC, 0);
  
        func = RNA_def_function(srna, "calc_point_density_minmax", "rna_ShaderNodePointDensity_density_minmax");
        RNA_def_function_ui_description(func, "Calculate point density");
 -      RNA_def_pointer(func, "scene", "Scene", "", "");
 -      RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
 +      RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
        parm = RNA_def_property(func, "min", PROP_FLOAT, PROP_COORDS);
        RNA_def_property_array(parm, 3);
        RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
@@@ -4403,6 -4501,32 +4433,32 @@@ static void def_sh_subsurface(StructRN
        RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update");
  }
  
+ static void def_sh_tex_ies(StructRNA *srna)
+ {
+       PropertyRNA *prop;
+       prop = RNA_def_property(srna, "ies", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "id");
+       RNA_def_property_struct_type(prop, "Text");
+       RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+       RNA_def_property_ui_text(prop, "IES Text", "Internal IES file");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+       RNA_def_struct_sdna_from(srna, "NodeShaderTexIES", "storage");
+       prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+       RNA_def_property_ui_text(prop, "File Path", "IES light path");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+       prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeTexIES_mode_set", NULL);
+       RNA_def_property_enum_items(prop, node_ies_mode_items);
+       RNA_def_property_ui_text(prop, "Source", "Whether the IES file is loaded from disk or from a Text datablock");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+       RNA_def_struct_sdna_from(srna, "bNode", NULL);
+ }
  static void def_sh_script(StructRNA *srna)
  {
        PropertyRNA *prop;
@@@ -4821,15 -4945,15 +4877,15 @@@ static void def_cmp_render_layers(Struc
        RNA_def_property_struct_type(prop, "Scene");
        RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
        RNA_def_property_ui_text(prop, "Scene", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
 +      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update");
        
        prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "custom1");
 -      RNA_def_property_enum_items(prop, prop_scene_layer_items);
 -      RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_scene_layer_itemf");
 +      RNA_def_property_enum_items(prop, prop_view_layer_items);
 +      RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_view_layer_itemf");
        RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
        RNA_def_property_ui_text(prop, "Layer", "");
 -      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
 +      RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update");
  }
  
  static void rna_def_cmp_output_file_slot_file(BlenderRNA *brna)
index 5acd0a9fceaac9c980aae8422758a6378338a99c,cc0bef300477b6c7daec15b3e8fb4bafbb78b616..67c86180188d40068cd0d6008fd884f6c8ec5ca4
@@@ -32,7 -32,6 +32,7 @@@ set(IN
        ../blenkernel
        ../blenlib
        ../blentranslation
 +      ../depsgraph
        ../gpu
        ../imbuf
        ../makesdna
@@@ -135,17 -134,22 +135,17 @@@ set(SR
        shader/nodes/node_shader_curves.c
        shader/nodes/node_shader_gamma.c
        shader/nodes/node_shader_brightness.c
 -      shader/nodes/node_shader_geom.c
        shader/nodes/node_shader_hueSatVal.c
        shader/nodes/node_shader_invert.c
 -      shader/nodes/node_shader_lamp.c
        shader/nodes/node_shader_mapping.c
 -      shader/nodes/node_shader_material.c
        shader/nodes/node_shader_math.c
        shader/nodes/node_shader_mixRgb.c
        shader/nodes/node_shader_normal.c
 -      shader/nodes/node_shader_output.c
        shader/nodes/node_shader_rgb.c
        shader/nodes/node_shader_sepcombRGB.c
        shader/nodes/node_shader_sepcombHSV.c
        shader/nodes/node_shader_sepcombXYZ.c
        shader/nodes/node_shader_squeeze.c
 -      shader/nodes/node_shader_texture.c
        shader/nodes/node_shader_valToRgb.c
        shader/nodes/node_shader_value.c
        shader/nodes/node_shader_wireframe.c
        shader/nodes/node_shader_fresnel.c
        shader/nodes/node_shader_geometry.c
        shader/nodes/node_shader_holdout.c
+       shader/nodes/node_shader_ies_light.c
        shader/nodes/node_shader_layer_weight.c
        shader/nodes/node_shader_light_falloff.c
        shader/nodes/node_shader_light_path.c
        shader/nodes/node_shader_mix_shader.c
 +      shader/nodes/node_shader_shaderToRgb.c
        shader/nodes/node_shader_normal_map.c
        shader/nodes/node_shader_object_info.c
        shader/nodes/node_shader_hair_info.c
 +      shader/nodes/node_shader_eevee_specular.c
        shader/nodes/node_shader_output_lamp.c
        shader/nodes/node_shader_output_material.c
        shader/nodes/node_shader_output_world.c
index 3d6a8647628b0e26619459af2cc8a528ca6bd46e,7cb52cda55055cf0cdb6ad3ef001a8229b85bf0c..158d20a5c19f0ec19ae295fc013cc70a73fc84d3
@@@ -44,16 -44,20 +44,16 @@@ void register_node_tree_type_sh(void)
  
  void register_node_type_sh_group(void);
  
 -void register_node_type_sh_output(void);
 -void register_node_type_sh_material(void);
  void register_node_type_sh_camera(void);
 -void register_node_type_sh_lamp(void);
  void register_node_type_sh_value(void);
  void register_node_type_sh_rgb(void);
  void register_node_type_sh_mix_rgb(void);
  void register_node_type_sh_valtorgb(void);
  void register_node_type_sh_rgbtobw(void);
 -void register_node_type_sh_texture(void);
 +void register_node_type_sh_shadertorgb(void);
  void register_node_type_sh_normal(void);
  void register_node_type_sh_gamma(void);
  void register_node_type_sh_brightcontrast(void);
 -void register_node_type_sh_geom(void);
  void register_node_type_sh_mapping(void);
  void register_node_type_sh_curve_vec(void);
  void register_node_type_sh_curve_rgb(void);
@@@ -61,6 -65,7 +61,6 @@@ void register_node_type_sh_math(void)
  void register_node_type_sh_vect_math(void);
  void register_node_type_sh_squeeze(void);
  void register_node_type_sh_dynamic(void);
 -void register_node_type_sh_material_ext(void);
  void register_node_type_sh_invert(void);
  void register_node_type_sh_seprgb(void);
  void register_node_type_sh_combrgb(void);
@@@ -116,12 -121,9 +116,12 @@@ void register_node_type_sh_mix_shader(v
  void register_node_type_sh_add_shader(void);
  void register_node_type_sh_uvmap(void);
  void register_node_type_sh_uvalongstroke(void);
 +void register_node_type_sh_eevee_metallic(void);
 +void register_node_type_sh_eevee_specular(void);
  
  void register_node_type_sh_output_lamp(void);
  void register_node_type_sh_output_material(void);
 +void register_node_type_sh_output_eevee_material(void);
  void register_node_type_sh_output_world(void);
  void register_node_type_sh_output_linestyle(void);
  
@@@ -136,6 -138,7 +136,7 @@@ void register_node_type_sh_tex_musgrave
  void register_node_type_sh_tex_noise(void);
  void register_node_type_sh_tex_checker(void);
  void register_node_type_sh_bump(void);
+ void register_node_type_sh_tex_ies(void);
  
  #endif
  
index efb8eb66737f6c3c16ba93e6037be74264dbecbd,5864b3deb39554f62fc48ce022120f125e79474b..437093a9cb3b166632ce2af0b02d8e12f0a80141
@@@ -40,29 -40,33 +40,29 @@@ DefNode( Node,           NODE_GROUP_INP
  DefNode( Node,           NODE_GROUP_OUTPUT,       def_group_output,       "GROUP_OUTPUT",   GroupOutput,      "Group Output",      ""              )
  DefNode( Node,           NODE_REROUTE,            0,                      "REROUTE",        Reroute,          "Reroute",           ""              )
  
 -DefNode( ShaderNode,     SH_NODE_OUTPUT,          def_sh_output,          "OUTPUT",         Output,           "Output",            ""              )
 -DefNode( ShaderNode,     SH_NODE_MATERIAL,        def_sh_material,        "MATERIAL",       Material,         "Material",          ""              )
  DefNode( ShaderNode,     SH_NODE_RGB,             0,                      "RGB",            RGB,              "RGB",               ""              )
  DefNode( ShaderNode,     SH_NODE_VALUE,           0,                      "VALUE",          Value,            "Value",             ""              )
  DefNode( ShaderNode,     SH_NODE_MIX_RGB,         def_mix_rgb,            "MIX_RGB",        MixRGB,           "MixRGB",            ""              )
  DefNode( ShaderNode,     SH_NODE_VALTORGB,        def_colorramp,          "VALTORGB",       ValToRGB,         "ColorRamp",         ""              )
  DefNode( ShaderNode,     SH_NODE_RGBTOBW,         0,                      "RGBTOBW",        RGBToBW,          "RGB to BW",         ""              )
 -DefNode( ShaderNode,     SH_NODE_TEXTURE,         def_texture,            "TEXTURE",        Texture,          "Texture",           ""              )
 +DefNode( ShaderNode,     SH_NODE_SHADERTORGB,     0,                      "SHADERTORGB",    ShaderToRGB,      "Shader to RGB",     ""              )
  DefNode( ShaderNode,     SH_NODE_NORMAL,          0,                      "NORMAL",         Normal,           "Normal",            ""              )
  DefNode( ShaderNode,     SH_NODE_GAMMA,           0,                      "GAMMA",          Gamma,            "Gamma",             ""              )
  DefNode( ShaderNode,     SH_NODE_BRIGHTCONTRAST,  0,                      "BRIGHTCONTRAST", BrightContrast,   "Bright Contrast",   ""              )
 -DefNode( ShaderNode,     SH_NODE_GEOMETRY,        def_sh_geometry,        "GEOMETRY",       Geometry,         "Geometry",          ""              )
  DefNode( ShaderNode,     SH_NODE_MAPPING,         def_sh_mapping,         "MAPPING",        Mapping,          "Mapping",           ""              )
  DefNode( ShaderNode,     SH_NODE_CURVE_VEC,       def_vector_curve,       "CURVE_VEC",      VectorCurve,      "Vector Curves",     ""              )
  DefNode( ShaderNode,     SH_NODE_CURVE_RGB,       def_rgb_curve,          "CURVE_RGB",      RGBCurve,         "RGB Curves",        ""              )
  DefNode( ShaderNode,     SH_NODE_CAMERA,          0,                      "CAMERA",         CameraData,       "Camera Data",       ""              )
 -DefNode( ShaderNode,     SH_NODE_LAMP,            def_sh_lamp,            "LAMP",           LampData,         "Lamp Data",         ""              )
  DefNode( ShaderNode,     SH_NODE_MATH,            def_math,               "MATH",           Math,             "Math",              ""              )
  DefNode( ShaderNode,     SH_NODE_VECT_MATH,       def_vector_math,        "VECT_MATH",      VectorMath,       "Vector Math",       ""              )
  DefNode( ShaderNode,     SH_NODE_SQUEEZE,         0,                      "SQUEEZE",        Squeeze,          "Squeeze Value",     ""              )
 -DefNode( ShaderNode,     SH_NODE_MATERIAL_EXT,    def_sh_material,        "MATERIAL_EXT",   ExtendedMaterial, "Extended Material", ""              )
  DefNode( ShaderNode,     SH_NODE_INVERT,          0,                      "INVERT",         Invert,           "Invert",            ""              )
  DefNode( ShaderNode,     SH_NODE_SEPRGB,          0,                      "SEPRGB",         SeparateRGB,      "Separate RGB",      ""              )
  DefNode( ShaderNode,     SH_NODE_COMBRGB,         0,                      "COMBRGB",        CombineRGB,       "Combine RGB",       ""              )
  DefNode( ShaderNode,     SH_NODE_HUE_SAT,         0,                      "HUE_SAT",        HueSaturation,    "Hue/Saturation",    ""              )
  
  DefNode( ShaderNode,     SH_NODE_OUTPUT_MATERIAL,    def_sh_output,          "OUTPUT_MATERIAL",    OutputMaterial,   "Material Output",   ""       )
 +DefNode( ShaderNode,     SH_NODE_EEVEE_SPECULAR,     0,                      "EEVEE_SPECULAR",     EeveeSpecular,    "Specular", "")
  DefNode( ShaderNode,     SH_NODE_OUTPUT_LAMP,        def_sh_output,          "OUTPUT_LAMP",        OutputLamp,       "Lamp Output",       ""       )
  DefNode( ShaderNode,     SH_NODE_OUTPUT_WORLD,       def_sh_output,          "OUTPUT_WORLD",       OutputWorld,      "World Output",      ""       )
  DefNode( ShaderNode,     SH_NODE_OUTPUT_LINESTYLE,   def_sh_output_linestyle,"OUTPUT_LINESTYLE",   OutputLineStyle,  "Line Style Output", ""       )
@@@ -126,6 -130,7 +126,7 @@@ DefNode( ShaderNode,     SH_NODE_COMBXY
  DefNode( ShaderNode,     SH_NODE_BEVEL,              def_sh_bevel,           "BEVEL",              Bevel,            "Bevel",             ""       )
  DefNode( ShaderNode,     SH_NODE_DISPLACEMENT,       def_sh_displacement,    "DISPLACEMENT",       Displacement,     "Displacement",      ""       )
  DefNode( ShaderNode,     SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement",""  )
+ DefNode( ShaderNode,     SH_NODE_TEX_IES,            def_sh_tex_ies,         "TEX_IES",            TexIES,           "IES Texture",       ""       )
  
  DefNode( CompositorNode, CMP_NODE_VIEWER,         def_cmp_viewer,         "VIEWER",         Viewer,           "Viewer",            ""              )
  DefNode( CompositorNode, CMP_NODE_RGB,            0,                      "RGB",            RGB,              "RGB",               ""              )