Texture painting:
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 6 Oct 2014 13:12:06 +0000 (15:12 +0200)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 6 Oct 2014 18:10:12 +0000 (20:10 +0200)
Do not generate materials/images/UVs if they are missing.

Now we spawn a panel ("Missing Data") with operators to generate the missing data and
pop a warning if user tries to paint without them.

The reason we have reverted this is that it is too easy to end up with more textures
than we wanted. It was impossible to enter texture paint without having textures added,
and code makes too many assumptions about what user may want.

Discussed during Sunday's meeting.

This might be a candidate for 2.72a but I'm not sure how other artists will take this
(and how refined and crash-free it is), better make a few iterations first.

And for interested parties...test please, don't wait until after a release to poke with such issues.

Also, add slot operator now adds a new unconnected image node in cycles. Only
used in the "Missing Data" panel. This should be a separate commit but I am squashing it into the same commit because
it relies too much on changes done here and can be reverted easily if complainstorm occurs again.

15 files changed:
release/scripts/startup/bl_ui/properties_paint_common.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/intern/depsgraph.c
source/blender/editors/mesh/mesh_data.c
source/blender/editors/render/render_shading.c
source/blender/editors/render/render_update.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/sculpt_paint/paint_intern.h
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_sculpt_paint.c

index 81bbc7754a76aab55f9445a1dd0893c6b58146bf..f1042856e4c5e7c499af631dacb7a907a90c4297 100644 (file)
@@ -36,7 +36,10 @@ class UnifiedPaintPanel():
         elif context.weight_paint_object:
             return toolsettings.weight_paint
         elif context.image_paint_object:
-            return toolsettings.image_paint
+            if (toolsettings.image_paint and toolsettings.image_paint.detect_data()):
+                return toolsettings.image_paint
+
+            return None
         elif context.particle_edit_object:
             return toolsettings.particle_edit
 
index ffd4299bc399778278529363449cd67efb72d97f..213bfd9d8087bc7e458a55c4bf95131afa22fc98 100644 (file)
@@ -775,6 +775,65 @@ class View3DPaintPanel(UnifiedPaintPanel):
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'TOOLS'
 
+class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_label = "Missing Data"
+
+    @classmethod
+    def poll(cls, context):
+        toolsettings = context.tool_settings.image_paint
+        return context.image_paint_object and not toolsettings.detect_data()
+
+    def draw(self, context):
+        layout = self.layout
+        toolsettings = context.tool_settings.image_paint
+
+        col = layout.column()
+        col.label("Missing Data", icon='ERROR')
+        if toolsettings.missing_uvs:
+            col.separator()
+            col.label("Missing UVs", icon='INFO')
+            col.label("Unwrap the mesh in edit mode or generate a simple UVs")
+            col.operator("mesh.uv_texture_add", text="Add Simple UVs")
+    
+        if toolsettings.mode == 'MATERIAL':
+            if toolsettings.missing_materials:
+                col.separator()
+                col.label("Missing Materials", icon='INFO')
+                col.label("Add a material and paint slot below")
+                col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+                   
+            elif toolsettings.missing_texture:
+                ob = context.active_object
+                mat = ob.active_material
+
+                col.separator()
+                if mat:
+                    col.label("Missing Texture Slots", icon='INFO')
+                    col.label("Add a paint slot below")
+                    col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+                else:
+                    col.label("Missing Materials", icon='INFO')
+                    col.label("Add a material and paint slot below")
+                    col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+
+        elif toolsettings.mode == 'IMAGE':
+            if toolsettings.missing_texture:
+                col.separator()
+                col.label("Missing Canvas", icon='INFO')
+                col.label("Add or assign a canvas image below")
+                col.label("Canvas Image")
+                col.template_ID(toolsettings, "canvas")
+                col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+
+        if toolsettings.missing_stencil:
+            col.separator()
+            col.label("Missing Stencil", icon='INFO')
+            col.label("Add or assign a stencil image below")
+            col.label("Stencil Image")
+            col.template_ID(toolsettings, "stencil_image")
+            col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
 
 class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
     bl_category = "Tools"
