Merge branch 'blender2.7'
authorCampbell Barton <ideasman42@gmail.com>
Thu, 3 Jan 2019 01:23:17 +0000 (12:23 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 3 Jan 2019 01:25:37 +0000 (12:25 +1100)
1  2 
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/intern/material.c
source/blender/editors/render/render_shading.c

@@@ -46,6 -46,7 +46,6 @@@ struct Scene
  
  void init_def_material(void);
  void BKE_material_free(struct Material *ma);
 -void BKE_material_free_ex(struct Material *ma, bool do_id_user);
  void test_object_materials(struct Main *bmain, struct Object *ob, struct ID *id);
  void test_all_objects_materials(struct Main *bmain, struct ID *id);
  void BKE_material_resize_object(struct Main *bmain, struct Object *ob, const short totcol, bool do_id_user);
@@@ -53,13 -54,11 +53,13 @@@ void BKE_material_init(struct Material 
  void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
  void BKE_material_remap_object_calc(struct  Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
  struct Material *BKE_material_add(struct Main *bmain, const char *name);
 +struct Material *BKE_material_add_gpencil(struct Main *bmain, const char *name);
  void BKE_material_copy_data(struct Main *bmain, struct Material *ma_dst, const struct Material *ma_src, const int flag);
  struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
  struct Material *BKE_material_localize(struct Material *ma);
  struct Material *give_node_material(struct Material *ma); /* returns node material or self */
  void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
 +void BKE_material_init_gpencil_settings(struct Material *ma);
  
  /* UNUSED */
  // void automatname(struct Material *);
@@@ -79,7 -78,8 +79,8 @@@ enum 
        BKE_MAT_ASSIGN_OBJECT
  };
  
- struct Material *give_current_material(struct Object *ob, short act);
+ struct Material **give_current_material_p(struct Object *ob, short act);
+ struct Material  *give_current_material(struct Object *ob, short act);
  void assign_material_id(struct Main *bmain, struct ID *id, struct Material *ma, short act);
  void assign_material(struct Main *bmain, struct Object *ob, struct Material *ma, short act, int assign_type);
  void assign_matarar(struct Main *bmain, struct Object *ob, struct Material ***matar, short totcol);
@@@ -88,8 -88,6 +89,8 @@@ short BKE_object_material_slot_find_ind
  bool  BKE_object_material_slot_add(struct Main *bmain, struct Object *ob);
  bool  BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
  
 +struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act);
 +
  void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
  void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
  
@@@ -100,19 -98,26 +101,19 @@@ struct Material *BKE_material_pop_id(st
  void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data);
  /* rendering */
  
 -void init_render_material(struct Main *bmain, struct Material *, int, float *);
 -void init_render_materials(struct Main *, int r_mode, float *amd, bool do_default_material);
 -void end_render_material(struct Material *);
 -void end_render_materials(struct Main *);
 -
 -bool material_in_material(struct Material *parmat, struct Material *mat);
 -
  void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
  
 -/* driver update hacks */
 -void material_drivers_update(struct Scene *scene, struct Material *mat, float ctime);
 -
  /* copy/paste */
  void clear_matcopybuf(void);
  void free_matcopybuf(void);
  void copy_matcopybuf(struct Main *bmain, struct Material *ma);
  void paste_matcopybuf(struct Main *bmain, struct Material *ma);
  
 -/* handle backward compatibility for tface/materials called from doversion */
 -int do_version_tface(struct Main *main);
 +/* Evaluation. */
 +
 +struct Depsgraph;
 +
 +void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material);
  
  #ifdef __cplusplus
  }
  #include "MEM_guardedalloc.h"
  
  #include "DNA_anim_types.h"
 +#include "DNA_collection_types.h"
  #include "DNA_curve_types.h"
 -#include "DNA_group_types.h"
  #include "DNA_material_types.h"
  #include "DNA_mesh_types.h"
  #include "DNA_meshdata_types.h"
  #include "DNA_customdata_types.h"
 +#include "DNA_gpencil_types.h"
  #include "DNA_ID.h"
  #include "DNA_meta_types.h"
  #include "DNA_node_types.h"
  #include "BLI_array_utils.h"
  
  #include "BKE_animsys.h"
 +#include "BKE_brush.h"
  #include "BKE_displist.h"
  #include "BKE_global.h"
 -#include "BKE_depsgraph.h"
 +#include "BKE_gpencil.h"
  #include "BKE_icons.h"
  #include "BKE_image.h"
  #include "BKE_library.h"
@@@ -75,9 -73,6 +75,9 @@@
  #include "BKE_editmesh.h"
  #include "BKE_font.h"
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
 +
  #include "GPU_material.h"
  
  /* used in UI and render */
@@@ -92,65 -87,125 +92,65 @@@ void init_def_material(void
  /** Free (or release) any data used by this material (does not free the material itself). */
  void BKE_material_free(Material *ma)
  {
 -      int a;
 -
        BKE_animdata_free((ID *)ma, false);
  
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              MEM_SAFE_FREE(ma->mtex[a]);
 -      }
 -
 -      MEM_SAFE_FREE(ma->ramp_col);
 -      MEM_SAFE_FREE(ma->ramp_spec);
 +      /* Free gpu material before the ntree */
 +      GPU_material_free(&ma->gpumaterial);
  
        /* is no lib link block, but material extension */
        if (ma->nodetree) {
 -              ntreeFreeTree(ma->nodetree);
 +              ntreeFreeNestedTree(ma->nodetree);
                MEM_freeN(ma->nodetree);
                ma->nodetree = NULL;
        }
  
        MEM_SAFE_FREE(ma->texpaintslot);
  
 -      GPU_material_free(&ma->gpumaterial);
 +      MEM_SAFE_FREE(ma->gp_style);
  
        BKE_icon_id_delete((ID *)ma);
        BKE_previewimg_free(&ma->preview);
  }
  
 +void BKE_material_init_gpencil_settings(Material *ma)
 +{
 +      if ((ma) && (ma->gp_style == NULL)) {
 +              ma->gp_style = MEM_callocN(sizeof(MaterialGPencilStyle), "Grease Pencil Material Settings");
 +
 +              MaterialGPencilStyle *gp_style = ma->gp_style;
 +              /* set basic settings */
 +              gp_style->stroke_rgba[3] = 1.0f;
 +              gp_style->pattern_gridsize = 0.1f;
 +              gp_style->gradient_radius = 0.5f;
 +              ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
 +              ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
 +              ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
 +              gp_style->texture_opacity = 1.0f;
 +              gp_style->texture_pixsize = 100.0f;
 +
 +              gp_style->flag |= GP_STYLE_STROKE_SHOW;
 +              gp_style->flag |= GP_STYLE_FILL_SHOW;
 +      }
 +}
 +
  void BKE_material_init(Material *ma)
  {
        BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id));
  
 -      ma->r = ma->g = ma->b = ma->ref = 0.8;
 +      ma->r = ma->g = ma->b = 0.8;
        ma->specr = ma->specg = ma->specb = 1.0;
 -      ma->mirr = ma->mirg = ma->mirb = 1.0;
 -      ma->spectra = 1.0;
 -      ma->amb = 1.0;
 -      ma->alpha = 1.0;
 -      ma->spec = ma->hasize = 0.5;
 -      ma->har = 50;
 -      ma->starc = ma->ringc = 4;
 -      ma->linec = 12;
 -      ma->flarec = 1;
 -      ma->flaresize = ma->subsize = 1.0;
 -      ma->flareboost = 1;
 -      ma->seed2 = 6;
 -      ma->friction = 0.5;
 -      ma->refrac = 4.0;
 -      ma->roughness = 0.5;
 -      ma->param[0] = 0.5;
 -      ma->param[1] = 0.1;
 -      ma->param[2] = 0.5;
 -      ma->param[3] = 0.1;
 -      ma->rms = 0.1;
 -      ma->darkness = 1.0;
 -
 -      ma->strand_sta = ma->strand_end = 1.0f;
 -
 -      ma->ang = 1.0;
 -      ma->ray_depth = 2;
 -      ma->ray_depth_tra = 2;
 -      ma->fresnel_mir = 0.0;
 -      ma->fresnel_tra = 0.0;
 -      ma->fresnel_tra_i = 1.25;
 -      ma->fresnel_mir_i = 1.25;
 -      ma->tx_limit = 0.0;
 -      ma->tx_falloff = 1.0;
 -      ma->shad_alpha = 1.0f;
 -      ma->vcol_alpha = 0;
 -
 -      ma->gloss_mir = ma->gloss_tra = 1.0;
 -      ma->samp_gloss_mir = ma->samp_gloss_tra = 18;
 -      ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005;
 -      ma->dist_mir = 0.0;
 -      ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
 -
 -      ma->rampfac_col = 1.0;
 -      ma->rampfac_spec = 1.0;
 +      // ma->alpha = 1.0;  /* DEPRECATED */
 +      ma->spec = 0.5;
 +
 +      ma->roughness = 0.25f;
 +
        ma->pr_lamp = 3;         /* two lamps, is bits */
        ma->pr_type = MA_SPHERE;
  
 -      ma->sss_radius[0] = 1.0f;
 -      ma->sss_radius[1] = 1.0f;
 -      ma->sss_radius[2] = 1.0f;
 -      ma->sss_col[0] = 1.0f;
 -      ma->sss_col[1] = 1.0f;
 -      ma->sss_col[2] = 1.0f;
 -      ma->sss_error = 0.05f;
 -      ma->sss_scale = 0.1f;
 -      ma->sss_ior = 1.3f;
 -      ma->sss_colfac = 1.0f;
 -      ma->sss_texfac = 0.0f;
 -      ma->sss_front = 1.0f;
 -      ma->sss_back = 1.0f;
 -
 -      ma->vol.density = 1.0f;
 -      ma->vol.emission = 0.0f;
 -      ma->vol.scattering = 1.0f;
 -      ma->vol.reflection = 1.0f;
 -      ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f;
 -      ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f;
 -      ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f;
 -      ma->vol.density_scale = 1.0f;
 -      ma->vol.depth_cutoff = 0.01f;
 -      ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED;
 -      ma->vol.stepsize = 0.2f;
 -      ma->vol.shade_type = MA_VOL_SHADE_SHADED;
 -      ma->vol.shadeflag |= MA_VOL_PRECACHESHADING;
 -      ma->vol.precache_resolution = 50;
 -      ma->vol.ms_spread = 0.2f;
 -      ma->vol.ms_diff = 1.f;
 -      ma->vol.ms_intensity = 1.f;
 -
 -      ma->game.flag = GEMAT_BACKCULL;
 -      ma->game.alpha_blend = 0;
 -      ma->game.face_orientation = 0;
 -
 -      ma->mode = MA_TRACEBLE | MA_SHADBUF | MA_SHADOW | MA_RAYBIAS | MA_TANGENT_STR | MA_ZTRANSP;
 -      ma->mode2 = MA_CASTSHADOW;
 -      ma->shade_flag = MA_APPROX_OCCLUSION;
        ma->preview = NULL;
 +
 +      ma->alpha_threshold = 0.5f;
 +
  }
  
  Material *BKE_material_add(Main *bmain, const char *name)
        return ma;
  }
  
 +Material *BKE_material_add_gpencil(Main *bmain, const char *name)
 +{
 +      Material *ma;
 +
 +      ma = BKE_material_add(bmain, name);
 +
 +      /* grease pencil settings */
 +      if (ma != NULL) {
 +              BKE_material_init_gpencil_settings(ma);
 +              BKE_brush_update_material(bmain, ma, NULL);
 +      }
 +      return ma;
 +}
 +
 +
  /**
   * Only copy internal data of Material ID from source to already allocated/initialized destination.
   * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
   */
  void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag)
  {
 -      for (int a = 0; a < MAX_MTEX; a++) {
 -              if (ma_src->mtex[a]) {
 -                      ma_dst->mtex[a] = MEM_mallocN(sizeof(*ma_dst->mtex[a]), __func__);
 -                      *ma_dst->mtex[a] = *ma_src->mtex[a];
 -              }
 -      }
 -
 -      if (ma_src->ramp_col) {
 -              ma_dst->ramp_col = MEM_dupallocN(ma_src->ramp_col);
 -      }
 -      if (ma_src->ramp_spec) {
 -              ma_dst->ramp_spec = MEM_dupallocN(ma_src->ramp_spec);
 -      }
 -
        if (ma_src->nodetree) {
                /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
                 *       (see BKE_libblock_copy_ex()). */
                ma_dst->texpaintslot = MEM_dupallocN(ma_src->texpaintslot);
        }
  
 +      if (ma_src->gp_style != NULL) {
 +              ma_dst->gp_style = MEM_dupallocN(ma_src->gp_style);
 +      }
 +
        BLI_listbase_clear(&ma_dst->gpumaterial);
 +
 +      /* TODO Duplicate Engine Settings and set runtime to NULL */
  }
  
  Material *BKE_material_copy(Main *bmain, const Material *ma)
