Texture painting:

Include explicit control for texturing:

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

The new option "Image", will use an explicit image field that artists can use
to select the image to paint on. This will should allow painting regardless
of the renderer used or for use in modifiers.
This commit is contained in:
Antony Riakiotakis 2014-08-28 16:40:38 +02:00
parent 512b738352
commit cf3ce7322a
12 changed files with 378 additions and 172 deletions

View File

@ -17,6 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from bpy.types import Menu
class UnifiedPaintPanel():
@ -86,6 +87,18 @@ class UnifiedPaintPanel():
parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
class VIEW3D_MT_tools_projectpaint_clone(Menu):
bl_label = "Clone Layer"
def draw(self, context):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
props.data_path = "active_object.data.uv_texture_clone_index"
props.value = i
def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=False):
capabilities = brush.image_paint_capabilities
@ -139,24 +152,38 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
elif brush.image_tool == 'CLONE':
col.separator()
if projpaint:
col.prop(settings, "use_clone_layer", text="Clone from paint slot")
if settings.mode == 'MATERIAL':
col.prop(settings, "use_clone_layer", text="Clone from paint slot")
elif settings.mode == 'IMAGE':
col.prop(settings, "use_clone_layer", text="Clone from image/UV map")
if settings.use_clone_layer:
ob = context.active_object
col = layout.column()
if len(ob.material_slots) > 1:
col.label("Materials")
col.template_list("MATERIAL_UL_matslots", "",
ob, "material_slots",
ob, "active_material_index", rows=2)
if settings.mode == 'MATERIAL':
if len(ob.material_slots) > 1:
col.label("Materials")
col.template_list("MATERIAL_UL_matslots", "",
ob, "material_slots",
ob, "active_material_index", rows=2)
mat = ob.active_material
if mat:
col.label("Clone Slot")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_images",
mat, "paint_clone_slot", rows=2)
mat = ob.active_material
if mat:
col.label("Clone Slot")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_images",
mat, "paint_clone_slot", rows=2)
elif settings.mode == 'IMAGE':
mesh = ob.data
clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
col.label("Image")
col.template_ID(settings, "clone_image")
col.label("UV Map")
col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
else:
col.prop(brush, "clone_image", text="Image")

View File

@ -1026,31 +1026,39 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
ob = context.active_object
col = layout.column()
if len(ob.material_slots) > 1:
col.label("Materials")
col.template_list("MATERIAL_UL_matslots", "layers",
ob, "material_slots",
ob, "active_material_index", rows=2)
col.label("Painting Mode")
col.prop(settings, "mode", text = "")
col.separator()
mat = ob.active_material
if mat:
col.label("Available Paint Slots")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_images",
mat, "paint_active_slot", rows=2)
if settings.mode == 'MATERIAL':
if len(ob.material_slots) > 1:
col.label("Materials")
col.template_list("MATERIAL_UL_matslots", "layers",
ob, "material_slots",
ob, "active_material_index", rows=2)
if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
row = col.row(align=True)
row.operator_menu_enum("paint.add_texture_paint_slot", "type")
row.operator("paint.delete_texture_paint_slot", text="", icon='X')
mat = ob.active_material
if mat:
col.label("Available Paint Slots")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_images",
mat, "paint_active_slot", rows=2)
if mat.texture_paint_slots:
slot = mat.texture_paint_slots[mat.paint_active_slot]
if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
row = col.row(align=True)
row.operator_menu_enum("paint.add_texture_paint_slot", "type")
row.operator("paint.delete_texture_paint_slot", text="", icon='X')
col.prop(mat.texture_slots[slot.index], "blend_type")
col.separator()
col.label("UV Map")
col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
if mat.texture_paint_slots:
slot = mat.texture_paint_slots[mat.paint_active_slot]
col.prop(mat.texture_slots[slot.index], "blend_type")
col.separator()
col.label("UV Map")
col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
elif settings.mode == 'IMAGE':
col.template_ID(settings, "canvas")
col.separator()
col.operator("image.save_dirty", text="Save All Images")
@ -1089,7 +1097,6 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
col.label("Image")
row = col.row(align=True)
row.operator("image.new", icon='ZOOMIN', text="Add New").texstencil = True;
row.template_ID(ipaint, "stencil_image")
col.label("Visualization")
@ -1643,18 +1650,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
self.unified_paint_settings(col, context)
class VIEW3D_MT_tools_projectpaint_clone(Menu):
bl_label = "Clone Layer"
def draw(self, context):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
props.data_path = "active_object.data.uv_texture_clone_index"
props.value = i
class VIEW3D_MT_tools_projectpaint_stencil(Menu):
bl_label = "Mask Layer"

