diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2014-10-06 17:12:06 +0400 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2014-10-06 22:10:12 +0400 |
commit | c03951da141497000dc9ab895f4f2299a5365c7a (patch) | |
tree | a06a93f6814b8825102d9d8bbdcab5d3f99f668f /source/blender | |
parent | 1f4915e2901c628ebfc8ab9f8e8a99e104e2cdbe (diff) |
Texture painting:
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/depsgraph.c | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.c | 13 | ||||
-rw-r--r-- | source/blender/editors/render/render_shading.c | 19 | ||||
-rw-r--r-- | source/blender/editors/render/render_update.c | 19 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 48 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 278 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 54 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawmesh.c | 14 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 7 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_sculpt_paint.c | 60 |
13 files changed, 351 insertions, 171 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 4eafdae9ebd..b080ca37e67 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -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 */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 93bb4849718..44a0b93fc01 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -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); } } diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index bf8559add6f..68471bfc2ba 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -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; } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 72b4da64c3e..6c996bcbd67 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -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); diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 6b58d3d55aa..df7ca9f11b2 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -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) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 87866f764bc..f4189b512e5 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -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; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index be9a614a6fe..352e633218a 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -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 */ diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 5e1ac0cf8a8..c3b7ec60e71 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -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); diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index f34d0ff3f7b..e03c8a5f106 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -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; } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index cd95e67f070..58b56e99119 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -49,17 +49,20 @@ #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); } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index fb97a6ac9f4..fa9ba23e454 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -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); } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ab13c704df4..f8f962107f6 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index b5b938ca2db..09e42e48e93 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -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) |