@@@ -235,25 -283,30 +235,25 @@@ Material *BKE_material_localize(Materia
         *
         * NOTE: Only possible once nested node trees are fully converted to that too. */
  
 -      Material *man;
 -      int a;
 -
 -      man = BKE_libblock_copy_nolib(&ma->id, false);
 -
 -      /* no increment for texture ID users, in previewrender.c it prevents decrement */
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              if (ma->mtex[a]) {
 -                      man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial");
 -                      memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex));
 -              }
 -      }
 -
 -      if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
 -      if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
 +      Material *man = BKE_libblock_copy_for_localize(&ma->id);
  
        man->texpaintslot = NULL;
        man->preview = NULL;
  
 -      if (ma->nodetree)
 +      if (ma->nodetree != NULL) {
                man->nodetree = ntreeLocalize(ma->nodetree);
 +      }
 +
 +      if (ma->gp_style != NULL) {
 +              man->gp_style = MEM_dupallocN(ma->gp_style);
 +      }
  
        BLI_listbase_clear(&man->gpumaterial);
  
 +      /* TODO Duplicate Engine Settings and set runtime to NULL */
 +
 +      man->id.tag |= LIB_TAG_LOCALIZED;
 +
        return man;
  }
  
@@@ -267,7 -320,6 +267,7 @@@ Material ***give_matarar(Object *ob
        Mesh *me;
        Curve *cu;
        MetaBall *mb;
 +      bGPdata *gpd;
  
        if (ob->type == OB_MESH) {
                me = ob->data;
                mb = ob->data;
                return &(mb->mat);
        }
 +      else if (ob->type == OB_GPENCIL) {
 +              gpd = ob->data;
 +              return &(gpd->mat);
 +      }
        return NULL;
  }
  
@@@ -293,7 -341,6 +293,7 @@@ short *give_totcolp(Object *ob
        Mesh *me;
        Curve *cu;
        MetaBall *mb;
 +      bGPdata *gpd;
  
        if (ob->type == OB_MESH) {
                me = ob->data;
                mb = ob->data;
                return &(mb->totcol);
        }
 +      else if (ob->type == OB_GPENCIL) {
 +              gpd = ob->data;
 +              return &(gpd->totcol);
 +      }
        return NULL;
  }
  
@@@ -327,8 -370,6 +327,8 @@@ Material ***give_matarar_id(ID *id
                        return &(((Curve *)id)->mat);
                case ID_MB:
                        return &(((MetaBall *)id)->mat);
 +              case ID_GD:
 +                      return &(((bGPdata *)id)->mat);
                default:
                        break;
        }
@@@ -347,8 -388,6 +347,8 @@@ short *give_totcolp_id(ID *id
                        return &(((Curve *)id)->totcol);
                case ID_MB:
                        return &(((MetaBall *)id)->totcol);
 +              case ID_GD:
 +                      return &(((bGPdata *)id)->totcol);
                default:
                        break;
        }
@@@ -370,9 -409,6 +370,9 @@@ static void material_data_index_remove_
                case ID_MB:
                        /* meta-elems don't have materials atm */
                        break;
 +              case ID_GD:
 +                      BKE_gpencil_material_index_remove((bGPdata *)id, index);
 +                      break;
                default:
                        break;
        }
@@@ -425,8 -461,7 +425,8 @@@ void BKE_material_resize_id(Main *bmain
        }
        *totcolp = totcol;
  
 -      DAG_relations_tag_update(bmain);
 +      DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
 +      DEG_relations_tag_update(bmain);
  }
  
  void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
  
                id_us_plus((ID *)ma);
                test_all_objects_materials(bmain, id);
 -              DAG_relations_tag_update(bmain);
 +
 +              DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
 +              DEG_relations_tag_update(bmain);
        }
  }
  
@@@ -479,8 -512,7 +479,8 @@@ Material *BKE_material_pop_id(Main *bma
                                material_data_index_remove_id(id, index);
                        }
  
 -                      DAG_relations_tag_update(bmain);
 +                      DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
 +                      DEG_relations_tag_update(bmain);
                }
        }
  
@@@ -507,14 -539,13 +507,14 @@@ void BKE_material_clear_id(Main *bmain
                        material_data_index_clear_id(id);
                }
  
 -              DAG_relations_tag_update(bmain);
 +              DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
 +              DEG_relations_tag_update(bmain);
        }
  }
  
- Material *give_current_material(Object *ob, short act)
+ Material **give_current_material_p(Object *ob, short act)
  {
-       Material ***matarar, *ma;
+       Material ***matarar, **ma_p;
        const short *totcolp;
  
        if (ob == NULL) return NULL;
        }
  
        if (ob->matbits && ob->matbits[act - 1]) {    /* in object */
-               ma = ob->mat[act - 1];
+               ma_p = &ob->mat[act - 1];
        }
        else {                              /* in data */
  
  
                matarar = give_matarar(ob);
  
-               if (matarar && *matarar) ma = (*matarar)[act - 1];
-               else ma = NULL;
+               if (matarar && *matarar) {
+                       ma_p = &(*matarar)[act - 1];
+               }
+               else {
+                       ma_p = NULL;
+               }
        }
  
