Initial Grease Pencil 3.0 stage #106848

Merged
Falk David merged 224 commits from filedescriptor/blender:grease-pencil-v3 into main 2023-05-30 11:14:22 +02:00
6 changed files with 80 additions and 44 deletions
Showing only changes of commit c72ade033d - Show all commits

View File

@ -152,7 +152,7 @@ class TreeNode : public ::GreasePencilLayerTreeNode {
public:
struct Item {
const int64_t index;
const TreeNode &node;
TreeNode &node;
};

Better to return a span here maybe?

Better to return a span here maybe?
private:
@ -546,29 +546,69 @@ class GreasePencilDrawingRuntime {
class GreasePencilRuntime {
private:
LayerGroup root_group_;
const Layer *active_layer_ = nullptr;
int active_layer_index_ = -1;
Layer *active_layer_ = nullptr;
public:
GreasePencilRuntime() {}
GreasePencilRuntime(const GreasePencilRuntime &other) : root_group_(other.root_group_) {}
GreasePencilRuntime(const GreasePencilRuntime &other)
: root_group_(other.root_group_), active_layer_index_(other.active_layer_index_)
{
active_layer_ = get_active_layer_from_index(other.active_layer_index_);
}
/* TODO: There should be a const version of this for reads and a mutable version of this for
* writes. */
LayerGroup &root_group()
{
return root_group_;
}
const Layer *active_layer() const
bool has_active_layer() const
{
return active_layer_;
return active_layer_ != nullptr;
}
void set_active_layer(const Layer *new_active_layer)
const Layer &active_layer() const
{
active_layer_ = new_active_layer;
BLI_assert(active_layer_ != nullptr);
return *active_layer_;
}
Layer &active_layer_for_write() const
{
BLI_assert(active_layer_ != nullptr);
return *active_layer_;
}
void set_active_layer(int index)
{
active_layer_index_ = index;
active_layer_ = get_active_layer_from_index(index);
}
int active_layer_index() const
{
return active_layer_index_;
}
public:
void *batch_cache = nullptr;
private:
Layer *get_active_layer_from_index(int index)
{
if (index < 0) {
return nullptr;
}
for (auto item : this->root_group().children_with_index_in_pre_order()) {
if (item.node.is_layer() && item.index == index) {
return &item.node.as_layer();
}
}
return nullptr;
}
};
} // namespace blender::bke

View File

@ -606,11 +606,6 @@ void GreasePencil::foreach_visible_drawing(
}
}
const blender::bke::greasepencil::Layer *GreasePencil::active_layer() const
{
return this->runtime->active_layer();
}
blender::bke::greasepencil::LayerGroup &GreasePencil::root_group()
{
BLI_assert(this->runtime != nullptr);
@ -771,12 +766,7 @@ void GreasePencil::save_layer_tree_to_storage()
i++;
}
for (auto item : this->root_group().children_with_index_in_pre_order()) {
if (&item.node == this->runtime->active_layer()) {
this->layer_tree_storage.active_layer_index = item.index;
break;
}
}
this->layer_tree_storage.active_layer_index = this->runtime->active_layer_index();
}
static void read_layer_node_recursive(blender::bke::greasepencil::LayerGroup &current_group,
@ -822,12 +812,7 @@ void GreasePencil::load_layer_tree_from_storage()
read_layer_node_recursive(this->runtime->root_group(), this->layer_tree_storage.nodes, i + 1);
}
for (auto item : this->root_group().children_with_index_in_pre_order()) {
if (item.index == this->layer_tree_storage.active_layer_index) {
this->runtime->set_active_layer(&item.node.as_layer());
break;
}
}
this->runtime->set_active_layer(this->layer_tree_storage.active_layer_index);
}
void GreasePencil::read_layer_tree_storage(BlendDataReader *reader)

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
/** \file
@ -108,9 +108,13 @@ void legacy_gpencil_to_grease_pencil(GreasePencil &grease_pencil, bGPdata &gpd)
grease_pencil.drawing_array = reinterpret_cast<GreasePencilDrawingOrReference **>(
MEM_cnew_array<GreasePencilDrawing *>(num_drawings, __func__));
int i = 0;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd.layers) {
int i = 0, layer_idx = 0;
int active_layer_index = 0;
LISTBASE_FOREACH_INDEX (bGPDlayer *, gpl, &gpd.layers, layer_idx) {
Layer &new_layer = grease_pencil.root_group().add_layer(Layer(gpl->info));
if ((gpl->flag & GP_LAYER_ACTIVE) != 0) {
active_layer_index = layer_idx;
}
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
grease_pencil.drawing_array[i] = reinterpret_cast<GreasePencilDrawingOrReference *>(
MEM_new<GreasePencilDrawing>(__func__));
@ -130,6 +134,8 @@ void legacy_gpencil_to_grease_pencil(GreasePencil &grease_pencil, bGPdata &gpd)
i++;
}
}
grease_pencil.runtime->set_active_layer(active_layer_index);
}
} // namespace blender::bke::greasepencil::convert

View File

@ -49,14 +49,16 @@ TEST(greasepencil, set_active_layer)
Layer layer1("Layer1");
Layer layer2("Layer2");
Layer *layer1_ref = &grease_pencil.root_group().add_layer(std::move(layer1));
Layer *layer2_ref = &grease_pencil.root_group().add_layer(std::move(layer2));
const Layer &layer1_ref = grease_pencil.root_group().add_layer(std::move(layer1));
const Layer &layer2_ref = grease_pencil.root_group().add_layer(std::move(layer2));
grease_pencil.runtime->set_active_layer(layer1_ref);
EXPECT_EQ(layer1_ref, grease_pencil.active_layer());
grease_pencil.runtime->set_active_layer(0);
EXPECT_TRUE(grease_pencil.runtime->has_active_layer());
EXPECT_EQ(layer1_ref, grease_pencil.runtime->active_layer());
grease_pencil.runtime->set_active_layer(layer2_ref);
EXPECT_EQ(layer2_ref, grease_pencil.active_layer());
grease_pencil.runtime->set_active_layer(1);
EXPECT_TRUE(grease_pencil.runtime->has_active_layer());
EXPECT_EQ(layer2_ref, grease_pencil.runtime->active_layer());
/* Save to storage. */
grease_pencil.free_layer_tree_storage();
@ -68,8 +70,8 @@ TEST(greasepencil, set_active_layer)
grease_pencil.load_layer_tree_from_storage();
/* Check if the active layer is still the second one. */
EXPECT_NE(grease_pencil.active_layer(), nullptr);
EXPECT_STREQ(grease_pencil.active_layer()->name, "Layer2");
EXPECT_TRUE(grease_pencil.runtime->has_active_layer());
EXPECT_STREQ(grease_pencil.runtime->active_layer().name, "Layer2");
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -47,9 +47,12 @@ struct PaintOperationExecutor {
Object *ob_eval = DEG_get_evaluated_object(depsgraph, obact);
Review

It seems a bit weird to modifier the evaluated object here. Is that purposeful? Or am I missing something?

It seems a bit weird to modifier the evaluated object here. Is that purposeful? Or am I missing something?
Review

Yes, this is done on purpose so that the extra copy from orig to eval for rendering is not needed every update. Once drawing is done, the stroke is copied from the eval buffer to orig.

Yes, this is done on purpose so that the extra copy from orig to eval for rendering is not needed every update. Once drawing is done, the stroke is copied from the eval buffer to orig.
Review

Okay, makes sense. This definitely deserves a comment, since typically changing the evaluated data isn't a good idea.

Okay, makes sense. This definitely deserves a comment, since typically changing the evaluated data isn't a good idea.
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob_eval->data);
const bke::greasepencil::Layer *active_layer = grease_pencil.active_layer();
BLI_assert(active_layer != nullptr);
int index = active_layer->drawing_at(scene->r.cfra);
if (!grease_pencil.runtime->has_active_layer()) {
/* TODO: create a new layer. */
grease_pencil.runtime->set_active_layer(0);
}
const bke::greasepencil::Layer &active_layer = grease_pencil.runtime->active_layer();
int index = active_layer.drawing_at(scene->r.cfra);
BLI_assert(index != -1);
GreasePencilDrawing &drawing = *reinterpret_cast<GreasePencilDrawing *>(
@ -83,11 +86,12 @@ void PaintOperation::on_stroke_done(const bContext &C)
GreasePencil &grease_pencil_orig = *static_cast<GreasePencil *>(obact->data);
GreasePencil &grease_pencil_eval = *static_cast<GreasePencil *>(ob_eval->data);
const bke::greasepencil::Layer *active_layer_orig = grease_pencil_orig.active_layer();
const bke::greasepencil::Layer *active_layer_eval = grease_pencil_eval.active_layer();
BLI_assert(active_layer_orig != nullptr && active_layer_eval != nullptr);
int index_orig = active_layer_orig->drawing_at(scene->r.cfra);
int index_eval = active_layer_eval->drawing_at(scene->r.cfra);
BLI_assert(grease_pencil_orig.runtime->has_active_layer() &&
grease_pencil_eval.runtime->has_active_layer());
const bke::greasepencil::Layer &active_layer_orig = grease_pencil_orig.runtime->active_layer();
const bke::greasepencil::Layer &active_layer_eval = grease_pencil_eval.runtime->active_layer();
int index_orig = active_layer_orig.drawing_at(scene->r.cfra);
int index_eval = active_layer_eval.drawing_at(scene->r.cfra);
BLI_assert(index_orig != -1 && index_eval != -1);
GreasePencilDrawing &drawing_orig = *reinterpret_cast<GreasePencilDrawing *>(

View File

@ -238,7 +238,6 @@ typedef struct GreasePencil {
void remove_drawing(int index);
void foreach_visible_drawing(int frame,
blender::FunctionRef<void(GreasePencilDrawing &)> function);
const blender::bke::greasepencil::Layer *active_layer() const;
blender::bke::greasepencil::LayerGroup &root_group();
#endif
} GreasePencil;