Brush Assets: Various changes regarding brush assignment #119801

Merged
Brecht Van Lommel merged 5 commits from brecht/blender:refactor-brush into brush-assets-project 2024-03-22 20:08:59 +01:00
16 changed files with 55 additions and 479 deletions
Showing only changes of commit 626d6e76e0 - Show all commits

View File

@ -180,16 +180,5 @@ void BKE_brush_scale_size(int *r_brush_size,
*/
bool BKE_brush_has_cube_tip(const Brush *brush, PaintMode paint_mode);
/* Accessors */
#define BKE_brush_tool_get(brush, p) \
(CHECK_TYPE_ANY(brush, Brush *, const Brush *), \
*(const char *)POINTER_OFFSET(brush, (p)->runtime.tool_offset))
#define BKE_brush_tool_set(brush, p, tool) \
{ \
CHECK_TYPE_ANY(brush, Brush *); \
*(char *)POINTER_OFFSET(brush, (p)->runtime.tool_offset) = tool; \
} \
((void)0)
/* debugging only */
void BKE_brush_debug_print_state(Brush *br);

View File

@ -184,16 +184,12 @@ void BKE_paint_free(Paint *p);
*/
void BKE_paint_copy(const Paint *src, Paint *tar, int flag);
void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint);
void BKE_paint_cavity_curve_preset(Paint *p, int preset);
eObjectMode BKE_paint_object_mode_from_paintmode(PaintMode mode);
bool BKE_paint_ensure_from_paintmode(Main *bmain, Scene *sce, PaintMode mode);
Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode);
const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(PaintMode mode);
const char *BKE_paint_get_tool_enum_translation_context_from_paintmode(PaintMode mode);
const char *BKE_paint_get_tool_prop_id_from_paintmode(PaintMode mode);
uint BKE_paint_get_brush_tool_offset_from_paintmode(PaintMode mode);
Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer);
Paint *BKE_paint_get_active_from_context(const bContext *C);
@ -211,6 +207,8 @@ bool BKE_paint_brush_set_essentials(Main *bmain, Paint *paint, const char *name)
void BKE_paint_brush_set_default_references(ToolSettings *ts);
void BKE_paint_brush_validate(Main *bmain, Paint *paint);
/**
* Check if the given brush is a valid Brush Asset.
*
@ -286,19 +284,6 @@ void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, f
void BKE_paint_stroke_get_average(const Scene *scene, const Object *ob, float stroke[3]);
/* Tool slot API. */
void BKE_paint_toolslots_init_from_main(Main *bmain);
void BKE_paint_toolslots_len_ensure(Paint *paint, int len);
void BKE_paint_toolslots_brush_update_ex(Paint *paint, Brush *brush);
void BKE_paint_toolslots_brush_update(Paint *paint);
/**
* Run this to ensure brush types are set for each slot on entering modes
* (for new scenes for example).
*/
void BKE_paint_toolslots_brush_validate(Main *bmain, Paint *paint);
Brush *BKE_paint_toolslots_brush_get(Paint *paint, int slot_index);
/* .blend I/O */
void BKE_paint_blend_write(BlendWriter *writer, Paint *paint);

View File

