Texture painting:
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 28 Aug 2014 14:40:38 +0000 (16:40 +0200)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 28 Aug 2014 18:41:05 +0000 (20:41 +0200)
Include explicit control for texturing:

This commit introduces a painting mode option, available in
the slots panel. The default value "Material"  will create slots from the
blender material, same as just merged from the paint branch.

The new option "Image", will use an explicit image field that artists can use
to select the image to paint on. This will should allow painting regardless
of the renderer used or for use in modifiers.

12 files changed:
release/scripts/startup/bl_ui/properties_paint_common.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/intern/material.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_sculpt_paint.c

index 046e54d41fcb2d47b5bb35d8727fa3a69514f89c..5c758b6568b76a26609a76037255bc4ef568d4a2 100644 (file)
@@ -17,6 +17,7 @@
 # ##### END GPL LICENSE BLOCK #####
 
 # <pep8 compliant>
+from bpy.types import Menu
 
 
 class UnifiedPaintPanel():
@@ -86,6 +87,18 @@ class UnifiedPaintPanel():
         parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
 
 
+class VIEW3D_MT_tools_projectpaint_clone(Menu):
+    bl_label = "Clone Layer"
+
+    def draw(self, context):
+        layout = self.layout
+
+        for i, tex in enumerate(context.active_object.data.uv_textures):
+            props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
+            props.data_path = "active_object.data.uv_texture_clone_index"
+            props.value = i
+
+
 def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=False):
     capabilities = brush.image_paint_capabilities
 
@@ -139,24 +152,38 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
     elif brush.image_tool == 'CLONE':
         col.separator()
         if projpaint:
-            col.prop(settings, "use_clone_layer", text="Clone from paint slot")
+            if settings.mode == 'MATERIAL':
+                col.prop(settings, "use_clone_layer", text="Clone from paint slot")
+            elif settings.mode == 'IMAGE':
+                col.prop(settings, "use_clone_layer", text="Clone from image/UV map")
 
             if settings.use_clone_layer:
                 ob = context.active_object
                 col = layout.column()
 
-                if len(ob.material_slots) > 1:
-                    col.label("Materials")
-                    col.template_list("MATERIAL_UL_matslots", "",
-                                      ob, "material_slots",
-                                      ob, "active_material_index", rows=2)
-
-                mat = ob.active_material
-                if mat:
-                    col.label("Clone Slot")
-                    col.template_list("TEXTURE_UL_texpaintslots", "",
-                                      mat, "texture_paint_images",
-                                      mat, "paint_clone_slot", rows=2)
+                if settings.mode == 'MATERIAL':
+                    if len(ob.material_slots) > 1:
+                        col.label("Materials")
+                        col.template_list("MATERIAL_UL_matslots", "",
+                                          ob, "material_slots",
+                                          ob, "active_material_index", rows=2)
+
+                    mat = ob.active_material
+                    if mat:
+                        col.label("Clone Slot")
+                        col.template_list("TEXTURE_UL_texpaintslots", "",
+                                          mat, "texture_paint_images",
+                                          mat, "paint_clone_slot", rows=2)
+
+                elif settings.mode == 'IMAGE':
+                    mesh = ob.data
+
+                    clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
+                    col.label("Image")
+                    col.template_ID(settings, "clone_image")
+                    col.label("UV Map")
+                    col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
+                    
 
         else:
             col.prop(brush, "clone_image", text="Image")
index 59c68fc615d72501a1576a5c03a46a17111081e1..6b0c5b1e993b0dbe14c45d4d1dd56eae7d8c3ff0 100644 (file)
@@ -1026,31 +1026,39 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
         ob = context.active_object
         col = layout.column()
 