@@ -1072,8 +1131,9 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
         elif settings.mode == 'IMAGE':
             mesh = ob.data
             uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else ""
-            col.label("Image")
+            col.label("Canvas Image")
             col.template_ID(settings, "canvas")
+            col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
             col.label("UV Map")
             col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
 
@@ -1111,9 +1171,10 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
         col.label("UV Map")
         col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
 
-        col.label("Image")
-        row = col.row(align=True)
-        row.template_ID(ipaint, "stencil_image")
+        col.label("Stencil Image")
+        col.template_ID(ipaint, "stencil_image")
+        col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+
  
         col.label("Visualization")
         row = col.row(align=True)
@@ -1211,7 +1272,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
         brush_texture_settings(col, brush, context.sculpt_object)
 
 
-class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
+class VIEW3D_PT_tools_mask_texture(View3DPanel, View3DPaintPanel):
     bl_category = "Tools"
     bl_context = "imagepaint"
     bl_label = "Texture Mask"
@@ -1219,8 +1280,8 @@ class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
 
     @classmethod
     def poll(cls, context):
-        brush = context.tool_settings.image_paint.brush
-        return (context.image_paint_object and brush)
+        settings = cls.paint_settings(context)
+        return (settings and settings.image_paint.brush and context.image_paint_object and brush)
 
     def draw(self, context):
         layout = self.layout
@@ -1475,11 +1536,8 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
 
     @classmethod
     def poll(cls, context):
-        toolsettings = context.tool_settings
-        return ((context.sculpt_object and toolsettings.sculpt) or
-                (context.vertex_paint_object and toolsettings.vertex_paint) or
-                (context.weight_paint_object and toolsettings.weight_paint) or
-                (context.image_paint_object and toolsettings.image_paint))
+        settings = cls.paint_settings(context)
+        return settings
 
     def draw(self, context):
         layout = self.layout
index 4eafdae9ebd36fa8fbf607f358187b37bf89bf59..b080ca37e67919abfced7852e9c049ba2c98cba6 100644 (file)
@@ -50,6 +50,7 @@ struct PaintCurve;
 struct Palette;
 struct PaletteColor;
 struct PBVH;
+struct ReportList;
 struct Scene;
 struct Sculpt;
 struct StrokeCache;
@@ -121,6 +122,9 @@ struct Palette *BKE_paint_palette(struct Paint *paint);
 void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
 void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
 
+void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil);
+bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil);
+
 /* testing face select mode
  * Texture paint could be removed since selected faces are not used
  * however hiding faces is useful */
index 93bb4849718710064d7a6f368f3527b3787f6d63..44a0b93fc01bfb35349f859c7857bd38cfe1d2ef 100644 (file)
@@ -75,6 +75,7 @@
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
+#include "BKE_paint.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
 #include "BKE_scene.h"
@@ -2509,6 +2510,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
                        obt = sce->basact ? sce->basact->object : NULL;
                        if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
                                BKE_texpaint_slots_refresh_object(sce, obt);
+                               BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL);
                                GPU_drawobject_free(obt->derivedFinal);
                        }
                }
index bf8559add6f8c57ffba18058700d135375788028..68471bfc2ba5d00207feb00442db881cbf37b576 100644 (file)
@@ -47,6 +47,7 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
+#include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_editmesh.h"
 
@@ -502,6 +503,12 @@ static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
        if (ED_mesh_uv_texture_add(me, NULL, true) == -1)
                return OPERATOR_CANCELLED;
 
+       if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+               Scene *scene = CTX_data_scene(C);
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       }
+       
        return OPERATOR_FINISHED;
 }
 
@@ -622,6 +629,12 @@ static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
        if (!ED_mesh_uv_texture_remove_active(me))
                return OPERATOR_CANCELLED;
 
+       if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+               Scene *scene = CTX_data_scene(C);
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       }
+       
        return OPERATOR_FINISHED;
 }
 
index 72b4da64c3e0bbd1ce1066f5520686f07efad648..6c996bcbd677b588e3095477c2bc5a5f24686ab6 100644 (file)
@@ -58,6 +58,7 @@
 #include "BKE_linestyle.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_texture.h"
