From 4411d3eeac3110ed6aecbaec4d0f9c2cd7b3d850 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 7 Feb 2023 13:57:46 -0500 Subject: [PATCH 1/3] Assets: Implement viewport drag and drop for geometry nodes Currently there's no way to assign a geometry node group from the asset browser to an object as a modifier without first appending/linking it manually. This patch adds a drag and drop operator that adds a new modifier and assigns the dragged tree. --- source/blender/editors/include/ED_object.h | 3 + source/blender/editors/object/object_intern.h | 5 + source/blender/editors/object/object_ops.c | 1 + .../blender/editors/object/object_relations.c | 115 ++++++++++++++++++ .../editors/space_view3d/space_view3d.cc | 53 ++++++++ 5 files changed, 177 insertions(+) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index baa84b550aa..a511d7625f8 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -241,6 +241,9 @@ void ED_object_parent(struct Object *ob, struct Object *parent, int type, const char *ED_object_ot_drop_named_material_tooltip(struct bContext *C, const char *name, const int mval[2]); +char *ED_object_ot_drop_geometry_nodes_tooltip(struct bContext *C, + struct PointerRNA *properties, + const int mval[2]); /* bitflags for enter/exit editmode */ enum { diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b136f311557..c58ce0d8424 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -62,6 +62,11 @@ void OBJECT_OT_clear_override_library(struct wmOperatorType *ot); * Assigns to object under cursor, only first material slot. */ void OBJECT_OT_drop_named_material(struct wmOperatorType *ot); +/** + * Used for drop-box. + * Assigns to object under cursor, creates a new geometry nodes modifier. + */ +void OBJECT_OT_drop_geometry_nodes(struct wmOperatorType *ot); /** * \note Only for empty-image objects, this operator is needed */ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index a73cc98c78e..c8e06ef97c7 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -262,6 +262,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_bake_image); WM_operatortype_append(OBJECT_OT_bake); WM_operatortype_append(OBJECT_OT_drop_named_material); + WM_operatortype_append(OBJECT_OT_drop_geometry_nodes); WM_operatortype_append(OBJECT_OT_unlink_data); WM_operatortype_append(OBJECT_OT_laplaciandeform_bind); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 5315e89c62d..f982b80c37d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -99,6 +99,8 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "MOD_nodes.h" + #include "object_intern.h" /* ------------------------------------------------------------------- */ @@ -2867,6 +2869,119 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot) /** \} */ +/* ------------------------------------------------------------------- */ +/** \name Drop Geometry Nodes on Object Operator + * \{ */ + +char *ED_object_ot_drop_geometry_nodes_tooltip(bContext *C, + PointerRNA *properties, + const int mval[2]) +{ + Object *ob = ED_view3d_give_object_under_cursor(C, mval); + if (ob == NULL) { + return BLI_strdup(""); + } + + uint32_t session_uuid = RNA_int_get(properties, "session_uuid"); + ID *id = BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, session_uuid); + if (!id) { + return BLI_strdup(""); + } + + const char *tooltip = TIP_("Drop node tree %s on object %s"); + return BLI_sprintfN(tooltip, id->name, ob->id.name); +} + +static bool check_geometry_node_group_sockets(wmOperator *op, const bNodeTree *tree) +{ + const bNodeSocket *first_input = (const bNodeSocket *)tree->inputs.first; + if (!first_input) { + BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry input socket"); + return false; + } + if (first_input->type != SOCK_GEOMETRY) { + BKE_report(op->reports, RPT_ERROR, "The first input must be a geometry socket"); + return false; + } + const bNodeSocket *first_output = (const bNodeSocket *)tree->outputs.first; + if (!first_output) { + BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry output socket"); + return false; + } + if (first_output->type != SOCK_GEOMETRY) { + BKE_report(op->reports, RPT_ERROR, "The first output must be a geometry socket"); + return false; + } + return true; +} + +static int drop_geometry_nodes_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = ED_view3d_give_object_under_cursor(C, event->mval); + if (!ob) { + return OPERATOR_CANCELLED; + } + + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + + const uint32_t uuid = RNA_int_get(op->ptr, "session_uuid"); + bNodeTree *node_tree = (bNodeTree *)BKE_libblock_find_session_uuid(bmain, ID_NT, uuid); + if (!node_tree) { + return OPERATOR_CANCELLED; + } + if (node_tree->type != NTREE_GEOMETRY) { + BKE_report(op->reports, RPT_ERROR, "Node group must be a geometry node tree"); + return OPERATOR_CANCELLED; + } + + if (!check_geometry_node_group_sockets(op, node_tree)) { + return OPERATOR_CANCELLED; + } + + NodesModifierData *nmd = (NodesModifierData *)ED_object_modifier_add( + op->reports, bmain, scene, ob, node_tree->id.name + 2, eModifierType_Nodes); + if (!nmd) { + BKE_report(op->reports, RPT_ERROR, "Could not add geometry nodes modifier"); + return OPERATOR_CANCELLED; + } + + nmd->node_group = node_tree; + id_us_plus(&node_tree->id); + MOD_nodes_update_interface(ob, nmd); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, NULL); + + return OPERATOR_FINISHED; +} + +/** \} */ + +void OBJECT_OT_drop_geometry_nodes(wmOperatorType *ot) +{ + ot->name = "Drop Geometry Node Group on Object"; + ot->idname = "OBJECT_OT_drop_geometry_nodes"; + + ot->invoke = drop_geometry_nodes_invoke; + ot->poll = ED_operator_view3d_active; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + + PropertyRNA *prop = RNA_def_int(ot->srna, + "session_uuid", + 0, + INT32_MIN, + INT32_MAX, + "Session UUID", + "Session UUID of the geometry node group being dropped", + INT32_MIN, + INT32_MAX); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE)); +} + +/** \} */ + /* ------------------------------------------------------------------- */ /** \name Unlink Object Operator * \{ */ diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index 396e75f6b4e..62eca30ce95 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -37,6 +37,7 @@ #include "BKE_idprop.h" #include "BKE_lattice.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_mball.h" @@ -702,6 +703,52 @@ static bool view3d_volume_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEven return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME); } +static bool view3d_geometry_nodes_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) +{ + if (!view3d_drop_id_in_main_region_poll(C, drag, event, ID_NT)) { + return false; + } + + if (drag->type == WM_DRAG_ID) { + const bNodeTree *node_tree = reinterpret_cast( + WM_drag_get_local_ID(drag, ID_NT)); + if (!node_tree) { + return false; + } + return node_tree->type == NTREE_GEOMETRY; + } + + if (drag->type == WM_DRAG_ASSET) { + const wmDragAsset *asset_data = WM_drag_get_asset_data(drag, ID_NT); + if (!asset_data) { + return false; + } + const IDProperty *tree_type = BKE_asset_metadata_idprop_find(asset_data->metadata, "type"); + if (!tree_type || IDP_Int(tree_type) != NTREE_GEOMETRY) { + return false; + } + if (wmDropBox *drop_box = drag->drop_state.active_dropbox) { + const uint32_t uuid = RNA_int_get(drop_box->ptr, "session_uuid"); + bNodeTree *node_tree = reinterpret_cast( + BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, uuid)); + if (node_tree) { + return node_tree->type == NTREE_GEOMETRY; + } + } + } + return true; +} + +static char *view3d_geometry_nodes_drop_tooltip(bContext *C, + wmDrag * /*drag*/, + const int xy[2], + struct wmDropBox *drop) +{ + ARegion *region = CTX_wm_region(C); + int mval[2] = {xy[0] - region->winrct.xmin, xy[1] - region->winrct.ymin}; + return ED_object_ot_drop_geometry_nodes_tooltip(C, drop->ptr, mval); +} + static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state, Object *ob, float obmat_final[4][4]) @@ -930,6 +977,12 @@ static void view3d_dropboxes() view3d_id_drop_copy, WM_drag_free_imported_drag_ID, view3d_mat_drop_tooltip); + WM_dropbox_add(lb, + "OBJECT_OT_drop_geometry_nodes", + view3d_geometry_nodes_drop_poll, + view3d_id_drop_copy, + WM_drag_free_imported_drag_ID, + view3d_geometry_nodes_drop_tooltip); WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, -- 2.30.2 From b65cdb4d669e86581ba66a18d836845fb1fb159d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 9 Feb 2023 09:58:42 -0500 Subject: [PATCH 2/3] Cleanup: Add const to various places --- source/blender/editors/include/ED_object.h | 4 ++-- source/blender/editors/object/object_relations.c | 10 +++++----- source/blender/editors/space_view3d/space_view3d.cc | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index a511d7625f8..47378dbe468 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -241,8 +241,8 @@ void ED_object_parent(struct Object *ob, struct Object *parent, int type, const char *ED_object_ot_drop_named_material_tooltip(struct bContext *C, const char *name, const int mval[2]); -char *ED_object_ot_drop_geometry_nodes_tooltip(struct bContext *C, - struct PointerRNA *properties, +char *ED_object_ot_drop_geometry_nodes_tooltip(const struct bContext *C, + const struct PointerRNA *properties, const int mval[2]); /* bitflags for enter/exit editmode */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f982b80c37d..ed15078bf31 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2873,17 +2873,17 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot) /** \name Drop Geometry Nodes on Object Operator * \{ */ -char *ED_object_ot_drop_geometry_nodes_tooltip(bContext *C, - PointerRNA *properties, +char *ED_object_ot_drop_geometry_nodes_tooltip(const bContext *C, + const PointerRNA *properties, const int mval[2]) { - Object *ob = ED_view3d_give_object_under_cursor(C, mval); + const Object *ob = ED_view3d_give_object_under_cursor(C, mval); if (ob == NULL) { return BLI_strdup(""); } - uint32_t session_uuid = RNA_int_get(properties, "session_uuid"); - ID *id = BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, session_uuid); + const uint32_t session_uuid = RNA_int_get(properties, "session_uuid"); + const ID *id = BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, session_uuid); if (!id) { return BLI_strdup(""); } diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index e1894f4a840..cd7794300f6 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -729,7 +729,7 @@ static bool view3d_geometry_nodes_drop_poll(bContext *C, wmDrag *drag, const wmE } if (wmDropBox *drop_box = drag->drop_state.active_dropbox) { const uint32_t uuid = RNA_int_get(drop_box->ptr, "session_uuid"); - bNodeTree *node_tree = reinterpret_cast( + const bNodeTree *node_tree = reinterpret_cast( BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, uuid)); if (node_tree) { return node_tree->type == NTREE_GEOMETRY; -- 2.30.2 From 643675962e3e54ac9618137ebf9635a7aa74f711 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 9 Feb 2023 10:01:06 -0500 Subject: [PATCH 3/3] Improve tooltip my by mentioning adding modifier --- source/blender/editors/object/object_relations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index ed15078bf31..4f76a3b3302 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2888,7 +2888,7 @@ char *ED_object_ot_drop_geometry_nodes_tooltip(const bContext *C, return BLI_strdup(""); } - const char *tooltip = TIP_("Drop node tree %s on object %s"); + const char *tooltip = TIP_("Add modifier with node group \"%s\" on object \"%s\""); return BLI_sprintfN(tooltip, id->name, ob->id.name); } -- 2.30.2