-        if len(ob.material_slots) > 1:
-            col.label("Materials")
-            col.template_list("MATERIAL_UL_matslots", "layers",
-                              ob, "material_slots",
-                              ob, "active_material_index", rows=2)
-
-        mat = ob.active_material
-        if mat:
-            col.label("Available Paint Slots")
-            col.template_list("TEXTURE_UL_texpaintslots", "",
-                              mat, "texture_paint_images",
-                              mat, "paint_active_slot", rows=2)
+        col.label("Painting Mode")
+        col.prop(settings, "mode", text = "")
+        col.separator()
 
-            if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
-                row = col.row(align=True)
-                row.operator_menu_enum("paint.add_texture_paint_slot", "type")
-                row.operator("paint.delete_texture_paint_slot", text="", icon='X')
+        if settings.mode == 'MATERIAL':
+            if len(ob.material_slots) > 1:
+                col.label("Materials")
+                col.template_list("MATERIAL_UL_matslots", "layers",
+                                  ob, "material_slots",
+                                  ob, "active_material_index", rows=2)
+
+            mat = ob.active_material
+            if mat:
+                col.label("Available Paint Slots")
+                col.template_list("TEXTURE_UL_texpaintslots", "",
+                                  mat, "texture_paint_images",
+                                  mat, "paint_active_slot", rows=2)
 
-                if mat.texture_paint_slots:
-                    slot = mat.texture_paint_slots[mat.paint_active_slot]
+                if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+                    row = col.row(align=True)
+                    row.operator_menu_enum("paint.add_texture_paint_slot", "type")
+                    row.operator("paint.delete_texture_paint_slot", text="", icon='X')
 
-                    col.prop(mat.texture_slots[slot.index], "blend_type")
-                    col.separator()
-                    col.label("UV Map")
-                    col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+                    if mat.texture_paint_slots:
+                        slot = mat.texture_paint_slots[mat.paint_active_slot]
+
+                        col.prop(mat.texture_slots[slot.index], "blend_type")
+                        col.separator()
+                        col.label("UV Map")
+                        col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+
+        elif settings.mode == 'IMAGE':
+            col.template_ID(settings, "canvas")
 
         col.separator()
         col.operator("image.save_dirty", text="Save All Images")
@@ -1089,7 +1097,6 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
 
         col.label("Image")
         row = col.row(align=True)
-        row.operator("image.new", icon='ZOOMIN', text="Add New").texstencil = True;
         row.template_ID(ipaint, "stencil_image")
  
         col.label("Visualization")
@@ -1643,18 +1650,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
         self.unified_paint_settings(col, context)
 
 
-class VIEW3D_MT_tools_projectpaint_clone(Menu):
-    bl_label = "Clone Layer"
-
-    def draw(self, context):
-        layout = self.layout
-
-        for i, tex in enumerate(context.active_object.data.uv_textures):
-            props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
-            props.data_path = "active_object.data.uv_texture_clone_index"
-            props.value = i
-
-
 class VIEW3D_MT_tools_projectpaint_stencil(Menu):
     bl_label = "Mask Layer"
 
index 50147149b0c7b78deeebb081155e20845acb73b5..e7500392c81756fd311cdd5f90315ded58043c47 100644 (file)
@@ -274,8 +274,7 @@ Material *localize_material(Material *ma)
        if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
        if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
 
-       if (ma->texpaintslot) man->texpaintslot = MEM_dupallocN(man->texpaintslot);
-
+       ma->texpaintslot = NULL;
        man->preview = NULL;
        
        if (ma->nodetree)
@@ -1328,9 +1327,16 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
 
        if (ma->texpaintslot) {
                MEM_freeN(ma->texpaintslot);
+               ma->tot_slots = 0;
                ma->texpaintslot = NULL;
        }
 
+       if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
+               ma->paint_active_slot = 0;
+               ma->paint_clone_slot = 0;
+               return;
+       }
+       
        if (use_nodes || ma->use_nodes) {
                bNode *node, *active_node;
 
@@ -1342,10 +1348,9 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
                                count++;
                }
 
-               ma->tot_slots = 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");
@@ -1367,10 +1372,9 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
                        }
                }
 