View File

@ -274,8 +274,7 @@ Material *localize_material(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
if (ma->texpaintslot) man->texpaintslot = MEM_dupallocN(man->texpaintslot);
ma->texpaintslot = NULL;
man->preview = NULL;
if (ma->nodetree)
@ -1328,9 +1327,16 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
if (ma->texpaintslot) {
MEM_freeN(ma->texpaintslot);
ma->tot_slots = 0;
ma->texpaintslot = NULL;
}
if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
return;
}
if (use_nodes || ma->use_nodes) {
bNode *node, *active_node;
@ -1342,10 +1348,9 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
count++;
}
ma->tot_slots = count;
if (count == 0) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
return;
}
ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
@ -1367,10 +1372,9 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
}
}
ma->tot_slots = count;
if (count == 0) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
return;
}
@ -1387,6 +1391,8 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
}
}
ma->tot_slots = count;
if (ma->paint_active_slot >= count) {
ma->paint_active_slot = count - 1;
}

View File

@ -5152,6 +5152,14 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->imapaint.stencil =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.stencil);
if (sce->toolsettings->imapaint.clone)
sce->toolsettings->imapaint.clone =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.clone);
if (sce->toolsettings->imapaint.canvas)
sce->toolsettings->imapaint.canvas =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.canvas);
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base = sce->base.first; base; base = next) {

View File

@ -1363,41 +1363,87 @@ void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
Mesh *me;
int layernum;
ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
bScreen *sc;
Scene *scene = CTX_data_scene(C);
Main *bmain = CTX_data_main(C);
Brush *br = BKE_paint_brush(&imapaint->paint);
/* no material, add one */
if (ob->totcol == 0) {
Material *ma = BKE_material_add(CTX_data_main(C), "Material");
/* no material found, just assign to first slot */
assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
proj_paint_add_slot(C, ma, NULL);
}
else {
/* there may be material slots but they may be empty, check */
int i;
for (i = 1; i < ob->totcol + 1; i++) {
Material *ma = give_current_material(ob, i);
if (ma) {
if (!ma->texpaintslot) {
/* refresh here just in case */
BKE_texpaint_slot_refresh_cache(scene, ma);
/* if still no slots, we have to add */
if (!ma->texpaintslot)
proj_paint_add_slot(C, ma, NULL);
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
/* no material, add one */
if (ob->totcol == 0) {
Material *ma = BKE_material_add(CTX_data_main(C), "Material");
/* no material found, just assign to first slot */
assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
proj_paint_add_slot(C, ma, NULL);
}
else {
/* there may be material slots but they may be empty, check */
int i;
for (i = 1; i < ob->totcol + 1; i++) {
Material *ma = give_current_material(ob, i);
if (ma) {
if (!ma->texpaintslot) {
/* refresh here just in case */
BKE_texpaint_slot_refresh_cache(scene, ma);
/* if still no slots, we have to add */
if (!ma->texpaintslot) {
proj_paint_add_slot(C, ma, NULL);
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima);
}
}
}
}
}
}
}
else {
Material *ma = BKE_material_add(CTX_data_main(C), "Material");
/* no material found, just assign to first slot */
assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
proj_paint_add_slot(C, ma, NULL);
}
}
else {
Material *ma = BKE_material_add(CTX_data_main(C), "Material");
/* no material found, just assign to first slot */
assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF);
proj_paint_add_slot(C, ma, NULL);
}
}
}
else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE){
if (imapaint->canvas == NULL) {
int width;
int height;
Main *bmain = CTX_data_main(C);
float color[4] = {0.0, 0.0, 0.0, 1.0};
width = 1024;
height = 1024;
imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color);
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas);
}
}
}
}
}
}
me = BKE_mesh_from_object(ob);
layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
@ -1449,7 +1495,8 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
else {
bScreen *sc;
Main *bmain = CTX_data_main(C);
Material *ma;
Image *ima = NULL;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
/* This has to stay here to regenerate the texture paint
* cache in case we are loading a file */
@ -1457,19 +1504,26 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
paint_proj_mesh_data_ensure(C, ob, op);
/* set the current material active paint slot on image editor */
ma = give_current_material(ob, ob->actcol);
/* entering paint mode also sets image to editors */
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */
if (ma->tot_slots > 0) {
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
}
if (ma->texpaintslot)
ima = ma->texpaintslot[ma->paint_active_slot].ima;
}
else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
ima = imapaint->canvas;
}
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, ima);
}
}
}

