GPv3: Initial modifier support #110500

Merged
Falk David merged 3 commits from filedescriptor/blender:gpv3-initial-modifier-support into main 2023-07-28 14:25:47 +02:00
4 changed files with 67 additions and 7 deletions

View File

@ -111,6 +111,9 @@ typedef enum {
/** Accepts #BMesh input (without conversion). */
eModifierTypeFlag_AcceptsBMesh = (1 << 11),
/** Accepts #GreasePencil data input. */
eModifierTypeFlag_AcceptsGreasePencil = (1 << 12),
} ModifierTypeFlag;
ENUM_OPERATORS(ModifierTypeFlag, eModifierTypeFlag_AcceptsBMesh)

View File

@ -9,12 +9,14 @@
#include "BKE_anim_data.h"
#include "BKE_curves.hh"
#include "BKE_customdata.h"
#include "BKE_geometry_set.hh"
#include "BKE_grease_pencil.h"
#include "BKE_grease_pencil.hh"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BLI_bounds.hh"
@ -39,6 +41,10 @@
#include "DNA_ID_enums.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "MEM_guardedalloc.h"
@ -1072,20 +1078,65 @@ BoundBox *BKE_grease_pencil_boundbox_get(Object *ob)
return ob->runtime.bb;
}
void BKE_grease_pencil_data_update(Depsgraph * /*depsgraph*/, Scene * /*scene*/, Object *object)
static void grease_pencil_evaluate_modifiers(Depsgraph *depsgraph,
Scene *scene,
Object *object,
blender::bke::GeometrySet &geometry_set)
{
/* Modifier evaluation modes. */
const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
filedescriptor marked this conversation as resolved Outdated

Picky, but these parentheses don't really help IMO

Picky, but these parentheses don't really help IMO
ModifierMode required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
filedescriptor marked this conversation as resolved Outdated

Can you use the proper enum type for this variable?

Can you use the proper enum type for this variable?
if (BKE_object_is_in_editmode(object)) {
required_mode |= eModifierMode_Editmode;
filedescriptor marked this conversation as resolved Outdated

This enum has ENUM_OPERATORS now, this casting shouldn't be necessary

This enum has `ENUM_OPERATORS` now, this casting shouldn't be necessary
}
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
BKE_modifiers_clear_errors(object);
/* Get effective list of modifiers to execute. Some effects like shape keys
* are added as virtual modifiers before the user created modifiers. */
VirtualModifierData virtualModifierData;
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
/* Evaluate modifiers. */
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
filedescriptor marked this conversation as resolved Outdated

Use functional style cast for enum types

Use functional style cast for enum types
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
continue;
}
if (mti->modify_geometry_set != nullptr) {
mti->modify_geometry_set(md, &mectx, &geometry_set);
}
}
}
void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
{
using namespace blender::bke;
/* Free any evaluated data and restore original data. */
BKE_object_free_derived_caches(object);
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(object->data);
/* Evaluate modifiers. */
/* TODO: evaluate modifiers. */
GreasePencil *grease_pencil = static_cast<GreasePencil *>(object->data);
GeometrySet geometry_set = GeometrySet::create_with_grease_pencil(
grease_pencil, GeometryOwnershipType::ReadOnly);
grease_pencil_evaluate_modifiers(depsgraph, scene, object, geometry_set);
if (!geometry_set.has_grease_pencil()) {
filedescriptor marked this conversation as resolved Outdated

Maybe reference the explanation for the const cast from another object type, since otherwise this raises some eyebrows

Maybe reference the explanation for the const cast from another object type, since otherwise this raises some eyebrows
geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain());
}
/* For now the evaluated data is not const. We could use #get_grease_pencil_for_write, but that
* would result in a copy when it's shared. So for now, we use a const_cast here. */
filedescriptor marked this conversation as resolved Outdated

To make the geometry_set_eval and data_eval consistent, this second call to BKE_object_eval_assign_data could be replaced with:

if (!geometry_set.has_grease_pencil()) {
  geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain());
}

Eventually it would be nice to remove data_eval completely for geometry object types, that gets us a bit closer.

To make the `geometry_set_eval` and `data_eval` consistent, this second call to `BKE_object_eval_assign_data` could be replaced with: ``` if (!geometry_set.has_grease_pencil()) { geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain()); } ``` Eventually it would be nice to remove `data_eval` completely for geometry object types, that gets us a bit closer.

Do you mean the first call to BKE_object_eval_assign_data?
Wouldn't that mean that for the object we only change object->runtime.geometry_set_eval and not the other things that BKE_object_eval_assign_data changes?

Do you mean the first call to `BKE_object_eval_assign_data`? Wouldn't that mean that for the `object` we only change `object->runtime.geometry_set_eval` and not the other things that `BKE_object_eval_assign_data` changes?

Yeah, like this:

if (!geometry_set.has_grease_pencil()) {
  geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain());
}

GreasePencil *grease_pencil_eval = const_cast<GreasePencil *>(
    geometry_set.get_grease_pencil_for_read());
BKE_object_eval_assign_data(object, &grease_pencil_eval->id, false);

object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
Yeah, like this: ``` if (!geometry_set.has_grease_pencil()) { geometry_set.replace_grease_pencil(BKE_grease_pencil_new_nomain()); } GreasePencil *grease_pencil_eval = const_cast<GreasePencil *>( geometry_set.get_grease_pencil_for_read()); BKE_object_eval_assign_data(object, &grease_pencil_eval->id, false); object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set)); ```
GreasePencil *grease_pencil_eval = const_cast<GreasePencil *>(
geometry_set.get_grease_pencil_for_read());
/* Assign evaluated object. */
/* TODO: Get eval from modifiers geometry set. */
GreasePencil *grease_pencil_eval = reinterpret_cast<GreasePencil *>(
BKE_id_copy_ex(nullptr, &grease_pencil->id, nullptr, LIB_ID_COPY_LOCALIZE));
BKE_object_eval_assign_data(object, &grease_pencil_eval->id, true);
BKE_object_eval_assign_data(object, &grease_pencil_eval->id, false);
object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
}
/** \} */

View File

@ -1494,6 +1494,9 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
return true;
}
if (ob->type == OB_GREASE_PENCIL && (mti->flags & eModifierTypeFlag_AcceptsGreasePencil)) {
return true;
}
return false;
}

View File

@ -8,6 +8,8 @@
#pragma once
#include "BLI_utildefines.h"
#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_session_uuid_types.h"
@ -114,6 +116,7 @@ typedef enum ModifierMode {
eModifierMode_ApplyOnSpline = (1 << 6),
eModifierMode_DisableTemporary = (1u << 31),
} ModifierMode;
ENUM_OPERATORS(ModifierMode, eModifierMode_DisableTemporary);
typedef struct ModifierData {
struct ModifierData *next, *prev;