-       return ma;
+       return ma_p;
+ }
+ Material *give_current_material(Object *ob, short act)
+ {
+       Material **ma_p = give_current_material_p(ob, act);
+       return ma_p ? *ma_p : NULL;
  }
  
 +MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act)
 +{
 +      Material *ma = give_current_material(ob, act);
 +      if (ma != NULL) {
 +              if (ma->gp_style == NULL) {
 +                      BKE_material_init_gpencil_settings(ma);
 +              }
 +
 +              return ma->gp_style;
 +      }
 +      else {
 +              return NULL;
 +      }
 +}
 +
  Material *give_node_material(Material *ma)
  {
        if (ma && ma->use_nodes && ma->nodetree) {
@@@ -618,8 -643,7 +627,8 @@@ void BKE_material_resize_object(Main *b
        if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
        if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
  
 -      DAG_relations_tag_update(bmain);
 +      DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_GEOMETRY);
 +      DEG_relations_tag_update(bmain);
  }
  
  void test_object_materials(Main *bmain, Object *ob, ID *id)
@@@ -661,6 -685,14 +670,6 @@@ void assign_material_id(Main *bmain, I
        if (act > MAXMAT) return;
        if (act < 1) act = 1;
  
 -      /* this is needed for Python overrides,
 -       * we just have to take care that the UI can't do this */
 -#if 0
 -      /* prevent crashing when using accidentally */
 -      BLI_assert(id->lib == NULL);
 -      if (id->lib) return;
 -#endif
 -
        /* test arraylens */
  
        totcolp = give_totcolp_id(id);
@@@ -800,9 -832,6 +809,9 @@@ void BKE_material_remap_object(Object *
        else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
                BKE_curve_material_remap(ob->data, remap, ob->totcol);
        }
 +      else if (ob->type == OB_GPENCIL) {
 +              BKE_gpencil_material_remap(ob->data, remap, ob->totcol);
 +      }
        else {
                /* add support for this object data! */
                BLI_assert(matar == NULL);
@@@ -919,8 -948,278 +928,8 @@@ bool BKE_object_material_slot_add(Main 
        return true;
  }
  
 -static void do_init_render_material(Main *bmain, Material *ma, int r_mode, float *amb)
 -{
 -      MTex *mtex;
 -      int a, needuv = 0, needtang = 0;
 -
 -      if (ma->flarec == 0) ma->flarec = 1;
 -
 -      /* add all texcoflags from mtex, texco and mapto were cleared in advance */
 -      for (a = 0; a < MAX_MTEX; a++) {
 -
 -              /* separate tex switching */
 -              if (ma->septex & (1 << a)) continue;
 -
 -              mtex = ma->mtex[a];
 -              if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
 -
 -                      ma->texco |= mtex->texco;
 -                      ma->mapto |= mtex->mapto;
 -
 -                      /* always get derivatives for these textures */
 -                      if (ELEM(mtex->tex->type, TEX_IMAGE, TEX_ENVMAP)) ma->texco |= TEXCO_OSA;
 -                      else if (mtex->texflag & (MTEX_COMPAT_BUMP | MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA;
 -
 -                      if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1;
 -                      else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1;
 -                      else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1;
 -
 -                      if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT))
 -                              needtang = 1;
 -              }
 -      }
 -
 -      if (needtang) ma->mode |= MA_NORMAP_TANG;
 -      else ma->mode &= ~MA_NORMAP_TANG;
 -
 -      if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
 -              needuv = 1;
 -              if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;     /* for texfaces */
 -      }
 -      if (needuv) ma->texco |= NEED_UV;
 -
 -      /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */
 -      if (r_mode & R_RAYTRACE) {
 -              if ((ma->mode & (MA_RAYMIRROR | MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) {
 -                      ma->texco |= NEED_UV | TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM;
 -                      if (r_mode & R_OSA) ma->texco |= TEXCO_OSA;
 -              }
 -      }
 -
 -      if (amb) {
 -              ma->ambr = ma->amb * amb[0];
 -              ma->ambg = ma->amb * amb[1];
 -              ma->ambb = ma->amb * amb[2];
 -      }
 -
 -      /* local group override */
 -      if ((ma->shade_flag & MA_GROUP_LOCAL) && ma->id.lib && ma->group && ma->group->id.lib) {
 -              Group *group;
 -
 -              for (group = bmain->group.first; group; group = group->id.next) {
 -                      if (!ID_IS_LINKED(group) && STREQ(group->id.name, ma->group->id.name)) {
 -                              ma->group = group;
 -                      }
 -              }
 -      }
 -}
 -
 -static void init_render_nodetree(Main *bmain, bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
 -{
 -      bNode *node;
 -
 -      /* parses the geom+tex nodes */
 -      ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l);
 -      for (node = ntree->nodes.first; node; node = node->next) {
 -              if (node->id) {
 -                      if (GS(node->id->name) == ID_MA) {
 -                              Material *ma = (Material *)node->id;
 -                              if (ma != basemat) {
 -                                      do_init_render_material(bmain, ma, r_mode, amb);
 -                                      basemat->texco |= ma->texco;
 -                              }
 -
 -                              basemat->mode_l |= ma->mode & ~(MA_MODE_PIPELINE | MA_SHLESS);
 -                              basemat->mode2_l |= ma->mode2 & ~MA_MODE2_PIPELINE;
 -                              /* basemat only considered shadeless if all node materials are too */
 -                              if (!(ma->mode & MA_SHLESS))
 -                                      basemat->mode_l &= ~MA_SHLESS;
 -
 -                              if (ma->strand_surfnor > 0.0f)
 -                                      basemat->mode_l |= MA_STR_SURFDIFF;
 -                      }
 -                      else if (node->type == NODE_GROUP)
 -                              init_render_nodetree(bmain, (bNodeTree *)node->id, basemat, r_mode, amb);
 -              }
 -              else if (node->typeinfo->type == SH_NODE_NORMAL_MAP) {
 -                      basemat->mode2_l |= MA_TANGENT_CONCRETE;
 -                      NodeShaderNormalMap *nm = node->storage;
 -                      bool taken_into_account = false;
 -                      for (int i = 0; i < basemat->nmap_tangent_names_count; i++) {
 -                              if (STREQ(basemat->nmap_tangent_names[i], nm->uv_map)) {
 -                                      taken_into_account = true;
 -                                      break;
 -                              }
 -                      }
 -                      if (!taken_into_account) {
 -                              BLI_assert(basemat->nmap_tangent_names_count < MAX_MTFACE + 1);
 -                              strcpy(basemat->nmap_tangent_names[basemat->nmap_tangent_names_count++], nm->uv_map);
 -                      }
 -              }
 -      }
 -}
 -
 -void init_render_material(Main *bmain, Material *mat, int r_mode, float *amb)
 -{
 -
 -      do_init_render_material(bmain, mat, r_mode, amb);
 -
 -      if (mat->nodetree && mat->use_nodes) {
 -              /* mode_l will take the pipeline options from the main material, and the or-ed
 -               * result of non-pipeline options from the nodes. shadeless is an exception,
 -               * mode_l will have it set when all node materials are shadeless. */
 -              mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS;
 -              mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE;
 -              mat->nmap_tangent_names_count = 0;
 -              init_render_nodetree(bmain, mat->nodetree, mat, r_mode, amb);
 -
 -              if (!mat->nodetree->execdata)
 -                      mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
 -      }
 -      else {
 -              mat->mode_l = mat->mode;
 -              mat->mode2_l = mat->mode2;
 -
 -              if (mat->strand_surfnor > 0.0f)
 -                      mat->mode_l |= MA_STR_SURFDIFF;
 -      }
 -}
 -
 -void init_render_materials(Main *bmain, int r_mode, float *amb, bool do_default_material)
 -{
 -      Material *ma;
 -
 -      /* clear these flags before going over materials, to make sure they
 -       * are cleared only once, otherwise node materials contained in other
 -       * node materials can go wrong */
 -      for (ma = bmain->mat.first; ma; ma = ma->id.next) {
 -              if (ma->id.us) {
 -                      ma->texco = 0;
 -                      ma->mapto = 0;
 -              }
 -      }
 -
 -      /* two steps, first initialize, then or the flags for layers */
 -      for (ma = bmain->mat.first; ma; ma = ma->id.next) {
 -              /* is_used flag comes back in convertblender.c */
 -              ma->flag &= ~MA_IS_USED;
 -              if (ma->id.us)
 -                      init_render_material(bmain, ma, r_mode, amb);
 -      }
 -
 -      if (do_default_material) {
 -              init_render_material(bmain, &defmaterial, r_mode, amb);
 -      }
 -}
 -
 -/* only needed for nodes now */
 -void end_render_material(Material *mat)
 -{
 -      if (mat && mat->nodetree && mat->use_nodes) {
 -              if (mat->nodetree->execdata)
 -                      ntreeShaderEndExecTree(mat->nodetree->execdata);
 -      }
 -}
 -
 -void end_render_materials(Main *bmain)
 -{
 -      Material *ma;
 -      for (ma = bmain->mat.first; ma; ma = ma->id.next)
 -              if (ma->id.us)
 -                      end_render_material(ma);
 -}
 -
 -static bool material_in_nodetree(bNodeTree *ntree, Material *mat)
 -{
 -      bNode *node;
 -
 -      for (node = ntree->nodes.first; node; node = node->next) {
 -              if (node->id) {
 -                      if (GS(node->id->name) == ID_MA) {
 -                              if (node->id == (ID *)mat) {
 -                                      return true;
 -                              }
 -                      }
 -                      else if (node->type == NODE_GROUP) {
 -                              if (material_in_nodetree((bNodeTree *)node->id, mat)) {
 -                                      return true;
 -                              }
 -                      }
 -              }
 -      }
 -
 -      return false;
 -}
 -
 -bool material_in_material(Material *parmat, Material *mat)
 -{
 -      if (parmat == mat)
 -              return true;
 -      else if (parmat->nodetree && parmat->use_nodes)
 -              return material_in_nodetree(parmat->nodetree, mat);
 -      else
 -              return false;
 -}
 -
 -
  /* ****************** */
  
 -/* Update drivers for materials in a nodetree */
 -static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
 -{
 -      bNode *node;
 -
 -      /* nodetree itself */
 -      if (ntree->adt && ntree->adt->drivers.first) {
 -              BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
 -      }
 -
 -      /* nodes */
 -      for (node = ntree->nodes.first; node; node = node->next) {
 -              if (node->id) {
 -                      if (GS(node->id->name) == ID_MA) {
 -                              material_drivers_update(scene, (Material *)node->id, ctime);
 -                      }
 -                      else if (node->type == NODE_GROUP) {
 -                              material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
 -                      }
 -              }
 -      }
 -}
 -
 -/* Calculate all drivers for materials
 - * FIXME: this is really a terrible method which may result in some things being calculated
 - * multiple times. However, without proper despgraph support for these things, we are forced
 - * into this sort of thing...
 - */
 -void material_drivers_update(Scene *scene, Material *ma, float ctime)
 -{
 -      //if (G.f & G_DEBUG)
 -      //      printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
 -
 -      /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
 -       * (see BKE_scene_update_tagged()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
 -       * in the meantime... [#32017]
 -       */
 -      if (ma->id.tag & LIB_TAG_DOIT)
 -              return;
 -
 -      ma->id.tag |= LIB_TAG_DOIT;
 -
 -      /* material itself */
 -      if (ma->adt && ma->adt->drivers.first) {
 -              BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
 -      }
 -
 -      /* nodes */
 -      if (ma->nodetree) {
 -              material_node_drivers_update(scene, ma->nodetree, ctime);
 -      }
 -
 -      ma->id.tag &= ~LIB_TAG_DOIT;
 -}
 -
  bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
  {
        Material *mao, ***matarar;
        }
  
        /* check indices from mesh */
 -      if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
 +      if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
                material_data_index_remove_id((ID *)ob->data, actcol - 1);
 -              if (ob->curve_cache) {
 -                      BKE_displist_free(&ob->curve_cache->disp);
 +              if (ob->runtime.curve_cache) {
 +                      BKE_displist_free(&ob->runtime.curve_cache->disp);
                }
        }
  
        return true;
  }
  
 -static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
 -{
 -      return (mtex && (mtex->texco == TEXCO_UV) &&
 -              mtex->tex && (mtex->tex->type == TEX_IMAGE) &&
 -              mtex->tex->ima);
 -}
 -
  static bNode *nodetree_uv_node_recursive(bNode *node)
  {
        bNode *inode;
        return NULL;
  }
  
 -void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
 +static int count_texture_nodes_recursive(bNodeTree *nodetree)
 +{
 +      int tex_nodes = 0;
 +
 +      for (bNode *node = nodetree->nodes.first; node; node = node->next) {
 +              if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
 +                      tex_nodes++;
 +              }
 +              else if (node->type == NODE_GROUP) {
 +                      /* recurse into the node group and see if it contains any textures */
 +                      tex_nodes += count_texture_nodes_recursive((bNodeTree *)node->id);
 +              }
 +      }
 +
 +      return tex_nodes;
 +}
 +
 +static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_node, Material *ma, int *index)
  {
 -      MTex **mtex;
 -      short count = 0;
 -      short index = 0, i;
 +      for (bNode *node = nodetree->nodes.first; node; node = node->next) {
 +              if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
 +                      if (active_node == node) {
 +                              ma->paint_active_slot = *index;
 +                      }
 +                      ma->texpaintslot[*index].ima = (Image *)node->id;
  
 -      bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
 -      bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
 +                      /* for new renderer, we need to traverse the treeback in search of a UV node */
 +                      bNode *uvnode = nodetree_uv_node_recursive(node);
 +
 +                      if (uvnode) {
 +                              NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage;
 +                              ma->texpaintslot[*index].uvname = storage->uv_map;
 +                              /* set a value to index so UI knows that we have a valid pointer for the mesh */
 +                              ma->texpaintslot[*index].valid = true;
 +                      }
 +                      else {
 +                              /* just invalidate the index here so UV map does not get displayed on the UI */
 +                              ma->texpaintslot[*index].valid = false;
 +                      }
 +                      (*index)++;
 +              }
 +              else if (node->type == NODE_GROUP) {
 +                      /* recurse into the node group and see if it contains any textures */
 +                      fill_texpaint_slots_recursive((bNodeTree *)node->id, active_node, ma, index);
 +              }
 +      }
 +}
 +
 +void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
 +{
 +      int count = 0;
 +      int index = 0;
  
        if (!ma)
                return;
                return;
        }
  
 -      if (use_nodes || ma->use_nodes) {
 -              bNode *node, *active_node;
 -
 -              if (!(ma->nodetree)) {
 -                      ma->paint_active_slot = 0;
 -                      ma->paint_clone_slot = 0;
 -                      return;
 -              }
 -
 -              for (node = ma->nodetree->nodes.first; node; node = node->next) {
 -                      if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id)
 -                              count++;
 -              }
 -
 -              if (count == 0) {
 -                      ma->paint_active_slot = 0;
 -                      ma->paint_clone_slot = 0;
 -                      return;
 -              }
 -              ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
 -
 -              active_node = nodeGetActiveTexture(ma->nodetree);
 -
 -              for (node = ma->nodetree->nodes.first; node; node = node->next) {
 -                      if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
 -                              if (active_node == node)
 -                                      ma->paint_active_slot = index;
 -                              ma->texpaintslot[index].ima = (Image *)node->id;
 -
 -                              /* for new renderer, we need to traverse the treeback in search of a UV node */
 -                              if (use_nodes) {
 -                                      bNode *uvnode = nodetree_uv_node_recursive(node);
 -
 -                                      if (uvnode) {
 -                                              NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage;
 -                                              ma->texpaintslot[index].uvname = storage->uv_map;
 -                                              /* set a value to index so UI knows that we have a valid pointer for the mesh */
 -                                              ma->texpaintslot[index].index = 0;
 -                                      }
 -                                      else {
 -                                              /* just invalidate the index here so UV map does not get displayed on the UI */
 -                                              ma->texpaintslot[index].index = -1;
 -                                      }
 -                              }
 -                              else {
 -                                      ma->texpaintslot[index].index = -1;
 -                              }
 -                              index++;
 -                      }
 -              }
 +      if (!(ma->nodetree)) {
 +              ma->paint_active_slot = 0;
 +              ma->paint_clone_slot = 0;
 +              return;
        }
 -      else if (is_bi) {
 -              for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
 -                      if (get_mtex_slot_valid_texpaint(*mtex)) {
 -                              count++;
 -                      }
 -              }
 -
 -              if (count == 0) {
 -                      ma->paint_active_slot = 0;
 -                      ma->paint_clone_slot = 0;
 -                      return;
 -              }
 -
 -              ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
  
 -              for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
 -                      if (get_mtex_slot_valid_texpaint(*mtex)) {
 -                              ma->texpaintslot[index].ima = (*mtex)->tex->ima;
 -                              ma->texpaintslot[index].uvname = (*mtex)->uvname;
 -                              ma->texpaintslot[index].index = i;
 +      count = count_texture_nodes_recursive(ma->nodetree);
  
 -                              index++;
 -                      }
 -              }
 -      }
 -      else {
 +      if (count == 0) {
                ma->paint_active_slot = 0;
                ma->paint_clone_slot = 0;
                return;
        }
  
 +      ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
 +
 +      bNode *active_node = nodeGetActiveTexture(ma->nodetree);
 +
 +      fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, &index);
  
        ma->tot_slots = count;
  
