tornavis/source/blender/blenkernel/intern/paint_toolslots.cc

172 lines
4.9 KiB
C++

/* 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_modifier_types.h"
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
#include "BKE_brush.hh"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#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;
id_us_plus(&brush->id);
}
}
}
}
/**
* 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];
id_us_plus(&brush->id);
if (tslot->brush) {
id_us_min(&tslot->brush->id);
}
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)
{
id_us_min(&tslot->brush->id);
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;
}