WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 351 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.
7 changed files with 158 additions and 59 deletions
Showing only changes of commit e2fce46588 - Show all commits

View File

@ -199,9 +199,17 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer);
Paint *BKE_paint_get_active_from_context(const bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const bContext *C);
PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref);
/* Paint brush retrieval and assignment. */
Brush *BKE_paint_brush(Paint *paint);
const Brush *BKE_paint_brush_for_read(const Paint *p);
void BKE_paint_brush_set(Paint *paint, Brush *br);
const Brush *BKE_paint_brush_for_read(const Paint *paint);
void BKE_paint_brush_set(Paint *paint, Brush *brush);
bool BKE_paint_brush_set_default(Main *bmain, Paint *paint);
bool BKE_paint_brush_set_essentials(Main *bmain, Paint *paint, const char *name);
void BKE_paint_brush_set_default_references(ToolSettings *ts);
/**
* Check if the given brush is a valid Brush Asset.
@ -224,11 +232,7 @@ bool BKE_paint_brush_asset_set(Paint *paint,
*/
std::optional<AssetWeakReference *> BKE_paint_brush_asset_get(Paint *paint, Brush **r_brush);
/**
* Attempt to restore a valid active brush in `paint` from brush asset information stored in
* `paint`.
*/
void BKE_paint_brush_asset_restore(Main *bmain, Paint *p);
/* Paint palette. */
Palette *BKE_paint_palette(Paint *paint);
void BKE_paint_palette_set(Paint *p, Palette *palette);

View File