View File

@ -220,6 +220,8 @@ typedef struct ProjPaintState {
MTFace *dm_mtface_stencil;
Image *stencil_ima;
Image *canvas_ima;
Image *clone_ima;
float stencil_value;
/* projection painting only */
@ -256,6 +258,7 @@ typedef struct ProjPaintState {
bool do_layer_stencil;
bool do_layer_stencil_inv;
bool do_stencil_brush;
bool do_material_slots;
bool do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
bool do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
@ -368,16 +371,23 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_
MFace *mf = ps->dm_mface + face_index;
Material *ma = ps->dm->mat[mf->mat_nr];
TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
return slot ? slot->ima : NULL;
return slot ? slot->ima : ps->canvas_ima;
}
}
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
{
MFace *mf = ps->dm_mface + face_index;
Material *ma = ps->dm->mat[mf->mat_nr];
return &ma->texpaintslot[ma->paint_clone_slot];
return ma->texpaintslot + ma->paint_clone_slot;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index)
{
MFace *mf = ps->dm_mface + face_index;
Material *ma = ps->dm->mat[mf->mat_nr];
TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot;
return slot ? slot->ima : ps->clone_ima;
}
/* fast projection bucket array lookup, use the safe version for bound checking */
@ -1466,7 +1476,7 @@ static ProjPixel *project_paint_uvpixel_init(
if (ps->tool == PAINT_TOOL_CLONE) {
if (ps->dm_mtface_clone) {
ImBuf *ibuf_other;
Image *other_tpage = project_paint_face_clone_slot(ps, face_index)->ima;
Image *other_tpage = project_paint_face_clone_image(ps, face_index);
const MTFace *tf_other = ps->dm_mtface_clone[face_index];
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
@ -3005,6 +3015,19 @@ static void project_paint_begin(ProjPaintState *ps)
if (ps->do_stencil_brush)
tf_base = ps->dm_mtface_stencil;
}
if (ps->do_layer_clone) {
int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
if (layer_num != -1)
tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
if (tf_clone_base == NULL) {
/* get active instead */
tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
}
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
if (ps->dm->type != DM_TYPE_CDDM) {
@ -3291,6 +3314,7 @@ static void project_paint_begin(ProjPaintState *ps)
/* all faces should have a valid slot, reassert here */
if (slot == NULL) {
tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
tpage = ps->canvas_ima;
}
else {
if (slot != slot_last) {
@ -3302,32 +3326,43 @@ static void project_paint_begin(ProjPaintState *ps)
/* don't allow using the same inage for painting and stencilling */
if (slot->ima == ps->stencil_ima)
continue;
tpage = slot->ima;
}
}
else {
tpage = ps->stencil_ima;
}
*tf = tf_base + face_index;
if (ps->do_layer_clone) {
slot_clone = project_paint_face_clone_slot(ps, face_index);
/* all faces should have a valid slot, reassert here */
if (ELEM(slot_clone, NULL, slot))
continue;
tf_clone = ps->dm_mtface_clone + face_index;
if (slot_clone != slot_last_clone) {
if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
slot_last_clone = slot_clone;
if (ps->do_material_slots) {
slot_clone = project_paint_face_clone_slot(ps, face_index);
/* all faces should have a valid slot, reassert here */
if (ELEM(slot_clone, NULL, slot))
continue;
}
else if (ps->clone_ima == ps->canvas_ima)
continue;
tf_clone = ps->dm_mtface_clone + face_index;
if (ps->do_material_slots) {
if (slot_clone != slot_last_clone) {
if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
slot_last_clone = slot_clone;
}
}
*tf_clone = tf_clone_base + face_index;
}
/* tfbase here should be non-null! */
BLI_assert (tf_base != NULL);
if (is_face_sel && ((slot && (tpage = slot->ima)) || (tpage = project_paint_face_paint_image(ps, face_index)))) {
if (is_face_sel && tpage) {
const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
v1coSS = ps->screenCoords[mf->v1];
@ -4480,7 +4515,13 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->scene = scene;
ps->ob = ob; /* allow override of active object */
ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
ps->stencil_ima = settings->imapaint.stencil;
ps->canvas_ima = (!ps->do_material_slots) ?
settings->imapaint.canvas : NULL;
ps->clone_ima = (!ps->do_material_slots) ?
settings->imapaint.clone : NULL;
/* setup projection painting data */
ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;

View File

@ -312,7 +312,7 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
if (mf.v4)
dm->getVert(dm, mf.v4, &mv[3]);
if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname)))
if (!(slot && slot->uvname && (tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname))))
tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
tf = &tf_base[a];
@ -428,6 +428,8 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
/* first try getting a colour directly from the mesh faces if possible */
Object *ob = OBACT;
bool sample_success = false;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
if (ob) {
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
@ -446,51 +448,58 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
view3d_operator_needs_opengl(C);
if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
Image *image = imapaint_face_image(dm, faceindex);
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (ibuf && ibuf->rect) {
float uv[2];
float u, v;
imapaint_pick_uv(scene, ob, faceindex, mval, uv);
sample_success = true;
u = fmodf(uv[0], 1.0f);
v = fmodf(uv[1], 1.0f);
if (u < 0.0f) u += 1.0f;
if (v < 0.0f) v += 1.0f;
u = u * ibuf->x - 0.5f;
v = v * ibuf->y - 0.5f;
if (ibuf->rect_float) {
float rgba_f[4];
bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
straight_to_premul_v4(rgba_f);
if (use_palette) {
linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
Image *image;
if (use_material)
image = imapaint_face_image(dm, faceindex);
else
image = imapaint->canvas;
if (image) {
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (ibuf && ibuf->rect) {
float uv[2];
float u, v;
imapaint_pick_uv(scene, ob, faceindex, mval, uv);
sample_success = true;
u = fmodf(uv[0], 1.0f);
v = fmodf(uv[1], 1.0f);
if (u < 0.0f) u += 1.0f;
if (v < 0.0f) v += 1.0f;
u = u * ibuf->x - 0.5f;
v = v * ibuf->y - 0.5f;
if (ibuf->rect_float) {
float rgba_f[4];
bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
straight_to_premul_v4(rgba_f);
if (use_palette) {
linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
}
else {
linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
BKE_brush_color_set(scene, br, rgba_f);
}
}
else {
linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
BKE_brush_color_set(scene, br, rgba_f);
}
}
else {
unsigned char rgba[4];
bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
if (use_palette) {
rgb_uchar_to_float(color->rgb, rgba);
}
else {
float rgba_f[3];
rgb_uchar_to_float(rgba_f, rgba);
BKE_brush_color_set(scene, br, rgba_f);
unsigned char rgba[4];
bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
if (use_palette) {
rgb_uchar_to_float(color->rgb, rgba);
}
else {
float rgba_f[3];
rgb_uchar_to_float(rgba_f, rgba);
BKE_brush_color_set(scene, br, rgba_f);
}
}
}
BKE_image_release_ibuf(image, ibuf, NULL);
}
BKE_image_release_ibuf(image, ibuf, NULL);
}
}
dm->release(dm);

View File

@ -1907,7 +1907,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
char *name = _name;
float color[4];
int width, height, floatbuf, gen_type, alpha;
bool stencil;
/* retrieve state */
sima = CTX_wm_space_image(C);
@ -1927,7 +1926,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
gen_type = RNA_enum_get(op->ptr, "generated_type");
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
stencil = RNA_boolean_get(op->ptr, "texstencil");
if (!alpha)
color[3] = 1.0f;
@ -1960,13 +1958,6 @@ static int image_new_exec(bContext *C, wmOperator *op)
tex->ima = ima;
ED_area_tag_redraw(CTX_wm_area(C));
}
else if (stencil) {
ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
if (imapaint->stencil)
id_us_min(&imapaint->stencil->id);
imapaint->stencil = ima;
}
}
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);

View File

@ -212,7 +212,8 @@ static Material *give_current_material_or_def(Object *ob, int matnr)
static struct TextureDrawState {
Object *ob;
Image *stencil;
Image *stencil; /* texture painting stencil */
Image *canvas; /* texture painting canvas, for image mode */
bool stencil_invert;
bool use_game_mat;
int is_lit, is_tex;
@ -221,7 +222,8 @@ static struct TextureDrawState {
unsigned char obcol[4];
float stencil_col[4];
bool is_texpaint;
} Gtexdraw = {NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false};
bool texpaint_material; /* use material slots for texture painting */
} Gtexdraw = {NULL, NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false, false};
static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
{
@ -280,7 +282,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
alphablend = GPU_BLEND_ALPHA;
}
else if (texpaint && ma) {
ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
if (gtexdraw.texpaint_material)
ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
else
ima = gtexdraw.canvas;
}
else
textured = 0;
@ -394,6 +399,8 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
Gtexdraw.stencil_invert = ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
copy_v3_v3(Gtexdraw.stencil_col, imapaint->stencil_col);
Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas;
Gtexdraw.is_tex = is_tex;
/* load the stencil texture here */

View File

@ -841,12 +841,14 @@ typedef struct ImagePaintSettings {
short seam_bleed, normal_angle;
short screen_grab_size[2]; /* capture size for re-projection */
int pad1;
int mode; /* mode used for texture painting */
void *paintcursor; /* wm handle */
struct Image *stencil; /* workaround until we support true layer masks */
void *paintcursor; /* wm handle */
struct Image *stencil; /* workaround until we support true layer masks */
struct Image *clone; /* clone layer for image mode for projective texture painting */
struct Image *canvas; /* canvas when the explicit system is used for painting */
float stencil_col[3];
float pad2;
float pad1;
} ImagePaintSettings;
/* ------------------------------------------- */
@ -1708,6 +1710,11 @@ typedef enum SculptFlags {
SCULPT_DYNTOPO_DETAIL_CONSTANT = (1 << 13)
} SculptFlags;
typedef enum ImagePaintMode {
IMAGEPAINT_MODE_MATERIAL, /* detect texture paint slots from the material */
IMAGEPAINT_MODE_IMAGE, /* select texture paint image directly */
} ImagePaintMode;
#if (DNA_DEPRECATED_GCC_POISON == 1)
#pragma GCC poison SCULPT_SYMM_X SCULPT_SYMM_Y SCULPT_SYMM_Z SCULPT_SYMMETRY_FEATHER
#endif

View File

@ -181,7 +181,6 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s
bScreen *sc;
Material *ma = ptr->id.data;
if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
struct bNode *node;
int index = 0;

View File

@ -34,8 +34,13 @@
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_paint.h"
#include "BKE_material.h"
#include "ED_image.h"
#include "WM_api.h"
#include "WM_types.h"
@ -286,11 +291,44 @@ static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* not the best solution maybe, but will refresh the 3D viewport */
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
Object *ob = OBACT;
/* of course we need to invalidate here */
BKE_texpaint_slots_refresh_object(scene, ob);
/* we assume that changing the current mode will invalidate the uv layers so we need to tag an update */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
}
static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
bScreen *sc;
Image *ima = scene->toolsettings->imapaint.canvas;
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, ima);
}
}
}
}
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
#else
static void rna_def_palettecolor(BlenderRNA *brna)
@ -571,6 +609,14 @@ static void rna_def_image_paint(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem paint_type_items[] = {
{IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0,
"Material", "Detect image slots from the material"},
{IMAGEPAINT_MODE_IMAGE, "IMAGE", 0,
"Image", "Set image for texture painting directly"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "ImagePaint", "Paint");
RNA_def_struct_sdna(srna, "ImagePaintSettings");
@ -596,24 +642,35 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "stencil");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update");
prop = RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clone");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Clone Image", "Image used as clone source");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "stencil_col");
RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update");
prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE);
@ -634,6 +691,11 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_int_array(srna, "screen_grab_size", 2, NULL, 0, 0, "screen_grab_size",
"Size to capture the image for re-projecting", 0, 0);
RNA_def_property_range(prop, 512, 16384);
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, paint_type_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
}
static void rna_def_particle_edit(BlenderRNA *brna)