Fix T97469: Sculpt colors crash in multiresolution or dynamic topology modes.

Sculpt paint tools now pop up an error message if
dynamic topology or multires are enabled.

Implementation notes:

* SCULPT_vertex_colors_poll is now a static function in sculpt_ops.c.
  It is now used solely by the legacy color attribute conversion
  operators (SCULPT_OT_vertex_to_loop_colors and SCULPT_OT_loop_to_vertex_colors)
  and should be deleted when they are.
* There is a new method, SCULPT_handles_colors_report, that returns true if
  the sculpt session can handle color attributes; otherwise it returns false
  and displays an error message to the user.
This commit is contained in:
Joseph Eagar 2022-04-20 23:38:55 -07:00
parent 575ade22d4
commit 6f190f7f43
Notes: blender-bot 2023-02-14 04:39:18 +01:00
Referenced by issue #97553, Regression: Sculpt Brushes not supported in Multiresolution and Dyntopo Mode
Referenced by issue #97469, Sculpt paint tool crash to desktop with multiresolution modifier
Referenced by issue #97110, Regression: Using Sculpt mode Paint tool and Dyntopo crashes blender.
4 changed files with 66 additions and 23 deletions

View File

@ -3914,16 +3914,6 @@ bool SCULPT_mode_poll(bContext *C)
return ob && ob->mode & OB_MODE_SCULPT;
}
bool SCULPT_vertex_colors_poll(bContext *C)
{
if (!SCULPT_mode_poll(C)) {
return false;
}
Object *ob = CTX_data_active_object(C);
return ob->sculpt && SCULPT_has_colors(ob->sculpt);
}
bool SCULPT_mode_poll_view3d(bContext *C)
{
return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C));
@ -5256,6 +5246,24 @@ static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float
return SCULPT_stroke_get_location(C, co, mouse);
}
bool SCULPT_handles_colors_report(SculptSession *ss, ReportList *reports)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
return true;
case PBVH_BMESH:
BKE_report(reports, RPT_ERROR, "Not supported in dynamic topology mode.");
return false;
case PBVH_GRIDS:
BKE_report(reports, RPT_ERROR, "Not supported in multiresolution mode.");
return false;
}
BLI_assert_msg(0, "PBVH corruption, type was invalid.");
return false;
}
static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
{
/* Don't start the stroke until mouse goes over the mesh.
@ -5438,6 +5446,12 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
sculpt_brush_stroke_init(C, op);
Object *ob = CTX_data_active_object(C);
if (!SCULPT_handles_colors_report(ob->sculpt, op->reports)) {
return OPERATOR_CANCELLED;
}
stroke = paint_stroke_new(C,
op,
SCULPT_stroke_get_location,

View File

@ -24,6 +24,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "IMB_colormanagement.h"
@ -342,10 +343,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
}
/* Disable for multires and dyntopo for now */
if (!ss->pbvh) {
return OPERATOR_CANCELLED;
}
if (BKE_pbvh_type(pbvh) != PBVH_FACES) {
if (!ss->pbvh || !SCULPT_handles_colors_report(ss, op->reports)) {
return OPERATOR_CANCELLED;
}

View File

@ -782,7 +782,17 @@ bool SCULPT_mode_poll_view3d(struct bContext *C);
bool SCULPT_poll(struct bContext *C);
bool SCULPT_poll_view3d(struct bContext *C);
bool SCULPT_vertex_colors_poll(struct bContext *C);
/**
* Returns true if sculpt session can handle color attributes
* (BKE_pbvh_type(ss->pbvh) == PBVH_FACES). If false an error
* message will be shown to the user. Operators should return
* OPERATOR_CANCELLED in this case.
*
* NOTE: Does not check if a color attribute actually exists.
* Calling code must handle this itself; in most cases a call to
* BKE_sculpt_color_layer_create_if_needed() is sufficient.
*/
bool SCULPT_handles_colors_report(struct SculptSession *ss, struct ReportList *reports);
/** \} */

View File

@ -662,6 +662,21 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
static bool sculpt_colors_poll(bContext *C)
{
if (!SCULPT_mode_poll(C)) {
return false;
}
Object *ob = CTX_data_active_object(C);
if (!ob->sculpt || !ob->sculpt->pbvh || BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES) {
return false;
}
return SCULPT_has_colors(ob->sculpt);
}
static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot)
{
/* identifiers */
@ -670,7 +685,7 @@ static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot)
ot->idname = "SCULPT_OT_vertex_to_loop_colors";
/* api callbacks */
ot->poll = SCULPT_vertex_colors_poll;
ot->poll = sculpt_colors_poll;
ot->exec = vertex_to_loop_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -734,14 +749,14 @@ static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot)
ot->idname = "SCULPT_OT_loop_to_vertex_colors";
/* api callbacks */
ot->poll = SCULPT_vertex_colors_poll;
ot->poll = sculpt_colors_poll;
ot->exec = loop_to_vertex_colors_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int sculpt_sample_color_invoke(bContext *C,
wmOperator *UNUSED(op),
wmOperator *op,
const wmEvent *UNUSED(e))
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
@ -752,11 +767,17 @@ static int sculpt_sample_color_invoke(bContext *C,
int active_vertex = SCULPT_active_vertex_get(ss);
float active_vertex_color[4];
if (!SCULPT_has_colors(ss)) {
if (!SCULPT_handles_colors_report(ss, op->reports)) {
return OPERATOR_CANCELLED;
}
SCULPT_vertex_color_get(ss, active_vertex, active_vertex_color);
/* No color attribute? Set color to white. */
if (!SCULPT_has_colors(ss)) {
copy_v4_fl(active_vertex_color, 1.0f);
}
else {
SCULPT_vertex_color_get(ss, active_vertex, active_vertex_color);
}
float color_srgb[3];
copy_v3_v3(color_srgb, active_vertex_color);
@ -777,7 +798,7 @@ static void SCULPT_OT_sample_color(wmOperatorType *ot)
/* api callbacks */
ot->invoke = sculpt_sample_color_invoke;
ot->poll = SCULPT_vertex_colors_poll;
ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER;
}
@ -1025,8 +1046,8 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
/* Color data is not available in Multires. */
if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) {
/* Color data is not available in Multires or dyanmic topology. */
if (!SCULPT_handles_colors_report(ss, op->reports)) {
return OPERATOR_CANCELLED;
}