Add material slot reorder buttons
authorGaia Clary <gaia.clary@machinimatrix.org>
Mon, 27 Apr 2015 21:24:56 +0000 (07:24 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 27 Apr 2015 21:30:04 +0000 (07:30 +1000)
release/scripts/startup/bl_ui/properties_material.py
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/editors/render/render_intern.h
source/blender/editors/render/render_ops.c
source/blender/editors/render/render_shading.c

index cea0c9aef9538191e0855172a7ade678e7bc5b57..79199400b63b8366be31c7e068919a3fd5490fd6 100644 (file)
@@ -123,11 +123,16 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
         ob = context.object
         slot = context.material_slot
         space = context.space_data
+        is_sortable = (len(ob.material_slots) > 1)
 
         if ob:
+            rows = 1
+            if is_sortable:
+                rows = 4
+
             row = layout.row()
 
-            row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1)
+            row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
 
             col = row.column(align=True)
             col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -135,6 +140,12 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
 
             col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
 
+            if is_sortable:
+                col.separator()
+
+                col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+                col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
             if ob.mode == 'EDIT':
                 row = layout.row(align=True)
                 row.operator("object.material_slot_assign", text="Assign")
index ec3c044726957c9238d62449020d33a70eecd7c7..98c85415812f2a7b2179742afdf8aea2a5409143 100644 (file)
@@ -90,6 +90,7 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys);
 void BKE_curve_material_index_remove(struct Curve *cu, int index);
 void BKE_curve_material_index_clear(struct Curve *cu);
 int BKE_curve_material_index_validate(struct Curve *cu);
+void BKE_curve_material_remap(struct Curve *cu,const unsigned int *remap, unsigned int remap_len);
 
 ListBase    *BKE_curve_nurbs_get(struct Curve *cu);
 
index 56393727d285283f9d64ed72123a5639b40c0cb6..0cfa1aeecb539ac8e2fb316ec40bc95be9f26528 100644 (file)
@@ -50,6 +50,7 @@ void BKE_material_free_ex(struct Material *ma, bool do_id_user);
 void test_object_materials(struct Main *bmain, struct ID *id);
 void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
 void init_material(struct Material *ma);
+void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
 struct Material *BKE_material_add(struct Main *bmain, const char *name);
 struct Material *BKE_material_copy(struct Material *ma);
 struct Material *localize_material(struct Material *ma);
index c0d8902eb71a095e23d8da8ad70562a24eda1686..ebf4384d5a7ab294163f67d26d1c4edaf16159c2 100644 (file)
@@ -108,6 +108,7 @@ void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblis
 void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
 void BKE_mesh_material_index_remove(struct Mesh *me, short index);
 void BKE_mesh_material_index_clear(struct Mesh *me);
+void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
 void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
 
 const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
index 5fcdc9c2e78a0cd67e970d07a179ac9bca5dec88..cd59e30a406b36a6e80a68df09bedbbaf23bf45f 100644 (file)
@@ -4492,6 +4492,54 @@ int BKE_curve_material_index_validate(Curve *cu)
        }
 }
 
+void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
+{
+       const int curvetype = BKE_curve_type_get(cu);
+       const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+       if (n < remap_len_short) { \
+               BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+               n = remap[n]; \
+       } ((void)0)
+
+       if (curvetype == OB_FONT) {
+               struct CharInfo *strinfo;
+               int charinfo_len, i;
+
+               if (cu->editfont) {
+                       EditFont *ef = cu->editfont;
+                       strinfo = ef->textbufinfo;
+                       charinfo_len = ef->len;
+               }
+               else {
+                       strinfo = cu->strinfo;
+                       charinfo_len = cu->len_wchar;
+               }
+
+               for (i = 0; i <= charinfo_len; i++) {
+                       if (strinfo[i].mat_nr > 0) {
+                               strinfo[i].mat_nr -= 1;
+                               MAT_NR_REMAP(strinfo[i].mat_nr);
+                               strinfo[i].mat_nr += 1;
+                       }
+               }
+       }
+       else {
+               Nurb *nu;
+               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+               if (nurbs) {
+                       for (nu = nurbs->first; nu; nu = nu->next) {
+                               MAT_NR_REMAP(nu->mat_nr);
+                       }
+               }
+       }
+
+#undef MAT_NR_REMAP
+
+}
+
 void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
 {
        r_rect->xmin = cu->xof + tb->x;
index c7e6b3ba1b3ebe5e3d407170c98ad52fea096363..8932ac1f4c61f2a8774132a11a4698a2ac0c26bc 100644 (file)
@@ -53,6 +53,7 @@
 #include "BLI_listbase.h"              
 #include "BLI_utildefines.h"
 #include "BLI_string.h"
+#include "BLI_array_utils.h"
 
 #include "BKE_animsys.h"
 #include "BKE_displist.h"
@@ -66,6 +67,8 @@
 #include "BKE_scene.h"
 #include "BKE_node.h"
 #include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_font.h"
 
 #include "GPU_material.h"
 
@@ -922,6 +925,35 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
        test_object_materials(G.main, ob->data);
 }
 
