Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
172 lines
4.9 KiB
C++
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;
|
|
}
|