@@ -102,8 +103,15 @@ static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
 
        if (!ob)
                return OPERATOR_CANCELLED;
-
+       
        object_add_material_slot(ob);
+
+       if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+               Scene *scene = CTX_data_scene(C);
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       }
+       
        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);
@@ -138,8 +146,15 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op)
                BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode");
                return OPERATOR_CANCELLED;
        }
-
+       
        object_remove_material_slot(ob);
+
+       if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+               Scene *scene = CTX_data_scene(C);
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       }
+       
        DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
index 6b58d3d55aa663cc22b02ae7236c68bc2df314b0..df7ca9f11b28bd7ff3b4fb643c06022878e64982 100644 (file)
@@ -166,7 +166,6 @@ void ED_render_engine_changed(Main *bmain)
        bScreen *sc;
        ScrArea *sa;
        Scene *scene;
-       Material *ma;
 
        for (sc = bmain->screen.first; sc; sc = sc->id.next)
                for (sa = sc->areabase.first; sa; sa = sa->next)
@@ -176,13 +175,6 @@ void ED_render_engine_changed(Main *bmain)
 
        for (scene = bmain->scene.first; scene; scene = scene->id.next)
                ED_render_id_flush_update(bmain, &scene->id);
-
-       /* reset texture painting. Sending one dependency graph signal for any material should
-        * refresh any texture slots */
-       ma = bmain->mat.first;
-       if (ma) {
-               DAG_id_tag_update(&ma->id, 0);
-       }
 }
 
 /***************************** Updates ***********************************
@@ -482,15 +474,22 @@ static void image_changed(Main *bmain, Image *ima)
                        texture_changed(bmain, tex);
 }
 
-static void scene_changed(Main *bmain, Scene *UNUSED(scene))
+static void scene_changed(Main *bmain, Scene *scene)
 {
        Object *ob;
        Material *ma;
 
        /* glsl */
-       for (ob = bmain->object.first; ob; ob = ob->id.next)
+       for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->gpulamp.first)
                        GPU_lamp_free(ob);
+               
+               if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+                       BKE_texpaint_slots_refresh_object(scene, ob);
+                       BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+                       GPU_drawobject_free(ob->derivedFinal);                  
+               }
+       }
 
        for (ma = bmain->mat.first; ma; ma = ma->id.next)
                if (ma->gpumaterial.first)
index 87866f764bc136c5901fbc8d16c83e491aa247d1..f4189b512e58f644f8530e4773568436ea9b1062 100644 (file)
@@ -57,6 +57,7 @@
 
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_brush.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
@@ -87,6 +88,7 @@
 #include "RNA_enum_types.h"
 
 #include "GPU_draw.h"
+#include "GPU_buffers.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
@@ -752,14 +754,16 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
        copy_v2_v2(pop->prevmouse, mouse);
        copy_v2_v2(pop->startmouse, mouse);
 
-       if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
-               pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
-       }
-
        /* initialize from context */
        if (CTX_wm_region_view3d(C)) {
                Object *ob = OBACT;
-               paint_proj_mesh_data_ensure(C, ob, op);
+               bool uvs, mat, tex, stencil;
+               if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
+                       BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
+                       MEM_freeN(pop);
+                       WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+                       return NULL;                    
+               }
                pop->mode = PAINT_MODE_3D_PROJECT;
                pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
        }
@@ -773,6 +777,10 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
                return NULL;
        }
 
+       if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+               pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
+       }
+       
        settings->imapaint.flag |= IMAGEPAINT_DRAWING;
        ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
                                 ED_image_undo_restore, ED_image_undo_free, NULL);
@@ -1381,29 +1389,31 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
                 * cache in case we are loading a file */
                BKE_texpaint_slots_refresh_object(scene, ob);
 
