diff options
Diffstat (limited to 'source')
18 files changed, 331 insertions, 94 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index b95e2e504d0..b695132416e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 280 -#define BLENDER_SUBVERSION 29 +#define BLENDER_SUBVERSION 30 /* Several breakages with 280, e.g. collections vs layers */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 3782d26fc1b..b8938c87275 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -168,6 +168,13 @@ void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct B void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]); + +/* Tool slot API. */ +void BKE_paint_toolslots_init_from_main(struct Main *bmain); +void BKE_paint_toolslots_len_ensure(struct Paint *paint, int len); +void BKE_paint_toolslots_brush_update_ex(struct Scene *scene, struct Paint *paint, struct Brush *brush); +void BKE_paint_toolslots_brush_update(struct Scene *scene, struct Paint *paint); + /* Used for both vertex color and weight paint */ struct SculptVertexPaintGeomMap { int *vert_map_mem; diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 77c9df12428..f2e2c0406af 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -168,6 +168,7 @@ set(SRC intern/outliner_treehash.c intern/packedFile.c intern/paint.c + intern/paint_toolslots.c intern/particle.c intern/particle_child.c intern/particle_distribute.c diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 13087877d5d..94ff7f3f2e5 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -304,7 +304,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_subdivide = 1; brush->gpencil_settings->draw_random_sub = 0.0f; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -336,7 +336,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->thick_smoothlvl = 3; brush->gpencil_settings->draw_random_sub = 0.0f; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -365,7 +365,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_subdivide = 1; brush->gpencil_settings->draw_random_sub = 0.0f; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -402,7 +402,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_subdivide = 1; brush->gpencil_settings->draw_random_sub = 0.0f; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -438,7 +438,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_subdivide = 0; brush->gpencil_settings->draw_random_sub = 0; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_BLOCK; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -469,7 +469,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->draw_subdivide = 1; brush->gpencil_settings->draw_random_sub = 0.0f; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_DRAW; + brush->gpencil_tool = GPAINT_TOOL_DRAW; brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; @@ -483,7 +483,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->fill_threshold = 0.1f; brush->gpencil_settings->fill_simplylvl = 1; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_FILL; + brush->gpencil_tool = GPAINT_TOOL_FILL; brush->gpencil_settings->draw_smoothfac = 0.1f; brush->gpencil_settings->draw_smoothlvl = 1; @@ -501,7 +501,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->size = 30.0f; brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER); brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE; + brush->gpencil_tool = GPAINT_TOOL_ERASE; brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT; brush->gpencil_settings->era_strength_f = 100.0f; brush->gpencil_settings->era_thickness_f = 0.10f; @@ -511,7 +511,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->size = 30.0f; brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE; + brush->gpencil_tool = GPAINT_TOOL_ERASE; brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD; /* Stroke Eraser brush */ @@ -519,7 +519,7 @@ void BKE_brush_gpencil_presets(bContext *C) brush->size = 30.0f; brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE; - brush->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE; + brush->gpencil_tool = GPAINT_TOOL_ERASE; brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE; /* set default brush */ diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index e82e1cf2d6b..ea1b35e4c1e 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -280,6 +280,9 @@ static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex) static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) { FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER); + for (int i = 0; i < paint->tool_slots_len; i++) { + FOREACH_CALLBACK_INVOKE(data, paint->tool_slots[i].brush, IDWALK_CB_USER); + } FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER); FOREACH_FINALIZE_VOID; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 545581e65ec..93b54fcb132 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -549,6 +549,7 @@ void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const char col[3]) void BKE_paint_free(Paint *paint) { curvemapping_free(paint->cavity_curve); + MEM_SAFE_FREE(paint->tool_slots); } /* called when copying scene settings, so even if 'src' and 'tar' are the same @@ -559,10 +560,16 @@ void BKE_paint_copy(Paint *src, Paint *tar, const int flag) { tar->brush = src->brush; tar->cavity_curve = curvemapping_copy(src->cavity_curve); + tar->tool_slots = MEM_dupallocN(src->tool_slots); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)tar->brush); id_us_plus((ID *)tar->palette); + if (src->tool_slots != NULL) { + for (int i = 0; i < tar->tool_slots_len; i++) { + id_us_plus((ID *)tar->tool_slots[i].brush); + } + } } } diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c new file mode 100644 index 00000000000..bdafe217276 --- /dev/null +++ b/source/blender/blenkernel/intern/paint_toolslots.c @@ -0,0 +1,126 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/paint_toolslots.c + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "DNA_brush_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_paint.h" + +void BKE_paint_toolslots_len_ensure(Paint *paint, int len) +{ + if (paint->tool_slots_len < len) { + paint->tool_slots = MEM_recallocN(paint->tool_slots, sizeof(*paint->tool_slots) * len); + paint->tool_slots_len = len; + } +} + +typedef bool (*BrushCompatFn)(const Brush *brush); +typedef char (*BrushToolFn)(const Brush *brush); + +static void paint_toolslots_init_paint( + Main *bmain, + Paint *paint, + BrushCompatFn brush_compat_fn, BrushToolFn brush_tool_fn) +{ + for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) { + if (brush_compat_fn(brush)) { + uint slot_index = brush_tool_fn(brush); + BKE_paint_toolslots_len_ensure(paint, slot_index + 1); + if (paint->tool_slots[slot_index].brush == NULL) { + paint->tool_slots[slot_index].brush = brush; + id_us_plus(&brush->id); + } + } + } +} + +/* Image paint. */ +static bool brush_compat_from_imagepaint(const Brush *brush) { return brush->ob_mode & OB_MODE_TEXTURE_PAINT; } +static char brush_tool_from_imagepaint(const Brush *brush) { return brush->imagepaint_tool; } +/* Sculpt. */ +static bool brush_compat_from_sculpt(const Brush *brush) { return brush->ob_mode & OB_MODE_SCULPT; } +static char brush_tool_from_sculpt(const Brush *brush) { return brush->sculpt_tool; } +/* Vertex Paint. */ +static bool brush_compat_from_vertexpaint(const Brush *brush) { return brush->ob_mode & OB_MODE_VERTEX_PAINT; } +static char brush_tool_from_vertexpaint(const Brush *brush) { return brush->vertexpaint_tool; } +/* Weight Paint. */ +static bool brush_compat_from_weightpaint(const Brush *brush) { return brush->ob_mode & OB_MODE_WEIGHT_PAINT; } +static char brush_tool_from_weightpaint(const Brush *brush) { return brush->vertexpaint_tool; } +/* Grease Pencil. */ +static bool brush_compat_from_gpencil(const Brush *brush) { return brush->ob_mode & OB_MODE_GPENCIL_PAINT; } +static char brush_tool_from_gpencil(const Brush *brush) { return brush->gpencil_tool; } + +void BKE_paint_toolslots_init_from_main(struct Main *bmain) +{ + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + ToolSettings *ts = scene->toolsettings; + paint_toolslots_init_paint(bmain, &ts->imapaint.paint, brush_compat_from_imagepaint, brush_tool_from_imagepaint); + paint_toolslots_init_paint(bmain, &ts->sculpt->paint, brush_compat_from_sculpt, brush_tool_from_sculpt); + paint_toolslots_init_paint(bmain, &ts->vpaint->paint, brush_compat_from_vertexpaint, brush_tool_from_vertexpaint); + paint_toolslots_init_paint(bmain, &ts->wpaint->paint, brush_compat_from_weightpaint, brush_tool_from_weightpaint); + paint_toolslots_init_paint(bmain, &ts->gp_paint->paint, brush_compat_from_gpencil, brush_tool_from_gpencil); + } +} + + +void BKE_paint_toolslots_brush_update_ex(Scene *scene, Paint *paint, Brush *brush) +{ + ToolSettings *ts = scene->toolsettings; + int slot_index; + if (paint == &ts->imapaint.paint) { + slot_index = brush->imagepaint_tool; + } + else if (paint == &ts->sculpt->paint) { + slot_index = brush->sculpt_tool; + } + else if (paint == &ts->vpaint->paint) { + slot_index = brush->vertexpaint_tool; + } + else if (paint == &ts->wpaint->paint) { + slot_index = brush->vertexpaint_tool; + } + else if (paint == &ts->gp_paint->paint) { + slot_index = brush->gpencil_tool; + } + BKE_paint_toolslots_len_ensure(paint, slot_index + 1); + PaintToolSlot *tslot = &paint->tool_slots[slot_index]; + id_us_plus(&brush->id); + id_us_min(&tslot->brush->id); + tslot->brush = brush; +} + +void BKE_paint_toolslots_brush_update(Scene *scene, Paint *paint) +{ + if (paint->brush == NULL) { + return; + } + BKE_paint_toolslots_brush_update_ex(scene, paint, paint->brush); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ddda9eb610e..6b5b5c59706 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5910,6 +5910,11 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p) { if (p) { p->brush = newlibadr_us(fd, sce->id.lib, p->brush); + for (int i = 0; i < p->tool_slots_len; i++) { + if (p->tool_slots[i].brush != NULL) { + p->tool_slots[i].brush = newlibadr_us(fd, sce->id.lib, p->tool_slots[i].brush); + } + } p->palette = newlibadr_us(fd, sce->id.lib, p->palette); p->paint_cursor = NULL; } @@ -6205,6 +6210,8 @@ static void direct_link_paint(FileData *fd, Paint *p) direct_link_curvemapping(fd, p->cavity_curve); else BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE); + + p->tool_slots = newdataadr(fd, p->tool_slots); } static void direct_link_paint_helper(FileData *fd, Paint **paint) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 98bebd70d14..1384a4f28e2 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -909,6 +909,15 @@ void do_versions_after_linking_280(Main *bmain) } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 280, 30)) { + for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) { + if (brush->gpencil_settings != NULL) { + brush->gpencil_tool = brush->gpencil_settings->brush_type; + } + } + BKE_paint_toolslots_init_from_main(bmain); + } } /* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already. @@ -2030,7 +2039,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) { if (brush->gpencil_settings != NULL) { BrushGpencilSettings *gp = brush->gpencil_settings; - if (gp->brush_type == GP_BRUSH_TYPE_ERASE) { + if (gp->brush_type == GPAINT_TOOL_ERASE) { gp->era_strength_f = 100.0f; gp->era_thickness_f = 10.0f; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 16bc845a3e9..c3693de4866 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2434,6 +2434,7 @@ static void write_paint(WriteData *wd, Paint *p) if (p->cavity_curve) { write_curvemapping(wd, p->cavity_curve); } + writedata(wd, DATA, sizeof(PaintToolSlot) * p->tool_slots_len, p->tool_slots); } static void write_layer_collections(WriteData *wd, ListBase *lb) diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index ed3eab7b642..d9a233b78d8 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -134,7 +134,7 @@ static bool gp_stroke_paintmode_draw_poll(bContext *C) Brush *brush = BKE_brush_getactive_gpencil(ts); return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush && brush->gpencil_settings) && - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW)); + (brush->gpencil_tool == GPAINT_TOOL_DRAW)); } /* Poll callback for stroke painting (erase brush) */ @@ -146,7 +146,7 @@ static bool gp_stroke_paintmode_erase_poll(bContext *C) Brush *brush = BKE_brush_getactive_gpencil(ts); return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush && brush->gpencil_settings) && - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)); + (brush->gpencil_tool == GPAINT_TOOL_ERASE)); } /* Poll callback for stroke painting (fill) */ @@ -158,7 +158,7 @@ static bool gp_stroke_paintmode_fill_poll(bContext *C) Brush *brush = BKE_brush_getactive_gpencil(ts); return ((gpd) && (gpd->flag & GP_DATA_STROKE_PAINTMODE) && (brush && brush->gpencil_settings) && - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_FILL)); + (brush->gpencil_tool == GPAINT_TOOL_FILL)); } /* Poll callback for stroke sculpting mode */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index e734542eb43..afd91d50e1f 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1546,10 +1546,10 @@ static void gp_stroke_doeraser(tGPsdata *p) float press = 1.0f; /* detect if use pressure in eraser */ - if (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE) { + if (brush->gpencil_tool == GPAINT_TOOL_ERASE) { use_pressure = (bool)(brush->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE); } - else if ((eraser != NULL) & (eraser->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) { + else if ((eraser != NULL) & (eraser->gpencil_tool == GPAINT_TOOL_ERASE)) { use_pressure = (bool)(eraser->gpencil_settings->flag & GP_BRUSH_USE_PRESSURE); } if (use_pressure) { @@ -1645,7 +1645,7 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts) Brush *brush_old = paint->brush; for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) { if ((brush->ob_mode == OB_MODE_GPENCIL_PAINT) && - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) + (brush->gpencil_tool == GPAINT_TOOL_ERASE)) { /* save first eraser to use later if no default */ if (brush_dft == NULL) { @@ -1668,7 +1668,7 @@ static Brush *gp_get_default_eraser(Main *bmain, ToolSettings *ts) brush_dft->size = 30.0f; brush_dft->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER); brush_dft->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT; - brush_dft->gpencil_settings->brush_type = GP_BRUSH_TYPE_ERASE; + brush_dft->gpencil_tool = GPAINT_TOOL_ERASE; brush_dft->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT; /* reset current brush */ @@ -1704,7 +1704,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) /* assign to temp tGPsdata */ p->brush = brush; - if (brush->gpencil_settings->brush_type != GP_BRUSH_TYPE_ERASE) { + if (brush->gpencil_tool != GPAINT_TOOL_ERASE) { p->eraser = gp_get_default_eraser(p->bmain, ts); } else { @@ -2317,7 +2317,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) /* if mode is draw and the brush is eraser, cancel */ if (paintmode != GP_PAINTMODE_ERASER) { - if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) { + if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) { return 0; } } @@ -2358,7 +2358,7 @@ static void gpencil_draw_cursor_set(tGPsdata *p) { Brush *brush = p->brush; if ((p->paintmode == GP_PAINTMODE_ERASER) || - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) + (brush->gpencil_tool == GPAINT_TOOL_ERASE)) { WM_cursor_modal_set(p->win, BC_CROSSCURSOR); /* XXX need a better cursor */ } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index fd7ce2d4139..5b8c11ac38c 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1554,7 +1554,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata) } /* eraser has special shape and use a different shader program */ - if (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE) { + if (paintbrush->gpencil_tool == GPAINT_TOOL_ERASE) { ED_gpencil_brush_draw_eraser(paintbrush, x, y); return; } @@ -1576,7 +1576,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata) if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && - (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW)) + (paintbrush->gpencil_tool == GPAINT_TOOL_DRAW)) { radius = 2.0f; copy_v3_v3(color, gp_style->stroke_rgba); @@ -1621,7 +1621,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *customdata) if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && ((paintbrush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && - (paintbrush->gpencil_settings->brush_type == GP_BRUSH_TYPE_DRAW)) + (paintbrush->gpencil_tool == GPAINT_TOOL_DRAW)) { imm_draw_circle_fill_2d(pos, x, y, radius, 40); } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 4801aee3c60..9cf23f30287 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -80,8 +80,7 @@ typedef struct BrushGpencilSettings { int input_samples; /* maximum distance before generate new point for very fast mouse movements */ float uv_random; /* random factor for UV rotation */ - - int brush_type; /* type of brush (draw, fill, erase, etc..) */ + int brush_type DNA_DEPRECATED; /* moved to 'Brush.gpencil_tool' */ int eraser_mode; /* soft, hard or stroke */ float active_smooth; /* smooth while drawing factor */ float era_strength_f; /* factor to apply to strength for soft eraser */ @@ -133,13 +132,6 @@ typedef enum eGP_FillDrawModes { GP_FILL_DMODE_CONTROL = 2, } eGP_FillDrawModes; -/* BrushGpencilSettings->brush type */ -typedef enum eGP_BrushType { - GP_BRUSH_TYPE_DRAW = 0, - GP_BRUSH_TYPE_FILL = 1, - GP_BRUSH_TYPE_ERASE = 2, -} eGP_BrushType; - /* BrushGpencilSettings->gp_eraser_mode */ typedef enum eGP_BrushEraserMode { GP_BRUSH_ERASER_SOFT = 0, @@ -216,6 +208,8 @@ typedef struct Brush { char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */ char imagepaint_tool; /* active image paint tool */ char mask_tool; /* enum eBrushMaskTool, only used if sculpt_tool is SCULPT_TOOL_MASK */ + char gpencil_tool; /* Active grease pencil tool. */ + char _pad0[7]; float autosmooth_factor; @@ -416,6 +410,15 @@ typedef enum eBrushImagePaintTool { PAINT_TOOL_MASK = 5 } eBrushImagePaintTool; + +/* BrushGpencilSettings->brush type */ +typedef enum eBrushGPaintTool { + GPAINT_TOOL_DRAW = 0, + GPAINT_TOOL_FILL = 1, + GPAINT_TOOL_ERASE = 2, +} eBrushGPaintTool; + + /* direction that the brush displaces along */ enum { SCULPT_DISP_DIR_AREA = 0, diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7d71f1250e3..31627760aa3 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -797,9 +797,21 @@ typedef struct TimeMarker { #define PAINT_MAX_INPUT_SAMPLES 64 +/* We might want to store other things here. */ +typedef struct PaintToolSlot { + struct Brush *brush; +} PaintToolSlot; + /* Paint Tool Base */ typedef struct Paint { struct Brush *brush; + + /* Each tool has it's own active brush, + * The currently active tool is defined by the current 'brush'. */ + struct PaintToolSlot *tool_slots; + int tool_slots_len; + char _pad1[4]; + struct Palette *palette; struct CurveMapping *cavity_curve; /* cavity curve */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index ad193eecbe8..2c0d647332c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -469,6 +469,7 @@ extern StructRNA RNA_OutflowFluidSettings; extern StructRNA RNA_PackedFile; extern StructRNA RNA_Paint; extern StructRNA RNA_PaintCurve; +extern StructRNA RNA_PaintToolSlot; extern StructRNA RNA_Palette; extern StructRNA RNA_PaletteColor; extern StructRNA RNA_Panel; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2366c5186e3..0bcb29fe860 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -126,10 +126,10 @@ const EnumPropertyItem rna_enum_brush_image_tool_items[] = { #ifndef RNA_RUNTIME static EnumPropertyItem rna_enum_gpencil_brush_types_items[] = { - { GP_BRUSH_TYPE_DRAW, "DRAW", ICON_GP_STROKE, "Draw", "The brush is of type used for drawing strokes" }, - { GP_BRUSH_TYPE_FILL, "FILL", ICON_COLOR, "Fill", "The brush is of type used for filling areas" }, - { GP_BRUSH_TYPE_ERASE, "ERASE", ICON_PANEL_CLOSE, "Erase", "The brush is used for erasing strokes" }, - { 0, NULL, 0, NULL, NULL } + {GPAINT_TOOL_DRAW, "DRAW", ICON_GP_STROKE, "Draw", "The brush is of type used for drawing strokes"}, + {GPAINT_TOOL_FILL, "FILL", ICON_COLOR, "Fill", "The brush is of type used for filling areas"}, + {GPAINT_TOOL_ERASE, "ERASE", ICON_PANEL_CLOSE, "Erase", "The brush is used for erasing strokes"}, + {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = { @@ -508,33 +508,6 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi WM_main_add_notifier(NC_BRUSH | NA_EDITED, br); } -static const EnumPropertyItem *rna_DynamicGpencil_type_itemf( - bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - Main *bmain = CTX_data_main(C); - EnumPropertyItem *item = NULL, item_tmp = { 0 }; - int totitem = 0; - int i = 0; - - Brush *brush; - for (brush = bmain->brush.first; brush; brush = brush->id.next, i++) { - if (brush->gpencil_settings == NULL) - continue; - - item_tmp.identifier = brush->id.name + 2; - item_tmp.name = brush->id.name + 2; - item_tmp.value = i; - item_tmp.icon = brush->gpencil_settings->icon_id; - - RNA_enum_item_add(&item, &totitem, &item_tmp); - } - - RNA_enum_item_end(&item, &totitem); - *r_free = true; - - return item; -} - static void rna_TextureSlot_brush_angle_update(bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); @@ -725,7 +698,7 @@ static void rna_BrushGpencilSettings_default_eraser_update(Main *bmain, Scene *s for (Brush *brush = bmain->brush.first; brush; brush = brush->id.next) { if ((brush != brush_cur) && (brush->ob_mode == OB_MODE_GPENCIL_PAINT) && - (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) + (brush->gpencil_tool == GPAINT_TOOL_ERASE)) { brush->gpencil_settings->flag &= ~GP_BRUSH_DEFAULT_ERASER; } @@ -739,7 +712,7 @@ static void rna_BrushGpencilSettings_eraser_mode_update(Main *UNUSED(bmain), Sce Brush *brush = paint->brush; /* set eraser icon */ - if ((brush) && (brush->gpencil_settings->brush_type == GP_BRUSH_TYPE_ERASE)) { + if ((brush) && (brush->gpencil_tool == GPAINT_TOOL_ERASE)) { switch (brush->gpencil_settings->eraser_mode) { case GP_BRUSH_ERASER_SOFT: brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT; @@ -964,27 +937,11 @@ static void rna_def_gpencil_options(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - /* Grease Pencil Drawing - generated dynamically */ - static const EnumPropertyItem prop_dynamic_gpencil_type[] = { - {1, "DRAW", 0, "Draw", ""}, - {0, NULL, 0, NULL, NULL} - }; - srna = RNA_def_struct(brna, "BrushGpencilSettings", NULL); RNA_def_struct_sdna(srna, "BrushGpencilSettings"); RNA_def_struct_path_func(srna, "rna_BrushGpencilSettings_path"); RNA_def_struct_ui_text(srna, "Grease Pencil Brush Settings", "Settings for grease pencil brush"); - /* grease pencil drawing brushes */ - prop = RNA_def_property(srna, "grease_pencil_tool", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "brush_type"); - RNA_def_property_enum_items(prop, prop_dynamic_gpencil_type); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_DynamicGpencil_type_itemf"); - RNA_def_property_ui_text(prop, "Grease Pencil Tool", ""); - /* TODO: GPXX review update */ - RNA_def_property_update(prop, 0, NULL); - //RNA_def_property_update(prop, 0, "rna_Brush_gpencil_tool_update"); - /* Sensitivity factor for new strokes */ prop = RNA_def_property(srna, "pen_sensitivity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "draw_sensitivity"); @@ -1230,12 +1187,6 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Enable Cursor", "Enable cursor on screen"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); - prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "brush_type"); - RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_types_items); - RNA_def_property_ui_text(prop, "Type", "Category of the brush"); - RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); - prop = RNA_def_property(srna, "eraser_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "eraser_mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_eraser_modes_items); @@ -1407,6 +1358,12 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Image Paint Tool", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_imagepaint_tool_update"); + prop = RNA_def_property(srna, "gpencil_tool", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "gpencil_tool"); + RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_types_items); + RNA_def_property_ui_text(prop, "Type", "Category of the brush"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, prop_direction_items); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 9efb4fb4d97..dcddf77b963 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -273,23 +273,102 @@ static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr)) static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value) { Scene *scene = (Scene *)ptr->id.data; + const Paint *paint = ptr->data; ToolSettings *ts = scene->toolsettings; Brush *brush = value.id.data; int mode = 0; + uint brush_tool_offset = 0; /* check the origin of the Paint struct to see which paint * mode to select from */ - if (ptr->data == &ts->imapaint) + if (paint == &ts->imapaint.paint) { mode = OB_MODE_TEXTURE_PAINT; - else if (ptr->data == ts->sculpt) + brush_tool_offset = offsetof(Brush, imagepaint_tool); + } + else if (paint == &ts->sculpt->paint) { mode = OB_MODE_SCULPT; - else if (ptr->data == ts->vpaint) + brush_tool_offset = offsetof(Brush, sculpt_tool); + } + else if (paint == &ts->vpaint->paint) { mode = OB_MODE_VERTEX_PAINT; - else if (ptr->data == ts->wpaint) + brush_tool_offset = offsetof(Brush, vertexpaint_tool); + } + else if (paint == &ts->wpaint->paint) { mode = OB_MODE_WEIGHT_PAINT; - else if (ptr->data == ts->gp_paint) + brush_tool_offset = offsetof(Brush, vertexpaint_tool); + } + else if (paint == &ts->gp_paint->paint) { mode = OB_MODE_GPENCIL_PAINT; + brush_tool_offset = offsetof(Brush, gpencil_tool); + } + + if (brush->ob_mode & mode) { + if (paint->brush) { + const char *tool_a = (const char *)POINTER_OFFSET(paint->brush, brush_tool_offset); + const char *tool_b = (const char *)POINTER_OFFSET(brush, brush_tool_offset); + if (*tool_a == *tool_b) { + return true; + } + } + else { + return true; + } + } + + return false; +} + +static bool paint_contains_brush_slot(const Paint *paint, const PaintToolSlot *tslot, int *r_index) +{ + if ((tslot >= paint->tool_slots) && + (tslot < (paint->tool_slots + paint->tool_slots_len))) + { + *r_index = (int)(tslot - paint->tool_slots); + return true; + } + return false; +} + +static bool rna_Brush_mode_with_tool_poll(PointerRNA *ptr, PointerRNA value) +{ + Scene *scene = (Scene *)ptr->id.data; + const PaintToolSlot *tslot = ptr->data; + ToolSettings *ts = scene->toolsettings; + Brush *brush = value.id.data; + int mode = 0; + int slot_index = 0; + + if (paint_contains_brush_slot(&ts->imapaint.paint, tslot, &slot_index)) { + if (slot_index != brush->imagepaint_tool) { + return false; + } + mode = OB_MODE_TEXTURE_PAINT; + } + else if (paint_contains_brush_slot(&ts->sculpt->paint, tslot, &slot_index)) { + if (slot_index != brush->sculpt_tool) { + return false; + } + mode = OB_MODE_SCULPT; + } + else if (paint_contains_brush_slot(&ts->vpaint->paint, tslot, &slot_index)) { + if (slot_index != brush->vertexpaint_tool) { + return false; + } + mode = OB_MODE_VERTEX_PAINT; + } + else if (paint_contains_brush_slot(&ts->wpaint->paint, tslot, &slot_index)) { + if (slot_index != brush->vertexpaint_tool) { + return false; + } + mode = OB_MODE_WEIGHT_PAINT; + } + else if (paint_contains_brush_slot(&ts->gp_paint->paint, tslot, &slot_index)) { + if (slot_index != brush->gpencil_tool) { + return false; + } + mode = OB_MODE_GPENCIL_PAINT; + } return brush->ob_mode & mode; } @@ -383,9 +462,11 @@ static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr)) static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { + Scene *scene = (Scene *)ptr->id.data; Paint *paint = ptr->data; Brush *br = paint->brush; BKE_paint_invalidate_overlay_all(); + BKE_paint_toolslots_brush_update(scene, paint); WM_main_add_notifier(NC_BRUSH | NA_SELECTED, br); } @@ -498,6 +579,19 @@ static void rna_def_paint_curve(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_CURVE_BEZCURVE); } +static void rna_def_paint_tool_slot(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PaintToolSlot", NULL); + RNA_def_struct_ui_text(srna, "Paint Tool Slot", ""); + + prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Brush_mode_with_tool_poll"); + RNA_def_property_ui_text(prop, "Brush", ""); +} static void rna_def_paint(BlenderRNA *brna) { @@ -514,6 +608,14 @@ static void rna_def_paint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Brush", "Active Brush"); RNA_def_property_update(prop, 0, "rna_Paint_brush_update"); + /* paint_tool_slots */ + prop = RNA_def_property(srna, "tool_slots", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "tool_slots", "tool_slots_len"); + RNA_def_property_struct_type(prop, "PaintToolSlot"); + /* don't dereference pointer! */ + RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_iterator_array_get", NULL, NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Paint Tool Slots", ""); + prop = RNA_def_property(srna, "palette", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, NULL); @@ -1276,6 +1378,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna) /* *** Non-Animated *** */ RNA_define_animate_sdna(false); rna_def_paint_curve(brna); + rna_def_paint_tool_slot(brna); rna_def_paint(brna); rna_def_sculpt(brna); rna_def_uv_sculpt(brna); |