WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 354 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
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);