GPv3: Add user count to drawings
Adds a user count to drawings to track how many frames use the drawing. If the user count hits `0` the drawing should be deleted. Also adds a function to delete a frame in a layer. This will decrement the user count of the drawing and delete it if there are no users left. This is consistent with the way GPv2 worked. Pull Request: https://projects.blender.org/blender/blender/pulls/110579
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
* \brief Low-level operations for grease pencil.
|
||||
*/
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
@@ -62,6 +64,13 @@ class DrawingRuntime {
|
||||
* Triangle cache for all the strokes in the drawing.
|
||||
*/
|
||||
mutable SharedCache<Vector<uint3>> triangles_cache;
|
||||
|
||||
/**
|
||||
* Number of users for this drawing. The users are the frames in the Grease Pencil layers.
|
||||
* Different frames can refer to the same drawing, so we need to make sure we count these users
|
||||
* and remove a drawing if it has zero users.
|
||||
*/
|
||||
mutable std::atomic<int> user_count = 1;
|
||||
};
|
||||
|
||||
class Drawing : public ::GreasePencilDrawing {
|
||||
@@ -92,6 +101,22 @@ class Drawing : public ::GreasePencilDrawing {
|
||||
*/
|
||||
VArray<float> opacities() const;
|
||||
MutableSpan<float> opacities_for_write();
|
||||
|
||||
/**
|
||||
* Add a user for this drawing. When a drawing has multiple users, both users are allowed to
|
||||
* modifify this drawings data.
|
||||
*/
|
||||
void add_user() const;
|
||||
/**
|
||||
* Removes a user from this drawing. Note that this does not handle deleting the drawing if it
|
||||
* has not users.
|
||||
*/
|
||||
void remove_user() const;
|
||||
/**
|
||||
* Returns true for when this drawing has more than one user.
|
||||
*/
|
||||
bool is_instanced() const;
|
||||
bool has_users() const;
|
||||
};
|
||||
|
||||
class LayerGroup;
|
||||
@@ -504,6 +529,26 @@ class GreasePencilRuntime {
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
inline void blender::bke::greasepencil::Drawing::add_user() const
|
||||
{
|
||||
this->runtime->user_count.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline void blender::bke::greasepencil::Drawing::remove_user() const
|
||||
{
|
||||
this->runtime->user_count.fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline bool blender::bke::greasepencil::Drawing::is_instanced() const
|
||||
{
|
||||
return this->runtime->user_count.load(std::memory_order_relaxed) > 1;
|
||||
}
|
||||
|
||||
inline bool blender::bke::greasepencil::Drawing::has_users() const
|
||||
{
|
||||
return this->runtime->user_count.load(std::memory_order_relaxed) > 0;
|
||||
}
|
||||
|
||||
inline blender::bke::greasepencil::Drawing &GreasePencilDrawing::wrap()
|
||||
{
|
||||
return *reinterpret_cast<blender::bke::greasepencil::Drawing *>(this);
|
||||
|
||||
@@ -109,7 +109,6 @@ static void grease_pencil_copy_data(Main * /*bmain*/,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* TODO: Update drawing user counts. */
|
||||
}
|
||||
|
||||
/* Duplicate layer tree. */
|
||||
@@ -1384,8 +1383,6 @@ void GreasePencil::add_empty_drawings(const int add_num)
|
||||
new_drawings[i] = reinterpret_cast<GreasePencilDrawingBase *>(
|
||||
MEM_new<blender::bke::greasepencil::Drawing>(__func__));
|
||||
}
|
||||
|
||||
/* TODO: Update drawing user counts. */
|
||||
}
|
||||
|
||||
bool GreasePencil::insert_blank_frame(blender::bke::greasepencil::Layer &layer,
|
||||
@@ -1403,6 +1400,32 @@ bool GreasePencil::insert_blank_frame(blender::bke::greasepencil::Layer &layer,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GreasePencil::remove_frame_at(blender::bke::greasepencil::Layer &layer,
|
||||
const int frame_number)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
if (!layer.frames().contains(frame_number)) {
|
||||
return;
|
||||
}
|
||||
const GreasePencilFrame &frame_to_remove = layer.frames().lookup(frame_number);
|
||||
const int drawing_index_to_remove = frame_to_remove.drawing_index;
|
||||
if (!layer.remove_frame(frame_number)) {
|
||||
/* If removing the frame was not successful, return early. */
|
||||
return;
|
||||
}
|
||||
GreasePencilDrawingBase *drawing_base = this->drawings(drawing_index_to_remove);
|
||||
if (drawing_base->type != GP_DRAWING) {
|
||||
/* If the drawing is referenced from another object, we don't track it's users because we
|
||||
* cannot delete drawings from another object. Return early. */
|
||||
return;
|
||||
}
|
||||
Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap();
|
||||
drawing.remove_user();
|
||||
if (!drawing.has_users()) {
|
||||
this->remove_drawing(drawing_index_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
void GreasePencil::remove_drawing(const int index_to_remove)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
|
||||
@@ -485,6 +485,7 @@ typedef struct GreasePencil {
|
||||
int frame_number,
|
||||
int duration,
|
||||
eBezTriple_KeyframeType keytype);
|
||||
void remove_frame_at(blender::bke::greasepencil::Layer &layer, int frame_number);
|
||||
|
||||
void remove_drawing(int index);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user