-               paint_proj_mesh_data_ensure(C, ob, op);
-
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               
                /* 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->texpaintslot)
+                       if (ma && 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;
-                                               
-                                               if (!sima->pin)
-                                                       ED_space_image_set(sima, scene, scene->obedit, ima);
+               if (ima) {
+                       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;
+                                                       
+                                                       if (!sima->pin)
+                                                               ED_space_image_set(sima, scene, scene->obedit, ima);
+                                               }
                                        }
                                }
                        }
@@ -1420,7 +1430,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
                toggle_paint_cursor(C, 1);
        }
 
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       GPU_drawobject_free(ob->derivedFinal);
        WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
 
        return OPERATOR_FINISHED;
index be9a614a6fe5f361fc59e7c906a7255fe1da6053..352e633218a6dad45c298cba1a29a70ed1f67d21 100644 (file)
@@ -74,6 +74,7 @@
 #include "BKE_material.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
+#include "BKE_node.h"
 #include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
@@ -84,6 +85,7 @@
 
 #include "ED_image.h"
 #include "ED_mesh.h"
+#include "ED_node.h"
 #include "ED_paint.h"
 #include "ED_screen.h"
 #include "ED_uvedit.h"
@@ -362,7 +364,7 @@ static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int
 {
        MFace *mf = ps->dm_mface + face_index;
        Material *ma = ps->dm->mat[mf->mat_nr];
-       return ma->texpaintslot + ma->paint_active_slot;
+       return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
 }
 
 static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index)
@@ -373,7 +375,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_
        else {
                MFace *mf = ps->dm_mface + face_index;
                Material *ma = ps->dm->mat[mf->mat_nr];
-               TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
+               TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
                return slot ? slot->ima : ps->canvas_ima;
        }
 }
@@ -382,14 +384,14 @@ static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int
 {
        MFace *mf = ps->dm_mface + face_index;
        Material *ma = ps->dm->mat[mf->mat_nr];
-       return ma->texpaintslot + ma->paint_clone_slot;
+       return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
 }
 
 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;
+       TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
        return slot ? slot->ima : ps->clone_ima;
 }
 
@@ -4665,13 +4667,18 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
        IDProperty *idgroup;
        IDProperty *view_data = NULL;
        Object *ob = OBACT;
+       bool uvs, mat, tex;
 
        if (ob == NULL || ob->type != OB_MESH) {
                BKE_report(op->reports, RPT_ERROR, "No active mesh object");
                return OPERATOR_CANCELLED;
        }
 
-       paint_proj_mesh_data_ensure(C, ob, op);
+       if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) {
+               BKE_paint_data_warning(op->reports, uvs, mat, tex, true);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+               return OPERATOR_CANCELLED;              
+       }
 
        project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
 
@@ -4863,110 +4870,78 @@ void PAINT_OT_image_from_view(wmOperatorType *ot)
  * Data generation for projective texturing  *
  * *******************************************/
 
+void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil)
+{
+       BKE_reportf(reports, RPT_WARNING, "Missing%s%s%s%s detected!", 
+                  !uvs ? " UVs," : "",
+                  !mat ? " Materials," : "",
+                  !tex ? " Textures," : "",
+                  !stencil ? " Stencil," : ""
+                  );
+}
 
 /* Make sure that active object has a material, and assign UVs and image layers if they do not exist */
-void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
+bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil)
 {
        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);
+       ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
        Brush *br = BKE_paint_brush(&imapaint->paint);
+       bool hasmat = true;
+       bool hastex = true;
+       bool hasstencil = true;
+       bool hasuvs = true;
 
+       imapaint->missing_data = 0;
+       
        BLI_assert(ob->type == OB_MESH);
 
-       /* 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 (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+       if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
+               /* no material, add one */
+               if (ob->totcol == 0) {
+                       hasmat = false;
+                       hastex = false;
+               }
+               else {
+                       /* there may be material slots but they may be empty, check */
+                       int i;
+                       hasmat = false;
+                       hastex = false;
+                       
+                       for (i = 1; i < ob->totcol + 1; i++) {
+                               Material *ma = give_current_material(ob, i);
+                               
+                               if (ma) {
+                                       hasmat = true;
                                        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 (ma->texpaintslot) {
-                                                               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;
-                                                                                               
-                                                                                               if (!sima->pin)
-                                                                                                       ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima);
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }                                                       
+                                               if (ma->texpaintslot) {                                                 
+                                                       hastex = true;
+                                                       break;                                          
                                                }
                                        }
+                                       else {
+                                               hastex = true;
+                                               break;                                          
+                                       }
                                }
                        }
