Assets: Implement viewport drag and drop for geometry nodes #104430

Merged
Hans Goudey merged 5 commits from HooglyBoogly/blender:drag-drop-geometry-nodes-asset into main 2023-02-09 16:04:16 +01:00
5 changed files with 177 additions and 0 deletions

View File

@ -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(const struct bContext *C,
const struct PointerRNA *properties,
const int mval[2]);
/* bitflags for enter/exit editmode */
enum {

View File

@ -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
*/

View File

@ -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);

View File

@ -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(const bContext *C,
HooglyBoogly marked this conversation as resolved
Review

This function could use a bunch of consts :) ED_object_ot_drop_named_material_tooltip() could too, but not the scope of this patch.

This function could use a bunch of `const`s :) `ED_object_ot_drop_named_material_tooltip()` could too, but not the scope of this patch.
const PointerRNA *properties,
const int mval[2])
{
const Object *ob = ED_view3d_give_object_under_cursor(C, mval);
if (ob == NULL) {
return BLI_strdup("");
}
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("");
}
const char *tooltip = TIP_("Add modifier with node group \"%s\" on object \"%s\"");
HooglyBoogly marked this conversation as resolved
Review

Would rather explain what effect dropping has (like adding a modifier to apply the dragged geometry node group), this isn't really helpful as a tooltip. Again, we better give ED_object_ot_drop_named_material_tooltip() an update here, but out of scope.

Would rather explain what effect dropping has (like adding a modifier to apply the dragged geometry node group), this isn't really helpful as a tooltip. Again, we better give `ED_object_ot_drop_named_material_tooltip()` an update here, but out of scope.
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
* \{ */

View File

@ -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<const bNodeTree *>(
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");
const bNodeTree *node_tree = reinterpret_cast<const bNodeTree *>(
HooglyBoogly marked this conversation as resolved
Review

const

`const`
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,