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:
authorJeroen Bakker <jbakker>2022-04-08 17:37:35 +0300
committerJeroen Bakker <jeroen@blender.org>2022-04-08 17:42:50 +0300
commit8b7cd1ed2a17e40661101eea4adae99e8e3d02e9 (patch)
tree8c3f1f2a14d699fad0367ce529254f2efb517acf /source/blender/editors
parent63d2980efa2fb170b471e4905ec81cd1472e5268 (diff)
Painting: Canvas switcher for painting brushes/tools.
This patch adds color attributes to TexPaintSlot. This allows an easier selection when painting color attributes. Previously when selecting a paint tool the user had to start a stroke, before the UI reflected the correct TexPaintSlot. Now when switching the slot the active tool is checked and immediate the UI is drawn correctly. In the future the canvas selector will also be used to select an image or image texture node to paint on. Basic implementation has already been done inside this patch. A limitation of this patch is that is isn't possible anymore to rename images directly from the selection panel. This is currently allowed in master. But as CustomDataLayers aren't ID fields and not owned by the material supporting this wouldn't be easy. {F12953989} In the future we should update the create slot operator to also include color attributes. Sources could also be extended to use other areas of the object that use image textures (particles, geom nodes, etc... ). Reviewed By: brecht Maniphest Tasks: T96709 Differential Revision: https://developer.blender.org/D14455
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_paint.h25
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_canvas.cc203
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c5
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c32
8 files changed, 273 insertions, 5 deletions
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index 2df0b5d2c01..6b015895b60 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -6,10 +6,13 @@
#pragma once
+#include "DNA_view3d_enums.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+struct PaintModeSettings;
struct ImBuf;
struct Image;
struct ImageUser;
@@ -109,6 +112,28 @@ void ED_paintcurve_undo_push_end(struct bContext *C);
/** Export for ED_undo_sys. */
void ED_paintcurve_undosys_type(struct UndoType *ut);
+/* paint_canvas.cc */
+struct Image *ED_paint_canvas_image_get(const struct PaintModeSettings *settings,
+ struct Object *ob);
+int ED_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *settings,
+ struct Object *ob);
+
+/** Color type of an object can be overridden in sculpt/paint mode. */
+eV3DShadingColorType ED_paint_shading_color_override(struct bContext *C,
+ const struct PaintModeSettings *settings,
+ struct Object *ob,
+ eV3DShadingColorType orig_color_type);
+
+/**
+ * Does the given tool use a paint canvas.
+ *
+ * When #tref isn't given the active tool from the context is used.
+ */
+bool ED_paint_tool_use_canvas(struct bContext *C, struct bToolRef *tref);
+
+/* Store the last used tool in the sculpt session. */
+void ED_paint_tool_update_sticky_shading_color(struct bContext *C, struct Object *ob);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index fe7683d12f5..b89cbcf87fa 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -34,6 +34,7 @@ set(SRC
curves_sculpt_grow_shrink.cc
curves_sculpt_ops.cc
curves_sculpt_snake_hook.cc
+ paint_canvas.cc
paint_cursor.c
paint_curve.c
paint_curve_undo.c
diff --git a/source/blender/editors/sculpt_paint/paint_canvas.cc b/source/blender/editors/sculpt_paint/paint_canvas.cc
new file mode 100644
index 00000000000..9a1a61cf3ab
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_canvas.cc
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_compiler_compat.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_node_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+
+#include "DEG_depsgraph.h"
+
+#include "NOD_shader.h"
+
+#include "WM_toolsystem.h"
+
+namespace blender::ed::sculpt_paint::canvas {
+static TexPaintSlot *get_active_slot(Object *ob)
+{
+ Material *mat = BKE_object_material_get(ob, ob->actcol);
+ if (mat == nullptr) {
+ return nullptr;
+ }
+ if (mat->texpaintslot == nullptr) {
+ return nullptr;
+ }
+ if (mat->paint_active_slot >= mat->tot_slots) {
+ return nullptr;
+ }
+
+ TexPaintSlot *slot = &mat->texpaintslot[mat->paint_active_slot];
+ return slot;
+}
+
+} // namespace blender::ed::sculpt_paint::canvas
+
+extern "C" {
+
+using namespace blender;
+using namespace blender::ed::sculpt_paint::canvas;
+
+/* Does the paint tool with the given idname uses a canvas. */
+static bool paint_tool_uses_canvas(StringRef idname)
+{
+ return ELEM(idname, "builtin_brush.Paint", "builtin_brush.Smear", "builtin.color_filter");
+}
+
+static bool paint_tool_shading_color_follows_last_used(StringRef idname)
+{
+ /* TODO(jbakker): complete this list. */
+ return ELEM(idname, "builtin_brush.Mask");
+}
+
+void ED_paint_tool_update_sticky_shading_color(struct bContext *C, struct Object *ob)
+{
+ if (ob == nullptr || ob->sculpt == nullptr) {
+ return;
+ }
+
+ bToolRef *tref = WM_toolsystem_ref_from_context(C);
+ if (tref == nullptr) {
+ return;
+ }
+ /* Do not modify when tool follows lat used tool. */
+ if (paint_tool_shading_color_follows_last_used(tref->idname)) {
+ return;
+ }
+
+ ob->sculpt->sticky_shading_color = paint_tool_uses_canvas(tref->idname);
+}
+
+static bool paint_tool_shading_color_follows_last_used_tool(struct bContext *C, struct Object *ob)
+{
+ if (ob == nullptr || ob->sculpt == nullptr) {
+ return false;
+ }
+
+ bToolRef *tref = WM_toolsystem_ref_from_context(C);
+ if (tref == nullptr) {
+ return false;
+ }
+
+ return paint_tool_shading_color_follows_last_used(tref->idname);
+}
+
+bool ED_paint_tool_use_canvas(struct bContext *C, bToolRef *tref)
+{
+ if (tref == nullptr) {
+ tref = WM_toolsystem_ref_from_context(C);
+ }
+ if (tref == nullptr) {
+ return false;
+ }
+
+ return paint_tool_uses_canvas(tref->idname);
+}
+
+eV3DShadingColorType ED_paint_shading_color_override(bContext *C,
+ const PaintModeSettings *settings,
+ Object *ob,
+ eV3DShadingColorType orig_color_type)
+{
+ if (!U.experimental.use_sculpt_texture_paint) {
+ return orig_color_type;
+ }
+ /* NOTE: This early exit is temporarily, until a paint mode has been added.
+ * For better integration with the vertex paint in sculpt mode we sticky
+ * with the last stoke when using tools like masking.
+ */
+ if (!ED_paint_tool_use_canvas(C, nullptr) &&
+ !(paint_tool_shading_color_follows_last_used_tool(C, ob) &&
+ ob->sculpt->sticky_shading_color)) {
+ return orig_color_type;
+ }
+
+ eV3DShadingColorType color_type = orig_color_type;
+ switch (settings->canvas_source) {
+ case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
+ color_type = V3D_SHADING_VERTEX_COLOR;
+ break;
+ case PAINT_CANVAS_SOURCE_IMAGE:
+ color_type = V3D_SHADING_TEXTURE_COLOR;
+ break;
+ case PAINT_CANVAS_SOURCE_MATERIAL: {
+ TexPaintSlot *slot = get_active_slot(ob);
+ if (slot == nullptr) {
+ break;
+ }
+
+ if (slot->ima) {
+ color_type = V3D_SHADING_TEXTURE_COLOR;
+ }
+ if (slot->attribute_name) {
+ color_type = V3D_SHADING_VERTEX_COLOR;
+ }
+
+ break;
+ }
+ }
+
+ return color_type;
+}
+
+Image *ED_paint_canvas_image_get(const struct PaintModeSettings *settings, struct Object *ob)
+{
+ switch (settings->canvas_source) {
+ case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
+ return nullptr;
+ case PAINT_CANVAS_SOURCE_IMAGE:
+ return settings->canvas_image;
+ case PAINT_CANVAS_SOURCE_MATERIAL: {
+ TexPaintSlot *slot = get_active_slot(ob);
+ if (slot == nullptr) {
+ break;
+ }
+ return slot->ima;
+ }
+ }
+ return nullptr;
+}
+
+int ED_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *settings,
+ struct Object *ob)
+{
+ switch (settings->canvas_source) {
+ case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
+ return -1;
+ case PAINT_CANVAS_SOURCE_IMAGE: {
+ /* Use active uv map of the object. */
+ if (ob->type != OB_MESH) {
+ return -1;
+ }
+
+ const Mesh *mesh = static_cast<Mesh *>(ob->data);
+ return CustomData_get_active_layer_index(&mesh->ldata, CD_MLOOPUV);
+ }
+ case PAINT_CANVAS_SOURCE_MATERIAL: {
+ /* Use uv map of the canvas. */
+ TexPaintSlot *slot = get_active_slot(ob);
+ if (slot == nullptr) {
+ break;
+ }
+
+ if (ob->type != OB_MESH) {
+ return -1;
+ }
+
+ if (slot->uvname == nullptr) {
+ return -1;
+ }
+
+ const Mesh *mesh = static_cast<Mesh *>(ob->data);
+ return CustomData_get_named_layer_index(&mesh->ldata, CD_MLOOPUV, slot->uvname);
+ }
+ }
+ return -1;
+}
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 233cfc3b33d..1303da71435 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -6336,7 +6336,7 @@ bool ED_paint_proj_mesh_data_check(
hasmat = true;
if (ma->texpaintslot == NULL) {
/* refresh here just in case */
- BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_texpaint_slot_refresh_cache(scene, ma, ob);
}
if (ma->texpaintslot != NULL &&
(ma->texpaintslot[ma->paint_active_slot].ima == NULL ||
@@ -6607,7 +6607,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
nodePositionPropagate(out_node);
if (ima) {
- BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_texpaint_slot_refresh_cache(scene, ma, ob);
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 4b5ac51a525..3f26f590b70 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -281,7 +281,7 @@ static void imapaint_pick_uv(
float p[2], w[3], absw, minabsw;
float matrix[4][4], proj[4][4];
int view[4];
- const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
+ const ePaintCanvasSource mode = scene->toolsettings->imapaint.mode;
const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
const int tottri = me_eval->runtime.looptris.len;
@@ -317,7 +317,7 @@ static void imapaint_pick_uv(
copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
}
- if (mode == IMAGEPAINT_MODE_MATERIAL) {
+ if (mode == PAINT_CANVAS_SOURCE_MATERIAL) {
const Material *ma;
const TexPaintSlot *slot;
@@ -431,7 +431,7 @@ void paint_sample_color(
Material *ma = BKE_object_material_get(ob_eval, mp->mat_nr + 1);
/* Force refresh since paint slots are not updated when changing interpolation. */
- BKE_texpaint_slot_refresh_cache(scene, ma);
+ BKE_texpaint_slot_refresh_cache(scene, ma, ob);
if (ma && ma->texpaintslot) {
image = ma->texpaintslot[ma->paint_active_slot].ima;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index e03f12025c8..24c5a9fce52 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -70,6 +70,7 @@
#include "WM_types.h"
#include "ED_object.h"
+#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_view3d.h"
@@ -4991,6 +4992,8 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
* earlier steps modifying the data. */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, need_mask, needs_colors);
+
+ ED_paint_tool_update_sticky_shading_color(C, ob);
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
@@ -5191,6 +5194,8 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
+ /* NOTE: This should be removed when paint mode is available. Paint mode can force based on the
+ * canvas it is painting on. (ref. use_sculpt_texture_paint). */
if (brush && SCULPT_TOOL_NEEDS_COLOR(brush->sculpt_tool)) {
View3D *v3d = CTX_wm_view3d(C);
if (v3d) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index cbb9180a209..e4180a36a98 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -36,6 +36,7 @@
#include "WM_types.h"
#include "ED_object.h"
+#include "ED_paint.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "paint_intern.h"
@@ -293,6 +294,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
FilterCache *filter_cache = ss->filter_cache;
filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
+ ED_paint_tool_update_sticky_shading_color(C, ob);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 3f2fbb97de1..6cb3d629e55 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1300,6 +1300,27 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params)
}
}
+static void view3d_do_msg_notify_workbench_view_update(struct bContext *C,
+ struct wmMsgSubscribeKey *UNUSED(msg_key),
+ struct wmMsgSubscribeValue *msg_val)
+{
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *area = (ScrArea *)msg_val->user_data;
+ View3D *v3d = (View3D *)area->spacedata.first;
+ if (v3d->shading.type == OB_SOLID) {
+ RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
+ DRWUpdateContext drw_context = {NULL};
+ drw_context.bmain = CTX_data_main(C);
+ drw_context.depsgraph = CTX_data_depsgraph_pointer(C);
+ drw_context.scene = scene;
+ drw_context.view_layer = CTX_data_view_layer(C);
+ drw_context.region = (ARegion *)(msg_val->owner);
+ drw_context.v3d = v3d;
+ drw_context.engine_type = engine_type;
+ DRW_notify_view_update(&drw_context);
+ }
+}
+
static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
{
struct wmMsgBus *mbus = params->message_bus;
@@ -1341,6 +1362,12 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP
.notify = ED_region_do_msg_notify_tag_redraw,
};
+ wmMsgSubscribeValue msg_sub_value_workbench_view_update = {
+ .owner = region,
+ .user_data = area,
+ .notify = view3d_do_msg_notify_workbench_view_update,
+ };
+
for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
msg_key_params.ptr.type = type_array[i];
WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
@@ -1374,6 +1401,11 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP
case OB_MODE_PARTICLE_EDIT:
WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
break;
+
+ case OB_MODE_SCULPT:
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, WorkSpace, tools, &msg_sub_value_workbench_view_update);
+ break;
default:
break;
}