@ -253,7 +253,6 @@ set(SRC
intern/packedFile.cc
intern/paint.cc
intern/paint_canvas.cc
intern/paint_toolslots.cc
intern/particle.cc
intern/particle_child.cc
intern/particle_distribute.cc

View File

@ -441,61 +441,6 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(const PaintMode m
return nullptr;
}
const char *BKE_paint_get_tool_prop_id_from_paintmode(const PaintMode mode)
{
switch (mode) {
case PaintMode::Sculpt:
return "sculpt_tool";
case PaintMode::Vertex:
return "vertex_tool";
case PaintMode::Weight:
return "weight_tool";
case PaintMode::Texture2D:
case PaintMode::Texture3D:
return "image_tool";
case PaintMode::SculptUV:
return "uv_sculpt_tool";
case PaintMode::GPencil:
return "gpencil_tool";
case PaintMode::VertexGPencil:
return "gpencil_vertex_tool";
case PaintMode::SculptGPencil:
return "gpencil_sculpt_tool";
case PaintMode::WeightGPencil:
return "gpencil_weight_tool";
case PaintMode::SculptCurves:
return "curves_sculpt_tool";
case PaintMode::Invalid:
break;
}
/* Invalid paint mode. */
return nullptr;
}
const char *BKE_paint_get_tool_enum_translation_context_from_paintmode(const PaintMode mode)
{
switch (mode) {
case PaintMode::Sculpt:
case PaintMode::GPencil:
case PaintMode::Texture2D:
case PaintMode::Texture3D:
return BLT_I18NCONTEXT_ID_BRUSH;
case PaintMode::Vertex:
case PaintMode::Weight:
case PaintMode::SculptUV:
case PaintMode::VertexGPencil:
case PaintMode::SculptGPencil:
case PaintMode::WeightGPencil:
case PaintMode::SculptCurves:
case PaintMode::Invalid:
break;
}
/* Invalid paint mode. */
return BLT_I18NCONTEXT_DEFAULT;
}
Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
{
if (sce && view_layer) {
@ -705,8 +650,6 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
{
if (p) {
p->brush = br;
BKE_paint_toolslots_brush_update(p);
}
}
@ -863,30 +806,35 @@ bool BKE_paint_brush_set_essentials(Main *bmain, Paint *paint, const char *name)
return paint_brush_set_from_asset_reference(bmain, paint);
}
void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
void BKE_paint_brush_validate(Main *bmain, Paint *paint)
{
/* Clear brush with invalid mode. Unclear if this can still happen,
* but kept from old paint toolslots code. */
Brush *brush = BKE_paint_brush(paint);
if (brush && (paint->runtime.ob_mode & brush->ob_mode) == 0) {
BKE_paint_brush_set(paint, nullptr);
BKE_paint_brush_set_default(bmain, paint);
}
}
static void paint_runtime_init(const ToolSettings *ts, Paint *paint)
{
if (paint == &ts->imapaint.paint) {
paint->runtime.tool_offset = offsetof(Brush, imagepaint_tool);
paint->runtime.ob_mode = OB_MODE_TEXTURE_PAINT;
}
else if (ts->sculpt && paint == &ts->sculpt->paint) {
paint->runtime.tool_offset = offsetof(Brush, sculpt_tool);
paint->runtime.ob_mode = OB_MODE_SCULPT;
}
else if (ts->vpaint && paint == &ts->vpaint->paint) {
paint->runtime.tool_offset = offsetof(Brush, vertexpaint_tool);
paint->runtime.ob_mode = OB_MODE_VERTEX_PAINT;
}
else if (ts->wpaint && paint == &ts->wpaint->paint) {
paint->runtime.tool_offset = offsetof(Brush, weightpaint_tool);
paint->runtime.ob_mode = OB_MODE_WEIGHT_PAINT;
}
else if (ts->uvsculpt && paint == &ts->uvsculpt->paint) {
paint->runtime.tool_offset = offsetof(Brush, uv_sculpt_tool);
paint->runtime.ob_mode = OB_MODE_EDIT;
}
else if (ts->gp_paint && paint == &ts->gp_paint->paint) {
paint->runtime.tool_offset = offsetof(Brush, gpencil_tool);
if (U.experimental.use_grease_pencil_version3) {
paint->runtime.ob_mode = OB_MODE_PAINT_GREASE_PENCIL;
}
@ -895,24 +843,22 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
}
}
else if (ts->gp_vertexpaint && paint == &ts->gp_vertexpaint->paint) {
paint->runtime.tool_offset = offsetof(Brush, gpencil_vertex_tool);
paint->runtime.ob_mode = OB_MODE_VERTEX_GPENCIL_LEGACY;
}
else if (ts->gp_sculptpaint && paint == &ts->gp_sculptpaint->paint) {
paint->runtime.tool_offset = offsetof(Brush, gpencil_sculpt_tool);
paint->runtime.ob_mode = OB_MODE_SCULPT_GPENCIL_LEGACY;
}
else if (ts->gp_weightpaint && paint == &ts->gp_weightpaint->paint) {
paint->runtime.tool_offset = offsetof(Brush, gpencil_weight_tool);
paint->runtime.ob_mode = OB_MODE_WEIGHT_GPENCIL_LEGACY;
}
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();
}
paint->runtime.initialized = true;
}
uint BKE_paint_get_brush_tool_offset_from_paintmode(const PaintMode mode)
@ -1283,13 +1229,11 @@ bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
{
Paint *paint = nullptr;
if (*r_paint) {
/* Tool offset should never be 0 for initialized paint settings, so it's a reliable way to
* check if already initialized. */
if ((*r_paint)->runtime.tool_offset == 0) {
if (!(*r_paint)->runtime.initialized) {
/* Currently only image painting is initialized this way, others have to be allocated. */
BLI_assert(ELEM(*r_paint, (Paint *)&ts->imapaint));
BKE_paint_runtime_init(ts, *r_paint);
paint_runtime_init(ts, *r_paint);
}
else {
BLI_assert(ELEM(*r_paint,
@ -1306,11 +1250,10 @@ bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
(Paint *)&ts->imapaint));
#ifndef NDEBUG
Paint paint_test = **r_paint;
BKE_paint_runtime_init(ts, *r_paint);
paint_runtime_init(ts, *r_paint);
/* Swap so debug doesn't hide errors when release fails. */
std::swap(**r_paint, paint_test);
BLI_assert(paint_test.runtime.ob_mode == (*r_paint)->runtime.ob_mode);
BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
#endif
}
paint_brush_set_from_asset_reference(bmain, *r_paint);
@ -1360,7 +1303,7 @@ bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
*r_paint = paint;
BKE_paint_runtime_init(ts, paint);
paint_runtime_init(ts, paint);
BKE_paint_brush_set_default(bmain, paint);
return false;
@ -1386,7 +1329,6 @@ void BKE_paint_init(Main *bmain, Scene *sce, PaintMode mode, const uchar col[3])
void BKE_paint_free(Paint *paint)
{
BKE_curvemapping_free(paint->cavity_curve);
MEM_SAFE_FREE(paint->tool_slots);
MEM_delete(paint->brush_asset_reference);
}
@ -1394,7 +1336,6 @@ void BKE_paint_copy(const Paint *src, Paint *dst, const int flag)
{
dst->brush = src->brush;
dst->cavity_curve = BKE_curvemapping_copy(src->cavity_curve);
dst->tool_slots = static_cast<PaintToolSlot *>(MEM_dupallocN(src->tool_slots));
if (src->brush_asset_reference) {
dst->brush_asset_reference = MEM_new<AssetWeakReference>(__func__,
@ -1426,7 +1367,6 @@ void BKE_paint_blend_write(BlendWriter *writer, Paint *p)
if (p->brush_asset_reference) {
BKE_asset_weak_reference_write(writer, p->brush_asset_reference);
}
BLO_write_struct_array(writer, PaintToolSlot, p->tool_slots_len, p->tool_slots);
}
void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Paint *p)
@ -1444,17 +1384,8 @@ void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Pain
BKE_asset_weak_reference_read(reader, p->brush_asset_reference);
}
BLO_read_data_address(reader, &p->tool_slots);
/* Workaround for invalid data written in older versions. */
const size_t expected_size = sizeof(PaintToolSlot) * p->tool_slots_len;
if (p->tool_slots && MEM_allocN_len(p->tool_slots) < expected_size) {
MEM_freeN(p->tool_slots);
p->tool_slots = static_cast<PaintToolSlot *>(MEM_callocN(expected_size, "PaintToolSlot"));
}
p->paint_cursor = nullptr;
BKE_paint_runtime_init(scene->toolsettings, p);
paint_runtime_init(scene->toolsettings, p);
}
bool paint_is_grid_face_hidden(const blender::BoundedBitSpan grid_hidden,

View File

@ -1,164 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include <climits>
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
#include "BKE_brush.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_paint.hh"
/* -------------------------------------------------------------------- */
/** \name Tool Slot Initialization / Versioning
*
* These functions run to update old files (while versioning),
* take care only to perform low-level functions here.
* \{ */
void BKE_paint_toolslots_len_ensure(Paint *paint, int len)
{
/* Tool slots are 'uchar'. */
BLI_assert(len <= UCHAR_MAX);
if (paint->tool_slots_len < len) {
paint->tool_slots = static_cast<PaintToolSlot *>(
MEM_recallocN(paint->tool_slots, sizeof(*paint->tool_slots) * len));
paint->tool_slots_len = len;
}
}
static void paint_toolslots_init(Main *bmain, Paint *paint)
{
if (paint == nullptr) {
return;
}
const eObjectMode ob_mode = eObjectMode(paint->runtime.ob_mode);
BLI_assert(paint->runtime.tool_offset && ob_mode);
for (Brush *brush = static_cast<Brush *>(bmain->brushes.first); brush;
brush = static_cast<Brush *>(brush->id.next))
{
if (brush->ob_mode & ob_mode) {
const int slot_index = BKE_brush_tool_get(brush, paint);
BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
if (paint->tool_slots[slot_index].brush == nullptr) {
paint->tool_slots[slot_index].brush = brush;
}
}
}
}
/**
* Initialize runtime since this is called from versioning code.
*/
static void paint_toolslots_init_with_runtime(Main *bmain, ToolSettings *ts, Paint *paint)
{
if (paint == nullptr) {
return;
}
/* Needed so #Paint_Runtime is updated when versioning. */
BKE_paint_runtime_init(ts, paint);
paint_toolslots_init(bmain, paint);
}
void BKE_paint_toolslots_init_from_main(Main *bmain)
{
for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene;
scene = static_cast<Scene *>(scene->id.next))
{
ToolSettings *ts = scene->toolsettings;
paint_toolslots_init_with_runtime(bmain, ts, &ts->imapaint.paint);
if (ts->sculpt) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->sculpt->paint);
}
if (ts->vpaint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->vpaint->paint);
}
if (ts->wpaint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->wpaint->paint);
}
if (ts->uvsculpt) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->uvsculpt->paint);
}
if (ts->gp_paint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->gp_paint->paint);
}
if (ts->gp_vertexpaint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->gp_vertexpaint->paint);
}
if (ts->gp_sculptpaint) {
paint_toolslots_init_with_runtime(bmain, ts, &ts->gp_sculptpaint->paint);
}
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);
}
}
}
/** \} */
void BKE_paint_toolslots_brush_update_ex(Paint *paint, Brush *brush)
{
const uint tool_offset = paint->runtime.tool_offset;
UNUSED_VARS_NDEBUG(tool_offset);
BLI_assert(tool_offset != 0);
const int slot_index = BKE_brush_tool_get(brush, paint);
BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
PaintToolSlot *tslot = &paint->tool_slots[slot_index];
tslot->brush = brush;
}
void BKE_paint_toolslots_brush_update(Paint *paint)
{
if (paint->brush == nullptr) {
return;
}
BKE_paint_toolslots_brush_update_ex(paint, paint->brush);
}
void BKE_paint_toolslots_brush_validate(Main *bmain, Paint *paint)
{
/* Clear slots with invalid slots or mode (unlikely but possible). */
const uint tool_offset = paint->runtime.tool_offset;
UNUSED_VARS_NDEBUG(tool_offset);
const eObjectMode ob_mode = eObjectMode(paint->runtime.ob_mode);
BLI_assert(tool_offset && ob_mode);
for (int i = 0; i < paint->tool_slots_len; i++) {
PaintToolSlot *tslot = &paint->tool_slots[i];
if (tslot->brush) {
if ((i != BKE_brush_tool_get(tslot->brush, paint)) || (tslot->brush->ob_mode & ob_mode) == 0)
{
tslot->brush = nullptr;
}
}
}
/* Unlikely but possible the active brush is not currently using a slot. */
BKE_paint_toolslots_brush_update(paint);
/* Fill slots from brushes. */
paint_toolslots_init(bmain, paint);
}
Brush *BKE_paint_toolslots_brush_get(Paint *paint, int slot_index)
{
if (slot_index < paint->tool_slots_len) {
PaintToolSlot *tslot = &paint->tool_slots[slot_index];
return tslot->brush;
}
return nullptr;
}

