Geometry Nodes: support creating import nodes when dropping file paths
Now import nodes are automatically created in Geometry Nodes when dropping `.obj`, `.stl`, `.ply` and `.csv` files. Note that this is still hidden behind an experimental feature flag. Pull Request: https://projects.blender.org/blender/blender/pulls/135036
This commit is contained in:
@@ -175,21 +175,7 @@ void WM_OT_drop_import_file(wmOperatorType *ot)
|
||||
|
||||
static void drop_import_file_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
const auto paths = WM_drag_get_paths(drag);
|
||||
|
||||
char dir[FILE_MAX];
|
||||
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
|
||||
RNA_string_set(drop->ptr, "directory", dir);
|
||||
|
||||
RNA_collection_clear(drop->ptr, "files");
|
||||
for (const auto &path : paths) {
|
||||
char file[FILE_MAX];
|
||||
BLI_path_split_file_part(path.c_str(), file, sizeof(file));
|
||||
|
||||
PointerRNA itemptr{};
|
||||
RNA_collection_add(drop->ptr, "files", &itemptr);
|
||||
RNA_string_set(&itemptr, "name", file);
|
||||
}
|
||||
blender::ed::io::paths_to_operator_properties(drop->ptr, WM_drag_get_paths(drag));
|
||||
}
|
||||
|
||||
static bool drop_import_file_poll(bContext *C, wmDrag *drag, const wmEvent * /*event*/)
|
||||
|
||||
@@ -111,4 +111,22 @@ Vector<std::string> paths_from_operator_properties(PointerRNA *ptr)
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
void paths_to_operator_properties(PointerRNA *ptr, const Span<std::string> paths)
|
||||
{
|
||||
char dir[FILE_MAX];
|
||||
BLI_path_split_dir_part(paths[0].c_str(), dir, sizeof(dir));
|
||||
RNA_string_set(ptr, "directory", dir);
|
||||
|
||||
RNA_collection_clear(ptr, "files");
|
||||
for (const auto &path : paths) {
|
||||
char file[FILE_MAX];
|
||||
BLI_path_split_file_part(path.c_str(), file, sizeof(file));
|
||||
|
||||
PointerRNA itemptr{};
|
||||
RNA_collection_add(ptr, "files", &itemptr);
|
||||
RNA_string_set(&itemptr, "name", file);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::ed::io
|
||||
|
||||
@@ -29,4 +29,5 @@ bool poll_file_object_drop(const bContext *C, blender::bke::FileHandlerType *fh)
|
||||
* If the pointer has a `filepath` property is also returned as fallback.
|
||||
*/
|
||||
Vector<std::string> paths_from_operator_properties(PointerRNA *ptr);
|
||||
void paths_to_operator_properties(PointerRNA *ptr, const Span<std::string> paths);
|
||||
} // namespace blender::ed::io
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "BLI_easing.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
@@ -701,7 +702,7 @@ struct NodeStackAnimationData {
|
||||
wmTimer *anim_timer;
|
||||
};
|
||||
|
||||
static int node_add_file_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
static int node_add_nodes_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
NodeStackAnimationData *data = static_cast<NodeStackAnimationData *>(op->customdata);
|
||||
|
||||
@@ -877,7 +878,7 @@ void NODE_OT_add_file(wmOperatorType *ot)
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = node_add_file_exec;
|
||||
ot->modal = node_add_file_modal;
|
||||
ot->modal = node_add_nodes_modal;
|
||||
ot->invoke = node_add_file_invoke;
|
||||
ot->poll = node_add_file_poll;
|
||||
|
||||
@@ -1033,6 +1034,115 @@ void NODE_OT_add_material(wmOperatorType *ot)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Import Node Operator
|
||||
* \{ */
|
||||
|
||||
static int node_add_import_node_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
bNodeTree *ntree = snode->edittree;
|
||||
|
||||
const Vector<std::string> paths = ed::io::paths_from_operator_properties(op->ptr);
|
||||
|
||||
Vector<bNode *> new_nodes;
|
||||
for (const StringRefNull path : paths) {
|
||||
bNode *node = nullptr;
|
||||
if (path.endswith(".csv")) {
|
||||
node = add_node(*C, "GeometryNodeImportCSV", snode->runtime->cursor);
|
||||
}
|
||||
else if (path.endswith(".obj")) {
|
||||
node = add_node(*C, "GeometryNodeImportOBJ", snode->runtime->cursor);
|
||||
}
|
||||
else if (path.endswith(".ply")) {
|
||||
node = add_node(*C, "GeometryNodeImportPLY", snode->runtime->cursor);
|
||||
}
|
||||
else if (path.endswith(".stl")) {
|
||||
node = add_node(*C, "GeometryNodeImportSTL", snode->runtime->cursor);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
bNodeSocket &path_socket = node->input_by_identifier("Path");
|
||||
BLI_assert(path_socket.type == SOCK_STRING);
|
||||
auto *socket_data = static_cast<bNodeSocketValueString *>(path_socket.default_value);
|
||||
STRNCPY(socket_data->value, path.c_str());
|
||||
new_nodes.append(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_nodes.is_empty()) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
node_deselect_all(*ntree);
|
||||
|
||||
for (const int i : new_nodes.index_range()) {
|
||||
bNode *node = new_nodes[i];
|
||||
node->flag |= NODE_SELECT;
|
||||
}
|
||||
bke::node_set_active(*ntree, *new_nodes[0]);
|
||||
|
||||
NodeStackAnimationData *data = MEM_new<NodeStackAnimationData>(__func__);
|
||||
data->nodes = std::move(new_nodes);
|
||||
data->anim_timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
|
||||
op->customdata = data;
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
BKE_main_ensure_invariants(*bmain, ntree->id);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int node_add_import_node_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
|
||||
/* Convert mouse coordinates to v2d space. */
|
||||
UI_view2d_region_to_view(®ion->v2d,
|
||||
event->mval[0],
|
||||
event->mval[1],
|
||||
&snode->runtime->cursor[0],
|
||||
&snode->runtime->cursor[1]);
|
||||
|
||||
snode->runtime->cursor[0] /= UI_SCALE_FAC;
|
||||
snode->runtime->cursor[1] /= UI_SCALE_FAC;
|
||||
|
||||
return node_add_import_node_exec(C, op);
|
||||
}
|
||||
|
||||
static bool node_add_import_node_poll(bContext *C)
|
||||
{
|
||||
const SpaceNode *snode = CTX_wm_space_node(C);
|
||||
return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_GEOMETRY;
|
||||
}
|
||||
|
||||
void NODE_OT_add_import_node(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Add Import Node";
|
||||
ot->description = "Add an import node to the node tree";
|
||||
ot->idname = "NODE_OT_add_import_node";
|
||||
|
||||
ot->poll = node_add_import_node_poll;
|
||||
ot->exec = node_add_import_node_exec;
|
||||
ot->invoke = node_add_import_node_invoke;
|
||||
ot->modal = node_add_nodes_modal;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string_dir_path(
|
||||
ot->srna, "directory", nullptr, FILE_MAX, "Directory", "Directory of the file");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Add Color Operator
|
||||
* \{ */
|
||||
|
||||
@@ -298,6 +298,7 @@ void NODE_OT_add_file(wmOperatorType *ot);
|
||||
void NODE_OT_add_mask(wmOperatorType *ot);
|
||||
void NODE_OT_add_material(wmOperatorType *ot);
|
||||
void NODE_OT_add_color(wmOperatorType *ot);
|
||||
void NODE_OT_add_import_node(wmOperatorType *ot);
|
||||
void NODE_OT_new_node_tree(wmOperatorType *ot);
|
||||
|
||||
/* `node_group.cc` */
|
||||
|
||||
@@ -85,6 +85,7 @@ void node_operatortypes()
|
||||
WM_operatortype_append(NODE_OT_add_mask);
|
||||
WM_operatortype_append(NODE_OT_add_material);
|
||||
WM_operatortype_append(NODE_OT_add_color);
|
||||
WM_operatortype_append(NODE_OT_add_import_node);
|
||||
|
||||
WM_operatortype_append(NODE_OT_new_node_tree);
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "io_utils.hh"
|
||||
|
||||
#include "node_intern.hh" /* own include */
|
||||
|
||||
using blender::float2;
|
||||
@@ -857,6 +859,25 @@ static bool node_color_drop_poll(bContext *C, wmDrag *drag, const wmEvent * /*ev
|
||||
return (drag->type == WM_DRAG_COLOR) && !UI_but_active_drop_color(C);
|
||||
}
|
||||
|
||||
static bool node_import_file_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
{
|
||||
if (!U.experimental.use_new_file_import_nodes) {
|
||||
return false;
|
||||
}
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return false;
|
||||
}
|
||||
const blender::Span<std::string> paths = WM_drag_get_paths(drag);
|
||||
for (const StringRef path : paths) {
|
||||
if (path.endswith(".csv") || path.endswith(".obj") || path.endswith(".ply") ||
|
||||
path.endswith(".stl"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void node_group_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
ID *id = WM_drag_get_local_ID_or_import_from_asset(C, drag, 0);
|
||||
@@ -883,6 +904,11 @@ static void node_id_im_drop_copy(bContext *C, wmDrag *drag, wmDropBox *drop)
|
||||
}
|
||||
}
|
||||
|
||||
static void node_import_file_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
io::paths_to_operator_properties(drop->ptr, WM_drag_get_paths(drag));
|
||||
}
|
||||
|
||||
/* this region dropbox definition */
|
||||
static void node_dropboxes()
|
||||
{
|
||||
@@ -926,6 +952,12 @@ static void node_dropboxes()
|
||||
nullptr);
|
||||
WM_dropbox_add(
|
||||
lb, "NODE_OT_add_color", node_color_drop_poll, UI_drop_color_copy, nullptr, nullptr);
|
||||
WM_dropbox_add(lb,
|
||||
"NODE_OT_add_import_node",
|
||||
node_import_file_drop_poll,
|
||||
node_import_file_drop_copy,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
/* ************* end drop *********** */
|
||||
|
||||
Reference in New Issue
Block a user