@@@ -1372,8 -1697,23 +1381,8 @@@ void clear_matcopybuf(void
  
  void free_matcopybuf(void)
  {
 -      int a;
 -
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              if (matcopybuf.mtex[a]) {
 -                      MEM_freeN(matcopybuf.mtex[a]);
 -                      matcopybuf.mtex[a] = NULL;
 -              }
 -      }
 -
 -      if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
 -      if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
 -
 -      matcopybuf.ramp_col = NULL;
 -      matcopybuf.ramp_spec = NULL;
 -
        if (matcopybuf.nodetree) {
 -              ntreeFreeTree(matcopybuf.nodetree);
 +              ntreeFreeLocalTree(matcopybuf.nodetree);
                MEM_freeN(matcopybuf.nodetree);
                matcopybuf.nodetree = NULL;
        }
  
  void copy_matcopybuf(Main *bmain, Material *ma)
  {
 -      int a;
 -      MTex *mtex;
 -
        if (matcopied)
                free_matcopybuf();
  
        memcpy(&matcopybuf, ma, sizeof(Material));
 -      if (matcopybuf.ramp_col) matcopybuf.ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
 -      if (matcopybuf.ramp_spec) matcopybuf.ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
  
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              mtex = matcopybuf.mtex[a];
 -              if (mtex) {
 -                      matcopybuf.mtex[a] = MEM_dupallocN(mtex);
 -              }
 -      }
        matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, bmain, false);
        matcopybuf.preview = NULL;
        BLI_listbase_clear(&matcopybuf.gpumaterial);
 +      /* TODO Duplicate Engine Settings and set runtime to NULL */
        matcopied = 1;
  }
  
  void paste_matcopybuf(Main *bmain, Material *ma)
  {
 -      int a;
 -      MTex *mtex;
        ID id;
  
        if (matcopied == 0)
                return;
 -      /* free current mat */
 -      if (ma->ramp_col) MEM_freeN(ma->ramp_col);
 -      if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              mtex = ma->mtex[a];
 -              if (mtex && mtex->tex)
 -                      id_us_min(&mtex->tex->id);
 -              if (mtex)
 -                      MEM_freeN(mtex);
 -      }
 +
 +      /* Free gpu material before the ntree */
 +      GPU_material_free(&ma->gpumaterial);
  
        if (ma->nodetree) {
 -              ntreeFreeTree(ma->nodetree);
 +              ntreeFreeNestedTree(ma->nodetree);
                MEM_freeN(ma->nodetree);
        }
  
 -      GPU_material_free(&ma->gpumaterial);
 -
        id = (ma->id);
        memcpy(ma, &matcopybuf, sizeof(Material));
        (ma->id) = id;
  
 -      if (matcopybuf.ramp_col) ma->ramp_col = MEM_dupallocN(matcopybuf.ramp_col);
 -      if (matcopybuf.ramp_spec) ma->ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec);
 -
 -      for (a = 0; a < MAX_MTEX; a++) {
 -              mtex = ma->mtex[a];
 -              if (mtex) {
 -                      ma->mtex[a] = MEM_dupallocN(mtex);
 -                      if (mtex->tex) {
 -                              /* first check this is in main (we may have loaded another file) [#35500] */
 -                              if (BLI_findindex(&bmain->tex, mtex->tex) != -1) {
 -                                      id_us_plus((ID *)mtex->tex);
 -                              }
 -                              else {
 -                                      ma->mtex[a]->tex = NULL;
 -                              }
 -                      }
 -              }
 -      }
 -
        ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, bmain, false);
  }
  
 -
 -/*********************** texface to material convert functions **********************/
 -/* encode all the TF information into a single int */
 -static int encode_tfaceflag(MTFace *tf, int convertall)
 -{
 -      /* calculate the flag */
 -      int flag = tf->mode;
 -
 -      /* options that change the material offline render */
 -      if (!convertall) {
 -              flag &= ~TF_OBCOL;
 -      }
 -
 -      /* clean flags that are not being converted */
 -      flag &= ~TF_TEX;
 -      flag &= ~TF_SHAREDVERT;
 -      flag &= ~TF_SHAREDCOL;
 -      flag &= ~TF_CONVERTED;
 -
 -      /* light tface flag is ignored in GLSL mode */
 -      flag &= ~TF_LIGHT;
 -
 -      /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
 -      flag |= tf->transp << 15;
 -
 -      /* increase 1 so flag 0 is different than no flag yet */
 -      return flag + 1;
 -}
 -
 -/* set the material options based in the tface flag */
 -static void decode_tfaceflag(Material *ma, int flag, int convertall)
 -{
 -      int alphablend;
 -      GameSettings *game = &ma->game;
 -
 -      /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
 -      flag -= 1;
 -
 -      alphablend = flag >> 15;  /* encoded in the encode_tfaceflag function */
 -      (*game).flag = 0;
 -
 -      /* General Material Options */
 -      if ((flag & TF_DYNAMIC) == 0) (*game).flag    |= GEMAT_NOPHYSICS;
 -
 -      /* Material Offline Rendering Properties */
 -      if (convertall) {
 -              if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
 -      }
 -
 -      /* Special Face Properties */
 -      if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
 -      if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
 -      if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
 -
 -      /* Face Orientation */
 -      if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
 -      else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
 -      else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
 -
 -      /* Alpha Blend */
 -      if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
 -      else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
 -      else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
 -      else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
 -}
 -
 -/* boolean check to see if the mesh needs a material */
 -static int check_tfaceneedmaterial(int flag)
 -{
 -      /* check if the flags we have are not deprecated != than default material options
 -       * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
 -
 -      /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
 -      flag -= 1;
 -
 -      /* deprecated flags */
 -      flag &= ~TF_OBCOL;
 -      flag &= ~TF_SHAREDVERT;
 -      flag &= ~TF_SHAREDCOL;
 -
 -      /* light tface flag is ignored in GLSL mode */
 -      flag &= ~TF_LIGHT;
 -
 -      /* automatic detected if tex image has alpha */
 -      flag &= ~(TF_ALPHA << 15);
 -      /* automatic detected if using texture */
 -      flag &= ~TF_TEX;
 -
 -      /* settings for the default NoMaterial */
 -      if (flag == TF_DYNAMIC)
 -              return 0;
 -
 -      else
 -              return 1;
 -}
 -
 -/* return number of digits of an integer */
 -/* XXX to be optmized or replaced by an equivalent blender internal function */
 -static int integer_getdigits(int number)
 -{
 -      int i = 0;
 -      if (number == 0) return 1;
 -
 -      while (number != 0) {
 -              number = (int)(number / 10);
 -              i++;
 -      }
 -      return i;
 -}
 -
 -static void calculate_tface_materialname(char *matname, char *newname, int flag)
 -{
 -      /* if flag has only light and collision and material matches those values
 -       * you can do strcpy(name, mat_name);
 -       * otherwise do: */
 -      int digits = integer_getdigits(flag);
 -      /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
 -       * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
 -      BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
 -}
 -
 -/* returns -1 if no match */
 -static short mesh_getmaterialnumber(Mesh *me, Material *ma)
 -{
 -      short a;
 -
 -      for (a = 0; a < me->totcol; a++) {
 -              if (me->mat[a] == ma) {
 -                      return a;
 -              }
 -      }
 -
 -      return -1;
 -}
 -
 -/* append material */
 -static short mesh_addmaterial(Main *bmain, Mesh *me, Material *ma)
 -{
 -      BKE_material_append_id(bmain, &me->id, NULL);
 -      me->mat[me->totcol - 1] = ma;
 -
 -      id_us_plus(&ma->id);
 -
 -      return me->totcol - 1;
 -}
 -
 -static void set_facetexture_flags(Material *ma, Image *image)
 -{
 -      if (image) {
 -              ma->mode |= MA_FACETEXTURE;
 -              /* we could check if the texture has alpha, but then more meshes sharing the same
 -               * material may need it. Let's make it simple. */
 -              if (BKE_image_has_alpha(image))
 -                      ma->mode |= MA_FACETEXTURE_ALPHA;
 -      }
 -}
 -
 -/* returns material number */
 -static short convert_tfacenomaterial(Main *bmain, Mesh *me, MTFace *tf, int flag)
 -{
 -      Material *ma;
 -      char idname[MAX_ID_NAME];
 -      short mat_nr = -1;
 -
 -      /* new material, the name uses the flag*/
 -      BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
 -
 -      if ((ma = BLI_findstring(&bmain->mat, idname + 2, offsetof(ID, name) + 2))) {
 -              mat_nr = mesh_getmaterialnumber(me, ma);
 -              /* assign the material to the mesh */
 -              if (mat_nr == -1) mat_nr = mesh_addmaterial(bmain, me, ma);
 -
 -              /* if needed set "Face Textures [Alpha]" Material options */
 -              set_facetexture_flags(ma, tf->tpage);
 -      }
 -      /* create a new material */
 -      else {
 -              ma = BKE_material_add(bmain, idname + 2);
 -
 -              if (ma) {
 -                      printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
 -                      mat_nr = mesh_addmaterial(bmain, me, ma);
 -
 -                      /* if needed set "Face Textures [Alpha]" Material options */
 -                      set_facetexture_flags(ma, tf->tpage);
 -
 -                      decode_tfaceflag(ma, flag, 1);
 -                      /* the final decoding will happen after, outside the main loop
 -                       * for now store the flag into the material and change light/tex/collision
 -                       * store the flag as a negative number */
 -                      ma->game.flag = -flag;
 -                      id_us_min((ID *)ma);
 -              }
 -              else {
 -                      printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
 -              }
 -      }
 -
 -      /* set as converted, no need to go bad to this face */
 -      tf->mode |= TF_CONVERTED;
 -      return mat_nr;
 -}
 -
 -/* Function to fully convert materials */
 -static void convert_tfacematerial(Main *bmain, Material *ma)
 -{
 -      Mesh *me;
 -      Material *mat_new;
 -      MFace *mf;
 -      MTFace *tf;
 -      int flag, index;
 -      int a;
 -      short mat_nr;
 -      CustomDataLayer *cdl;
 -      char idname[MAX_ID_NAME];
 -
 -      for (me = bmain->mesh.first; me; me = me->id.next) {
 -              /* check if this mesh uses this material */
 -              for (a = 0; a < me->totcol; a++)
 -                      if (me->mat[a] == ma) break;
 -
 -              /* no material found */
 -              if (a == me->totcol) continue;
 -
 -              /* get the active tface layer */
 -              index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
 -              cdl = (index == -1) ? NULL : &me->fdata.layers[index];
 -              if (!cdl) continue;
 -
 -              /* loop over all the faces and stop at the ones that use the material*/
 -              for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
 -                      if (me->mat[mf->mat_nr] != ma) continue;
 -
 -                      /* texface data for this face */
 -                      tf = ((MTFace *)cdl->data) + a;
 -                      flag = encode_tfaceflag(tf, 1);
 -
 -                      /* the name of the new material */
 -                      calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
 -
 -                      if ((mat_new = BLI_findstring(&bmain->mat, idname + 2, offsetof(ID, name) + 2))) {
 -                              /* material already existent, see if the mesh has it */
 -                              mat_nr = mesh_getmaterialnumber(me, mat_new);
 -                              /* material is not in the mesh, add it */
 -                              if (mat_nr == -1) mat_nr = mesh_addmaterial(bmain, me, mat_new);
 -                      }
 -                      /* create a new material */
 -                      else {
 -                              mat_new = BKE_material_copy(bmain, ma);
 -                              if (mat_new) {
 -                                      /* rename the material*/
 -                                      BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
 -                                      id_us_min((ID *)mat_new);
 -
 -                                      mat_nr = mesh_addmaterial(bmain, me, mat_new);
 -                                      decode_tfaceflag(mat_new, flag, 1);
 -                              }
 -                              else {
 -                                      printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
 -                                      mat_nr = mf->mat_nr;
 -                                      continue;
 -                              }
 -                      }
 -
 -                      /* if the material has a texture but no texture channel
 -                       * set "Face Textures [Alpha]" Material options
 -                       * actually we need to run it always, because of old behavior
 -                       * of using face texture if any texture channel was present (multitex) */
 -                      //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
 -                      set_facetexture_flags(mat_new, tf->tpage);
 -
 -                      /* set the material number to the face*/
 -                      mf->mat_nr = mat_nr;
 -              }
 -              /* remove material from mesh */
 -              for (a = 0; a < me->totcol; ) {
 -                      if (me->mat[a] == ma) {
 -                              BKE_material_pop_id(bmain, &me->id, a, true);
 -                      }
 -                      else {
 -                              a++;
 -                      }
 -              }
 -      }
 -}
 -
 -
 -#define MAT_BGE_DISPUTED -99999
 -
 -int do_version_tface(Main *main)
 +void BKE_material_eval(struct Depsgraph *depsgraph, Material *material)
  {
 -      Mesh *me;
 -      Material *ma;
 -      MFace *mf;
 -      MTFace *tf;
 -      CustomDataLayer *cdl;
 -      int a;
 -      int flag;
 -      int index;
 -
 -      /* Operator in help menu has been removed for 2.7x */
 -      int fileload = 1;
 -
 -      /* sometimes mesh has no materials but will need a new one. In those
 -       * cases we need to ignore the mf->mat_nr and only look at the face
 -       * mode because it can be zero as uninitialized or the 1st created material
 -       */
 -      int nomaterialslots;
 -
 -      /* alert to user to check the console */
 -      int nowarning = 1;
 -
 -      /* mark all the materials to conversion with a flag
 -       * if there is tface create a complete flag for that storing in flag
 -       * if there is tface and flag > 0: creates a new flag based on this face
 -       * if flags are different set flag to -1
 -       */
 -
 -      /* 1st part: marking mesh materials to update */
 -      for (me = main->mesh.first; me; me = me->id.next) {
 -              if (ID_IS_LINKED(me)) continue;
 -
 -              /* get the active tface layer */
 -              index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
 -              cdl = (index == -1) ? NULL : &me->fdata.layers[index];
 -              if (!cdl) continue;
 -
 -              nomaterialslots = (me->totcol == 0 ? 1 : 0);
 -
 -              /* loop over all the faces*/
 -              for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
 -                      /* texface data for this face */
 -                      tf = ((MTFace *)cdl->data) + a;
 -
 -                      /* conversion should happen only once */
 -                      if (fileload)
 -                              tf->mode &= ~TF_CONVERTED;
 -                      else {
 -                              if ((tf->mode & TF_CONVERTED)) continue;
 -                              else tf->mode |= TF_CONVERTED;
 -                      }
 -
 -                      /* no material slots */
 -                      if (nomaterialslots) {
 -                              flag = encode_tfaceflag(tf, 1);
 -
 -                              /* create/find a new material and assign to the face */
 -                              if (check_tfaceneedmaterial(flag)) {
 -                                      mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
 -                              }
 -                              /* else mark them as no-material to be reverted to 0 later */
 -                              else {
 -                                      mf->mat_nr = -1;
 -                              }
 -                      }
 -                      else if (mf->mat_nr < me->totcol) {
 -                              ma = me->mat[mf->mat_nr];
 -
 -                              /* no material create one if necessary */
 -                              if (!ma) {
 -                                      /* find a new material and assign to the face */
 -                                      flag = encode_tfaceflag(tf, 1);
 -
 -                                      /* create/find a new material and assign to the face */
 -                                      if (check_tfaceneedmaterial(flag))
 -                                              mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
 -
 -                                      continue;
 -                              }
 -
 -                              /* we can't read from this if it comes from a library,
 -                               * at doversion time: direct_link might not have happened on it,
 -                               * so ma->mtex is not pointing to valid memory yet.
 -                               * later we could, but it's better not */
 -                              else if (ID_IS_LINKED(ma))
 -                                      continue;
 -
 -                              /* material already marked as disputed */
 -                              else if (ma->game.flag == MAT_BGE_DISPUTED)
 -                                      continue;
 -
 -                              /* found a material */
 -                              else {
 -                                      flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
 -
 -                                      /* first time changing this material */
 -                                      if (ma->game.flag == 0)
 -                                              ma->game.flag = -flag;
 -
 -                                      /* mark material as disputed */
 -                                      else if (ma->game.flag != -flag) {
 -                                              ma->game.flag = MAT_BGE_DISPUTED;
 -                                              continue;
 -                                      }
 -
 -                                      /* material ok so far */
 -                                      else {
 -                                              ma->game.flag = -flag;
 -
 -                                              /* some people uses multitexture with TexFace by creating a texture
 -                                               * channel which not necessarily the tf->tpage image. But the game engine
 -                                               * was enabling it. Now it's required to set "Face Texture [Alpha] in the
 -                                               * material settings. */
 -                                              if (!fileload)
 -                                                      set_facetexture_flags(ma, tf->tpage);
 -                                      }
 -                              }
 -                      }
 -                      else {
 -                              continue;
 -                      }
 -              }
 -
 -              /* if we didn't have material slot and now we do, we need to
 -               * make sure the materials are correct */
 -              if (nomaterialslots) {
 -                      if (me->totcol > 0) {
 -                              for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
 -                                      if (mf->mat_nr == -1) {
 -                                              /* texface data for this face */
 -                                              tf = ((MTFace *)cdl->data) + a;
 -                                              mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
 -                                      }
 -                              }
 -                      }
 -                      else {
 -                              for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
 -                                      mf->mat_nr = 0;
 -                              }
 -                      }
 -              }
 -
 -      }
 -
 -      /* 2nd part - conversion */
 -      /* skip library files */
 -
 -      /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
 -      for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
 -              if (ID_IS_LINKED(ma)) continue;
 -
 -              /* disputed material */
 -              if (ma->game.flag == MAT_BGE_DISPUTED) {
 -                      ma->game.flag = 0;
 -                      if (fileload) {
 -                              printf("Warning: material \"%s\" skipped.\n", ma->id.name + 2);
 -                              nowarning = 0;
 -                      }
 -                      else {
 -                              convert_tfacematerial(main, ma);
 -                      }
 -                      continue;
 -              }
 -
 -              /* no conflicts in this material - 90% of cases
 -               * convert from tface system to material */
 -              else if (ma->game.flag < 0) {
 -                      decode_tfaceflag(ma, -(ma->game.flag), 1);
 -
 -                      /* material is good make sure all faces using
 -                       * this material are set to converted */
 -                      if (fileload) {
 -                              for (me = main->mesh.first; me; me = me->id.next) {
 -                                      /* check if this mesh uses this material */
 -                                      for (a = 0; a < me->totcol; a++)
 -                                              if (me->mat[a] == ma) break;
 -
 -                                      /* no material found */
 -                                      if (a == me->totcol) continue;
 -
 -                                      /* get the active tface layer */
 -                                      index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
 -                                      cdl = (index == -1) ? NULL : &me->fdata.layers[index];
 -                                      if (!cdl) continue;
 -
 -                                      /* loop over all the faces and stop at the ones that use the material*/
 -                                      for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
 -                                              if (me->mat[mf->mat_nr] == ma) {
 -                                                      /* texface data for this face */
 -                                                      tf = ((MTFace *)cdl->data) + a;
 -                                                      tf->mode |= TF_CONVERTED;
 -                                              }
 -                                      }
 -                              }
 -                      }
 -              }
 -              /* material is not used by faces with texface
 -               * set the default flag - do it only once */
 -              else {
 -                      if (fileload) {
 -                              ma->game.flag = GEMAT_BACKCULL;
 -                      }
 -              }
 -      }
 -
 -      return nowarning;
 +      DEG_debug_print_eval(depsgraph, __func__, material->id.name, material);
 +      GPU_material_free(&material->gpumaterial);
  }