View File

@ -602,26 +602,6 @@ static void scene_foreach_paint(LibraryForeachIDData *data,
&paint_old->brush,
IDWALK_CB_NOP);
for (int i = 0; i < paint_old->tool_slots_len; i++) {
/* This is a bit tricky.
* - In case we do not do `undo_restore`, `paint` and `paint_old` pointers are the same, so
* this is equivalent to simply looping over slots from `paint`.
* - In case we do `undo_restore`, we only want to consider the slots from the old one, since
* those are the one we keep in the end.
* + In case the new data has less valid slots, we feed in a dummy null pointer.
* + In case the new data has more valid slots, the extra ones are ignored.
*/
brush_tmp = nullptr;
brush_p = (paint && i < paint->tool_slots_len) ? &paint->tool_slots[i].brush : &brush_tmp;
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER_P(data,
brush_p,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
&paint_old->tool_slots[i].brush,
IDWALK_CB_NOP);
}
Palette *palette_tmp = nullptr;
Palette **palette_p = paint ? &paint->palette : &palette_tmp;
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER_P(data,

View File

@ -2557,7 +2557,6 @@ void do_versions_after_linking_280(FileData *fd, Main *bmain)
brush->gpencil_tool = brush->gpencil_settings->brush_type;
}
}
BKE_paint_toolslots_init_from_main(bmain);
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 280, 38)) {

View File

@ -2200,7 +2200,7 @@ static int gpencil_brush_reset_all_exec(bContext *C, wmOperator * /*op*/)
}
}
BKE_paint_toolslots_brush_validate(bmain, paint);
BKE_paint_brush_validate(bmain, paint);
/* Set Again the first brush of the mode. */
Brush *deft_brush = gpencil_brush_get_first_by_mode(bmain, paint, mode, tool);

