Grease Pencil: Add initial support for Node Tools
This adds inital Grease Pencil support for node tools. Node tools work in `Object Mode`, `Edit Mode`,`Sculpt Mode`, and `Draw Mode`. While Grease Pencil has many editing tools, including editing multiple frames at the same time, for now, node tools only allow editing the current frame. Currently, the idea is that node tools can do arbitrary changes to the drawings, but cannot do changes to the existing layer tree, e.g. changing the order of layers, removing a layer or groups, etc. All the node tool specific nodes like `Selection` and `Set Selection` are adapted to work with Grease Pencil. In `Draw Mode`, we currently interpret everything as selected. The `Active Element` node has a `Layer` mode that provides the index of the active layer (if there is one). When `Auto-Key` is used, a new keyframe is created on the current frame. Locked/invisible layers cannot be edited with node tools. Pull Request: https://projects.blender.org/blender/blender/pulls/136624
This commit is contained in:
@@ -50,12 +50,16 @@ def geometry_node_group_empty_tool_new(context):
|
||||
group.is_type_curve = True
|
||||
elif ob_type == 'POINTCLOUD':
|
||||
group.is_type_pointcloud = True
|
||||
elif ob_type == 'GREASEPENCIL':
|
||||
group.is_type_grease_pencil = True
|
||||
else:
|
||||
group.is_type_mesh = True
|
||||
|
||||
mode = ob.mode if ob else 'OBJECT'
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES'}:
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES', 'SCULPT_GREASE_PENCIL'}:
|
||||
group.is_mode_sculpt = True
|
||||
elif mode == 'PAINT_GREASE_PENCIL':
|
||||
group.is_mode_paint = True
|
||||
elif mode == 'EDIT':
|
||||
group.is_mode_edit = True
|
||||
else:
|
||||
|
||||
@@ -463,6 +463,7 @@ class NODE_PT_geometry_node_tool_object_types(Panel):
|
||||
types = [
|
||||
("is_type_mesh", "Mesh", 'MESH_DATA'),
|
||||
("is_type_curve", "Hair Curves", 'CURVES_DATA'),
|
||||
("is_type_grease_pencil", "Grease Pencil", 'OUTLINER_OB_GREASEPENCIL'),
|
||||
("is_type_pointcloud", "Point Cloud", 'POINTCLOUD_DATA'),
|
||||
]
|
||||
|
||||
@@ -499,6 +500,11 @@ class NODE_PT_geometry_node_tool_mode(Panel):
|
||||
row.label(text=name, icon=icon)
|
||||
row.prop(group, prop, text="")
|
||||
|
||||
if group.is_type_grease_pencil:
|
||||
row = col.row(align=True)
|
||||
row.label(text="Draw Mode", icon='GREASEPENCIL')
|
||||
row.prop(group, "is_mode_paint", text="")
|
||||
|
||||
|
||||
class NODE_PT_geometry_node_tool_options(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
|
||||
@@ -1212,6 +1212,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
elif mode_string == 'EDIT_GREASE_PENCIL':
|
||||
layout.menu("VIEW3D_MT_edit_greasepencil_point")
|
||||
layout.menu("VIEW3D_MT_edit_greasepencil_stroke")
|
||||
layout.template_node_operator_asset_root_items()
|
||||
|
||||
elif obj:
|
||||
if mode_string not in {'PAINT_TEXTURE', 'SCULPT_CURVES', 'SCULPT_GREASE_PENCIL', 'VERTEX_GREASE_PENCIL'}:
|
||||
@@ -1236,6 +1237,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
)
|
||||
if is_selection_mask:
|
||||
layout.menu("VIEW3D_MT_select_edit_grease_pencil")
|
||||
layout.template_node_operator_asset_root_items()
|
||||
else:
|
||||
layout.template_node_operator_asset_root_items()
|
||||
|
||||
@@ -2225,6 +2227,8 @@ class VIEW3D_MT_select_edit_grease_pencil(Menu):
|
||||
props.amount_start = 0
|
||||
props.amount_end = 1
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class VIEW3D_MT_paint_grease_pencil(Menu):
|
||||
bl_label = "Draw"
|
||||
@@ -5777,6 +5781,8 @@ class VIEW3D_MT_edit_greasepencil(Menu):
|
||||
|
||||
layout.menu("VIEW3D_MT_edit_greasepencil_delete")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_greasepencil_stroke(Menu):
|
||||
bl_label = "Stroke"
|
||||
@@ -5825,6 +5831,8 @@ class VIEW3D_MT_edit_greasepencil_stroke(Menu):
|
||||
|
||||
layout.operator("grease_pencil.reset_uvs")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_greasepencil_point(Menu):
|
||||
bl_label = "Point"
|
||||
@@ -5846,6 +5854,8 @@ class VIEW3D_MT_edit_greasepencil_point(Menu):
|
||||
|
||||
layout.operator_menu_enum("grease_pencil.set_handle_type", property="type")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
class VIEW3D_MT_edit_curves_add(Menu):
|
||||
bl_label = "Add"
|
||||
|
||||
@@ -899,6 +899,13 @@ TREENODE_COMMON_METHODS_FORWARD_IMPL(LayerGroup);
|
||||
|
||||
const AttributeAccessorFunctions &get_attribute_accessor_functions();
|
||||
|
||||
/**
|
||||
* Renames layers with empty names to "Layer".
|
||||
* \note While original data should not have layers with empty names, we allow layer names to be
|
||||
* empty in evaluated geometry.
|
||||
*/
|
||||
void ensure_non_empty_layer_names(Main &bmain, GreasePencil &grease_pencil);
|
||||
|
||||
} // namespace greasepencil
|
||||
|
||||
class GreasePencilRuntime {
|
||||
|
||||
@@ -1940,6 +1940,15 @@ void LayerGroup::update_from_dna_read()
|
||||
}
|
||||
}
|
||||
|
||||
void ensure_non_empty_layer_names(Main &bmain, GreasePencil &grease_pencil)
|
||||
{
|
||||
for (bke::greasepencil::Layer *layer : grease_pencil.layers_for_write()) {
|
||||
if (layer->name().is_empty()) {
|
||||
grease_pencil.rename_node(bmain, layer->as_node(), DATA_("Layer"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke::greasepencil
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
* \ingroup edcurves
|
||||
*/
|
||||
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_path_utils.hh"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "ED_curves.hh"
|
||||
#include "ED_grease_pencil.hh"
|
||||
#include "ED_object.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_select_utils.hh"
|
||||
@@ -27,6 +29,7 @@
|
||||
#include "BKE_customdata.hh"
|
||||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
@@ -253,12 +256,22 @@ static bke::GeometrySet get_original_geometry_eval_copy(Depsgraph &depsgraph,
|
||||
orig_mesh_states.append_as(*mesh_copy);
|
||||
return bke::GeometrySet::from_mesh(mesh_copy);
|
||||
}
|
||||
case OB_GREASE_PENCIL: {
|
||||
const GreasePencil *grease_pencil = static_cast<const GreasePencil *>(object.data);
|
||||
if (const bke::greasepencil::Layer *active_layer = grease_pencil->get_active_layer()) {
|
||||
operator_data.active_layer_index = *grease_pencil->get_layer_index(*active_layer);
|
||||
}
|
||||
GreasePencil *grease_pencil_copy = BKE_grease_pencil_copy_for_eval(grease_pencil);
|
||||
grease_pencil_copy->runtime->eval_frame = int(DEG_get_ctime(&depsgraph));
|
||||
return bke::GeometrySet::from_grease_pencil(grease_pencil_copy);
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static void store_result_geometry(const wmOperator &op,
|
||||
static void store_result_geometry(const bContext &C,
|
||||
const wmOperator &op,
|
||||
const Depsgraph &depsgraph,
|
||||
Main &bmain,
|
||||
Scene &scene,
|
||||
@@ -336,6 +349,59 @@ static void store_result_geometry(const wmOperator &op,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_GREASE_PENCIL: {
|
||||
const int eval_frame = int(DEG_get_ctime(&depsgraph));
|
||||
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
Vector<int> editable_layer_indices;
|
||||
for (const int layer_i : grease_pencil.layers().index_range()) {
|
||||
const bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
|
||||
if (!layer.is_editable()) {
|
||||
continue;
|
||||
}
|
||||
editable_layer_indices.append(layer_i);
|
||||
}
|
||||
|
||||
bool inserted_new_keyframe = false;
|
||||
for (const int layer_i : editable_layer_indices) {
|
||||
bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
|
||||
/* TODO: For now, we always create a blank keyframe, but it might be good to expose this as
|
||||
* an option and allow to duplicate the previous key. */
|
||||
const bool duplicate_previous_key = false;
|
||||
ed::greasepencil::ensure_active_keyframe(
|
||||
scene, grease_pencil, layer, duplicate_previous_key, inserted_new_keyframe);
|
||||
}
|
||||
GreasePencil *new_grease_pencil =
|
||||
geometry.get_component_for_write<bke::GreasePencilComponent>().get_for_write();
|
||||
if (!new_grease_pencil) {
|
||||
/* Clear the Grease Pencil geometry. */
|
||||
for (const int layer_i : editable_layer_indices) {
|
||||
bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
|
||||
if (bke::greasepencil::Drawing *drawing_orig = grease_pencil.get_drawing_at(layer,
|
||||
eval_frame))
|
||||
{
|
||||
drawing_orig->strokes_for_write() = {};
|
||||
drawing_orig->tag_topology_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask editable_layers = IndexMask::from_indices(editable_layer_indices.as_span(),
|
||||
memory);
|
||||
ed::greasepencil::apply_eval_grease_pencil_data(
|
||||
*new_grease_pencil, eval_frame, editable_layers, grease_pencil);
|
||||
|
||||
/* There might be layers with empty names after evaluation. Make sure to rename them. */
|
||||
bke::greasepencil::ensure_non_empty_layer_names(bmain, grease_pencil);
|
||||
BKE_object_material_from_eval_data(&bmain, &object, &new_grease_pencil->id);
|
||||
}
|
||||
|
||||
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||
if (inserted_new_keyframe) {
|
||||
WM_event_add_notifier(&C, NC_GPENCIL | NA_EDITED, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,7 +539,7 @@ static void replace_inputs_evaluated_data_blocks(
|
||||
|
||||
static bool object_has_editable_data(const Main &bmain, const Object &object)
|
||||
{
|
||||
if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH)) {
|
||||
if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH, OB_GREASE_PENCIL)) {
|
||||
return false;
|
||||
}
|
||||
if (!BKE_id_is_editable(&bmain, static_cast<const ID *>(object.data))) {
|
||||
@@ -635,7 +701,7 @@ static wmOperatorStatus run_node_group_exec(bContext *C, wmOperator *op)
|
||||
std::move(geometry_orig));
|
||||
|
||||
store_result_geometry(
|
||||
*op, *depsgraph_active, *bmain, *scene, *object, rv3d, std::move(new_geometry));
|
||||
*C, *op, *depsgraph_active, *bmain, *scene, *object, rv3d, std::move(new_geometry));
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, object->data);
|
||||
}
|
||||
|
||||
@@ -1066,6 +1132,20 @@ static GeometryNodeAssetTraitFlag asset_flag_for_context(const ObjectType type,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_GREASE_PENCIL: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_OBJECT | GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
case OB_MODE_EDIT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
case OB_MODE_SCULPT_GREASE_PENCIL:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_SCULPT | GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
case OB_MODE_PAINT_GREASE_PENCIL:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_PAINT | GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1131,6 +1211,28 @@ static asset::AssetItemTree *get_static_item_tree(const ObjectType type, const e
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
case OB_GREASE_PENCIL: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_EDIT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_SCULPT_GREASE_PENCIL: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_PAINT_GREASE_PENCIL: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1143,9 +1245,13 @@ static asset::AssetItemTree *get_static_item_tree(const Object &active_object)
|
||||
|
||||
void clear_operator_asset_trees()
|
||||
{
|
||||
for (const ObjectType type : {OB_MESH, OB_CURVES, OB_POINTCLOUD}) {
|
||||
for (const eObjectMode mode :
|
||||
{OB_MODE_OBJECT, OB_MODE_EDIT, OB_MODE_SCULPT, OB_MODE_SCULPT_CURVES})
|
||||
for (const ObjectType type : {OB_MESH, OB_CURVES, OB_POINTCLOUD, OB_GREASE_PENCIL}) {
|
||||
for (const eObjectMode mode : {OB_MODE_OBJECT,
|
||||
OB_MODE_EDIT,
|
||||
OB_MODE_SCULPT,
|
||||
OB_MODE_SCULPT_CURVES,
|
||||
OB_MODE_SCULPT_GREASE_PENCIL,
|
||||
OB_MODE_PAINT_GREASE_PENCIL})
|
||||
{
|
||||
if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
|
||||
tree->dirty = true;
|
||||
@@ -1243,6 +1349,36 @@ static Set<std::string> get_builtin_menus(const ObjectType object_type, const eO
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OB_GREASE_PENCIL: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
menus.add_new("Add");
|
||||
menus.add_new("Object");
|
||||
menus.add_new("Object/Apply");
|
||||
menus.add_new("Object/Convert");
|
||||
menus.add_new("Object/Quick Effects");
|
||||
break;
|
||||
case OB_MODE_EDIT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
menus.add_new("Grease Pencil");
|
||||
menus.add_new("Stroke");
|
||||
menus.add_new("Point");
|
||||
break;
|
||||
case OB_MODE_SCULPT_GREASE_PENCIL:
|
||||
menus.add_new("View");
|
||||
break;
|
||||
case OB_MODE_PAINT_GREASE_PENCIL:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Draw");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "GEO_merge_layers.hh"
|
||||
|
||||
#include "RNA_prototypes.hh"
|
||||
@@ -1873,21 +1875,23 @@ void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil,
|
||||
|
||||
/* Get the original material pointers from the result geometry. */
|
||||
VectorSet<Material *> original_materials;
|
||||
const Span<Material *> eval_materials = Span{merged_layers_grease_pencil.material_array,
|
||||
merged_layers_grease_pencil.material_array_num};
|
||||
const Span<Material *> eval_materials = Span{eval_grease_pencil.material_array,
|
||||
eval_grease_pencil.material_array_num};
|
||||
for (Material *eval_material : eval_materials) {
|
||||
if (eval_material != nullptr && eval_material->id.orig_id != nullptr) {
|
||||
original_materials.add_new(reinterpret_cast<Material *>(eval_material->id.orig_id));
|
||||
if (!eval_material) {
|
||||
return;
|
||||
}
|
||||
original_materials.add(DEG_get_original(eval_material));
|
||||
}
|
||||
|
||||
/* Build material indices mapping. This maps the materials indices on the original geometry to
|
||||
* the material indices used in the result geometry. The material indices for the drawings in the
|
||||
* result geometry are already correct, but this might not be the case for all drawings in the
|
||||
* original geometry (like for drawings that are not visible on the frame that the data is
|
||||
* the material indices used in the result geometry. The material indices for the drawings in
|
||||
* the result geometry are already correct, but this might not be the case for all drawings in
|
||||
* the original geometry (like for drawings that are not visible on the frame that the data is
|
||||
* being applied on). */
|
||||
Array<int> material_indices_map(orig_grease_pencil.material_array_num);
|
||||
for (const int mat_i : IndexRange(orig_grease_pencil.material_array_num)) {
|
||||
const IndexRange orig_material_indices = IndexRange(orig_grease_pencil.material_array_num);
|
||||
Array<int> material_indices_map(orig_grease_pencil.material_array_num, -1);
|
||||
for (const int mat_i : orig_material_indices) {
|
||||
Material *material = orig_grease_pencil.material_array[mat_i];
|
||||
const int map_index = original_materials.index_of_try(material);
|
||||
if (map_index != -1) {
|
||||
@@ -1897,8 +1901,7 @@ void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil,
|
||||
|
||||
/* Remap material indices for all other drawings. */
|
||||
if (!material_indices_map.is_empty() &&
|
||||
!array_utils::indices_are_range(material_indices_map,
|
||||
IndexRange(orig_grease_pencil.material_array_num)))
|
||||
!array_utils::indices_are_range(material_indices_map, orig_material_indices))
|
||||
{
|
||||
for (GreasePencilDrawingBase *base : orig_grease_pencil.drawings()) {
|
||||
if (base->type != GP_DRAWING) {
|
||||
@@ -1916,7 +1919,7 @@ void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil,
|
||||
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
|
||||
"material_index", AttrDomain::Curve);
|
||||
for (int &material_index : material_indices.span) {
|
||||
if (material_index >= 0 && material_index < material_indices_map.size()) {
|
||||
if (material_indices_map.index_range().contains(material_index)) {
|
||||
material_index = material_indices_map[material_index];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,11 +978,7 @@ static bool apply_grease_pencil_for_modifier(Depsgraph *depsgraph,
|
||||
|
||||
Main *bmain = DEG_get_bmain(depsgraph);
|
||||
/* There might be layers with empty names after evaluation. Make sure to rename them. */
|
||||
for (Layer *layer : grease_pencil_orig.layers_for_write()) {
|
||||
if (layer->name().is_empty()) {
|
||||
grease_pencil_orig.rename_node(*bmain, layer->as_node(), DATA_("Layer"));
|
||||
}
|
||||
}
|
||||
bke::greasepencil::ensure_non_empty_layer_names(*bmain, grease_pencil_result);
|
||||
BKE_object_material_from_eval_data(bmain, ob, &grease_pencil_result.id);
|
||||
return true;
|
||||
}
|
||||
@@ -1062,11 +1058,7 @@ static bool apply_grease_pencil_for_modifier_all_keyframes(Depsgraph *depsgraph,
|
||||
BKE_scene_graph_update_for_newframe(depsgraph);
|
||||
|
||||
/* There might be layers with empty names after evaluation. Make sure to rename them. */
|
||||
for (Layer *layer : grease_pencil_orig.layers_for_write()) {
|
||||
if (layer->name().is_empty()) {
|
||||
grease_pencil_orig.rename_node(*bmain, layer->as_node(), DATA_("Layer"));
|
||||
}
|
||||
}
|
||||
bke::greasepencil::ensure_non_empty_layer_names(*bmain, grease_pencil_orig);
|
||||
|
||||
WM_cursor_wait(false);
|
||||
return changed;
|
||||
|
||||
@@ -1018,6 +1018,9 @@ typedef enum GeometryNodeAssetTraitFlag {
|
||||
GEO_NODE_ASSET_MODIFIER = (1 << 6),
|
||||
GEO_NODE_ASSET_OBJECT = (1 << 7),
|
||||
GEO_NODE_ASSET_WAIT_FOR_CURSOR = (1 << 8),
|
||||
GEO_NODE_ASSET_GREASE_PENCIL = (1 << 9),
|
||||
/* Only used by Grease Pencil for now. */
|
||||
GEO_NODE_ASSET_PAINT = (1 << 10),
|
||||
} GeometryNodeAssetTraitFlag;
|
||||
ENUM_OPERATORS(GeometryNodeAssetTraitFlag, GEO_NODE_ASSET_WAIT_FOR_CURSOR);
|
||||
|
||||
|
||||
@@ -2207,6 +2207,15 @@ static void rna_GeometryNodeTree_is_mode_sculpt_set(PointerRNA *ptr, bool value)
|
||||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_SCULPT, value);
|
||||
}
|
||||
|
||||
static bool rna_GeometryNodeTree_is_mode_paint_get(PointerRNA *ptr)
|
||||
{
|
||||
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_PAINT);
|
||||
}
|
||||
static void rna_GeometryNodeTree_is_mode_paint_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_PAINT, value);
|
||||
}
|
||||
|
||||
static bool rna_GeometryNodeTree_is_type_mesh_get(PointerRNA *ptr)
|
||||
{
|
||||
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_MESH);
|
||||
@@ -2243,6 +2252,15 @@ static void rna_GeometryNodeTree_use_wait_for_click_set(PointerRNA *ptr, bool va
|
||||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_WAIT_FOR_CURSOR, value);
|
||||
}
|
||||
|
||||
static bool rna_GeometryNodeTree_is_type_grease_pencil_get(PointerRNA *ptr)
|
||||
{
|
||||
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
}
|
||||
static void rna_GeometryNodeTree_is_type_grease_pencil_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_GREASE_PENCIL, value);
|
||||
}
|
||||
|
||||
static bool random_value_type_supported(const EnumPropertyItem *item)
|
||||
{
|
||||
return ELEM(item->value, CD_PROP_FLOAT, CD_PROP_FLOAT3, CD_PROP_BOOL, CD_PROP_INT32);
|
||||
@@ -13357,6 +13375,14 @@ static void rna_def_geometry_nodetree(BlenderRNA *brna)
|
||||
prop, "rna_GeometryNodeTree_is_mode_sculpt_get", "rna_GeometryNodeTree_is_mode_sculpt_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
|
||||
prop = RNA_def_property(srna, "is_mode_paint", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_PAINT);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Paint", "The node group is used in paint mode");
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_GeometryNodeTree_is_mode_paint_get", "rna_GeometryNodeTree_is_mode_paint_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
|
||||
prop = RNA_def_property(srna, "is_type_mesh", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_MESH);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
@@ -13392,6 +13418,15 @@ static void rna_def_geometry_nodetree(BlenderRNA *brna)
|
||||
"rna_GeometryNodeTree_use_wait_for_click_get",
|
||||
"rna_GeometryNodeTree_use_wait_for_click_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
|
||||
prop = RNA_def_property(srna, "is_type_grease_pencil", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_GREASE_PENCIL);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Grease Pencil", "The node group is used for Grease Pencil");
|
||||
RNA_def_property_boolean_funcs(prop,
|
||||
"rna_GeometryNodeTree_is_type_grease_pencil_get",
|
||||
"rna_GeometryNodeTree_is_type_grease_pencil_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
}
|
||||
|
||||
static StructRNA *define_specific_node(BlenderRNA *brna,
|
||||
|
||||
@@ -207,6 +207,7 @@ struct GeoNodesOperatorData {
|
||||
int active_point_index = -1;
|
||||
int active_edge_index = -1;
|
||||
int active_face_index = -1;
|
||||
int active_layer_index = -1;
|
||||
};
|
||||
|
||||
struct GeoNodesCallData {
|
||||
|
||||
@@ -60,6 +60,10 @@ static void node_exec(GeoNodeExecParams params)
|
||||
params.set_output("Exists", operator_data->active_face_index >= 0);
|
||||
params.set_output("Index", std::max(0, operator_data->active_face_index));
|
||||
break;
|
||||
case AttrDomain::Layer:
|
||||
params.set_output("Exists", operator_data->active_layer_index >= 0);
|
||||
params.set_output("Index", std::max(0, operator_data->active_layer_index));
|
||||
break;
|
||||
default:
|
||||
params.set_default_remaining_outputs();
|
||||
BLI_assert_unreachable();
|
||||
@@ -69,11 +73,19 @@ static void node_exec(GeoNodeExecParams params)
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem rna_domain_items[] = {
|
||||
{int(AttrDomain::Point), "POINT", 0, "Point", ""},
|
||||
{int(AttrDomain::Edge), "EDGE", 0, "Edge", ""},
|
||||
{int(AttrDomain::Face), "FACE", 0, "Face", ""},
|
||||
{int(AttrDomain::Layer), "LAYER", 0, "Layer", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
RNA_def_node_enum(srna,
|
||||
"domain",
|
||||
"Domain",
|
||||
"",
|
||||
rna_enum_attribute_domain_only_mesh_no_corner_items,
|
||||
rna_domain_items,
|
||||
NOD_inline_enum_accessors(custom1),
|
||||
int(AttrDomain::Point));
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ class EditSelectionFieldInput final : public bke::GeometryFieldInput {
|
||||
switch (context.type()) {
|
||||
case GeometryComponent::Type::Curve:
|
||||
case GeometryComponent::Type::PointCloud:
|
||||
case GeometryComponent::Type::GreasePencil:
|
||||
return *attributes.lookup_or_default(
|
||||
".selection", domain, data_type, true_value(data_type));
|
||||
case GeometryComponent::Type::Mesh:
|
||||
@@ -114,6 +115,7 @@ class SculptSelectionFieldInput final : public bke::GeometryFieldInput {
|
||||
switch (context.type()) {
|
||||
case GeometryComponent::Type::Curve:
|
||||
case GeometryComponent::Type::PointCloud:
|
||||
case GeometryComponent::Type::GreasePencil:
|
||||
return *attributes.lookup_or_default(
|
||||
".selection", domain, data_type, true_value(data_type));
|
||||
case GeometryComponent::Type::Mesh: {
|
||||
@@ -156,7 +158,11 @@ static GField get_selection_field(const eObjectMode object_mode, const eCustomDa
|
||||
return GField(std::make_shared<EditSelectionFieldInput>(data_type));
|
||||
case OB_MODE_SCULPT:
|
||||
case OB_MODE_SCULPT_CURVES:
|
||||
case OB_MODE_SCULPT_GREASE_PENCIL:
|
||||
return GField(std::make_shared<SculptSelectionFieldInput>(data_type));
|
||||
case OB_MODE_PAINT_GREASE_PENCIL:
|
||||
return fn::make_constant_field(*bke::custom_data_type_to_cpp_type(data_type),
|
||||
true_value(data_type));
|
||||
default:
|
||||
return fn::make_constant_field(*bke::custom_data_type_to_cpp_type(data_type),
|
||||
false_value(data_type));
|
||||
|
||||
@@ -85,9 +85,9 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
}
|
||||
GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
|
||||
const eObjectMode mode = params.user_data()->call_data->operator_data->mode;
|
||||
if (mode == OB_MODE_OBJECT) {
|
||||
if (ELEM(mode, OB_MODE_OBJECT, OB_MODE_PAINT_GREASE_PENCIL)) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
"Selection control is not supported in object mode");
|
||||
"Selection control is not supported in this mode");
|
||||
params.set_output("Geometry", std::move(geometry));
|
||||
return;
|
||||
}
|
||||
@@ -167,6 +167,17 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
geometry.get_component_for_write<PointCloudComponent>(), ".selection", domain, field);
|
||||
}
|
||||
}
|
||||
if (geometry.has_grease_pencil()) {
|
||||
/* Grease Pencil only supports boolean selection. */
|
||||
const Field<bool> field = conversions.try_convert(selection, CPPType::get<bool>());
|
||||
if (ELEM(domain, AttrDomain::Point, AttrDomain::Curve)) {
|
||||
bke::try_capture_field_on_geometry(
|
||||
geometry.get_component_for_write<GreasePencilComponent>(),
|
||||
".selection",
|
||||
domain,
|
||||
field);
|
||||
}
|
||||
}
|
||||
});
|
||||
params.set_output("Geometry", std::move(geometry));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user