Curves: initial brush system integration for curves sculpt mode

This adds the boilerplate code that is necessary to use the tool/brush/paint
systems in the new sculpt curves mode.

Two temporary dummy tools are part of this patch. They do nothing and
only serve to test the boilerplate. When the first actual tool is added,
those dummy tools will be removed.

Differential Revision: https://developer.blender.org/D14117
This commit is contained in:
Jacques Lucke 2022-02-18 09:12:41 +01:00
parent 964d3a38fa
commit 61aaeb3745
26 changed files with 270 additions and 3 deletions

View File

@ -189,6 +189,7 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
'VERTEX_GPENCIL': "gpencil_vertex_tool",
'SCULPT_GPENCIL': "gpencil_sculpt_tool",
'WEIGHT_GPENCIL': "gpencil_weight_tool",
'SCULPT_CURVES': "curves_sculpt_tool",
}.get(mode, None)
else:
attr = None

View File

@ -5450,6 +5450,21 @@ def km_font(params):
return keymap
def km_sculpt_curves(params):
items = []
keymap = (
"Sculpt Curves",
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
{"items": items},
)
items.extend([
("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
])
return keymap
def km_object_non_modal(params):
items = []
keymap = (
@ -7771,6 +7786,7 @@ def generate_keymaps(params=None):
km_lattice(params),
km_particle(params),
km_font(params),
km_sculpt_curves(params),
km_object_non_modal(params),
# Modal maps.

View File

@ -2306,6 +2306,19 @@ class _defs_gpencil_weight:
)
class _defs_curves_sculpt:
@staticmethod
def generate_from_brushes(context):
return generate_from_enum_ex(
context,
idname_prefix="builtin_brush.",
icon_prefix="ops.curves.sculpt_",
type= bpy.types.Brush,
attr="curves_sculpt_tool",
)
class _defs_gpencil_vertex:
@staticmethod
@ -3065,6 +3078,9 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
else ()
),
],
'SCULPT_CURVES': [
_defs_curves_sculpt.generate_from_brushes,
],
}

View File

@ -74,9 +74,11 @@ typedef enum ePaintMode {
PAINT_MODE_VERTEX_GPENCIL = 7,
PAINT_MODE_SCULPT_GPENCIL = 8,
PAINT_MODE_WEIGHT_GPENCIL = 9,
/** Curves. */
PAINT_MODE_SCULPT_CURVES = 10,
/** Keep last. */
PAINT_MODE_INVALID = 10,
PAINT_MODE_INVALID = 11,
} ePaintMode;
#define PAINT_MODE_HAS_BRUSH(mode) !ELEM(mode, PAINT_MODE_SCULPT_UV)

View File