View File

@ -400,7 +400,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
if ((brush == nullptr) || (brush->gpencil_settings == nullptr)) {
BKE_brush_gpencil_paint_presets(bmain, ts, true);
}
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint);
BKE_paint_brush_validate(bmain, &ts->gp_paint->paint);
}
/* setup other modes */
@ -507,7 +507,7 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
const bool reset_mode = (BKE_paint_brush(&ts->gp_sculptpaint->paint) == nullptr);
BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
BKE_paint_brush_validate(bmain, &ts->gp_sculptpaint->paint);
}
/* setup other modes */
@ -621,7 +621,7 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
const bool reset_mode = (BKE_paint_brush(&ts->gp_weightpaint->paint) == nullptr);
BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
BKE_paint_brush_validate(bmain, &ts->gp_weightpaint->paint);
}
/* setup other modes */
@ -729,7 +729,7 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
const bool reset_mode = (BKE_paint_brush(&ts->gp_vertexpaint->paint) == nullptr);
BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
BKE_paint_brush_validate(bmain, &ts->gp_vertexpaint->paint);
/* Ensure Palette by default. */
BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));

View File

@ -1216,12 +1216,8 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
BKE_brush_gpencil_paint_presets(bmain, ts, true);
}
/* Set Draw brush. */
brush = BKE_paint_toolslots_brush_get(paint, 0);
BKE_brush_tool_set(brush, paint, 0);
BKE_paint_brush_set(paint, brush);
tgpi->brush = brush;
/* Set brush. */
tgpi->brush = BKE_paint_brush(paint);
/* control points */
tgpi->gpd->runtime.cp_points = static_cast<bGPDcontrolpoint *>(

View File

@ -901,7 +901,7 @@ void ED_object_texture_paint_mode_enter_ex(Main *bmain,
BKE_paint_init(bmain, scene, PaintMode::Texture3D, PAINT_CURSOR_TEXTURE_PAINT);
BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
BKE_paint_brush_validate(bmain, &imapaint->paint);
if (U.glreslimit != 0) {
BKE_image_free_all_gputextures(bmain);

View File

@ -860,7 +860,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint);
BKE_paint_brush_validate(bmain, &ts->vpaint->paint);
}
BKE_mesh_batch_cache_dirty_tag((Mesh *)ob->data, BKE_MESH_BATCH_DIRTY_ALL);

View File

@ -1674,7 +1674,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
BKE_paint_brush_validate(bmain, &ts->wpaint->paint);
}
/* Prepare armature posemode. */