@@@ -33,7 -33,6 +33,7 @@@
  
  #include "DNA_curve_types.h"
  #include "DNA_lamp_types.h"
 +#include "DNA_lightprobe_types.h"
  #include "DNA_material_types.h"
  #include "DNA_node_types.h"
  #include "DNA_object_types.h"
  #include "BKE_animsys.h"
  #include "BKE_context.h"
  #include "BKE_curve.h"
 -#include "BKE_depsgraph.h"
 +#include "BKE_editmesh.h"
  #include "BKE_font.h"
  #include "BKE_global.h"
  #include "BKE_image.h"
 +#include "BKE_layer.h"
  #include "BKE_library.h"
  #include "BKE_linestyle.h"
  #include "BKE_main.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_texture.h"
 +#include "BKE_workspace.h"
  #include "BKE_world.h"
 -#include "BKE_editmesh.h"
 -
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
  
  #ifdef WITH_FREESTYLE
  #  include "BKE_freestyle.h"
@@@ -86,7 -83,6 +86,7 @@@
  #include "ED_mesh.h"
  #include "ED_node.h"
  #include "ED_render.h"
 +#include "ED_scene.h"
  #include "ED_screen.h"
  
  #include "RNA_define.h"
  
  #include "RE_pipeline.h"
  
 +#include "engines/eevee/eevee_lightcache.h"
 +
  #include "render_intern.h"  // own include
  
 +/**
 + * Object list for material operations.
 + * has exception for pinned object.
 + */
 +static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
 +{
 +      ScrArea *sa = CTX_wm_area(C);
 +      SpaceButs *sbuts = NULL;
 +      View3D *v3d = NULL;
 +      if (sa->spacetype == SPACE_BUTS) {
 +              sbuts = sa->spacedata.first;
 +      }
 +      else if (sa->spacetype == SPACE_VIEW3D) {
 +              v3d = sa->spacedata.first;
 +      }
 +
 +      Object **objects;
 +      if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
 +              objects = MEM_mallocN(sizeof(*objects), __func__);
 +              objects[0] = (Object *)sbuts->pinid;
 +              *r_objects_len = 1;
 +      }
 +      else {
 +              ViewLayer *view_layer = CTX_data_view_layer(C);
 +              objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_objects_len);
 +      }
 +      return objects;
 +}
 +
  /********************** material slot operators *********************/
  
  static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