@ -327,6 +327,9 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
case PAINT_MODE_WEIGHT_GPENCIL:
paint_ptr = (Paint **)&ts->gp_weightpaint;
break;
case PAINT_MODE_SCULPT_CURVES:
paint_ptr = (Paint **)&ts->curves_sculpt;
break;
case PAINT_MODE_INVALID:
break;
}
@ -362,6 +365,8 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
return &ts->gp_sculptpaint->paint;
case PAINT_MODE_WEIGHT_GPENCIL:
return &ts->gp_weightpaint->paint;
case PAINT_MODE_SCULPT_CURVES:
return &ts->curves_sculpt->paint;
case PAINT_MODE_INVALID:
return NULL;
default:
@ -394,6 +399,8 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
return rna_enum_brush_gpencil_sculpt_types_items;
case PAINT_MODE_WEIGHT_GPENCIL:
return rna_enum_brush_gpencil_weight_types_items;
case PAINT_MODE_SCULPT_CURVES:
return rna_enum_brush_curves_sculpt_tool_items;
case PAINT_MODE_INVALID:
break;
}
@ -422,6 +429,8 @@ const char *BKE_paint_get_tool_prop_id_from_paintmode(ePaintMode mode)
return "gpencil_sculpt_tool";
case PAINT_MODE_WEIGHT_GPENCIL:
return "gpencil_weight_tool";
case PAINT_MODE_SCULPT_CURVES:
return "curves_sculpt_tool";
case PAINT_MODE_INVALID:
break;
}
@ -453,6 +462,8 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
return &ts->gp_sculptpaint->paint;
case OB_MODE_WEIGHT_GPENCIL:
return &ts->gp_weightpaint->paint;
case OB_MODE_SCULPT_CURVES:
return &ts->curves_sculpt->paint;
case OB_MODE_EDIT:
return ts->uvsculpt ? &ts->uvsculpt->paint : NULL;
default:
@ -573,6 +584,8 @@ ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
return PAINT_MODE_SCULPT_GPENCIL;
case CTX_MODE_WEIGHT_GPENCIL:
return PAINT_MODE_WEIGHT_GPENCIL;
case CTX_MODE_SCULPT_CURVES:
return PAINT_MODE_SCULPT_CURVES;
}
}
else if (tref->space_type == SPACE_IMAGE) {
@ -641,6 +654,10 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
paint->runtime.tool_offset = offsetof(Brush, gpencil_weight_tool);
paint->runtime.ob_mode = OB_MODE_WEIGHT_GPENCIL;
}
else if (ts->curves_sculpt && paint == &ts->curves_sculpt->paint) {
paint->runtime.tool_offset = offsetof(Brush, curves_sculpt_tool);
paint->runtime.ob_mode = OB_MODE_SCULPT_CURVES;
}
else {
BLI_assert_unreachable();
}
@ -668,6 +685,8 @@ uint BKE_paint_get_brush_tool_offset_from_paintmode(const ePaintMode mode)
return offsetof(Brush, gpencil_sculpt_tool);
case PAINT_MODE_WEIGHT_GPENCIL:
return offsetof(Brush, gpencil_weight_tool);
case PAINT_MODE_SCULPT_CURVES:
return offsetof(Brush, curves_sculpt_tool);
case PAINT_MODE_INVALID:
break; /* We don't use these yet. */
}
@ -1028,6 +1047,7 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
(Paint *)ts->vpaint,
(Paint *)ts->wpaint,
(Paint *)ts->uvsculpt,
(Paint *)ts->curves_sculpt,
(Paint *)&ts->imapaint));
#ifdef DEBUG
struct Paint paint_test = **r_paint;
@ -1075,6 +1095,10 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
UvSculpt *data = MEM_callocN(sizeof(*data), __func__);
paint = &data->paint;
}
else if ((CurvesSculpt **)r_paint == &ts->curves_sculpt) {
CurvesSculpt *data = MEM_callocN(sizeof(*data), __func__);
paint = &data->paint;
}
else if (*r_paint == &ts->imapaint.paint) {
paint = &ts->imapaint.paint;
}

View File

@ -98,6 +98,9 @@ void BKE_paint_toolslots_init_from_main(struct Main *bmain)
if (ts->gp_weightpaint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->gp_weightpaint->paint);
}
if (ts->curves_sculpt) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->curves_sculpt->paint);
}
}
}

View File