@ -33,6 +33,7 @@
#include "BLI_math_matrix.h"
#include "BLI_math_matrix.hh"
#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
@ -664,6 +665,32 @@ PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref)
return PaintMode::Invalid;
}
static bool paint_brush_set_from_asset_reference(Main *bmain, Paint *paint)
{
/* Attempt to restore a valid active brush from brush asset information. */
if (paint->brush != nullptr) {
return false;
}
if (paint->brush_asset_reference == nullptr) {
return false;
}
Brush *brush = reinterpret_cast<Brush *>(
BKE_asset_weak_reference_ensure(*bmain, ID_BR, *paint->brush_asset_reference));
BLI_assert(brush == nullptr || (brush->id.tag & LIB_TAG_ASSET_MAIN));
/* Ensure we have a brush with appropriate mode to assign.
* Could happen if contents of asset blend was manually changed. */
if (brush == nullptr || (paint->runtime.ob_mode & brush->ob_mode) == 0) {
MEM_delete(paint->brush_asset_reference);
paint->brush_asset_reference = nullptr;
return false;
}
paint->brush = brush;
return true;
}
Brush *BKE_paint_brush(Paint *p)
{
return (Brush *)BKE_paint_brush_for_read((const Paint *)p);
@ -733,26 +760,107 @@ std::optional<AssetWeakReference *> BKE_paint_brush_asset_get(Paint *paint, Brus
return {};
}
void BKE_paint_brush_asset_restore(Main *bmain, Paint *paint)
static void paint_brush_set_essentials_reference(Paint *paint, const char *name)
{
if (paint->brush != nullptr) {
return;
}
if (paint->brush_asset_reference == nullptr) {
return;
}
AssetWeakReference weak_ref = std::move(*paint->brush_asset_reference);
/* Set brush asset reference to a named brush in the essentials asset library. */
MEM_delete(paint->brush_asset_reference);
paint->brush_asset_reference = nullptr;
Brush *brush_asset = reinterpret_cast<Brush *>(
BKE_asset_weak_reference_ensure(*bmain, ID_BR, weak_ref));
AssetWeakReference *weak_ref = MEM_new<AssetWeakReference>(__func__);
weak_ref->asset_library_type = eAssetLibraryType::ASSET_LIBRARY_ESSENTIALS;
weak_ref->relative_asset_identifier = BLI_sprintfN("brushes/essentials_brushes.blend/Brush/%s",
name);
paint->brush_asset_reference = weak_ref;
paint->brush = nullptr;
}
/* Will either re-assign the brush_asset_reference to `paint`, or free it if loading a brush ID
* from it failed. */
BKE_paint_brush_asset_set(paint, brush_asset, weak_ref);
static void paint_brush_set_default_reference(Paint *paint)
{
const char *name = nullptr;
switch (paint->runtime.ob_mode) {
case OB_MODE_SCULPT:
name = "Draw";
break;
case OB_MODE_VERTEX_PAINT:
name = "Paint Vertex";
break;
case OB_MODE_WEIGHT_PAINT:
name = "Paint Weight";
break;
case OB_MODE_TEXTURE_PAINT:
name = "Paint Texture";
break;
case OB_MODE_SCULPT_CURVES:
name = "Comb Curves";
break;
case OB_MODE_EDIT:
/* TODO: UV sculpt. */
break;
case OB_MODE_PAINT_GREASE_PENCIL:
case OB_MODE_PAINT_GPENCIL_LEGACY:
name = "Pencil";
break;
case OB_MODE_VERTEX_GPENCIL_LEGACY:
name = "Paint Point Color";
break;
case OB_MODE_SCULPT_GPENCIL_LEGACY:
name = "Smooth Stroke";
break;
case OB_MODE_WEIGHT_GPENCIL_LEGACY:
name = "Paint Point Weight";
break;
default:
BLI_assert_unreachable();
return;
}
if (name) {
paint_brush_set_essentials_reference(paint, name);
}
}
void BKE_paint_brush_set_default_references(ToolSettings *ts)
{
if (ts->sculpt) {
paint_brush_set_default_reference(&ts->sculpt->paint);
}
if (ts->curves_sculpt) {
paint_brush_set_default_reference(&ts->curves_sculpt->paint);
}
if (ts->wpaint) {
paint_brush_set_default_reference(&ts->wpaint->paint);
}
if (ts->vpaint) {
paint_brush_set_default_reference(&ts->vpaint->paint);
}
if (ts->uvsculpt) {
paint_brush_set_default_reference(&ts->uvsculpt->paint);
}
if (ts->gp_paint) {
paint_brush_set_default_reference(&ts->gp_paint->paint);
}
if (ts->gp_vertexpaint) {
paint_brush_set_default_reference(&ts->gp_vertexpaint->paint);
}
if (ts->gp_sculptpaint) {
paint_brush_set_default_reference(&ts->gp_sculptpaint->paint);
}
if (ts->gp_weightpaint) {
paint_brush_set_default_reference(&ts->gp_weightpaint->paint);
}
paint_brush_set_default_reference(&ts->imapaint.paint);
}
bool BKE_paint_brush_set_default(Main *bmain, Paint *paint)
{
paint_brush_set_default_reference(paint);
return paint_brush_set_from_asset_reference(bmain, paint);
}
bool BKE_paint_brush_set_essentials(Main *bmain, Paint *paint, const char *name)
{
paint_brush_set_essentials_reference(paint, name);
return paint_brush_set_from_asset_reference(bmain, paint);
}
void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
@ -1205,7 +1313,7 @@ bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
#endif
}
BKE_paint_brush_asset_restore(bmain, *r_paint);
paint_brush_set_from_asset_reference(bmain, *r_paint);
return true;
}
@ -1253,7 +1361,7 @@ bool BKE_paint_ensure(Main *bmain, ToolSettings *ts, Paint **r_paint)
*r_paint = paint;
BKE_paint_runtime_init(ts, paint);
BKE_paint_brush_asset_restore(bmain, paint);
BKE_paint_brush_set_default(bmain, paint);
return false;
}

View File

@ -60,6 +60,7 @@
#include "BKE_mesh_legacy_convert.hh"
#include "BKE_nla.h"
#include "BKE_node_runtime.hh"
#include "BKE_paint.hh"
#include "BKE_scene.hh"
#include "BKE_tracking.h"
@ -1997,29 +1998,7 @@ static void update_paint_modes_for_brush_assets(Main &bmain)
{
/* Replace paint brushes with a reference to the default brush asset for that mode. */
LISTBASE_FOREACH (Scene *, scene, &bmain.scenes) {
auto set_paint_asset_ref = [&](Paint &paint, const blender::StringRef asset) {
AssetWeakReference *weak_ref = MEM_new<AssetWeakReference>(__func__);
weak_ref->asset_library_type = eAssetLibraryType::ASSET_LIBRARY_ESSENTIALS;
const std::string path = "brushes/essentials_brushes.blend/Brush/" + asset;
weak_ref->relative_asset_identifier = BLI_strdupn(path.data(), path.size());
paint.brush_asset_reference = weak_ref;
paint.brush = nullptr;
};
ToolSettings *ts = scene->toolsettings;
if (ts->sculpt) {
set_paint_asset_ref(ts->sculpt->paint, "Draw");
}
if (ts->curves_sculpt) {
set_paint_asset_ref(ts->curves_sculpt->paint, "Comb Curves");
}
if (ts->wpaint) {
set_paint_asset_ref(ts->wpaint->paint, "Paint Weight");
}
if (ts->vpaint) {
set_paint_asset_ref(ts->vpaint->paint, "Paint Vertex");
}
set_paint_asset_ref(ts->imapaint.paint, "Paint Texture");
BKE_paint_brush_set_default_references(scene->toolsettings);
}
/* Replace persistent tool references with the new single builtin brush tool. */

View File

@ -1217,7 +1217,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
}
/* Set Draw brush. */
Brush *brush = BKE_paint_toolslots_brush_get(paint, 0);
brush = BKE_paint_toolslots_brush_get(paint, 0);
BKE_brush_tool_set(brush, paint, 0);
BKE_paint_brush_set(paint, brush);