-                       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);
-                       }
                }
        }
-       
-       if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+       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);
-                       
-                       GPU_drawobject_free(ob->derivedFinal);
-                       
-                       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;
-                                                       
-                                                       if (!sima->pin)
-                                                               ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas);
-                                               }
-                                       }
-                               }
-                       }                       
+                       hastex = false;
                }               
        }
-               
+       
        me = BKE_mesh_from_object(ob);
        layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
 
        if (layernum == 0) {
-               BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended");
-
-               ED_mesh_uv_texture_add(me, "UVMap", true);
+               hasuvs = false;
        }
 
        /* Make sure we have a stencil to paint on! */
@@ -4974,16 +4949,29 @@ void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
                imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
 
                if (imapaint->stencil == 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->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color);
+                       hasstencil = false;
                }
        }
+
+       if (!hasuvs) imapaint->missing_data |= IMAGEPAINT_MISSING_UVS;
+       if (!hasmat) imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL;
+       if (!hastex) imapaint->missing_data |= IMAGEPAINT_MISSING_TEX;
+       if (!hasstencil) imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL;
+       
+       if (uvs) {
+               *uvs = hasuvs;
+       }
+       if (mat) {
+               *mat = hasmat;
+       }
+       if (tex) {
+               *tex = hastex;
+       }
+       if (stencil) {
+               *stencil = hasstencil;
+       }
+       
+       return hasuvs && hasmat && hastex && hasstencil;
 }
 
 /* Add layer operator */
@@ -5006,30 +4994,74 @@ static EnumPropertyItem layer_type_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
-bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
+static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
+{
+       Image *ima;
+       float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+       char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
+       int width = 1024;
+       int height = 1024;
+       bool use_float = false;
+       short gen_type = IMA_GENTYPE_BLANK;
+       bool alpha = false;
+
+       if (op) {
+               width = RNA_int_get(op->ptr, "width");
+               height = RNA_int_get(op->ptr, "height");
+               use_float = RNA_boolean_get(op->ptr, "float");
+               gen_type = RNA_enum_get(op->ptr, "generated_type");
+               RNA_float_get_array(op->ptr, "color", color);
+               alpha = RNA_boolean_get(op->ptr, "alpha");
+               RNA_string_get(op->ptr, "name", imagename);
+       }
+       ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
+                                                      gen_type, color);
+       
+       return ima;
+}
+
+static bool proj_paint_add_slot(bContext *C, wmOperator *op)
 {
        Object *ob = CTX_data_active_object(C);
        Scene *scene = CTX_data_scene(C);
+       Material *ma;
        bool is_bi = BKE_scene_uses_blender_internal(scene);
+       Image *ima = NULL;
 
        if (!ob)
                return false;
 
-       if (!ma)
-               ma = give_current_material(ob, ob->actcol);
+       ma = give_current_material(ob, ob->actcol);
 
        if (ma) {
+               Main *bmain = CTX_data_main(C);
+
+               if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) {
+                       bNode *imanode;
+                       bNodeTree *ntree = ma->nodetree;
 
-               if (!is_bi || ma->use_nodes) {
-                       /* not supported for now */
+                       if (!ntree) {
+                               ED_node_shader_default(C, &ma->id);
+                               ntree = ma->nodetree;
+                       }
+                       
+                       ma->use_nodes = true;
+                                               
+                       /* try to add an image node */
+                       imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+                       
+                       ima = proj_paint_image_create(op, bmain);
+                       imanode->id = &ima->id;
+                       
+                       nodeSetActive(ntree, imanode);
+                                       
+                       ntreeUpdateTree(CTX_data_main(C), ntree);
                }
                else {
                        MTex *mtex = add_mtex_id(&ma->id, -1);
 
                        /* successful creation of mtex layer, now create set */
                        if (mtex) {
-                               Main *bmain = CTX_data_main(C);
-                               Image *ima;
                                int type = MAP_COL;
                                int type_id = 0;
 
@@ -5049,47 +5081,33 @@ bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
                                mtex->mapto = type;
 
                                if (mtex->tex) {
-                                       float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-                                       char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
-                                       int width = 1024;
-                                       int height = 1024;
-                                       bool use_float = false;
-                                       short gen_type = IMA_GENTYPE_BLANK;
-                                       bool alpha = false;
-
-                                       if (op) {
-                                               width = RNA_int_get(op->ptr, "width");
-                                               height = RNA_int_get(op->ptr, "height");
-                                               use_float = RNA_boolean_get(op->ptr, "float");
-                                               gen_type = RNA_enum_get(op->ptr, "generated_type");
-                                               RNA_float_get_array(op->ptr, "color", color);
-                                               alpha = RNA_boolean_get(op->ptr, "alpha");
-                                               RNA_string_get(op->ptr, "name", imagename);
-                                       }
-
-                                       ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
-                                                                                      gen_type, color);
-
-                                       BKE_texpaint_slot_refresh_cache(scene, ma);
-                                       BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
-                                       WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
-                                       WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
-                                       DAG_id_tag_update(&ma->id, 0);
-                                       ED_area_tag_redraw(CTX_wm_area(C));
+                                       ima = mtex->tex->ima = proj_paint_image_create(op, bmain);
                                }
 
                                WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
-                               return true;
                        }
+                       WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);                             
+               }
+               
+               if (ima) {
+                       BKE_texpaint_slot_refresh_cache(scene, ma);
+                       BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+                       WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+                       DAG_id_tag_update(&ma->id, 0);
+                       ED_area_tag_redraw(CTX_wm_area(C));
+                       
+                       return true;                    
                }
        }