@ -718,6 +718,16 @@ static void scene_foreach_toolsettings(LibraryForeachIDData *data,
reader,
&toolsett_old->gp_weightpaint->paint));
}
if (toolsett->curves_sculpt) {
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_FUNCTION_CALL(
data,
do_undo_restore,
scene_foreach_paint(data,
&toolsett->curves_sculpt->paint,
do_undo_restore,
reader,
&toolsett_old->curves_sculpt->paint));
}
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
toolsett->gp_sculpt.guide.reference_object,
@ -972,6 +982,10 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BLO_write_struct(writer, GpWeightPaint, tos->gp_weightpaint);
BKE_paint_blend_write(writer, &tos->gp_weightpaint->paint);
}
if (tos->curves_sculpt) {
BLO_write_struct(writer, CurvesSculpt, tos->curves_sculpt);
BKE_paint_blend_write(writer, &tos->curves_sculpt->paint);
}
/* write grease-pencil custom ipo curve to file */
if (tos->gp_interpolate.custom_ipo) {
BKE_curvemapping_blend_write(writer, tos->gp_interpolate.custom_ipo);
@ -1148,6 +1162,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_vertexpaint);
direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_sculptpaint);
direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_weightpaint);
direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->curves_sculpt);
BKE_paint_blend_read_data(reader, sce, &sce->toolsettings->imapaint.paint);
@ -1406,6 +1421,9 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id)
if (sce->toolsettings->gp_weightpaint) {
BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->gp_weightpaint->paint);
}
if (sce->toolsettings->curves_sculpt) {
BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->curves_sculpt->paint);
}
if (sce->toolsettings->sculpt) {
BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->sculpt->gravity_object);
@ -1726,6 +1744,10 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint);
BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag);
}
if (ts->curves_sculpt) {
ts->curves_sculpt = MEM_dupallocN(ts->curves_sculpt);
BKE_paint_copy(&ts->curves_sculpt->paint, &ts->curves_sculpt->paint, flag);
}
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
ts->particle.paintcursor = NULL;
@ -1781,6 +1803,10 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
BKE_paint_free(&toolsettings->gp_weightpaint->paint);
MEM_freeN(toolsettings->gp_weightpaint);
}
if (toolsettings->curves_sculpt) {
BKE_paint_free(&toolsettings->curves_sculpt->paint);
MEM_freeN(toolsettings->curves_sculpt);
}
BKE_paint_free(&toolsettings->imapaint.paint);
/* free Grease Pencil interpolation curve */

View File

@ -182,6 +182,7 @@ static void OVERLAY_cache_init(void *vedata)
case CTX_MODE_WEIGHT_GPENCIL:
OVERLAY_edit_gpencil_cache_init(vedata);
break;
case CTX_MODE_SCULPT_CURVES:
case CTX_MODE_OBJECT:
break;
default:
@ -661,6 +662,8 @@ static void OVERLAY_draw_scene(void *vedata)
case CTX_MODE_WEIGHT_GPENCIL:
OVERLAY_edit_gpencil_draw(vedata);
break;
case CTX_MODE_SCULPT_CURVES:
break;
default:
break;
}

View File

@ -6,6 +6,7 @@ set(INC
../../blenlib
../../blentranslation
../../depsgraph
../../functions
../../makesdna
../../makesrna
../../windowmanager

View File

@ -10,9 +10,13 @@
#include "ED_object.h"
#include "WM_api.h"
#include "WM_toolsystem.h"
#include "WM_types.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "DNA_scene_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -32,6 +36,7 @@ static bool curves_sculptmode_toggle_poll(bContext *C)
static int curves_sculptmode_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
const bool is_mode_set = ob->mode == OB_MODE_SCULPT_CURVES;
@ -45,9 +50,11 @@ static int curves_sculptmode_toggle_exec(bContext *C, wmOperator *op)
ob->mode = OB_MODE_OBJECT;
}
else {
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->curves_sculpt);
ob->mode = OB_MODE_SCULPT_CURVES;
}
WM_toolsystem_update_from_context_view3d(C);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, nullptr);
return OPERATOR_CANCELLED;
}

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void ED_operatortypes_sculpt_curves(void);
#ifdef __cplusplus
}
#endif

View File

