WIP: Brush assets project #106303
|
@ -427,9 +427,9 @@ class PREFERENCES_OT_keyconfig_remove(Operator):
|
|||
# Add-on Operators
|
||||
|
||||
class PREFERENCES_OT_addon_enable(Operator):
|
||||
"""Enable an add-on"""
|
||||
"""Turn on this extension"""
|
||||
bl_idname = "preferences.addon_enable"
|
||||
bl_label = "Enable Add-on"
|
||||
bl_label = "Enable Extension"
|
||||
|
||||
module: StringProperty(
|
||||
name="Module",
|
||||
|
@ -473,9 +473,9 @@ class PREFERENCES_OT_addon_enable(Operator):
|
|||
|
||||
|
||||
class PREFERENCES_OT_addon_disable(Operator):
|
||||
"""Disable an add-on"""
|
||||
"""Turn off this extension"""
|
||||
bl_idname = "preferences.addon_disable"
|
||||
bl_label = "Disable Add-on"
|
||||
bl_label = "Disable Extension"
|
||||
|
||||
module: StringProperty(
|
||||
name="Module",
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include <array>
|
||||
|
@ -324,15 +325,24 @@ void BKE_library_ID_test_usages(Main *bmain,
|
|||
/** Parameters and result data structure for the 'unused IDs' functions below. */
|
||||
struct LibQueryUnusedIDsData {
|
||||
/** Process local data-blocks. */
|
||||
bool do_local_ids;
|
||||
bool do_local_ids = false;
|
||||
/** Process linked data-blocks. */
|
||||
bool do_linked_ids;
|
||||
bool do_linked_ids = false;
|
||||
/**
|
||||
* Process all actually unused data-blocks, including these that are currently only used by
|
||||
* other unused data-blocks, and 'dependency islands' of several data-blocks using each-other,
|
||||
* without any external valid user.
|
||||
*/
|
||||
bool do_recursive;
|
||||
bool do_recursive = false;
|
||||
|
||||
/**
|
||||
* Callback filter, if defined and it returns `true`, the given `id` may be considered as unused,
|
||||
* otherwise it will always be considered as used.
|
||||
*
|
||||
* Allows for more complex handling of which IDs should be deleted, on top of the basic
|
||||
* local/linked choices.
|
||||
*/
|
||||
blender::FunctionRef<bool(ID *id)> filter_fn = nullptr;
|
||||
|
||||
/**
|
||||
* Amount of detected as unused data-blocks, per type and total as the last value of the array
|
||||
|
|
|
@ -238,7 +238,6 @@ static ID **collection_owner_pointer_get(ID *id)
|
|||
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
|
||||
|
||||
Collection *master_collection = (Collection *)id;
|
||||
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
|
||||
|
|
|
@ -1708,6 +1708,13 @@ template<typename T> static void shrink_array(T **array, int *num, const int shr
|
|||
{
|
||||
BLI_assert(shrink_num > 0);
|
||||
const int new_array_num = *num - shrink_num;
|
||||
if (new_array_num == 0) {
|
||||
MEM_freeN(*array);
|
||||
*array = nullptr;
|
||||
*num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
T *new_array = reinterpret_cast<T *>(MEM_cnew_array<T *>(new_array_num, __func__));
|
||||
|
||||
blender::uninitialized_move_n(*array, new_array_num, new_array);
|
||||
|
@ -1924,6 +1931,7 @@ static void remove_drawings_unchecked(GreasePencil &grease_pencil,
|
|||
for (auto [key, value] : layer->frames_for_write().items()) {
|
||||
if (value.drawing_index == swap_index) {
|
||||
value.drawing_index = index_to_remove;
|
||||
layer->tag_frames_map_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2521,7 +2529,7 @@ void GreasePencil::remove_layer(blender::bke::greasepencil::Layer &layer)
|
|||
layer.parent_group().unlink_node(layer.as_node());
|
||||
|
||||
/* Remove drawings. */
|
||||
for (GreasePencilFrame frame : layer.frames_for_write().values()) {
|
||||
for (const GreasePencilFrame frame : layer.frames().values()) {
|
||||
GreasePencilDrawingBase *drawing_base = this->drawing(frame.drawing_index);
|
||||
if (drawing_base->type != GP_DRAWING) {
|
||||
continue;
|
||||
|
@ -2598,7 +2606,8 @@ static void write_drawing_array(GreasePencil &grease_pencil, BlendWriter *writer
|
|||
|
||||
static void free_drawing_array(GreasePencil &grease_pencil)
|
||||
{
|
||||
if (grease_pencil.drawing_array == nullptr || grease_pencil.drawing_array_num == 0) {
|
||||
if (grease_pencil.drawing_array == nullptr) {
|
||||
BLI_assert(grease_pencil.drawing_array_num == 0);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < grease_pencil.drawing_array_num; i++) {
|
||||
|
|
|
@ -363,4 +363,96 @@ TEST(greasepencil, remove_frame_fixed_duration_overwrite_end)
|
|||
EXPECT_TRUE(layer.frames().lookup(5).is_null());
|
||||
}
|
||||
|
||||
TEST(greasepencil, remove_drawings_no_change)
|
||||
{
|
||||
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(
|
||||
BKE_id_new_nomain(ID_GP, "Grease Pencil test"));
|
||||
|
||||
grease_pencil->add_empty_drawings(3);
|
||||
|
||||
Layer &layer_a = grease_pencil->add_layer("LayerA");
|
||||
Layer &layer_b = grease_pencil->add_layer("LayerB");
|
||||
layer_b.add_frame(10, 0);
|
||||
layer_b.add_frame(20, 1);
|
||||
layer_b.add_frame(30, 2);
|
||||
|
||||
EXPECT_EQ(layer_a.frames().size(), 0);
|
||||
EXPECT_EQ(layer_b.frames().size(), 3);
|
||||
EXPECT_EQ(layer_b.frames().lookup(10).drawing_index, 0);
|
||||
EXPECT_EQ(layer_b.frames().lookup(20).drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames().lookup(30).drawing_index, 2);
|
||||
/* Test DNA storage data too. */
|
||||
layer_a.prepare_for_dna_write();
|
||||
layer_b.prepare_for_dna_write();
|
||||
EXPECT_EQ(layer_a.frames_storage.num, 0);
|
||||
EXPECT_EQ(layer_b.frames_storage.num, 3);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[0].drawing_index, 0);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[1].drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[2].drawing_index, 2);
|
||||
|
||||
grease_pencil->remove_layer(layer_a);
|
||||
EXPECT_EQ(layer_b.frames().size(), 3);
|
||||
EXPECT_EQ(layer_b.frames().lookup(10).drawing_index, 0);
|
||||
EXPECT_EQ(layer_b.frames().lookup(20).drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames().lookup(30).drawing_index, 2);
|
||||
/* Test DNA storage data too. */
|
||||
layer_b.prepare_for_dna_write();
|
||||
EXPECT_EQ(layer_b.frames_storage.num, 3);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[0].drawing_index, 0);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[1].drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[2].drawing_index, 2);
|
||||
|
||||
BKE_id_free(nullptr, grease_pencil);
|
||||
}
|
||||
|
||||
TEST(greasepencil, remove_drawings_with_no_users)
|
||||
{
|
||||
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(
|
||||
BKE_id_new_nomain(ID_GP, "Grease Pencil test"));
|
||||
|
||||
/* Test drawing index correctness: Removing users from drawings should remove those drawings, and
|
||||
* all index references should get updated to match the changed drawing indices. */
|
||||
|
||||
grease_pencil->add_empty_drawings(5);
|
||||
|
||||
Layer &layer_a = grease_pencil->add_layer("LayerA");
|
||||
layer_a.add_frame(10, 0);
|
||||
layer_a.add_frame(20, 1);
|
||||
layer_a.add_frame(30, 2);
|
||||
Layer &layer_b = grease_pencil->add_layer("LayerB");
|
||||
layer_b.add_frame(10, 3);
|
||||
layer_b.add_frame(30, 4);
|
||||
|
||||
EXPECT_EQ(layer_a.frames().size(), 3);
|
||||
EXPECT_EQ(layer_a.frames().lookup(10).drawing_index, 0);
|
||||
EXPECT_EQ(layer_a.frames().lookup(20).drawing_index, 1);
|
||||
EXPECT_EQ(layer_a.frames().lookup(30).drawing_index, 2);
|
||||
EXPECT_EQ(layer_b.frames().size(), 2);
|
||||
EXPECT_EQ(layer_b.frames().lookup(10).drawing_index, 3);
|
||||
EXPECT_EQ(layer_b.frames().lookup(30).drawing_index, 4);
|
||||
/* Test DNA storage data too. */
|
||||
layer_a.prepare_for_dna_write();
|
||||
layer_b.prepare_for_dna_write();
|
||||
EXPECT_EQ(layer_a.frames_storage.num, 3);
|
||||
EXPECT_EQ(layer_a.frames_storage.values[0].drawing_index, 0);
|
||||
EXPECT_EQ(layer_a.frames_storage.values[1].drawing_index, 1);
|
||||
EXPECT_EQ(layer_a.frames_storage.values[2].drawing_index, 2);
|
||||
EXPECT_EQ(layer_b.frames_storage.num, 2);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[0].drawing_index, 3);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[1].drawing_index, 4);
|
||||
|
||||
/* Drawings 0,1,2 get removed, drawings 3,4 move up (order changes). */
|
||||
grease_pencil->remove_layer(layer_a);
|
||||
EXPECT_EQ(layer_b.frames().size(), 2);
|
||||
EXPECT_EQ(layer_b.frames().lookup(10).drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames().lookup(30).drawing_index, 0);
|
||||
/* Test DNA storage data too. */
|
||||
layer_b.prepare_for_dna_write();
|
||||
EXPECT_EQ(layer_b.frames_storage.num, 2);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[0].drawing_index, 1);
|
||||
EXPECT_EQ(layer_b.frames_storage.values[1].drawing_index, 0);
|
||||
|
||||
BKE_id_free(nullptr, grease_pencil);
|
||||
}
|
||||
|
||||
} // namespace blender::bke::greasepencil::tests
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "DNA_anim_types.h"
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_linklist_stack.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
@ -600,7 +601,7 @@ void BKE_library_ID_test_usages(Main *bmain,
|
|||
* user feedback ('what would be the amounts of IDs detected as unused if this option was
|
||||
* enabled').
|
||||
*/
|
||||
struct UnusedIdsData {
|
||||
struct UnusedIDsData {
|
||||
Main *bmain;
|
||||
|
||||
const int id_tag;
|
||||
|
@ -609,12 +610,26 @@ struct UnusedIdsData {
|
|||
bool do_linked_ids;
|
||||
bool do_recursive;
|
||||
|
||||
blender::FunctionRef<bool(ID *id)> filter_fn;
|
||||
|
||||
std::array<int, INDEX_ID_MAX> *num_total;
|
||||
std::array<int, INDEX_ID_MAX> *num_local;
|
||||
std::array<int, INDEX_ID_MAX> *num_linked;
|
||||
|
||||
blender::Set<ID *> unused_ids{};
|
||||
|
||||
UnusedIDsData(Main *bmain, const int id_tag, LibQueryUnusedIDsData ¶meters)
|
||||
: bmain(bmain),
|
||||
id_tag(id_tag),
|
||||
do_local_ids(parameters.do_local_ids),
|
||||
do_linked_ids(parameters.do_linked_ids),
|
||||
do_recursive(parameters.do_recursive),
|
||||
num_total(¶meters.num_total),
|
||||
num_local(¶meters.num_local),
|
||||
num_linked(¶meters.num_linked)
|
||||
{
|
||||
}
|
||||
|
||||
void reset(const bool do_local_ids,
|
||||
const bool do_linked_ids,
|
||||
const bool do_recursive,
|
||||
|
@ -632,8 +647,11 @@ struct UnusedIdsData {
|
|||
}
|
||||
};
|
||||
|
||||
static void lib_query_unused_ids_tag_id(ID *id, UnusedIdsData &data)
|
||||
static void lib_query_unused_ids_tag_id(ID *id, UnusedIDsData &data)
|
||||
{
|
||||
if (data.filter_fn && !data.filter_fn(id)) {
|
||||
return;
|
||||
}
|
||||
id->tag |= data.id_tag;
|
||||
data.unused_ids.add(id);
|
||||
|
||||
|
@ -652,7 +670,7 @@ static void lib_query_unused_ids_tag_id(ID *id, UnusedIdsData &data)
|
|||
|
||||
/* Returns `true` if given ID is detected as part of at least one dependency loop, false otherwise.
|
||||
*/
|
||||
static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIdsData &data)
|
||||
static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIDsData &data)
|
||||
{
|
||||
/* We should never deal with embedded, not-in-main IDs here. */
|
||||
BLI_assert((id->flag & LIB_EMBEDDED_DATA) == 0);
|
||||
|
@ -764,7 +782,7 @@ static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIdsData &data)
|
|||
return is_part_of_dependency_loop;
|
||||
}
|
||||
|
||||
static void lib_query_unused_ids_tag(UnusedIdsData &data)
|
||||
static void lib_query_unused_ids_tag(UnusedIDsData &data)
|
||||
{
|
||||
BKE_main_relations_tag_set(data.bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
|
||||
|
||||
|
@ -851,15 +869,14 @@ void BKE_lib_query_unused_ids_amounts(Main *bmain, LibQueryUnusedIDsData ¶me
|
|||
* this call.
|
||||
*/
|
||||
|
||||
UnusedIdsData data{
|
||||
bmain,
|
||||
0,
|
||||
true,
|
||||
parameters.do_linked_ids,
|
||||
parameters.do_recursive,
|
||||
parameters.do_local_ids ? ¶meters.num_total : &num_dummy,
|
||||
¶meters.num_local,
|
||||
(parameters.do_local_ids && parameters.do_linked_ids) ? ¶meters.num_linked : &num_dummy};
|
||||
UnusedIDsData data(bmain, 0, parameters);
|
||||
data.do_local_ids = true;
|
||||
if (!parameters.do_local_ids) {
|
||||
data.num_total = &num_dummy;
|
||||
}
|
||||
if (!(parameters.do_local_ids && parameters.do_linked_ids)) {
|
||||
data.num_linked = &num_dummy;
|
||||
}
|
||||
lib_query_unused_ids_tag(data);
|
||||
|
||||
if (!(parameters.do_local_ids && parameters.do_linked_ids)) {
|
||||
|
@ -887,14 +904,7 @@ void BKE_lib_query_unused_ids_tag(Main *bmain, const int tag, LibQueryUnusedIDsD
|
|||
parameters.num_local.fill(0);
|
||||
parameters.num_linked.fill(0);
|
||||
|
||||
UnusedIdsData data{bmain,
|
||||
tag,
|
||||
parameters.do_local_ids,
|
||||
parameters.do_linked_ids,
|
||||
parameters.do_recursive,
|
||||
¶meters.num_total,
|
||||
¶meters.num_local,
|
||||
¶meters.num_linked};
|
||||
UnusedIDsData data(bmain, tag, parameters);
|
||||
|
||||
if (parameters.do_recursive) {
|
||||
BKE_main_relations_create(bmain, 0);
|
||||
|
|
|
@ -34,6 +34,7 @@ void set_selected_frames_type(bke::greasepencil::Layer &layer,
|
|||
for (GreasePencilFrame &frame : layer.frames_for_write().values()) {
|
||||
if (frame.is_selected()) {
|
||||
frame.type = key_type;
|
||||
layer.tag_frames_map_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +171,10 @@ bool duplicate_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::L
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
layer.tag_frames_map_changed();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -210,6 +215,7 @@ bool select_frame_at(bke::greasepencil::Layer &layer,
|
|||
return false;
|
||||
}
|
||||
select_frame(*frame, select_mode);
|
||||
layer.tag_frames_map_changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -232,6 +238,7 @@ void select_all_frames(bke::greasepencil::Layer &layer, const short select_mode)
|
|||
{
|
||||
for (auto item : layer.frames_for_write().items()) {
|
||||
select_frame(item.value, select_mode);
|
||||
layer.tag_frames_map_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,6 +276,8 @@ void select_frames_region(KeyframeEditData *ked,
|
|||
select_frame(frame, select_mode);
|
||||
}
|
||||
}
|
||||
|
||||
node.as_layer().tag_frames_map_changed();
|
||||
}
|
||||
}
|
||||
else if (node.is_group()) {
|
||||
|
@ -288,6 +297,7 @@ void select_frames_range(bke::greasepencil::TreeNode &node,
|
|||
for (auto [frame_number, frame] : node.as_layer().frames_for_write().items()) {
|
||||
if (IN_RANGE(float(frame_number), min, max)) {
|
||||
select_frame(frame, select_mode);
|
||||
node.as_layer().tag_frames_map_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,14 +234,24 @@ static Array<int> get_frame_numbers_for_layer(const bke::greasepencil::Layer &la
|
|||
const int current_frame,
|
||||
const bool use_multi_frame_editing)
|
||||
{
|
||||
Vector<int> frame_numbers({current_frame});
|
||||
Vector<int> frame_numbers;
|
||||
if (use_multi_frame_editing) {
|
||||
bool current_frame_is_covered = false;
|
||||
const int drawing_index_at_current_frame = layer.drawing_index_at(current_frame);
|
||||
for (const auto [frame_number, frame] : layer.frames().items()) {
|
||||
if (frame_number != current_frame && frame.is_selected()) {
|
||||
frame_numbers.append_unchecked(frame_number);
|
||||
if (!frame.is_selected()) {
|
||||
continue;
|
||||
}
|
||||
frame_numbers.append(frame_number);
|
||||
current_frame_is_covered |= (frame.drawing_index == drawing_index_at_current_frame);
|
||||
}
|
||||
if (current_frame_is_covered) {
|
||||
return frame_numbers.as_span();
|
||||
}
|
||||
}
|
||||
|
||||
frame_numbers.append(current_frame);
|
||||
|
||||
return frame_numbers.as_span();
|
||||
}
|
||||
|
||||
|
|
|
@ -2163,7 +2163,10 @@ static int unused_message_popup_width_compute(bContext *C)
|
|||
/* Computation of unused data amounts, with all options ON.
|
||||
* Used to estimate the maximum required width for the dialog. */
|
||||
Main *bmain = CTX_data_main(C);
|
||||
LibQueryUnusedIDsData data = {true, true, true, {}, {}, {}};
|
||||
LibQueryUnusedIDsData data;
|
||||
data.do_local_ids = true;
|
||||
data.do_linked_ids = true;
|
||||
data.do_recursive = true;
|
||||
BKE_lib_query_unused_ids_amounts(bmain, data);
|
||||
|
||||
std::string unused_message = "";
|
||||
|
|
|
@ -82,7 +82,7 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t)
|
|||
continue;
|
||||
}
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, tc.obedit);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object_eval->data);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(tc.obedit->data);
|
||||
Span<const bke::greasepencil::Layer *> layers = grease_pencil.layers();
|
||||
|
||||
int layer_points_offset = 0;
|
||||
|
|
Loading…
Reference in New Issue