-
+       
        return false;
 }
 
 static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
 {
-       return proj_paint_add_slot(C, NULL, op);
+       if(proj_paint_add_slot(C, op))
+               return OPERATOR_FINISHED;
+       else return OPERATOR_CANCELLED;
 }
 
 
@@ -5100,6 +5118,12 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *
        Material *ma = give_current_material(ob, ob->actcol);
        int type = RNA_enum_get(op->ptr, "type");
 
+       if (!ma) {
+               ma = BKE_material_add(CTX_data_main(C), "Material");
+               /* no material found, just assign to first slot */
+               assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);           
+       }
+       
        type = RNA_enum_from_value(layer_type_items, type);
 
        /* get the name of the texture layer type */
index 5e1ac0cf8a88f464cdcc6eeb732169b5b3f1fcc9..c3b7ec60e715b5e75bd087b541543fb7726da430 100644 (file)
@@ -169,8 +169,6 @@ void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float m
 void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size);
 void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
 void paint_proj_stroke_done(void *ps);
-void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op);
-bool proj_paint_add_slot(bContext *C, struct Material *ma, struct wmOperator *op);
 
 void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
 bool paint_use_opacity_masking(struct Brush *brush);
index f34d0ff3f7b1ac1beb2c4e072373a24fa695c6d5..e03c8a5f106a09cc092e6922e1c7dbcd43d3d6b4 100644 (file)
@@ -395,7 +395,7 @@ static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
        Image *ima;
        MFace *mf = dm->getTessFaceArray(dm) + face_index;
        Material *ma = dm->mat[mf->mat_nr];
-       ima = ma->texpaintslot[ma->paint_active_slot].ima;
+       ima = ma ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
 
        return ima;
 }
index cd95e67f07043286f4dbc0312514f4e1128adba7..58b56e99119b86ad923fce552b2a8f916f6f5e08 100644 (file)
 #include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_icons.h"
 #include "BKE_image.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_packedFile.h"
+#include "BKE_paint.h"
 #include "BKE_report.h"
 #include "BKE_screen.h"
 #include "BKE_sound.h"
 
 #include "GPU_draw.h"
+#include "GPU_buffers.h"
 
 #include "IMB_colormanagement.h"
 #include "IMB_imbuf.h"
@@ -1905,6 +1908,12 @@ void IMAGE_OT_reload(wmOperatorType *ot)
 /********************** new image operator *********************/
 #define IMA_DEF_NAME N_("Untitled")
 