@ -24,6 +24,7 @@ set(INC
)
set(SRC
curves_sculpt_ops.cc
paint_cursor.c
paint_curve.c
paint_curve_undo.c
@ -66,6 +67,7 @@ set(SRC
sculpt_undo.c
sculpt_uv.c
curves_sculpt_intern.h
paint_intern.h
sculpt_intern.h
)

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
struct bContext;
#ifdef __cplusplus
extern "C" {
#endif
bool CURVES_SCULPT_mode_poll(struct bContext *C);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "WM_api.h"
#include "ED_curves_sculpt.h"
#include "curves_sculpt_intern.h"
#include "paint_intern.h"
bool CURVES_SCULPT_mode_poll(struct bContext *C)
{
Object *ob = CTX_data_active_object(C);
return ob && ob->mode & OB_MODE_SCULPT_CURVES;
}
static bool stroke_get_location(bContext *C, float out[3], const float mouse[2])
{
out[0] = mouse[0];
out[1] = mouse[1];
out[2] = 0;
UNUSED_VARS(C);
return true;
}
static bool stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
{
UNUSED_VARS(C, op, mouse);
return true;
}
static void stroke_update_step(bContext *C, PaintStroke *stroke, PointerRNA *itemptr)
{
UNUSED_VARS(C, stroke, itemptr);
}
static void stroke_done(const bContext *C, PaintStroke *stroke)
{
UNUSED_VARS(C, stroke);
}
static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
PaintStroke *stroke = paint_stroke_new(C,
op,
stroke_get_location,
stroke_test_start,
stroke_update_step,
nullptr,
stroke_done,
event->type);
op->customdata = stroke;
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op)
{
paint_stroke_cancel(C, op);
}
static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
{
ot->name = "Stroke Curves Sculpt";
ot->idname = "SCULPT_CURVES_OT_brush_stroke";
ot->description = "Sculpt curves using a brush";
ot->invoke = sculpt_curves_stroke_invoke;
ot->modal = paint_stroke_modal;
ot->cancel = sculpt_curves_stroke_cancel;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
paint_stroke_operator_properties(ot);
}
void ED_operatortypes_sculpt_curves()
{
WM_operatortype_append(SCULPT_CURVES_OT_brush_stroke);
}

View File

@ -39,6 +39,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
#include "curves_sculpt_intern.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@ -758,6 +759,7 @@ static const ePaintMode brush_select_paint_modes[] = {
PAINT_MODE_VERTEX_GPENCIL,
PAINT_MODE_SCULPT_GPENCIL,
PAINT_MODE_WEIGHT_GPENCIL,
PAINT_MODE_SCULPT_CURVES,
};
static int brush_select_exec(bContext *C, wmOperator *op)
@ -1388,6 +1390,10 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap = paint_stroke_modal_keymap(keyconf);
WM_modalkeymap_assign(keymap, "SCULPT_OT_brush_stroke");
/* Curves Sculpt mode. */
keymap = WM_keymap_ensure(keyconf, "Sculpt Curves", 0, 0);
keymap->poll = CURVES_SCULPT_mode_poll;
/* sculpt expand. */
sculpt_expand_modal_keymap(keyconf);
}

View File

@ -29,6 +29,7 @@
#include "ED_clip.h"
#include "ED_curve.h"
#include "ED_curves.h"
#include "ED_curves_sculpt.h"
#include "ED_fileselect.h"
#include "ED_geometry.h"
#include "ED_gizmo_library.h"
@ -96,6 +97,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_mesh();
ED_operatortypes_geometry();
ED_operatortypes_sculpt();
ED_operatortypes_sculpt_curves();
ED_operatortypes_uvedit();
ED_operatortypes_paint();
ED_operatortypes_physics();

View File

@ -413,6 +413,9 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *region)
keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0);
WM_event_add_keymap_handler(&region->handlers, keymap);
keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt Curves", 0, 0);
WM_event_add_keymap_handler(&region->handlers, keymap);
/* editfont keymap swallows all... */
keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0);
WM_event_add_keymap_handler(&region->handlers, keymap);
@ -1523,6 +1526,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
case CTX_MODE_VERTEX_GPENCIL:
ARRAY_SET_ITEMS(contexts, ".greasepencil_vertex");
break;
case CTX_MODE_SCULPT_CURVES:
ARRAY_SET_ITEMS(contexts, ".curves_sculpt");
break;
default:
break;
}

View File