View File

@ -1256,11 +1256,12 @@ static int brush_asset_delete_exec(bContext *C, wmOperator *op)
// TODO: delete whole asset main if empty?
refresh_asset_library(C, *library);
BKE_paint_brush_set_default(bmain, paint);
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST | NA_REMOVED, nullptr);
WM_main_add_notifier(NC_BRUSH | NA_EDITED, nullptr);
/* TODO: activate default brush. */
return OPERATOR_FINISHED;
}

View File

@ -575,24 +575,28 @@ void last_stroke_update(Scene *scene, const float location[3])
/* -------------------------------------------------------------------- */
void smooth_brush_toggle_on(const bContext *C, Paint *paint, StrokeCache *cache)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Brush *cur_brush = BKE_paint_brush(paint);
/* Switch to the blur (smooth) brush if possible. */
/* Note: used for both vertexpaint and weightpaint, VPAINT_TOOL_BLUR & WPAINT_TOOL_BLUR are the
* same, see comments for eBrushVertexPaintTool & eBrushWeightPaintTool. */
Brush *smooth_brush = BKE_paint_toolslots_brush_get(paint, WPAINT_TOOL_BLUR);
BKE_paint_brush_set_essentials(bmain,
paint,
(paint->runtime.ob_mode = OB_MODE_WEIGHT_PAINT) ? "Blur Weight" :
"Blur Vertex");
Brush *smooth_brush = BKE_paint_brush(paint);
if (!smooth_brush) {
BKE_paint_brush_set(paint, cur_brush);
CLOG_WARN(&LOG, "Switching to the blur (smooth) brush not possible, corresponding brush not");
cache->saved_active_brush_name[0] = '\0';
return;
}
Brush *cur_brush = paint->brush;
int cur_brush_size = BKE_brush_size_get(scene, cur_brush);
STRNCPY(cache->saved_active_brush_name, cur_brush->id.name + 2);
BKE_paint_brush_set(paint, smooth_brush);
cache->saved_smooth_size = BKE_brush_size_get(scene, smooth_brush);
BKE_brush_size_set(scene, smooth_brush, cur_brush_size);
BKE_curvemapping_init(smooth_brush->curve);

View File

@ -4125,8 +4125,9 @@ static void smooth_brush_toggle_on(const bContext *C,
Paint *paint,
blender::ed::sculpt_paint::StrokeCache *cache)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Brush *cur_brush = paint->brush;
Brush *cur_brush = BKE_paint_brush(paint);
if (cur_brush->sculpt_tool == SCULPT_TOOL_MASK) {
cache->saved_mask_brush_tool = cur_brush->mask_tool;
@ -4145,8 +4146,11 @@ static void smooth_brush_toggle_on(const bContext *C,
}
/* Switch to the smooth brush if possible. */
Brush *smooth_brush = BKE_paint_toolslots_brush_get(paint, SCULPT_TOOL_SMOOTH);
BKE_paint_brush_set_essentials(bmain, paint, "Smooth");
Brush *smooth_brush = BKE_paint_brush(paint);
if (!smooth_brush) {
BKE_paint_brush_set(paint, cur_brush);
CLOG_WARN(&LOG, "Switching to the smooth brush not possible, corresponding brush not");
cache->saved_active_brush_name[0] = '\0';
return;
@ -4156,7 +4160,6 @@ static void smooth_brush_toggle_on(const bContext *C,
STRNCPY(cache->saved_active_brush_name, cur_brush->id.name + 2);
BKE_paint_brush_set(paint, smooth_brush);
cache->saved_smooth_size = BKE_brush_size_get(scene, smooth_brush);
BKE_brush_size_set(scene, smooth_brush, cur_brush_size);
BKE_curvemapping_init(smooth_brush->curve);