-               ma->tot_slots = count;
-
                if (count == 0) {
                        ma->paint_active_slot = 0;
+                       ma->paint_clone_slot = 0;
                        return;
                }
 
@@ -1387,6 +1391,8 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
                }
        }
 
+       ma->tot_slots = count;
+       
        if (ma->paint_active_slot >= count) {
                ma->paint_active_slot = count - 1;
        }
index 8ada7b77babd4c19d660b6c103662eb0b0a427e6..b2e49be1a5e2c9a9ceeb68762667cd3f3c562a14 100644 (file)
@@ -5152,6 +5152,14 @@ static void lib_link_scene(FileData *fd, Main *main)
                                sce->toolsettings->imapaint.stencil =
                                        newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.stencil);
 
+                       if (sce->toolsettings->imapaint.clone)
+                               sce->toolsettings->imapaint.clone =
+                                       newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.clone);
+
+                       if (sce->toolsettings->imapaint.canvas)
+                               sce->toolsettings->imapaint.canvas =
+                                       newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.canvas);
+                       
                        sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
                        
                        for (base = sce->base.first; base; base = next) {
index ea6d56155cc3af23fd32203e2a6950a294828b34..f596f33053415a11cf4370d7a19c882241433b1d 100644 (file)
@@ -1363,41 +1363,87 @@ void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
        Mesh *me;
        int layernum;
        ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
+       bScreen *sc;
        Scene *scene = CTX_data_scene(C);
+       Main *bmain = CTX_data_main(C);
        Brush *br = BKE_paint_brush(&imapaint->paint);
 
-       /* no material, add one */
-       if (ob->totcol == 0) {
-               Material *ma = BKE_material_add(CTX_data_main(C), "Material");
-               /* no material found, just assign to first slot */
-               assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
-               proj_paint_add_slot(C, ma, NULL);
-       }
-       else {
-               /* there may be material slots but they may be empty, check */
-               int i;
-
-               for (i = 1; i < ob->totcol + 1; i++) {
-                       Material *ma = give_current_material(ob, i);
-                       if (ma) {
-                               if (!ma->texpaintslot) {
-                                       /* refresh here just in case */
-                                       BKE_texpaint_slot_refresh_cache(scene, ma);                             
-                                       
-                                       /* if still no slots, we have to add */
-                                       if (!ma->texpaintslot)
-                                               proj_paint_add_slot(C, ma, NULL);
+       if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+               /* no material, add one */
+               if (ob->totcol == 0) {
+                       Material *ma = BKE_material_add(CTX_data_main(C), "Material");
+                       /* no material found, just assign to first slot */
+                       assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+                       proj_paint_add_slot(C, ma, NULL);
+               }
+               else {
+                       /* there may be material slots but they may be empty, check */
+                       int i;
+                       
+                       for (i = 1; i < ob->totcol + 1; i++) {
+                               Material *ma = give_current_material(ob, i);
+                               if (ma) {
+                                       if (!ma->texpaintslot) {
+                                               /* refresh here just in case */
+                                               BKE_texpaint_slot_refresh_cache(scene, ma);                             
+                                               
+                                               /* if still no slots, we have to add */
+                                               if (!ma->texpaintslot) {
+                                                       proj_paint_add_slot(C, ma, NULL);
+                                                       
+                                                       for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+                                                               ScrArea *sa;
+                                                               for (sa = sc->areabase.first; sa; sa = sa->next) {
+                                                                       SpaceLink *sl;
+                                                                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                                                               if (sl->spacetype == SPACE_IMAGE) {
+                                                                                       SpaceImage *sima = (SpaceImage *)sl;
+                                                                                       
+                                                                                       ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima);
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                                       
+                                               }
+                                       }
+                               }
+                               else {
+                                       Material *ma = BKE_material_add(CTX_data_main(C), "Material");
+                                       /* no material found, just assign to first slot */
+                                       assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
+                                       proj_paint_add_slot(C, ma, NULL);                               
                                }
-                       }
-                       else {
-                               Material *ma = BKE_material_add(CTX_data_main(C), "Material");
-                               /* no material found, just assign to first slot */
-                               assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
-                               proj_paint_add_slot(C, ma, NULL);                               
                        }
                }
        }
+       else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE){
+               if (imapaint->canvas == NULL) {
+                       int width;
+                       int height;
+                       Main *bmain = CTX_data_main(C);
+                       float color[4] = {0.0, 0.0, 0.0, 1.0};
 
+                       width = 1024;
+                       height = 1024;
+                       imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color);
+                       
+                       for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+                               ScrArea *sa;
+                               for (sa = sc->areabase.first; sa; sa = sa->next) {
+                                       SpaceLink *sl;
+                                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                               if (sl->spacetype == SPACE_IMAGE) {
+                                                       SpaceImage *sima = (SpaceImage *)sl;
+                                                       
+                                                       ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas);
+                                               }
+                                       }
+                               }
+                       }                       
+               }               
+       }
+               
        me = BKE_mesh_from_object(ob);
        layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
 
@@ -1449,7 +1495,8 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
        else {
                bScreen *sc;
                Main *bmain = CTX_data_main(C);
-               Material *ma;
+               Image *ima = NULL;
+               ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
 
                /* This has to stay here to regenerate the texture paint
                 * cache in case we are loading a file */
@@ -1457,19 +1504,26 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
 
                paint_proj_mesh_data_ensure(C, ob, op);
 
-               /* set the current material active paint slot on image editor */
-               ma = give_current_material(ob, ob->actcol);
+               /* entering paint mode also sets image to editors */
+               if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+                       Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */
 
-               if (ma->tot_slots > 0) {
-                       for (sc = bmain->screen.first; sc; sc = sc->id.next) {
-                               ScrArea *sa;
-                               for (sa = sc->areabase.first; sa; sa = sa->next) {
-                                       SpaceLink *sl;
-                                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
-                                               if (sl->spacetype == SPACE_IMAGE) {
-                                                       SpaceImage *sima = (SpaceImage *)sl;
-                                                       ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
-                                               }
+                       if (ma->texpaintslot)
+                               ima = ma->texpaintslot[ma->paint_active_slot].ima;
+               }
+               else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+                       ima = imapaint->canvas;
+               }       
+               
+               for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+                       ScrArea *sa;
+                       for (sa = sc->areabase.first; sa; sa = sa->next) {
+                               SpaceLink *sl;
+                               for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                       if (sl->spacetype == SPACE_IMAGE) {
+                                               SpaceImage *sima = (SpaceImage *)sl;
+                                               
+                                               ED_space_image_set(sima, scene, scene->obedit, ima);
                                        }
                                }
                        }
index 9362510a84dc6ac03f0ea50b22120c54d25af4d3..3c6fb5dfe20574e8b024bbe26a586e5ebcb2b5a0 100644 (file)
@@ -220,6 +220,8 @@ typedef struct ProjPaintState {
        MTFace         *dm_mtface_stencil;
 
        Image *stencil_ima;
+       Image *canvas_ima;
+       Image *clone_ima;
        float stencil_value;
 
        /* projection painting only */
@@ -256,6 +258,7 @@ typedef struct ProjPaintState {
        bool  do_layer_stencil;
        bool  do_layer_stencil_inv;
        bool  do_stencil_brush;
+       bool  do_material_slots;
 
        bool  do_occlude;               /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
        bool  do_backfacecull;          /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
@@ -368,16 +371,23 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_
                MFace *mf = ps->dm_mface + face_index;
                Material *ma = ps->dm->mat[mf->mat_nr];
                TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
-               return slot ? slot->ima : NULL;
+               return slot ? slot->ima : ps->canvas_ima;
        }
 }
 
-
 static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
 {
        MFace *mf = ps->dm_mface + face_index;
        Material *ma = ps->dm->mat[mf->mat_nr];
-       return &ma->texpaintslot[ma->paint_clone_slot];
+       return ma->texpaintslot + ma->paint_clone_slot;
+}
+
+static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index)
+{
+       MFace *mf = ps->dm_mface + face_index;
+       Material *ma = ps->dm->mat[mf->mat_nr];
+       TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot;
+       return slot ? slot->ima : ps->clone_ima;
 }
 
 /* fast projection bucket array lookup, use the safe version for bound checking  */