@ -40,6 +40,7 @@ set(SRC
../include/ED_clip.h
../include/ED_curve.h
../include/ED_curves.h
../include/ED_curves_sculpt.h
../include/ED_datafiles.h
../include/ED_file_indexer.h
../include/ED_fileselect.h

View File

@ -455,6 +455,12 @@ typedef enum eBrushUVSculptTool {
UV_SCULPT_TOOL_PINCH = 2,
} eBrushUVSculptTool;
/* Brush.curves_sculpt_tool. */
typedef enum eBrushCurvesSculptTool {
CURVES_SCULPT_TOOL_TEST1 = 0,
CURVES_SCULPT_TOOL_TEST2 = 1,
} eBrushCurvesSculptTool;
/** When #BRUSH_ACCUMULATE is used */
#define SCULPT_TOOL_HAS_ACCUMULATE(t) \
ELEM(t, \

View File

@ -256,7 +256,9 @@ typedef struct Brush {
char gpencil_sculpt_tool;
/** Active grease pencil weight tool. */
char gpencil_weight_tool;
char _pad1[6];
/** Active curves sculpt tool. */
char curves_sculpt_tool;
char _pad1[5];
float autosmooth_factor;

View File

@ -995,6 +995,10 @@ typedef struct Sculpt {
struct Object *gravity_object;
} Sculpt;
typedef struct CurvesSculpt {
Paint paint;
} CurvesSculpt;
typedef struct UvSculpt {
Paint paint;
} UvSculpt;
@ -1380,6 +1384,8 @@ typedef struct ToolSettings {
GpSculptPaint *gp_sculptpaint;
/** Gpencil weight paint. */
GpWeightPaint *gp_weightpaint;
/** Curves sculpt. */
CurvesSculpt *curves_sculpt;
/* Vertex group weight - used only for editmode, not weight
* paint */

View File

@ -107,6 +107,7 @@ DEF_ENUM(rna_enum_brush_gpencil_types_items)
DEF_ENUM(rna_enum_brush_gpencil_vertex_types_items)
DEF_ENUM(rna_enum_brush_gpencil_sculpt_types_items)
DEF_ENUM(rna_enum_brush_gpencil_weight_types_items)
DEF_ENUM(rna_enum_brush_curves_sculpt_tool_items);
DEF_ENUM(rna_enum_brush_image_tool_items)
DEF_ENUM(rna_enum_axis_xy_items)

View File

@ -243,6 +243,12 @@ const EnumPropertyItem rna_enum_brush_gpencil_weight_types_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_brush_curves_sculpt_tool_items[] = {
{CURVES_SCULPT_TOOL_TEST1, "TEST1", ICON_NONE, "Test 1", ""},
{CURVES_SCULPT_TOOL_TEST2, "TEST2", ICON_NONE, "Test 2", ""},
{0, NULL, 0, NULL, NULL},
};
#ifndef RNA_RUNTIME
static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
{GP_BRUSH_ERASER_SOFT,
@ -2312,6 +2318,11 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grease Pencil Weight Paint Tool", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "curves_sculpt_tool", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_brush_curves_sculpt_tool_items);
RNA_def_property_ui_text(prop, "Curves Sculpt Tool", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
/** End per mode tool properties. */
prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);

View File

@ -352,6 +352,12 @@ static bool rna_Brush_mode_with_tool_poll(PointerRNA *ptr, PointerRNA value)
}
mode = OB_MODE_WEIGHT_GPENCIL;
}
else if (paint_contains_brush_slot(&ts->curves_sculpt->paint, tslot, &slot_index)) {
if (slot_index != brush->curves_sculpt_tool) {
return false;
}
mode = OB_MODE_SCULPT_CURVES;
}
return brush->ob_mode & mode;
}

View File

@ -158,7 +158,7 @@ wmKeyMap *WM_keymap_guess_from_context(const bContext *C)
km_id = "Grease Pencil Stroke Vertex Mode";
break;
case CTX_MODE_SCULPT_CURVES:
km_id = "Curves Sculpt Mode";
km_id = "Curves Sculpt";
break;
}
}

View File

@ -663,6 +663,8 @@ static const char *toolsystem_default_tool(const bToolKey *tkey)
return "builtin_brush.Weight";
case CTX_MODE_VERTEX_GPENCIL:
return "builtin_brush.Draw";
case CTX_MODE_SCULPT_CURVES:
return "builtin_brush.Test 1";
/* end temporary hack. */
case CTX_MODE_PARTICLE: