[Bf-blender-cvs] [1a650fdcb28] master: Object: support removing unused material slots for selected objects

Campbell Barton noreply at git.blender.org
Sun Aug 30 05:50:44 CEST 2020


Commit: 1a650fdcb286ad3759c65a9952aa2e02966eba0b
Author: Campbell Barton
Date:   Sun Aug 30 13:33:35 2020 +1000
Branches: master
https://developer.blender.org/rB1a650fdcb286ad3759c65a9952aa2e02966eba0b

Object: support removing unused material slots for selected objects

This is useful to run in object-mode, instead of from the property editor,
note that this still only used the current object when activated from
the property editor.

===================================================================

M	source/blender/editors/render/render_shading.c

===================================================================

diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 3f31cbf7e48..078817e091a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -56,6 +56,7 @@
 #include "BKE_linestyle.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
@@ -95,42 +96,114 @@
 
 #include "render_intern.h"  // own include
 
+static bool object_materials_supported_poll_ex(bContext *C, const Object *ob);
+
 /* -------------------------------------------------------------------- */
 /** \name Local Utilities
  * \{ */
 
-/**
- * Object list for material operations.
- * has exception for pinned object.
- */
-static Object **object_array_for_shading(bContext *C, uint *r_objects_len)
-{
-  ScrArea *area = CTX_wm_area(C);
-  SpaceProperties *sbuts = NULL;
-  View3D *v3d = NULL;
-  if (area != NULL) {
-    if (area->spacetype == SPACE_PROPERTIES) {
-      sbuts = area->spacedata.first;
-    }
-    else if (area->spacetype == SPACE_VIEW3D) {
-      v3d = area->spacedata.first;
-    }
+static Object **object_array_for_shading_impl(bContext *C,
+                                              bool (*filter_fn)(struct Object *ob,
+                                                                void *user_data),
+                                              void *filter_user_data,
+                                              uint *r_objects_len)
+{
+  Object **objects;
+
+  Object *ob = NULL;
+  bool use_ob = true;
+  if (CTX_wm_space_properties(C)) {
+    /* May return pinned object. */
+    ob = ED_object_context(C);
+  }
+  else {
+    /* Otherwise use full selection. */
+    use_ob = false;
   }
 
-  Object **objects;
-  if (sbuts != NULL && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) {
-    objects = MEM_mallocN(sizeof(*objects), __func__);
-    objects[0] = (Object *)sbuts->pinid;
-    *r_objects_len = 1;
+  if (use_ob) {
+    if (!filter_fn(ob, filter_user_data)) {
+      ob = NULL;
+    }
+    *r_objects_len = (ob != NULL) ? 1 : 0;
+    objects = MEM_mallocN(sizeof(*objects) * *r_objects_len, __func__);
+    if (ob != NULL) {
+      objects[0] = ob;
+    }
   }
   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);
+    const View3D *v3d = CTX_wm_view3d(C); /* may be NULL. */
+    objects = BKE_view_layer_array_selected_objects_params(
+        view_layer,
+        v3d,
+        r_objects_len,
+        &((const struct ObjectsInViewLayerParams){
+            .no_dup_data = true,
+            .filter_fn = filter_fn,
+            .filter_userdata = filter_user_data,
+        }));
   }
   return objects;
 }
 
+static bool object_array_for_shading_edit_mode_enabled_filter(Object *ob, void *user_data)
+{
+  bContext *C = user_data;
+  if (object_materials_supported_poll_ex(C, ob)) {
+    if (BKE_object_is_in_editmode(ob) == true) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static Object **object_array_for_shading_edit_mode_enabled(bContext *C, uint *r_objects_len)
+{
+  return object_array_for_shading_impl(
+      C, object_array_for_shading_edit_mode_enabled_filter, C, r_objects_len);
+}
+
+static bool object_array_for_shading_edit_mode_disabled_filter(Object *ob, void *user_data)
+{
+  bContext *C = user_data;
+  if (object_materials_supported_poll_ex(C, ob)) {
+    if (BKE_object_is_in_editmode(ob) == false) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static Object **object_array_for_shading_edit_mode_disabled(bContext *C, uint *r_objects_len)
+{
+  return object_array_for_shading_impl(
+      C, object_array_for_shading_edit_mode_disabled_filter, C, r_objects_len);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Shared Operator Poll Functions
+ * \{ */
+
+static bool object_materials_supported_poll_ex(bContext *C, const Object *ob)
+{
+  if (!ED_operator_object_active_local_editable_ex(C, ob)) {
+    return false;
+  }
+  const ID *data = ob->data;
+  return (OB_TYPE_SUPPORT_MATERIAL(ob->type) &&
+          /* Object data checks. */
+          data && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
+}
+
+static bool object_materials_supported_poll(bContext *C)
+{
+  Object *ob = ED_object_context(C);
+  return object_materials_supported_poll_ex(C, ob);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -170,7 +243,7 @@ void OBJECT_OT_material_slot_add(wmOperatorType *ot)
 
   /* api callbacks */
   ot->exec = material_slot_add_exec;
-  ot->poll = ED_operator_object_active_local_editable;
+  ot->poll = object_materials_supported_poll;
 
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -221,7 +294,7 @@ void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
 
   /* api callbacks */
   ot->exec = material_slot_remove_exec;
-  ot->poll = ED_operator_object_active_local_editable;
+  ot->poll = object_materials_supported_poll;
 
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -242,7 +315,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
   const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : NULL;
 
   uint objects_len = 0;
-  Object **objects = object_array_for_shading(C, &objects_len);
+  Object **objects = object_array_for_shading_edit_mode_enabled(C, &objects_len);
   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
     Object *ob = objects[ob_index];
     short mat_nr_active = -1;
@@ -330,7 +403,7 @@ void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
 
   /* api callbacks */
   ot->exec = material_slot_assign_exec;
-  ot->poll = ED_operator_object_active_local_editable;
+  ot->poll = object_materials_supported_poll;
 
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -349,7 +422,7 @@ static int material_slot_de_select(bContext *C, bool select)
   const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : NULL;
 
   uint objects_len = 0;
-  Object **objects = object_array_for_shading(C, &objects_len);
+  Object **objects = object_array_for_shading_edit_mode_enabled(C, &objects_len);
   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
     Object *ob = objects[ob_index];
     short mat_nr_active = -1;
@@ -614,8 +687,8 @@ void OBJECT_OT_material_slot_move(wmOperatorType *ot)
   ot->description = "Move the active material up/down in the list";
 
   /* api callbacks */
-  ot->poll = ED_operator_object_active_local_editable;
   ot->exec = material_slot_move_exec;
+  ot->poll = object_materials_supported_poll;
 
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -636,35 +709,38 @@ void OBJECT_OT_material_slot_move(wmOperatorType *ot)
 
 static int material_slot_remove_unused_exec(bContext *C, wmOperator *op)
 {
-  Object *ob = CTX_data_active_object(C);
-
-  if (!ob) {
-    return OPERATOR_CANCELLED;
-  }
-
   /* Removing material slots in edit mode screws things up, see bug #21822.*/
-  if (ob == CTX_data_edit_object(C)) {
+  Object *ob_active = CTX_data_active_object(C);
+  if (ob_active && BKE_object_is_in_editmode(ob_active)) {
     BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
     return OPERATOR_CANCELLED;
   }
 
-  int actcol = ob->actcol;
-
+  Main *bmain = CTX_data_main(C);
   int removed = 0;
-  for (int slot = 1; slot <= ob->totcol; slot++) {
-    while (slot <= ob->totcol && !BKE_object_material_slot_used(ob->data, slot)) {
-      ob->actcol = slot;
-      BKE_object_material_slot_remove(CTX_data_main(C), ob);
 
-      if (actcol >= slot) {
-        actcol--;
-      }
+  uint objects_len = 0;
+  Object **objects = object_array_for_shading_edit_mode_disabled(C, &objects_len);
+  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+    Object *ob = objects[ob_index];
+    int actcol = ob->actcol;
+    for (int slot = 1; slot <= ob->totcol; slot++) {
+      while (slot <= ob->totcol && !BKE_object_material_slot_used(ob->data, slot)) {
+        ob->actcol = slot;
+        BKE_object_material_slot_remove(bmain, ob);
+
+        if (actcol >= slot) {
+          actcol--;
+        }
 
-      removed++;
+        removed++;
+      }
     }
-  }
+    ob->actcol = actcol;
 
-  ob->actcol = actcol;
+    DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+  }
+  MEM_freeN(objects);
 
   if (!removed) {
     return OPERATOR_CANCELLED;
@@ -672,16 +748,15 @@ static int material_slot_remove_unused_exec(bContext *C, wmOperator *op)
 
   BKE_reportf(op->reports, RPT_INFO, "Removed %d slots", removed);
 
-  if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+  if (ob_active->mode & OB_MODE_TEXTURE_PAINT) {
     Scene *scene = CTX_data_scene(C);
-    BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+    BKE_paint_proj_mesh_data_check(scene, ob_active, NULL, NULL, NULL, NULL);
     WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
   }
 
-  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);
+  WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_active);
+  WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob_active);
+  WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob_active);
 
   return OPERATOR_FINISHED;
 }
@@ -695,7 +770,7 @@ void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot)
 
   /* api callbacks */
   ot->exec = material_slot_remove_unused_exec;
-  ot->poll = ED_operator_object_active_local_editable;
+  ot->poll = object_materials_supported_poll;
 
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -768,8 +843,8 @@ void MATERIAL_OT_new(wmOperatorType *ot)
   ot->description = "Add a new material";
 
   /* api callbacks */
-  ot->poll = ED_operator_object_active_local_editable;
   ot->exec = new_material_exec;
+  ot->poll =

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list