GeometrySet: Add new GreasePencilComponent

This is mostly boilerplate code to add a new `GeometryComponent` as well as making sure
the new `GeometryComponent::Type` is handled in all the `switch` statements.

Pull Request: https://projects.blender.org/blender/blender/pulls/110457
This commit is contained in:
Falk David
2023-07-26 13:59:37 +02:00
committed by Falk David
parent cda7e5af19
commit 5846b9164a
11 changed files with 239 additions and 2 deletions
+65 -1
View File
@@ -22,10 +22,11 @@ struct Curve;
struct Mesh;
struct PointCloud;
struct Volume;
struct GreasePencil;
namespace blender::bke {
#define GEO_COMPONENT_TYPE_ENUM_SIZE 6
#define GEO_COMPONENT_TYPE_ENUM_SIZE 7
enum class GeometryOwnershipType {
/* The geometry is owned. This implies that it can be changed. */
@@ -63,6 +64,7 @@ class GeometryComponent : public ImplicitSharingMixin {
Volume = 3,
Curve = 4,
Edit = 5,
GreasePencil = 6,
};
private:
@@ -120,6 +122,7 @@ inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryCompon
* - #PointCloudComponent
* - #InstancesComponent
* - #VolumeComponent
* - #GreasePencilComponent
*
* Copying a geometry set is a relatively cheap operation, because it does not copy the referenced
* geometry components, so #GeometrySet can often be passed or moved by value.
@@ -266,6 +269,11 @@ struct GeometrySet {
*/
static GeometrySet create_with_instances(
Instances *instances, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/**
* Create a new geometry set that only contains the given Grease Pencil data.
*/
static GeometrySet create_with_grease_pencil(
GreasePencil *grease_pencil, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/* Utility methods for access. */
/**
@@ -292,6 +300,10 @@ struct GeometrySet {
* Returns true when the geometry set has any data that is not an instance.
*/
bool has_realized_data() const;
/**
* Returns true when the geometry set has a Grease Pencil component that has grease pencil data.
*/
bool has_grease_pencil() const;
/**
* Return true if the geometry set has any component that isn't empty.
*/
@@ -321,6 +333,10 @@ struct GeometrySet {
* Returns read-only curve edit hints or null.
*/
const CurvesEditHints *get_curve_edit_hints_for_read() const;
/**
* Returns a read-only Grease Pencil data-block or null.
*/
const GreasePencil *get_grease_pencil_for_read() const;
/**
* Returns a mutable mesh or null. No ownership is transferred.
@@ -346,6 +362,10 @@ struct GeometrySet {
* Returns mutable curve edit hints or null.
*/
CurvesEditHints *get_curve_edit_hints_for_write();
/**
* Returns a mutable Grease Pencil data-block or null. No ownership is transferred.
*/
GreasePencil *get_grease_pencil_for_write();
/* Utility methods for replacement. */
/**
@@ -372,6 +392,11 @@ struct GeometrySet {
*/
void replace_instances(Instances *instances,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/**
* Clear the existing Grease Pencil data-block and replace it with the given one.
*/
void replace_grease_pencil(GreasePencil *grease_pencil,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
private:
/**
@@ -655,4 +680,43 @@ class GeometryComponentEditData final : public GeometryComponent {
static constexpr inline GeometryComponent::Type static_type = GeometryComponent::Type::Edit;
};
/**
* A geometry component that stores #GreasePencil data.
* This component does not implement an attribute API, because the #GreasePencil data itself does
* not store any attributes, only the individual drawings within it.
*/
class GreasePencilComponent : public GeometryComponent {
private:
GreasePencil *grease_pencil_ = nullptr;
GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
public:
GreasePencilComponent();
~GreasePencilComponent();
GeometryComponent *copy() const override;
void clear() override;
bool has_grease_pencil() const;
/**
* Clear the component and replace it with the new \a grease_pencil data.
*/
void replace(GreasePencil *grease_pencil,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/**
* Return the Grease Pencil data and clear the component. The caller takes over responsibility
* for freeing the Grease Pencil data (if the component was responsible before).
*/
GreasePencil *release();
const GreasePencil *get_for_read() const;
GreasePencil *get_for_write();
bool is_empty() const final;
bool owns_direct_data() const override;
void ensure_owns_direct_data() override;
static constexpr inline GeometryComponent::Type static_type = Type::GreasePencil;
};
} // namespace blender::bke
@@ -542,6 +542,7 @@ inline bool GreasePencil::has_active_layer() const
void *BKE_grease_pencil_add(Main *bmain, const char *name);
GreasePencil *BKE_grease_pencil_new_nomain();
GreasePencil *BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src);
BoundBox *BKE_grease_pencil_boundbox_get(Object *ob);
void BKE_grease_pencil_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,
+1
View File
@@ -133,6 +133,7 @@ set(SRC
intern/freestyle.cc
intern/geometry_component_curves.cc
intern/geometry_component_edit_data.cc
intern/geometry_component_grease_pencil.cc
intern/geometry_component_instances.cc
intern/geometry_component_mesh.cc
intern/geometry_component_pointcloud.cc
@@ -0,0 +1,98 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_geometry_set.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_lib_id.h"
namespace blender::bke {
/* -------------------------------------------------------------------- */
/** \name Geometry Component Implementation
* \{ */
GreasePencilComponent::GreasePencilComponent() : GeometryComponent(Type::GreasePencil) {}
GreasePencilComponent::~GreasePencilComponent()
{
this->clear();
}
GeometryComponent *GreasePencilComponent::copy() const
{
GreasePencilComponent *new_component = new GreasePencilComponent();
if (grease_pencil_ != nullptr) {
new_component->grease_pencil_ = BKE_grease_pencil_copy_for_eval(grease_pencil_);
new_component->ownership_ = GeometryOwnershipType::Owned;
}
return new_component;
}
void GreasePencilComponent::clear()
{
BLI_assert(this->is_mutable() || this->is_expired());
if (grease_pencil_ != nullptr) {
if (ownership_ == GeometryOwnershipType::Owned) {
BKE_id_free(nullptr, grease_pencil_);
}
grease_pencil_ = nullptr;
}
}
bool GreasePencilComponent::has_grease_pencil() const
{
return grease_pencil_ != nullptr;
}
void GreasePencilComponent::replace(GreasePencil *grease_pencil, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
this->clear();
grease_pencil_ = grease_pencil;
ownership_ = ownership;
}
GreasePencil *GreasePencilComponent::release()
{
BLI_assert(this->is_mutable());
GreasePencil *grease_pencil = grease_pencil_;
grease_pencil_ = nullptr;
return grease_pencil;
}
const GreasePencil *GreasePencilComponent::get_for_read() const
{
return grease_pencil_;
}
GreasePencil *GreasePencilComponent::get_for_write()
{
BLI_assert(this->is_mutable());
if (ownership_ == GeometryOwnershipType::ReadOnly) {
grease_pencil_ = BKE_grease_pencil_copy_for_eval(grease_pencil_);
ownership_ = GeometryOwnershipType::Owned;
}
return grease_pencil_;
}
bool GreasePencilComponent::is_empty() const
{
return grease_pencil_ == nullptr;
}
bool GreasePencilComponent::owns_direct_data() const
{
return ownership_ == GeometryOwnershipType::Owned;
}
void GreasePencilComponent::ensure_owns_direct_data()
{
BLI_assert(this->is_mutable());
if (ownership_ != GeometryOwnershipType::Owned) {
grease_pencil_ = BKE_grease_pencil_copy_for_eval(grease_pencil_);
ownership_ = GeometryOwnershipType::Owned;
}
}
} // namespace blender::bke
@@ -76,6 +76,7 @@ GeometryFieldContext::GeometryFieldContext(const GeometryComponent &component,
}
case GeometryComponent::Type::Volume:
case GeometryComponent::Type::Edit:
case GeometryComponent::Type::GreasePencil:
BLI_assert_unreachable();
break;
}
@@ -51,6 +51,8 @@ GeometryComponentPtr GeometryComponent::create(Type component_type)
return new CurveComponent();
case Type::Edit:
return new GeometryComponentEditData();
case Type::GreasePencil:
return new GreasePencilComponent();
}
BLI_assert_unreachable();
return {};
@@ -344,6 +346,12 @@ const CurvesEditHints *GeometrySet::get_curve_edit_hints_for_read() const
return (component == nullptr) ? nullptr : component->curves_edit_hints_.get();
}
const GreasePencil *GeometrySet::get_grease_pencil_for_read() const
{
const GreasePencilComponent *component = this->get_component_for_read<GreasePencilComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
}
bool GeometrySet::has_pointcloud() const
{
const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
@@ -381,10 +389,16 @@ bool GeometrySet::has_realized_data() const
return false;
}
bool GeometrySet::has_grease_pencil() const
{
const GreasePencilComponent *component = this->get_component_for_read<GreasePencilComponent>();
return component != nullptr && component->has_grease_pencil();
}
bool GeometrySet::is_empty() const
{
return !(this->has_mesh() || this->has_curves() || this->has_pointcloud() ||
this->has_volume() || this->has_instances());
this->has_volume() || this->has_instances() || this->has_grease_pencil());
}
GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
@@ -424,6 +438,14 @@ GeometrySet GeometrySet::create_with_instances(Instances *instances,
return geometry_set;
}
GeometrySet GeometrySet::create_with_grease_pencil(GreasePencil *grease_pencil,
GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
geometry_set.replace_grease_pencil(grease_pencil, ownership);
return geometry_set;
}
void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
if (mesh == nullptr) {
@@ -494,6 +516,21 @@ void GeometrySet::replace_volume(Volume *volume, GeometryOwnershipType ownership
component.replace(volume, ownership);
}
void GeometrySet::replace_grease_pencil(GreasePencil *grease_pencil,
GeometryOwnershipType ownership)
{
if (grease_pencil == nullptr) {
this->remove<GreasePencilComponent>();
return;
}
if (grease_pencil == this->get_grease_pencil_for_read()) {
return;
}
this->remove<GreasePencilComponent>();
GreasePencilComponent &component = this->get_component_for_write<GreasePencilComponent>();
component.replace(grease_pencil, ownership);
}
Mesh *GeometrySet::get_mesh_for_write()
{
MeshComponent *component = this->get_component_ptr<MeshComponent>();
@@ -534,6 +571,12 @@ CurvesEditHints *GeometrySet::get_curve_edit_hints_for_write()
return component.curves_edit_hints_.get();
}
GreasePencil *GeometrySet::get_grease_pencil_for_write()
{
GreasePencilComponent *component = this->get_component_ptr<GreasePencilComponent>();
return component == nullptr ? nullptr : component->get_for_write();
}
void GeometrySet::attribute_foreach(const Span<GeometryComponent::Type> component_types,
const bool include_instances,
const AttributeForeachCallback callback) const
@@ -709,6 +752,9 @@ bool object_has_geometry_set_instances(const Object &object)
break;
case GeometryComponent::Type::Edit:
break;
case GeometryComponent::Type::GreasePencil:
is_instance = object.type != OB_GREASE_PENCIL;
break;
}
if (is_instance) {
return true;
@@ -1044,6 +1044,12 @@ GreasePencil *BKE_grease_pencil_new_nomain()
return grease_pencil;
}
GreasePencil *BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src)
{
return reinterpret_cast<GreasePencil *>(
BKE_id_copy_ex(nullptr, &grease_pencil_src->id, nullptr, LIB_ID_COPY_LOCALIZE));
}
BoundBox *BKE_grease_pencil_boundbox_get(Object *ob)
{
using namespace blender;
@@ -985,6 +985,10 @@ static void create_inspection_string_for_geometry_info(const geo_log::GeometryIn
}
break;
}
case bke::GeometryComponent::Type::GreasePencil: {
/* TODO. Do nothing for now. */
break;
}
}
if (type != component_types.last()) {
ss << ".\n";
@@ -1038,6 +1042,10 @@ static void create_inspection_string_for_geometry_socket(std::stringstream &ss,
case bke::GeometryComponent::Type::Edit: {
break;
}
case bke::GeometryComponent::Type::GreasePencil: {
ss << TIP_("Grease Pencil");
break;
}
}
if (type != supported_types.last()) {
ss << ", ";
@@ -627,6 +627,10 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
}
break;
}
case bke::GeometryComponent::Type::GreasePencil: {
/* TODO. Do nothing for now. */
break;
}
}
}
}
@@ -126,6 +126,10 @@ GeometryInfoLog::GeometryInfoLog(const bke::GeometrySet &geometry_set)
case bke::GeometryComponent::Type::Volume: {
break;
}
case bke::GeometryComponent::Type::GreasePencil: {
/* TODO. Do nothing for now. */
break;
}
}
}
}
@@ -96,6 +96,10 @@ void GeoNodeExecParams::check_input_geometry_set(StringRef identifier,
case GeometryComponent::Type::Edit: {
continue;
}
case GeometryComponent::Type::GreasePencil: {
message += TIP_("Grease Pencil");
break;
}
}
this->error_message_add(NodeWarningType::Info, std::move(message));
}