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.
This commit is contained in:
Antonis Ryakiotakis 2014-10-06 15:12:06 +02:00 committed by Sergey Sharybin
parent 855e377a5c
commit ff623f3875
15 changed files with 425 additions and 184 deletions

View 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

View 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"
@ -1071,8 +1130,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)
@ -1110,9 +1170,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)
@ -1210,7 +1271,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"
@ -1218,8 +1279,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
@ -1474,11 +1535,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

View 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 */

View 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);
}
}

View 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;
}

View 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);

View 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)

View 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;

View 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 || ma->use_nodes) {
/* not supported for now */
if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) {
bNode *imanode;
bNodeTree *ntree = ma->nodetree;
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 */

View 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);

View 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;
}

View File

@ -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);
}

View 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);
}

View File

@ -835,7 +835,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;
@ -1733,6 +1733,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 */

View 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)