@@ -1466,7 +1476,7 @@ static ProjPixel *project_paint_uvpixel_init(
        if (ps->tool == PAINT_TOOL_CLONE) {
                if (ps->dm_mtface_clone) {
                        ImBuf *ibuf_other;
-                       Image *other_tpage = project_paint_face_clone_slot(ps, face_index)->ima;
+                       Image *other_tpage = project_paint_face_clone_image(ps, face_index);
                        const MTFace *tf_other = ps->dm_mtface_clone[face_index];
 
                        if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
@@ -3005,6 +3015,19 @@ static void project_paint_begin(ProjPaintState *ps)
                if (ps->do_stencil_brush)
                        tf_base = ps->dm_mtface_stencil;
        }
+       
+       if (ps->do_layer_clone) {
+               int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+
+               if (layer_num != -1)
+                       tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+               if (tf_clone_base == NULL) {
+                       /* get active instead */
+                       tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+               }
+               
+       }
 
        /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
        if (ps->dm->type != DM_TYPE_CDDM) {
@@ -3291,6 +3314,7 @@ static void project_paint_begin(ProjPaintState *ps)
                        /* all faces should have a valid slot, reassert here */
                        if (slot == NULL) {
                                tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+                               tpage = ps->canvas_ima;
                        }
                        else {
                                if (slot != slot_last) {
@@ -3302,32 +3326,43 @@ static void project_paint_begin(ProjPaintState *ps)
                                /* don't allow using the same inage for painting and stencilling */
                                if (slot->ima == ps->stencil_ima)
                                        continue;
+                               
+                               tpage = slot->ima;
                        }
                }
+               else {
+                       tpage = ps->stencil_ima;
+               }
 
                *tf = tf_base + face_index;
 
                if (ps->do_layer_clone) {
-                       slot_clone = project_paint_face_clone_slot(ps, face_index);
-                       /* all faces should have a valid slot, reassert here */
-                       if (ELEM(slot_clone, NULL, slot))
+                       if (ps->do_material_slots) {
+                               slot_clone = project_paint_face_clone_slot(ps, face_index);
+                               /* all faces should have a valid slot, reassert here */
+                               if (ELEM(slot_clone, NULL, slot))
+                                       continue;
+                       }
+                       else if (ps->clone_ima == ps->canvas_ima)
                                continue;
-
+                       
                        tf_clone = ps->dm_mtface_clone + face_index;
-
-                       if (slot_clone != slot_last_clone) {
-                               if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
-                                       tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
-                               slot_last_clone = slot_clone;
+                       
+                       if (ps->do_material_slots) {
+                               if (slot_clone != slot_last_clone) {
+                                       if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
+                                               tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+                                       slot_last_clone = slot_clone;
+                               }
                        }
-
+                       
                        *tf_clone = tf_clone_base + face_index;
                }
 
                /* tfbase here should be non-null! */
                BLI_assert (tf_base != NULL);
 
-               if (is_face_sel && ((slot && (tpage = slot->ima)) || (tpage = project_paint_face_paint_image(ps, face_index)))) {
+               if (is_face_sel && tpage) {
                        const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
 
                        v1coSS = ps->screenCoords[mf->v1];
@@ -4480,7 +4515,13 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
        ps->scene = scene;
        ps->ob = ob; /* allow override of active object */
 
+       ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
        ps->stencil_ima = settings->imapaint.stencil;
+       ps->canvas_ima = (!ps->do_material_slots) ? 
+                                                settings->imapaint.canvas : NULL;
+       ps->clone_ima = (!ps->do_material_slots) ? 
+                                                settings->imapaint.clone : NULL;
+
        /* setup projection painting data */
        ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
        ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
index 0d463172f99146bc2e3b9b0f733d25dc054efd7f..486bf2a5d6699f79d4468a56f05b404be610762f 100644 (file)
@@ -312,7 +312,7 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
                        if (mf.v4)
                                dm->getVert(dm, mf.v4, &mv[3]);
 
-                       if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname)))
+                       if (!(slot && slot->uvname && (tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname))))
                                tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
 
                        tf = &tf_base[a];
@@ -428,6 +428,8 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
                /* first try getting a colour directly from the mesh faces if possible */
                Object *ob = OBACT;
                bool sample_success = false;
+               ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+               bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
 
                if (ob) {
                        DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
@@ -446,51 +448,58 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
                                view3d_operator_needs_opengl(C);
 
                                if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
-                                       Image *image = imapaint_face_image(dm, faceindex);
-
-                                       ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
-                                       if (ibuf && ibuf->rect) {
-                                               float uv[2];
-                                               float u, v;
-                                               imapaint_pick_uv(scene, ob, faceindex, mval, uv);
-                                               sample_success = true;
-
-                                               u = fmodf(uv[0], 1.0f);
-                                               v = fmodf(uv[1], 1.0f);
-
-                                               if (u < 0.0f) u += 1.0f;
-                                               if (v < 0.0f) v += 1.0f;
-
-                                               u = u * ibuf->x - 0.5f;
-                                               v = v * ibuf->y - 0.5f;
-
-                                               if (ibuf->rect_float) {
-                                                       float rgba_f[4];
-                                                       bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
-                                                       straight_to_premul_v4(rgba_f);
-                                                       if (use_palette) {
-                                                               linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
+                                       Image *image;
+                                       
+                                       if (use_material) 
+                                               image = imapaint_face_image(dm, faceindex);
+                                       else
+                                               image = imapaint->canvas;
+                                       
+                                       if (image) {
+                                               ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+                                               if (ibuf && ibuf->rect) {
+                                                       float uv[2];
+                                                       float u, v;
+                                                       imapaint_pick_uv(scene, ob, faceindex, mval, uv);
+                                                       sample_success = true;
+                                                       
+                                                       u = fmodf(uv[0], 1.0f);
+                                                       v = fmodf(uv[1], 1.0f);
+                                                       
+                                                       if (u < 0.0f) u += 1.0f;
+                                                       if (v < 0.0f) v += 1.0f;
+                                                       
+                                                       u = u * ibuf->x - 0.5f;
+                                                       v = v * ibuf->y - 0.5f;
+                                                       
+                                                       if (ibuf->rect_float) {
+                                                               float rgba_f[4];
+                                                               bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+                                                               straight_to_premul_v4(rgba_f);
+                                                               if (use_palette) {
+                                                                       linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
+                                                               }
+                                                               else {
+                                                                       linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
+                                                                       BKE_brush_color_set(scene, br, rgba_f);
+                                                               }
                                                        }
                                                        else {
-                                                               linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
-                                                               BKE_brush_color_set(scene, br, rgba_f);
-                                                       }
-                                               }
-                                               else {
-                                                       unsigned char rgba[4];
-                                                       bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
-                                                       if (use_palette) {
-                                                               rgb_uchar_to_float(color->rgb, rgba);
-                                                       }
-                                                       else {
-                                                               float rgba_f[3];
-                                                               rgb_uchar_to_float(rgba_f, rgba);
-                                                               BKE_brush_color_set(scene, br, rgba_f);
+                                                               unsigned char rgba[4];
+                                                               bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+                                                               if (use_palette) {
+                                                                       rgb_uchar_to_float(color->rgb, rgba);
+                                                               }
+                                                               else {
+                                                                       float rgba_f[3];
+                                                                       rgb_uchar_to_float(rgba_f, rgba);
+                                                                       BKE_brush_color_set(scene, br, rgba_f);
+                                                               }
                                                        }
                                                }
+                                       
+                                               BKE_image_release_ibuf(image, ibuf, NULL);
                                        }
-
-                                       BKE_image_release_ibuf(image, ibuf, NULL);
                                }
                        }
                        dm->release(dm);
index f402f1cb4c8e7d52e825fec7e57a9ade4c864c5d..0a3713a41e445eaa60058f604c20290e8fc90235 100644 (file)
@@ -1907,7 +1907,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
        char *name = _name;
        float color[4];
        int width, height, floatbuf, gen_type, alpha;
-       bool stencil;
 
        /* retrieve state */
        sima = CTX_wm_space_image(C);
@@ -1927,7 +1926,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
        gen_type = RNA_enum_get(op->ptr, "generated_type");
        RNA_float_get_array(op->ptr, "color", color);
        alpha = RNA_boolean_get(op->ptr, "alpha");
-       stencil = RNA_boolean_get(op->ptr, "texstencil");
 
        if (!alpha)
                color[3] = 1.0f;
@@ -1960,13 +1958,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
                        tex->ima = ima;
                        ED_area_tag_redraw(CTX_wm_area(C));
                }
-               else if (stencil) {
-                       ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
-
-                       if (imapaint->stencil)
-                               id_us_min(&imapaint->stencil->id);
-                       imapaint->stencil = ima;
-               }
        }
 
        BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
index e571584a10ff712af44a1cc7b04e31dcef97768c..dd9b9dea02a72c467ff8cd978cc68a3d697c338a 100644 (file)
@@ -212,7 +212,8 @@ static Material *give_current_material_or_def(Object *ob, int matnr)
 
 static struct TextureDrawState {
        Object *ob;
-       Image *stencil;
+       Image *stencil; /* texture painting stencil */
+       Image *canvas;  /* texture painting canvas, for image mode */
        bool stencil_invert;
        bool use_game_mat;
        int is_lit, is_tex;
@@ -221,7 +222,8 @@ static struct TextureDrawState {
        unsigned char obcol[4];
        float stencil_col[4];
        bool is_texpaint;
-} Gtexdraw = {NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false};
+       bool texpaint_material; /* use material slots for texture painting */
+} Gtexdraw = {NULL, NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false, false};
 
 static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
 {
@@ -280,7 +282,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
                        alphablend = GPU_BLEND_ALPHA;
        }
        else if (texpaint && ma) {
-               ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+               if (gtexdraw.texpaint_material)
+                       ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+               else 
+                       ima = gtexdraw.canvas;
        }
        else
                textured = 0;
@@ -394,6 +399,8 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
        Gtexdraw.stencil_invert = ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
        Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
        copy_v3_v3(Gtexdraw.stencil_col, imapaint->stencil_col);
+       Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
+       Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas;
        Gtexdraw.is_tex = is_tex;
 
        /* load the stencil texture here */
index d7bc8e56e3827854105c182f16e734b64b3bb8b2..c8b8e4d52a4274c0d50e039af60bc98b3e55ae5f 100644 (file)
@@ -841,12 +841,14 @@ typedef struct ImagePaintSettings {
        short seam_bleed, normal_angle;
        short screen_grab_size[2]; /* capture size for re-projection */
 
-       int pad1;
+       int mode;                  /* mode used for texture painting */
 
-       void *paintcursor;                      /* wm handle */
-       struct Image *stencil;      /* workaround until we support true layer masks */
+       void *paintcursor;                 /* wm handle */
+       struct Image *stencil;     /* workaround until we support true layer masks */
+       struct Image *clone;       /* clone layer for image mode for projective texture painting */
+       struct Image *canvas;      /* canvas when the explicit system is used for painting */
        float stencil_col[3];
-       float pad2;
+       float pad1;
 } ImagePaintSettings;
 
 /* ------------------------------------------- */
@@ -1708,6 +1710,11 @@ typedef enum SculptFlags {
        SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13)
 } SculptFlags;
 
+typedef enum ImagePaintMode {
+       IMAGEPAINT_MODE_MATERIAL, /* detect texture paint slots from the material */
+       IMAGEPAINT_MODE_IMAGE,    /* select texture paint image directly */
+} ImagePaintMode;
+
 #if (DNA_DEPRECATED_GCC_POISON == 1)
 #pragma GCC poison SCULPT_SYMM_X SCULPT_SYMM_Y SCULPT_SYMM_Z SCULPT_SYMMETRY_FEATHER
 #endif
index c395b963d489ed26521f0faf4e297bfbbbae91af..37b6947cfac2c9d30294ae4e4703802473eefd5b 100644 (file)
@@ -181,7 +181,6 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s
        bScreen *sc;
        Material *ma = ptr->id.data;
 
-
        if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
                struct bNode *node;
                int index = 0;
index af6cf493f1e00412aac3abb6f8c003652e6e4dac..c4b5461dece7c91ff35b2984a01530585d2e4967 100644 (file)
 #include "DNA_ID.h"
 #include "DNA_scene_types.h"
 #include "DNA_brush_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 
 #include "BKE_paint.h"
+#include "BKE_material.h"
+
+#include "ED_image.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -286,11 +291,44 @@ static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
        WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
 }
 