@@@ -189,7 -154,7 +189,7 @@@ static int material_slot_remove_exec(bC
                WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
        }
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
        WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
@@@ -214,17 -179,12 +214,17 @@@ void OBJECT_OT_material_slot_remove(wmO
  
  static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      Object *ob = ED_object_context(C);
 -
 -      if (!ob)
 -              return OPERATOR_CANCELLED;
 +      View3D *v3d = CTX_wm_view3d(C);
 +      bool changed_multi = false;
  
 -      if (ob && ob->actcol > 0) {
 +      uint objects_len = 0;
 +      Object **objects = object_array_for_shading(C, &objects_len);
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              Object *ob = objects[ob_index];
 +              if (ob->actcol <= 0) {
 +                      continue;
 +              }
 +              bool changed = false;
                if (ob->type == OB_MESH) {
                        BMEditMesh *em = BKE_editmesh_from_object(ob);
                        BMFace *efa;
  
                        if (em) {
                                BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
 -                                      if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
 +                                      if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
 +                                              changed = true;
                                                efa->mat_nr = ob->actcol - 1;
 +                                      }
                                }
                        }
                }
  
                        if (nurbs) {
                                for (nu = nurbs->first; nu; nu = nu->next) {
 -                                      if (ED_curve_nurb_select_check(ob->data, nu)) {
 +                                      if (ED_curve_nurb_select_check(v3d, nu)) {
 +                                              changed = true;
                                                nu->mat_nr = ob->actcol - 1;
                                        }
                                }
                        int i, selstart, selend;
  
                        if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) {
 -                              for (i = selstart; i <= selend; i++)
 +                              for (i = selstart; i <= selend; i++) {
 +                                      changed = true;
                                        ef->textbufinfo[i].mat_nr = ob->actcol;
 +                              }
                        }
                }
 -      }
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 -      WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
 +              if (changed) {
 +                      changed_multi = true;
 +                      DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
 +                      WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
 +              }
 +      }
 +      MEM_freeN(objects);
  
 -      return OPERATOR_FINISHED;
 +      return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
  }
  
  void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
  
  static int material_slot_de_select(bContext *C, bool select)
  {
 -      Object *ob = ED_object_context(C);
 +      bool changed_multi = false;
  
 -      if (!ob)
 -              return OPERATOR_CANCELLED;
 +      uint objects_len = 0;
 +      Object **objects = object_array_for_shading(C, &objects_len);
 +      for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
 +              Object *ob = objects[ob_index];
 +              bool changed = false;
  
 -      if (ob->type == OB_MESH) {
 -              BMEditMesh *em = BKE_editmesh_from_object(ob);
 +              if (ob->type == OB_MESH) {
 +                      BMEditMesh *em = BKE_editmesh_from_object(ob);
  
 -              if (em) {
 -                      EDBM_deselect_by_material(em, ob->actcol - 1, select);
 +                      if (em) {
 +                              changed = EDBM_deselect_by_material(em, ob->actcol - 1, select);
 +                      }
                }
 -      }
 -      else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
 -              ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
 -              Nurb *nu;
 -              BPoint *bp;
 -              BezTriple *bezt;
 -              int a;
 -
 -              if (nurbs) {
 -                      for (nu = nurbs->first; nu; nu = nu->next) {
 -                              if (nu->mat_nr == ob->actcol - 1) {
 -                                      if (nu->bezt) {
 -                                              a = nu->pntsu;
 -                                              bezt = nu->bezt;
 -                                              while (a--) {
 -                                                      if (bezt->hide == 0) {
 -                                                              if (select) {
 -                                                                      bezt->f1 |= SELECT;
 -                                                                      bezt->f2 |= SELECT;
 -                                                                      bezt->f3 |= SELECT;
 -                                                              }
 -                                                              else {
 -                                                                      bezt->f1 &= ~SELECT;
 -                                                                      bezt->f2 &= ~SELECT;
 -                                                                      bezt->f3 &= ~SELECT;
 +              else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
 +                      ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data);
 +                      Nurb *nu;
 +                      BPoint *bp;
 +                      BezTriple *bezt;
 +                      int a;
 +
 +                      if (nurbs) {
 +                              for (nu = nurbs->first; nu; nu = nu->next) {
 +                                      if (nu->mat_nr == ob->actcol - 1) {
 +                                              if (nu->bezt) {
 +                                                      a = nu->pntsu;
 +                                                      bezt = nu->bezt;
 +                                                      while (a--) {
 +                                                              if (bezt->hide == 0) {
 +                                                                      changed = true;
 +                                                                      if (select) {
 +                                                                              bezt->f1 |= SELECT;
 +                                                                              bezt->f2 |= SELECT;
 +                                                                              bezt->f3 |= SELECT;
 +                                                                      }
 +                                                                      else {
 +                                                                              bezt->f1 &= ~SELECT;
 +                                                                              bezt->f2 &= ~SELECT;
 +                                                                              bezt->f3 &= ~SELECT;
 +                                                                      }
                                                                }
 +                                                              bezt++;
                                                        }
 -                                                      bezt++;
                                                }
 -                                      }
 -                                      else if (nu->bp) {
 -                                              a = nu->pntsu * nu->pntsv;
 -                                              bp = nu->bp;
 -                                              while (a--) {
 -                                                      if (bp->hide == 0) {
 -                                                              if (select) bp->f1 |= SELECT;
 -                                                              else bp->f1 &= ~SELECT;
 +                                              else if (nu->bp) {
 +                                                      a = nu->pntsu * nu->pntsv;
 +                                                      bp = nu->bp;
 +                                                      while (a--) {
 +                                                              if (bp->hide == 0) {
 +                                                                      changed = true;
 +                                                                      if (select) bp->f1 |= SELECT;
 +                                                                      else bp->f1 &= ~SELECT;
 +                                                              }
 +                                                              bp++;
                                                        }
 -                                                      bp++;
                                                }
                                        }
                                }
                        }
                }
 +
 +              if (changed) {
 +                      changed_multi = true;
 +                      DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
 +                      WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
 +              }
        }
  
 -      WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
 +      MEM_freeN(objects);
  
 -      return OPERATOR_FINISHED;
 +      return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
  }
  
  static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op))
@@@ -422,7 -361,7 +422,7 @@@ static int material_slot_copy_exec(bCon
  
                        if (ob_iter->totcol == ob->totcol) {
                                ob_iter->actcol = ob->actcol;
 -                              DAG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
 +                              DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
                                WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
                        }
                }
  void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "Copy Material to Others";
 +      ot->name = "Copy Material to Selected";
        ot->idname = "OBJECT_OT_material_slot_copy";
 -      ot->description = "Copies materials to other selected objects";
 +      ot->description = "Copy material to selected objects";
  
        /* api callbacks */
        ot->exec = material_slot_copy_exec;
@@@ -487,7 -426,7 +487,7 @@@ static int material_slot_move_exec(bCon
  
        MEM_freeN(slot_remap);
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
  
@@@ -521,9 -460,9 +521,8 @@@ void OBJECT_OT_material_slot_move(wmOpe
  
  static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      Scene *scene = CTX_data_scene(C);
        Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
        Main *bmain = CTX_data_main(C);
-       Object *ob = CTX_data_active_object(C);
        PointerRNA ptr, idptr;
        PropertyRNA *prop;
  
                ma = BKE_material_copy(bmain, ma);
        }
        else {
 -              ma = BKE_material_add(bmain, DATA_("Material"));
 -
 -              if (BKE_scene_use_new_shading_nodes(scene)) {
 -                      ED_node_shader_default(C, &ma->id);
 -                      ma->use_nodes = true;
++              Object *ob = CTX_data_active_object(C);
 +              if ((!ob) || (ob->type != OB_GPENCIL)) {
 +                      ma = BKE_material_add(bmain, DATA_("Material"));
 +              }
 +              else {
 +                      ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
                }
 +              ED_node_shader_default(C, &ma->id);
 +              ma->use_nodes = true;
        }
  
        /* hook into UI */
        UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
  
        if (prop) {
+               if (RNA_struct_is_a(ptr.type, &RNA_Object)) {
+                       /* Add slot follows user-preferences for creating new slots,
+                        * RNA pointer assignment doesn't, see: T60014. */
+                       Object *ob = ptr.data;
+                       if (give_current_material_p(ob, ob->actcol) == NULL) {
+                               BKE_object_material_slot_add(bmain, ob);
+                       }
+               }
                /* when creating new ID blocks, use is already 1, but RNA
                 * pointer use also increases user, so this compensates it */
                id_us_min(&ma->id);
@@@ -599,6 -545,14 +608,6 @@@ static int new_texture_exec(bContext *C
                 * pointer use also increases user, so this compensates it */
                id_us_min(&tex->id);
  
 -              if (ptr.id.data && GS(((ID *)ptr.id.data)->name) == ID_MA &&
 -                  RNA_property_pointer_get(&ptr, prop).id.data == NULL)
 -              {
 -                      /* In case we are assigning new texture to a material, and active slot was empty, reset 'use' flag. */
 -                      Material *ma = (Material *)ptr.id.data;
 -                      ma->septex &= ~(1 << ma->texact);
 -              }
 -
                RNA_id_pointer_create(&tex->id, &idptr);
                RNA_property_pointer_set(&ptr, prop, idptr);
                RNA_property_update(C, &ptr, prop);
@@@ -627,6 -581,7 +636,6 @@@ void TEXTURE_OT_new(wmOperatorType *ot
  
  static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      Scene *scene = CTX_data_scene(C);
        World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
        Main *bmain = CTX_data_main(C);
        PointerRNA ptr, idptr;
        }
        else {
                wo = BKE_world_add(bmain, DATA_("World"));
 -
 -              if (BKE_scene_use_new_shading_nodes(scene)) {
 -                      ED_node_shader_default(C, &wo->id);
 -                      wo->use_nodes = true;
 -              }
 +              ED_node_shader_default(C, &wo->id);
 +              wo->use_nodes = true;
        }
  
        /* hook into UI */
@@@ -676,248 -634,61 +685,248 @@@ void WORLD_OT_new(wmOperatorType *ot
  
  /********************** render layer operators *********************/
  
 -static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
 +static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      wmWindow *win = CTX_wm_window(C);
        Scene *scene = CTX_data_scene(C);
 +      ViewLayer *view_layer = BKE_view_layer_add(scene, NULL);
  
 -      BKE_scene_add_render_layer(scene, NULL);
 -      scene->r.actlay = BLI_listbase_count(&scene->r.layers) - 1;
 +      if (win) {
 +              WM_window_set_active_view_layer(win, view_layer);
 +      }
  
 -      DAG_id_tag_update(&scene->id, 0);
 -      WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
 +      DEG_id_tag_update(&scene->id, 0);
 +      DEG_relations_tag_update(CTX_data_main(C));
 +      WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
  
        return OPERATOR_FINISHED;
  }
  
 -void SCENE_OT_render_layer_add(wmOperatorType *ot)
 +void SCENE_OT_view_layer_add(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "Add Render Layer";
 -      ot->idname = "SCENE_OT_render_layer_add";
 -      ot->description = "Add a render layer";
 +      ot->name = "Add View Layer";
 +      ot->idname = "SCENE_OT_view_layer_add";
 +      ot->description = "Add a view layer";
  
        /* api callbacks */
 -      ot->exec = render_layer_add_exec;
 +      ot->exec = view_layer_add_exec;
  
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
  }
  
 -static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
 +static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl))
 +      if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
                return OPERATOR_CANCELLED;
 +      }
  
 -      DAG_id_tag_update(&scene->id, 0);
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
        return OPERATOR_FINISHED;
  }
  
 -void SCENE_OT_render_layer_remove(wmOperatorType *ot)
 +void SCENE_OT_view_layer_remove(wmOperatorType *ot)
  {
        /* identifiers */
 -      ot->name = "Remove Render Layer";
 -      ot->idname = "SCENE_OT_render_layer_remove";
 -      ot->description = "Remove the selected render layer";
 +      ot->name = "Remove View Layer";
 +      ot->idname = "SCENE_OT_view_layer_remove";
 +      ot->description = "Remove the selected view layer";
  
        /* api callbacks */
 -      ot->exec = render_layer_remove_exec;
 +      ot->exec = view_layer_remove_exec;
  
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
  }
  
 +/********************** light cache operators *********************/
 +enum {
 +      LIGHTCACHE_SUBSET_ALL = 0,
 +      LIGHTCACHE_SUBSET_DIRTY,
 +      LIGHTCACHE_SUBSET_CUBE,
 +};
 +
 +static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op)
 +{
 +      if (scene->eevee.light_cache != NULL) {
 +              int subset = RNA_enum_get(op->ptr, "subset");
 +              switch (subset) {
 +                      case LIGHTCACHE_SUBSET_ALL:
 +                              scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE;
 +                              break;
 +                      case LIGHTCACHE_SUBSET_CUBE:
 +                              scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE;
 +                              break;
 +                      case LIGHTCACHE_SUBSET_DIRTY:
 +                              /* Leave tag untouched. */
 +                              break;
 +              }
 +      }
 +}
 +
 +/* catch esc */
 +static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event)
 +{
 +      Scene *scene = (Scene *) op->customdata;
 +
 +      /* no running blender, remove handler and pass through */
 +      if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) {
 +              return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
 +      }
 +
 +      /* running render */
 +      switch (event->type) {
 +              case ESCKEY:
 +                      return OPERATOR_RUNNING_MODAL;
 +      }
 +      return OPERATOR_PASS_THROUGH;
 +}
 +
 +static void light_cache_bake_cancel(bContext *C, wmOperator *op)
 +{
 +      wmWindowManager *wm = CTX_wm_manager(C);
 +      Scene *scene = (Scene *) op->customdata;
 +
 +      /* kill on cancel, because job is using op->reports */
 +      WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
 +}
 +
 +/* executes blocking render */
 +static int light_cache_bake_exec(bContext *C, wmOperator *op)
 +{
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Main *bmain = CTX_data_main(C);
 +      Scene *scene = CTX_data_scene(C);
 +
 +      G.is_break = false;
 +
 +      /* TODO abort if selected engine is not eevee. */
 +      void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false);
 +
 +      light_cache_bake_tag_cache(scene, op);
 +
 +      short stop = 0, do_update; float progress; /* Not actually used. */
 +      EEVEE_lightbake_job(rj, &stop, &do_update, &progress);
 +      EEVEE_lightbake_job_data_free(rj);
 +
 +      // no redraw needed, we leave state as we entered it
 +      ED_update_for_newframe(bmain, CTX_data_depsgraph(C));
 +
 +      WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 +{
 +      wmWindowManager *wm = CTX_wm_manager(C);
 +      wmWindow *win = CTX_wm_window(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Main *bmain = CTX_data_main(C);
 +      Scene *scene = CTX_data_scene(C);
 +      int delay = RNA_int_get(op->ptr, "delay");
 +
 +      wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay);
 +
 +      if (!wm_job) {
 +              return OPERATOR_CANCELLED;
 +      }
 +
 +      /* add modal handler for ESC */
 +      WM_event_add_modal_handler(C, op);
 +
 +      light_cache_bake_tag_cache(scene, op);
 +
 +      /* store actual owner of job, so modal operator could check for it,
 +       * the reason of this is that active scene could change when rendering
 +       * several layers from compositor [#31800]
 +       */
 +      op->customdata = scene;
 +
 +      WM_jobs_start(wm, wm_job);
 +
 +      WM_cursor_wait(0);
 +
 +      return OPERATOR_RUNNING_MODAL;
 +}
 +
 +void SCENE_OT_light_cache_bake(wmOperatorType *ot)
 +{
 +      static const EnumPropertyItem light_cache_subset_items[] = {
 +              {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes", "Bake both irradiance grids and reflection cubemaps"},
 +              {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only", "Only bake lightprobes that are marked as dirty"},
 +              {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only", "Try to only bake reflection cubemaps if irradiance "
 +                                                                   "grids are up to date"},
 +              {0, NULL, 0, NULL, NULL}
 +      };
 +
 +      /* identifiers */
 +      ot->name = "Bake Light Cache";
 +      ot->idname = "SCENE_OT_light_cache_bake";
 +      ot->description = "Bake the active view layer lighting";
 +
 +      /* api callbacks */
 +      ot->invoke = light_cache_bake_invoke;
 +      ot->modal = light_cache_bake_modal;
 +      ot->cancel = light_cache_bake_cancel;
 +      ot->exec = light_cache_bake_exec;
 +
 +      ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000);
 +      RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
 +
 +      ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update");
 +      RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
 +}
 +
 +static bool light_cache_free_poll(bContext *C)
 +{
 +      Scene *scene = CTX_data_scene(C);
 +
 +      return scene->eevee.light_cache;
 +}
 +
 +static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op))
 +{
 +      Scene *scene = CTX_data_scene(C);
 +
 +      /* kill potential bake job first (see T57011) */
 +      wmWindowManager *wm = CTX_wm_manager(C);
 +      WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE);
 +
 +      if (!scene->eevee.light_cache) {
 +              return OPERATOR_CANCELLED;
 +      }
 +
 +      EEVEE_lightcache_free(scene->eevee.light_cache);
 +      scene->eevee.light_cache = NULL;
 +
 +      EEVEE_lightcache_info_update(&scene->eevee);
 +
 +      DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
 +
 +      WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +void SCENE_OT_light_cache_free(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name = "Free Light Cache";
 +      ot->idname = "SCENE_OT_light_cache_free";
 +      ot->description = "Free cached indirect lighting";
 +
 +      /* api callbacks */
 +      ot->exec = light_cache_free_exec;
 +      ot->poll = light_cache_free_poll;
 +}
 +
  /********************** render view operators *********************/
  
  static bool render_view_remove_poll(bContext *C)
@@@ -1009,9 -780,9 +1018,9 @@@ static bool freestyle_active_module_pol
  static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      BKE_freestyle_module_add(&srl->freestyleConfig);
 +      BKE_freestyle_module_add(&view_layer->freestyle_config);
  
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
@@@ -1035,13 -806,13 +1044,13 @@@ void SCENE_OT_freestyle_module_add(wmOp
  static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
        FreestyleModuleConfig *module = ptr.data;
  
 -      BKE_freestyle_module_delete(&srl->freestyleConfig, module);
 +      BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
  
 -      DAG_id_tag_update(&scene->id, 0);
 +      DEG_id_tag_update(&scene->id, 0);
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
        return OPERATOR_FINISHED;
@@@ -1065,13 -836,13 +1074,13 @@@ void SCENE_OT_freestyle_module_remove(w
  static int freestyle_module_move_exec(bContext *C, wmOperator *op)
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
        FreestyleModuleConfig *module = ptr.data;
        int dir = RNA_enum_get(op->ptr, "direction");
  
 -      if (BKE_freestyle_module_move(&srl->freestyleConfig, module, dir)) {
 -              DAG_id_tag_update(&scene->id, 0);
 +      if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
 +              DEG_id_tag_update(&scene->id, 0);
                WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
        }
  
@@@ -1107,11 -878,11 +1116,11 @@@ static int freestyle_lineset_add_exec(b
  {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      BKE_freestyle_lineset_add(bmain, &srl->freestyleConfig, NULL);
 +      BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
  
 -      DAG_id_tag_update(&scene->id, 0);
 +      DEG_id_tag_update(&scene->id, 0);
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
        return OPERATOR_FINISHED;
@@@ -1133,20 -904,22 +1142,20 @@@ void SCENE_OT_freestyle_lineset_add(wmO
  
  static bool freestyle_active_lineset_poll(bContext *C)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      if (!srl) {
 +      if (!view_layer) {
                return false;
        }
  
 -      return BKE_freestyle_lineset_get_active(&srl->freestyleConfig) != NULL;
 +      return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
  }
  
  static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      FRS_copy_active_lineset(&srl->freestyleConfig);
 +      FRS_copy_active_lineset(&view_layer->freestyle_config);
  
        return OPERATOR_FINISHED;
  }
@@@ -1169,11 -942,11 +1178,11 @@@ void SCENE_OT_freestyle_lineset_copy(wm
  static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      FRS_paste_active_lineset(&srl->freestyleConfig);
 +      FRS_paste_active_lineset(&view_layer->freestyle_config);
  
 -      DAG_id_tag_update(&scene->id, 0);
 +      DEG_id_tag_update(&scene->id, 0);
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
        return OPERATOR_FINISHED;
@@@ -1197,11 -970,11 +1206,11 @@@ void SCENE_OT_freestyle_lineset_paste(w
  static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
  
 -      FRS_delete_active_lineset(&srl->freestyleConfig);
 +      FRS_delete_active_lineset(&view_layer->freestyle_config);
  
 -      DAG_id_tag_update(&scene->id, 0);
 +      DEG_id_tag_update(&scene->id, 0);
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
  
        return OPERATOR_FINISHED;
@@@ -1225,11 -998,11 +1234,11 @@@ void SCENE_OT_freestyle_lineset_remove(
  static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
  {
        Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        int dir = RNA_enum_get(op->ptr, "direction");
  
 -      if (FRS_move_active_lineset(&srl->freestyleConfig, dir)) {
 -              DAG_id_tag_update(&scene->id, 0);
 +      if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
 +              DEG_id_tag_update(&scene->id, 0);
                WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
        }
  
@@@ -1264,8 -1037,9 +1273,8 @@@ void SCENE_OT_freestyle_lineset_move(wm
  static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
  {
        Main *bmain = CTX_data_main(C);
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
  
        if (!lineset) {
                BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
        else {
                lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1301,8 -1075,9 +1310,8 @@@ void SCENE_OT_freestyle_linestyle_new(w
  
  static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        int type = RNA_enum_get(op->ptr, "type");
  
        if (!freestyle_linestyle_check_report(lineset, op->reports)) {
                BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
                return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1340,8 -1115,9 +1349,8 @@@ void SCENE_OT_freestyle_color_modifier_
  
  static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        int type = RNA_enum_get(op->ptr, "type");
  
        if (!freestyle_linestyle_check_report(lineset, op->reports)) {
                BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
                return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1379,8 -1155,9 +1388,8 @@@ void SCENE_OT_freestyle_alpha_modifier_
  
  static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        int type = RNA_enum_get(op->ptr, "type");
  
        if (!freestyle_linestyle_check_report(lineset, op->reports)) {
                BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
                return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1418,8 -1195,9 +1427,8 @@@ void SCENE_OT_freestyle_thickness_modif
  
  static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        int type = RNA_enum_get(op->ptr, "type");
  
        if (!freestyle_linestyle_check_report(lineset, op->reports)) {
                BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
                return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1470,8 -1248,9 +1479,8 @@@ static int freestyle_get_modifier_type(
  
  static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
        LineStyleModifier *modifier = ptr.data;
  
                        BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
                        return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1519,8 -1298,9 +1528,8 @@@ void SCENE_OT_freestyle_modifier_remove
  
  static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
        LineStyleModifier *modifier = ptr.data;
  
                        BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
                        return OPERATOR_CANCELLED;
        }
 -      DAG_id_tag_update(&lineset->linestyle->id, 0);
 +      DEG_id_tag_update(&lineset->linestyle->id, 0);
        WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
  
        return OPERATOR_FINISHED;
@@@ -1568,8 -1348,9 +1577,8 @@@ void SCENE_OT_freestyle_modifier_copy(w
  
  static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
  {
 -      Scene *scene = CTX_data_scene(C);
 -      SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
 -      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
        LineStyleModifier *modifier = ptr.data;
        int dir = RNA_enum_get(op->ptr, "direction");
        }
  
        if (changed) {
 -              DAG_id_tag_update(&lineset->linestyle->id, 0);
 +              DEG_id_tag_update(&lineset->linestyle->id, 0);
                WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
        }
  
@@@ -1633,8 -1414,8 +1642,8 @@@ void SCENE_OT_freestyle_modifier_move(w
  static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op)
  {
        Main *bmain = CTX_data_main(C);
 -      Scene *scene = CTX_data_scene(C);
 -      FreestyleLineStyle *linestyle = BKE_linestyle_active_from_scene(scene);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer);
  
        if (!linestyle) {
                BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene");
@@@ -1684,6 -1465,15 +1693,6 @@@ static int texture_slot_move_exec(bCont
                                BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0);
                                BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
  
 -                              if (GS(id->name) == ID_MA) {
 -                                      Material *ma = (Material *)id;
 -                                      int mtexuse = ma->septex & (1 << act);
 -                                      ma->septex &= ~(1 << act);
 -                                      ma->septex |= (ma->septex & (1 << (act - 1))) << 1;
 -                                      ma->septex &= ~(1 << (act - 1));
 -                                      ma->septex |= mtexuse >> 1;
 -                              }
 -
                                set_active_mtex(id, act - 1);
                        }
                }
                                BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0);
                                BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0);
  
 -                              if (GS(id->name) == ID_MA) {
 -                                      Material *ma = (Material *)id;
 -                                      int mtexuse = ma->septex & (1 << act);
 -                                      ma->septex &= ~(1 << act);
 -                                      ma->septex |= (ma->septex & (1 << (act + 1))) >> 1;
 -                                      ma->septex &= ~(1 << (act + 1));
 -                                      ma->septex |= mtexuse << 1;
 -                              }
 -
                                set_active_mtex(id, act + 1);
                        }
                }
  
 -              DAG_id_tag_update(id, 0);
 +              DEG_id_tag_update(id, 0);
                WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
        }
  
@@@ -1732,6 -1531,181 +1741,6 @@@ void TEXTURE_OT_slot_move(wmOperatorTyp
  
  
  
 -/********************** environment map operators *********************/
 -
 -static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *path, const char imtype)
 -{
 -      PropertyRNA *prop;
 -      float layout[12];
 -
 -      if ((prop = RNA_struct_find_property(op->ptr, "layout"))) {
 -              RNA_property_float_get_array(op->ptr, prop, layout);
 -      }
 -      else {
 -              memcpy(layout, default_envmap_layout, sizeof(layout));
 -      }
 -
 -      if (RE_WriteEnvmapResult(op->reports, scene, env, path, imtype, layout)) {
 -              return OPERATOR_FINISHED;
 -      }
 -      else {
 -              return OPERATOR_CANCELLED;
 -      }
 -
 -}
 -
 -static int envmap_save_exec(bContext *C, wmOperator *op)
 -{
 -      Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
 -      Scene *scene = CTX_data_scene(C);
 -      //int imtype = RNA_enum_get(op->ptr, "file_type");
 -      char imtype = scene->r.im_format.imtype;
 -      char path[FILE_MAX];
 -
 -      RNA_string_get(op->ptr, "filepath", path);
 -
 -      if (scene->r.scemode & R_EXTENSION) {
 -              BKE_image_path_ensure_ext_from_imformat(path, &scene->r.im_format);
 -      }
 -
 -      WM_cursor_wait(1);
 -
 -      save_envmap(op, scene, tex->env, path, imtype);
 -
 -      WM_cursor_wait(0);
 -
 -      WM_event_add_notifier(C, NC_TEXTURE, tex);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -static int envmap_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 -{
 -      Main *bmain = CTX_data_main(C);
 -      //Scene *scene= CTX_data_scene(C);
 -
 -      if (RNA_struct_property_is_set(op->ptr, "filepath"))
 -              return envmap_save_exec(C, op);
 -
 -      //RNA_enum_set(op->ptr, "file_type", scene->r.im_format.imtype);
 -      RNA_string_set(op->ptr, "filepath", BKE_main_blendfile_path(bmain));
 -      WM_event_add_fileselect(C, op);
 -
 -      return OPERATOR_RUNNING_MODAL;
 -}
 -
 -static bool envmap_save_poll(bContext *C)
 -{
 -      Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
 -
 -      if (!tex)
 -              return 0;
 -      if (!tex->env || !tex->env->ok)
 -              return 0;
 -      if (tex->env->cube[1] == NULL)
 -              return 0;
 -
 -      return 1;
 -}
 -
 -void TEXTURE_OT_envmap_save(wmOperatorType *ot)
 -{
 -      PropertyRNA *prop;
 -      /* identifiers */
 -      ot->name = "Save Environment Map";
 -      ot->idname = "TEXTURE_OT_envmap_save";
 -      ot->description = "Save the current generated Environment map to an image file";
 -
 -      /* api callbacks */
 -      ot->exec = envmap_save_exec;
 -      ot->invoke = envmap_save_invoke;
 -      ot->poll = envmap_save_poll;
 -
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; /* no undo since this doesnt modify the env-map */
 -
 -      /* properties */
 -      prop = RNA_def_float_array(ot->srna, "layout", 12, default_envmap_layout, 0.0f, 0.0f,
 -                                 "File layout",
 -                                 "Flat array describing the X,Y position of each cube face in the output image, "
 -                                 "where 1 is the size of a face - order is [+Z -Z +Y -X -Y +X] "
 -                                 "(use -1 to skip a face)", 0.0f, 0.0f);
 -      RNA_def_property_flag(prop, PROP_HIDDEN);
 -
 -      WM_operator_properties_filesel(
 -              ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_SAVE,
 -              WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
 -}
 -
 -static int envmap_clear_exec(bContext *C, wmOperator *UNUSED(op))
 -{
 -      Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
 -
 -      BKE_texture_envmap_free_data(tex->env);
 -
 -      WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -static bool envmap_clear_poll(bContext *C)
 -{
 -      Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
 -
 -      if (!tex)
 -              return 0;
 -      if (!tex->env || !tex->env->ok)
 -              return 0;
 -      if (tex->env->cube[1] == NULL)
 -              return 0;
 -
 -      return 1;
 -}
 -
 -void TEXTURE_OT_envmap_clear(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Clear Environment Map";
 -      ot->idname = "TEXTURE_OT_envmap_clear";
 -      ot->description = "Discard the environment map and free it from memory";
 -
 -      /* api callbacks */
 -      ot->exec = envmap_clear_exec;
 -      ot->poll = envmap_clear_poll;
 -
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 -}
 -
 -static int envmap_clear_all_exec(bContext *C, wmOperator *UNUSED(op))
 -{
 -      Main *bmain = CTX_data_main(C);
 -      Tex *tex;
 -
 -      for (tex = bmain->tex.first; tex; tex = tex->id.next)
 -              if (tex->env)
 -                      BKE_texture_envmap_free_data(tex->env);
 -
 -      WM_event_add_notifier(C, NC_TEXTURE | NA_EDITED, tex);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void TEXTURE_OT_envmap_clear_all(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name = "Clear All Environment Maps";
 -      ot->idname = "TEXTURE_OT_envmap_clear_all";
 -      ot->description = "Discard all environment maps in the .blend file and free them from memory";
 -
 -      /* api callbacks */
 -      ot->exec = envmap_clear_all_exec;
 -      ot->poll = envmap_clear_poll;
 -
 -      /* flags */
 -      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 -}
 -
  /********************** material operators *********************/
  
  /* material copy/paste */
@@@ -1803,6 -1777,17 +1812,6 @@@ static void copy_mtex_copybuf(ID *id
        MTex **mtex = NULL;
  
        switch (GS(id->name)) {
 -              case ID_MA:
 -                      mtex = &(((Material *)id)->mtex[(int)((Material *)id)->texact]);
 -                      break;
 -              case ID_LA:
 -                      mtex = &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]);
 -                      // la->mtex[(int)la->texact] // TODO
 -                      break;
 -              case ID_WO:
 -                      mtex = &(((World *)id)->mtex[(int)((World *)id)->texact]);
 -                      // mtex= wrld->mtex[(int)wrld->texact]; // TODO
 -                      break;
                case ID_PA:
                        mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
                        break;
@@@ -1830,6 -1815,17 +1839,6 @@@ static void paste_mtex_copybuf(ID *id
                return;
  
        switch (GS(id->name)) {
 -              case ID_MA:
 -                      mtex = &(((Material *)id)->mtex[(int)((Material *)id)->texact]);
 -                      break;
 -              case ID_LA:
 -                      mtex = &(((Lamp *)id)->mtex[(int)((Lamp *)id)->texact]);
 -                      // la->mtex[(int)la->texact] // TODO
 -                      break;
 -              case ID_WO:
 -                      mtex = &(((World *)id)->mtex[(int)((World *)id)->texact]);
 -                      // mtex= wrld->mtex[(int)wrld->texact]; // TODO
 -                      break;
                case ID_PA:
                        mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
                        break;
@@@ -1899,7 -1895,7 +1908,7 @@@ static int paste_mtex_exec(bContext *C
  
        if (id == NULL) {
                Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
 -              Lamp *la = CTX_data_pointer_get_type(C, "lamp", &RNA_Lamp).data;
 +              Lamp *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data;
                World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
                ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
                FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;