+enum {
+       GEN_CONTEXT_NONE = 0,
+       GEN_CONTEXT_PAINT_CANVAS = 1,
+       GEN_CONTEXT_PAINT_STENCIL = 2
+};
+
 static int image_new_exec(bContext *C, wmOperator *op)
 {
        SpaceImage *sima;
@@ -1918,6 +1927,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
        char *name = _name;
        float color[4];
        int width, height, floatbuf, gen_type, alpha;
+       int gen_context;
 
        /* retrieve state */
        sima = CTX_wm_space_image(C);
@@ -1937,6 +1947,7 @@ 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");
+       gen_context = RNA_enum_get(op->ptr, "gen_context");
 
        if (!alpha)
                color[3] = 1.0f;
@@ -1961,6 +1972,40 @@ static int image_new_exec(bContext *C, wmOperator *op)
        else if (sima) {
                ED_space_image_set(sima, scene, obedit, ima);
        }
+       else if (gen_context == GEN_CONTEXT_PAINT_CANVAS) {
+               bScreen *sc;
+               Object *ob = CTX_data_active_object(C);
+               
+               GPU_drawobject_free(ob->derivedFinal);  
+               if (scene->toolsettings->imapaint.canvas)
+                       id_us_min(&scene->toolsettings->imapaint.canvas->id);
+               scene->toolsettings->imapaint.canvas = ima;
+               
+               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;
+                                               
+                                               if (!sima->pin)
+                                                       ED_space_image_set(sima, scene, scene->obedit, ima);
+                                       }
+                               }
+                       }
+               }
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+       }
+       else if (gen_context == GEN_CONTEXT_PAINT_STENCIL) {
+               Object *ob = CTX_data_active_object(C);
+               if (scene->toolsettings->imapaint.stencil)
+                       id_us_min(&scene->toolsettings->imapaint.stencil->id);
+               scene->toolsettings->imapaint.stencil = ima;
+               BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);      
+               WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);             
+       }
        else {
                Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
                if (tex && tex->type == TEX_IMAGE) {
@@ -1991,6 +2036,13 @@ void IMAGE_OT_new(wmOperatorType *ot)
 {
        PropertyRNA *prop;
        static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+       static EnumPropertyItem gen_context_items[] = {
+               {GEN_CONTEXT_NONE, "NONE", 0, "None", ""},
+               {GEN_CONTEXT_PAINT_CANVAS, "PAINT_CANVAS", 0, "Paint Canvas", ""},
+           {GEN_CONTEXT_PAINT_STENCIL, "PAINT_STENCIL", 0, "Paint Stencil", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
        
        /* identifiers */
        ot->name = "New Image";
@@ -2017,7 +2069,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
                     "Generated Type", "Fill the image with a grid for UV map testing");
        RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
-       prop = RNA_def_boolean(ot->srna, "texstencil", 0, "Stencil", "Set Image as stencil");
+       prop = RNA_def_enum(ot->srna, "gen_context", gen_context_items, 0, "Gen Context", "Generation context");
        RNA_def_property_flag(prop, PROP_HIDDEN);
 
 }
index fb97a6ac9f49122778c0289cb8277a497cf2c72a..fa9ba23e45424f8ce42cf26bde577d2451798505 100644 (file)
@@ -279,10 +279,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
                if (!ma && BKE_image_has_alpha(texface->tpage))
                        alphablend = GPU_BLEND_ALPHA;
        }
-       else if (texpaint && ma) {
+       else if (texpaint) {
                if (gtexdraw.texpaint_material)
-                       ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
-               else 
+                       ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+               else
                        ima = gtexdraw.canvas;
        }
        else
@@ -315,6 +315,14 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
                                        
                                        glActiveTexture(GL_TEXTURE1);
                                        glEnable(GL_TEXTURE_2D);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+                                       glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
                                        glBindTexture(GL_TEXTURE_2D, ima->bindcode);
                                        glActiveTexture(GL_TEXTURE0);                                   
                                }
index ab13c704df4f7670e8e7b44ae3e93f2fdffdd58d..f8f962107f679ab4742b64d85291a015fbc47cdd 100644 (file)
@@ -836,7 +836,7 @@ typedef struct Paint {
 typedef struct ImagePaintSettings {
        Paint paint;
 
-       short flag, pad;
+       short flag, missing_data;
        
        /* for projection painting only */
        short seam_bleed, normal_angle;
@@ -1734,6 +1734,11 @@ typedef enum ImagePaintMode {
 #define IMAGEPAINT_PROJECT_LAYER_STENCIL       256
 #define IMAGEPAINT_PROJECT_LAYER_STENCIL_INV   512
 
+#define IMAGEPAINT_MISSING_UVS       (1 << 0)
+#define IMAGEPAINT_MISSING_MATERIAL  (1 << 1)
+#define IMAGEPAINT_MISSING_TEX       (1 << 2)
+#define IMAGEPAINT_MISSING_STENCIL   (1 << 3)
+
 /* toolsettings->uvcalc_flag */
 #define UVCALC_FILLHOLES                       1
 #define UVCALC_NO_ASPECT_CORRECT       2       /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */
index b5b938ca2db2c8c7e7b0feb2a877cc02f78a7a68..09e42e48e9313c9564c7f9e61854c5aacaf77ae9 100644 (file)
@@ -308,12 +308,22 @@ static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerR
        BKE_texpaint_slots_refresh_object(scene, ob);
 
        /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */
-       GPU_drawobject_free(ob->derivedFinal);  
-       WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
+       GPU_drawobject_free(ob->derivedFinal);
+       BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+       WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
+
+static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+{
+       Object *ob = OBACT;     
+       GPU_drawobject_free(ob->derivedFinal);
+       BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
+       WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
 }
 
 static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
 {
+       Object *ob = OBACT;
        bScreen *sc;
        Image *ima = scene->toolsettings->imapaint.canvas;
        
@@ -331,9 +341,16 @@ static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UN
                        }
                }
        }
-
+       
+       GPU_drawobject_free(ob->derivedFinal);
+       BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
 }
+
+static int rna_ImaPaint_detect_data(ImagePaintSettings *imapaint)
+{
+       return imapaint->missing_data == 0;
+}
 #else
 
 static void rna_def_palettecolor(BlenderRNA *brna)
@@ -614,6 +631,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
+       FunctionRNA *func;
 
        static EnumPropertyItem paint_type_items[] = {
                {IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0,
@@ -627,6 +645,13 @@ static void rna_def_image_paint(BlenderRNA *brna)
        RNA_def_struct_sdna(srna, "ImagePaintSettings");
        RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path");
        RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode");
+
+       /* functions */ 
+       func = RNA_def_function(srna, "detect_data", "rna_ImaPaint_detect_data");
+       RNA_def_function_ui_description(func, "Check if required texpaint data exist");
+
+       /* return type */
+       RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", ""));
        
        /* booleans */  
        prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE);
@@ -658,7 +683,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
        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_viewport_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
 
        prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
        RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -700,7 +725,32 @@ static void rna_def_image_paint(BlenderRNA *brna)
        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");  
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
+       
+       /* Missing data */
+       prop = RNA_def_property(srna, "missing_uvs", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_UVS);
+       RNA_def_property_ui_text(prop, "Missing UVs",
+                                "A UV layer is missing on the mesh");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);       
+       
+       prop = RNA_def_property(srna, "missing_materials", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_MATERIAL);
+       RNA_def_property_ui_text(prop, "Missing Materials",
+                                "The mesh is missing materials");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);       
+
+       prop = RNA_def_property(srna, "missing_stencil", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_STENCIL);
+       RNA_def_property_ui_text(prop, "Missing Stencil",
+                                "Image Painting does not have a stencil");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);       
+
+       prop = RNA_def_property(srna, "missing_texture", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_TEX);
+       RNA_def_property_ui_text(prop, "Missing Texture",
+                                "Image Painting does not have a texture to paint on");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);       
 }
 
 static void rna_def_particle_edit(BlenderRNA *brna)