-static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
 {
        /* not the best solution maybe, but will refresh the 3D viewport */
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
 }
+
+static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+       Object *ob = OBACT;
+       
+       /* of course we need to invalidate here */
+       BKE_texpaint_slots_refresh_object(scene, ob);
+
+       /* we assume that changing the current mode will invalidate the uv layers so we need to tag an update */
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
+}
+
+static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+{
+       bScreen *sc;
+       Image *ima = scene->toolsettings->imapaint.canvas;
+       
+       for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+               ScrArea *sa;
+               for (sa = sc->areabase.first; sa; sa = sa->next) {
+                       SpaceLink *sl;
+                       for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                               if (sl->spacetype == SPACE_IMAGE) {
+                                       SpaceImage *sima = (SpaceImage *)sl;
+                                       ED_space_image_set(sima, scene, scene->obedit, ima);
+                               }
+                       }
+               }
+       }
+
+       WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
 #else
 
 static void rna_def_palettecolor(BlenderRNA *brna)
@@ -571,6 +609,14 @@ static void rna_def_image_paint(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
+
+       static EnumPropertyItem paint_type_items[] = {
+               {IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0,
+                "Material", "Detect image slots from the material"},
+               {IMAGEPAINT_MODE_IMAGE, "IMAGE", 0,
+                "Image", "Set image for texture painting directly"},
+               {0, NULL, 0, NULL, NULL}
+       };
        
        srna = RNA_def_struct(brna, "ImagePaint", "Paint");
        RNA_def_struct_sdna(srna, "ImagePaintSettings");
@@ -596,24 +642,35 @@ static void rna_def_image_paint(BlenderRNA *brna)
        prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
        RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
-       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
        
        prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
        RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
-       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
 
        prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "stencil");
        RNA_def_property_flag(prop, PROP_EDITABLE);
        RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
-       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
 
+       prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update");
+       
+       prop = RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "clone");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Clone Image", "Image used as clone source");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       
        prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA);
        RNA_def_property_range(prop, 0.0, 1.0);
        RNA_def_property_float_sdna(prop, NULL, "stencil_col");
        RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
-       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
        
        prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE);
@@ -634,6 +691,11 @@ static void rna_def_image_paint(BlenderRNA *brna)
        prop = RNA_def_int_array(srna, "screen_grab_size", 2, NULL, 0, 0, "screen_grab_size",
                                 "Size to capture the image for re-projecting", 0, 0);
        RNA_def_property_range(prop, 512, 16384);
+       
+       prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, paint_type_items);
+       RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");  
 }
 
 static void rna_def_particle_edit(BlenderRNA *brna)