Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py53
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py65
-rw-r--r--source/blender/blenkernel/intern/material.c18
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c134
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c71
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c91
-rw-r--r--source/blender/editors/space_image/image_ops.c9
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c13
-rw-r--r--source/blender/makesdna/DNA_scene_types.h15
-rw-r--r--source/blender/makesrna/intern/rna_material.c1
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c72
12 files changed, 378 insertions, 172 deletions
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 046e54d41fc..5c758b6568b 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -17,6 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
+from bpy.types import Menu
class UnifiedPaintPanel():
@@ -86,6 +87,18 @@ class UnifiedPaintPanel():
parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
+class VIEW3D_MT_tools_projectpaint_clone(Menu):
+ bl_label = "Clone Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ for i, tex in enumerate(context.active_object.data.uv_textures):
+ props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
+ props.data_path = "active_object.data.uv_texture_clone_index"
+ props.value = i
+
+
def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=False):
capabilities = brush.image_paint_capabilities
@@ -139,24 +152,38 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
elif brush.image_tool == 'CLONE':
col.separator()
if projpaint:
- col.prop(settings, "use_clone_layer", text="Clone from paint slot")
+ if settings.mode == 'MATERIAL':
+ col.prop(settings, "use_clone_layer", text="Clone from paint slot")
+ elif settings.mode == 'IMAGE':
+ col.prop(settings, "use_clone_layer", text="Clone from image/UV map")
if settings.use_clone_layer:
ob = context.active_object
col = layout.column()
- if len(ob.material_slots) > 1:
- col.label("Materials")
- col.template_list("MATERIAL_UL_matslots", "",
- ob, "material_slots",
- ob, "active_material_index", rows=2)
-
- mat = ob.active_material
- if mat:
- col.label("Clone Slot")
- col.template_list("TEXTURE_UL_texpaintslots", "",
- mat, "texture_paint_images",
- mat, "paint_clone_slot", rows=2)
+ if settings.mode == 'MATERIAL':
+ if len(ob.material_slots) > 1:
+ col.label("Materials")
+ col.template_list("MATERIAL_UL_matslots", "",
+ ob, "material_slots",
+ ob, "active_material_index", rows=2)
+
+ mat = ob.active_material
+ if mat:
+ col.label("Clone Slot")
+ col.template_list("TEXTURE_UL_texpaintslots", "",
+ mat, "texture_paint_images",
+ mat, "paint_clone_slot", rows=2)
+
+ elif settings.mode == 'IMAGE':
+ mesh = ob.data
+
+ clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
+ col.label("Image")
+ col.template_ID(settings, "clone_image")
+ col.label("UV Map")
+ col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
+
else:
col.prop(brush, "clone_image", text="Image")
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 59c68fc615d..6b0c5b1e993 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1026,31 +1026,39 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
ob = context.active_object
col = layout.column()
- if len(ob.material_slots) > 1:
- col.label("Materials")
- col.template_list("MATERIAL_UL_matslots", "layers",
- ob, "material_slots",
- ob, "active_material_index", rows=2)
-
- mat = ob.active_material
- if mat:
- col.label("Available Paint Slots")
- col.template_list("TEXTURE_UL_texpaintslots", "",
- mat, "texture_paint_images",
- mat, "paint_active_slot", rows=2)
+ col.label("Painting Mode")
+ col.prop(settings, "mode", text = "")
+ col.separator()
- if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
- row = col.row(align=True)
- row.operator_menu_enum("paint.add_texture_paint_slot", "type")
- row.operator("paint.delete_texture_paint_slot", text="", icon='X')
+ if settings.mode == 'MATERIAL':
+ if len(ob.material_slots) > 1:
+ col.label("Materials")
+ col.template_list("MATERIAL_UL_matslots", "layers",
+ ob, "material_slots",
+ ob, "active_material_index", rows=2)
+
+ mat = ob.active_material
+ if mat:
+ col.label("Available Paint Slots")
+ col.template_list("TEXTURE_UL_texpaintslots", "",
+ mat, "texture_paint_images",
+ mat, "paint_active_slot", rows=2)
- if mat.texture_paint_slots:
- slot = mat.texture_paint_slots[mat.paint_active_slot]
+ if (not mat.use_nodes) and (context.scene.render.engine == 'BLENDER_RENDER'):
+ row = col.row(align=True)
+ row.operator_menu_enum("paint.add_texture_paint_slot", "type")
+ row.operator("paint.delete_texture_paint_slot", text="", icon='X')
- col.prop(mat.texture_slots[slot.index], "blend_type")
- col.separator()
- col.label("UV Map")
- col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+ if mat.texture_paint_slots:
+ slot = mat.texture_paint_slots[mat.paint_active_slot]
+
+ col.prop(mat.texture_slots[slot.index], "blend_type")
+ col.separator()
+ col.label("UV Map")
+ col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+
+ elif settings.mode == 'IMAGE':
+ col.template_ID(settings, "canvas")
col.separator()
col.operator("image.save_dirty", text="Save All Images")
@@ -1089,7 +1097,6 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
col.label("Image")
row = col.row(align=True)
- row.operator("image.new", icon='ZOOMIN', text="Add New").texstencil = True;
row.template_ID(ipaint, "stencil_image")
col.label("Visualization")
@@ -1643,18 +1650,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
self.unified_paint_settings(col, context)
-class VIEW3D_MT_tools_projectpaint_clone(Menu):
- bl_label = "Clone Layer"
-
- def draw(self, context):
- layout = self.layout
-
- for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
- props.data_path = "active_object.data.uv_texture_clone_index"
- props.value = i
-
-
class VIEW3D_MT_tools_projectpaint_stencil(Menu):
bl_label = "Mask Layer"
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 50147149b0c..e7500392c81 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -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;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 8ada7b77bab..b2e49be1a5e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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) {
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index ea6d56155cc..f596f330534 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -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);
}
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 9362510a84d..3c6fb5dfe20 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -220,6 +220,8 @@ typedef struct ProjPaintState {
MTFace *dm_mtface_stencil;
Image *stencil_ima;
+ Image *canvas_ima;
+ Image *clone_ima;
float stencil_value;
/* projection painting only */
@@ -256,6 +258,7 @@ typedef struct ProjPaintState {
bool do_layer_stencil;
bool do_layer_stencil_inv;
bool do_stencil_brush;
+ bool do_material_slots;
bool do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
bool do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
@@ -368,16 +371,23 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_
MFace *mf = ps->dm_mface + face_index;
Material *ma = ps->dm->mat[mf->mat_nr];
TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
- return slot ? slot->ima : NULL;
+ return slot ? slot->ima : ps->canvas_ima;
}
}
-
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
{
MFace *mf = ps->dm_mface + face_index;
Material *ma = ps->dm->mat[mf->mat_nr];
- return &ma->texpaintslot[ma->paint_clone_slot];
+ return ma->texpaintslot + ma->paint_clone_slot;
+}
+
+static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index)
+{
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot;
+ return slot ? slot->ima : ps->clone_ima;
}
/* fast projection bucket array lookup, use the safe version for bound checking */
@@ -1466,7 +1476,7 @@ static ProjPixel *project_paint_uvpixel_init(
if (ps->tool == PAINT_TOOL_CLONE) {
if (ps->dm_mtface_clone) {
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_clone_slot(ps, face_index)->ima;
+ Image *other_tpage = project_paint_face_clone_image(ps, face_index);
const MTFace *tf_other = ps->dm_mtface_clone[face_index];
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
@@ -3005,6 +3015,19 @@ static void project_paint_begin(ProjPaintState *ps)
if (ps->do_stencil_brush)
tf_base = ps->dm_mtface_stencil;
}
+
+ if (ps->do_layer_clone) {
+ int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+
+ if (layer_num != -1)
+ tf_clone_base = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (tf_clone_base == NULL) {
+ /* get active instead */
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+
+ }
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
if (ps->dm->type != DM_TYPE_CDDM) {
@@ -3291,6 +3314,7 @@ static void project_paint_begin(ProjPaintState *ps)
/* all faces should have a valid slot, reassert here */
if (slot == NULL) {
tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ tpage = ps->canvas_ima;
}
else {
if (slot != slot_last) {
@@ -3302,32 +3326,43 @@ static void project_paint_begin(ProjPaintState *ps)
/* don't allow using the same inage for painting and stencilling */
if (slot->ima == ps->stencil_ima)
continue;
+
+ tpage = slot->ima;
}
}
+ else {
+ tpage = ps->stencil_ima;
+ }
*tf = tf_base + face_index;
if (ps->do_layer_clone) {
- slot_clone = project_paint_face_clone_slot(ps, face_index);
- /* all faces should have a valid slot, reassert here */
- if (ELEM(slot_clone, NULL, slot))
+ if (ps->do_material_slots) {
+ slot_clone = project_paint_face_clone_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(slot_clone, NULL, slot))
+ continue;
+ }
+ else if (ps->clone_ima == ps->canvas_ima)
continue;
-
+
tf_clone = ps->dm_mtface_clone + face_index;
-
- if (slot_clone != slot_last_clone) {
- if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
- tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
- slot_last_clone = slot_clone;
+
+ if (ps->do_material_slots) {
+ if (slot_clone != slot_last_clone) {
+ if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ slot_last_clone = slot_clone;
+ }
}
-
+
*tf_clone = tf_clone_base + face_index;
}
/* tfbase here should be non-null! */
BLI_assert (tf_base != NULL);
- if (is_face_sel && ((slot && (tpage = slot->ima)) || (tpage = project_paint_face_paint_image(ps, face_index)))) {
+ if (is_face_sel && tpage) {
const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
v1coSS = ps->screenCoords[mf->v1];
@@ -4480,7 +4515,13 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->scene = scene;
ps->ob = ob; /* allow override of active object */
+ ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
ps->stencil_ima = settings->imapaint.stencil;
+ ps->canvas_ima = (!ps->do_material_slots) ?
+ settings->imapaint.canvas : NULL;
+ ps->clone_ima = (!ps->do_material_slots) ?
+ settings->imapaint.clone : NULL;
+
/* setup projection painting data */
ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 0d463172f99..486bf2a5d66 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -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);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index f402f1cb4c8..0a3713a41e4 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -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);
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index e571584a10f..dd9b9dea02a 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -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 */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index d7bc8e56e38..c8b8e4d52a4 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -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
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index c395b963d48..37b6947cfac 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -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;
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index af6cf493f1e..c4b5461dece 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -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)