View File

@ -527,7 +527,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, false, op->reports);
BKE_paint_toolslots_brush_validate(bmain, &ts->sculpt->paint);
BKE_paint_brush_validate(bmain, &ts->sculpt->paint);
if (ob->mode & mode_flag) {
Mesh *mesh = static_cast<Mesh *>(ob->data);

View File

@ -950,16 +950,11 @@ typedef struct TimeMarker {
typedef struct Paint_Runtime {
/** Avoid having to compare with scene pointer everywhere. */
unsigned int tool_offset;
unsigned int initialized;
unsigned short ob_mode;
char _pad[2];
} Paint_Runtime;
/** We might want to store other things here. */
typedef struct PaintToolSlot {
struct Brush *brush;
} PaintToolSlot;
/** Paint Tool Base. */
typedef struct Paint {
/**
@ -976,14 +971,6 @@ typedef struct Paint {
*/
struct AssetWeakReference *brush_asset_reference;
/**
* Each tool has its 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;
/** Cavity curve. */
struct CurveMapping *cavity_curve;

View File

@ -270,114 +270,27 @@ static std::optional<std::string> rna_ParticleEdit_path(const PointerRNA * /*ptr
return "tool_settings.particle_edit";
}
static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
static PointerRNA rna_Paint_brush_get(PointerRNA *ptr)
{
Paint *paint = static_cast<Paint *>(ptr->data);
Brush *brush = BKE_paint_brush(paint);
return RNA_id_pointer_create(&brush->id);
}
static void rna_Paint_brush_set(PointerRNA *ptr, PointerRNA value, ReportList * /*reports*/)
{
Paint *paint = static_cast<Paint *>(ptr->data);
Brush *brush = static_cast<Brush *>(value.data);
BKE_paint_brush_set(paint, brush);
BKE_paint_invalidate_overlay_all();
}
static bool rna_Paint_brush_poll(PointerRNA *ptr, PointerRNA value)
{
const Paint *paint = static_cast<Paint *>(ptr->data);
Brush *brush = (Brush *)value.owner_id;
const uint tool_offset = paint->runtime.tool_offset;
const eObjectMode ob_mode = eObjectMode(paint->runtime.ob_mode);
UNUSED_VARS_NDEBUG(tool_offset);
BLI_assert(tool_offset && ob_mode);
const Brush *brush = static_cast<Brush *>(value.data);
if (brush->ob_mode & ob_mode) {
if (paint->brush) {
if (BKE_brush_tool_get(paint->brush, paint) == BKE_brush_tool_get(brush, paint)) {
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->owner_id;
const PaintToolSlot *tslot = static_cast<PaintToolSlot *>(ptr->data);
ToolSettings *ts = scene->toolsettings;
Brush *brush = (Brush *)value.owner_id;
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->uvsculpt->paint, tslot, &slot_index)) {
if (slot_index != brush->uv_sculpt_tool) {
return false;
}
mode = OB_MODE_EDIT;
}
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->weightpaint_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;
}
if (U.experimental.use_grease_pencil_version3) {
mode = OB_MODE_PAINT_GREASE_PENCIL;
}
else {
mode = OB_MODE_PAINT_GPENCIL_LEGACY;
}
}
else if (paint_contains_brush_slot(&ts->gp_vertexpaint->paint, tslot, &slot_index)) {
if (slot_index != brush->gpencil_vertex_tool) {
return false;
}
mode = OB_MODE_VERTEX_GPENCIL_LEGACY;
}
else if (paint_contains_brush_slot(&ts->gp_sculptpaint->paint, tslot, &slot_index)) {
if (slot_index != brush->gpencil_sculpt_tool) {
return false;
}
mode = OB_MODE_SCULPT_GPENCIL_LEGACY;
}
else if (paint_contains_brush_slot(&ts->gp_weightpaint->paint, tslot, &slot_index)) {
if (slot_index != brush->gpencil_weight_tool) {
return false;
}
mode = OB_MODE_WEIGHT_GPENCIL_LEGACY;
}
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;
return (brush == nullptr) || (paint->runtime.ob_mode & brush->ob_mode) != 0;
}
static void rna_Sculpt_update(bContext *C, PointerRNA * /*ptr*/)
@ -453,16 +366,6 @@ static std::optional<std::string> rna_ParticleBrush_path(const PointerRNA * /*pt
return "tool_settings.particle_edit.brush";
}
static void rna_Paint_brush_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
{
Paint *paint = static_cast<Paint *>(ptr->data);
Brush *br = paint->brush;
BKE_paint_invalidate_overlay_all();
/* Needed because we're not calling 'BKE_paint_brush_set' which handles this. */
BKE_paint_toolslots_brush_update(paint);
WM_main_add_notifier(NC_BRUSH | NA_SELECTED, br);
}
static void rna_ImaPaint_viewport_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA * /*ptr*/)
{
/* not the best solution maybe, but will refresh the 3D viewport */
@ -598,20 +501,6 @@ 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", nullptr);
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, nullptr, nullptr, nullptr, "rna_Brush_mode_with_tool_poll");
RNA_def_property_ui_text(prop, "Brush", "");
}
static void rna_def_paint(BlenderRNA *brna)
{
StructRNA *srna;
@ -623,9 +512,11 @@ static void rna_def_paint(BlenderRNA *brna)
/* Global Settings */
prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, nullptr, nullptr, nullptr, "rna_Brush_mode_poll");
RNA_def_property_struct_type(prop, "Brush");
RNA_def_property_pointer_funcs(
prop, "rna_Paint_brush_get", "rna_Paint_brush_set", nullptr, "rna_Paint_brush_poll");
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
RNA_def_property_update(prop, NC_BRUSH | NA_SELECTED, nullptr);
prop = RNA_def_property(srna, "brush_asset_reference", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@ -634,22 +525,6 @@ static void rna_def_paint(BlenderRNA *brna)
"A weak reference to the matching brush asset, used e.g. to restore "
"the last used brush on file load");
/* paint_tool_slots */
prop = RNA_def_property(srna, "tool_slots", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, nullptr, "tool_slots", "tool_slots_len");
RNA_def_property_struct_type(prop, "PaintToolSlot");
/* don't dereference pointer! */
RNA_def_property_collection_funcs(prop,
nullptr,
nullptr,
nullptr,
"rna_iterator_array_get",
nullptr,
nullptr,
nullptr,
nullptr);
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, nullptr, nullptr, nullptr, nullptr);
@ -1687,7 +1562,6 @@ 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);