+
+void BKE_material_remap_object(Object *ob, const unsigned int *remap)
+{
+       Material ***matar = give_matarar(ob);
+       const short *totcol_p = give_totcolp(ob);
+
+       BLI_array_permute(ob->mat, ob->totcol, remap);
+
+       if (ob->matbits) {
+               BLI_array_permute(ob->matbits, ob->totcol, remap);
+       }
+
+       if(matar) {
+               BLI_array_permute(*matar, *totcol_p, remap);
+       }
+
+       if (ob->type == OB_MESH) {
+               BKE_mesh_material_remap(ob->data, remap, ob->totcol);
+       }
+       else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+               BKE_curve_material_remap(ob->data, remap, ob->totcol);
+       }
+       else {
+               /* add support for this object data! */
+               BLI_assert(matar == NULL);
+       }
+}
+
+
 /* XXX - this calls many more update calls per object then are needed, could be optimized */
 void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
 {
index 87325a7ff4705c62ad9817395a137c1f912cce88..12379bedb36c1c860c0e17033defecbd41fa7422 100644 (file)
@@ -1773,6 +1773,36 @@ void BKE_mesh_material_index_clear(Mesh *me)
        }
 }
 
+void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len)
+{
+       const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+       if (n < remap_len_short) { \
+               BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+               n = remap[n]; \
+       } ((void)0)
+
+       if (me->edit_btmesh) {
+               BMEditMesh *em = me->edit_btmesh;
+               BMIter iter;
+               BMFace *efa;
+
+               BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+                       MAT_NR_REMAP(efa->mat_nr);
+               }
+       }
+       else {
+               int i;
+               for (i = 0; i < me->totpoly; i++) {
+                       MAT_NR_REMAP(me->mpoly[i].mat_nr);
+               }
+       }
+
+#undef MAT_NR_REMAP
+
+}
+
 void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) 
 {
        Mesh *me = meshOb->data;
index 5c6744b0248e167e72778de41ab12f4097ff9658..54429f9f066ee65550d57450ceb1205379e2c198 100644 (file)
@@ -44,6 +44,7 @@ void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot);
 void OBJECT_OT_material_slot_select(struct wmOperatorType *ot);
 void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot);
 void OBJECT_OT_material_slot_copy(struct wmOperatorType *ot);
+void OBJECT_OT_material_slot_move(struct wmOperatorType *ot);
 
 void MATERIAL_OT_new(struct wmOperatorType *ot);
 void TEXTURE_OT_new(struct wmOperatorType *ot);
index 6aaad98f946948e8576bfbdd48fde95a9f76cf95..f98083f7e745f92c1ff0842812fba2afa6fd77c3 100644 (file)
@@ -47,6 +47,7 @@ void ED_operatortypes_render(void)
        WM_operatortype_append(OBJECT_OT_material_slot_select);
        WM_operatortype_append(OBJECT_OT_material_slot_deselect);
        WM_operatortype_append(OBJECT_OT_material_slot_copy);
+       WM_operatortype_append(OBJECT_OT_material_slot_move);
 
        WM_operatortype_append(MATERIAL_OT_new);
        WM_operatortype_append(TEXTURE_OT_new);
index 3de2153614812bae2770987ed98188629f502f1a..88f522a261501012dae356b492ad2b7692afc581 100644 (file)
@@ -41,8 +41,9 @@
 #include "DNA_space_types.h"
 #include "DNA_world_types.h"
 
-#include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
 
 #include "BLF_translation.h"
 
@@ -381,6 +382,73 @@ void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
 }
 
+static int material_slot_move_exec(bContext *C, wmOperator *op)
+{
+       Object *ob = ED_object_context(C);
+
+       unsigned int *slot_remap;
+       int index_pair[2];
+
+       int dir = RNA_enum_get(op->ptr, "direction");
+
+       if (!ob || ob->totcol < 2) {
+               return OPERATOR_CANCELLED;
+       }
+
+       /* up */
+       if (dir == 1 && ob->actcol > 1) {
+               index_pair[0] = ob->actcol - 2;
+               index_pair[1] = ob->actcol - 1;
+               ob->actcol--;
+       }
+       /* down */
+       else if (dir == -1 && ob->actcol < ob->totcol) {
+               index_pair[0] = ob->actcol - 1;
+               index_pair[1] = ob->actcol - 0;
+               ob->actcol++;
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
+
+       slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
+
+       range_vn_u(slot_remap, ob->totcol, 0);
+
+       slot_remap[index_pair[0]] = index_pair[1];
+       slot_remap[index_pair[1]] = index_pair[0];
+
+       BKE_material_remap_object(ob, slot_remap);
+
+       MEM_freeN(slot_remap);
+
+       WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob);
+
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_material_slot_move(wmOperatorType *ot)
+{
+       static EnumPropertyItem material_slot_move[] = {
+               {1, "UP", 0, "Up", ""},
+               {-1, "DOWN", 0, "Down", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       /* identifiers */
+       ot->name = "Move Material";
+       ot->idname = "OBJECT_OT_material_slot_move";
+       ot->description = "Move the active material up/down in the list";
+
+       /* api callbacks */
+       ot->exec = material_slot_move_exec;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+       RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
 /********************** new material operator *********************/
 
 static int new_material_exec(bContext *C, wmOperator *UNUSED(op))