94 this->nodes.clear_and_shrink();
96 this->old_ids_to_idinfo.
clear();
110 bool is_valid =
true;
118 id_info.new_id.reset();
119 if (!id_info.library_path.empty() && !libraries_path_to_id.
contains(id_info.library_path)) {
120 libraries_path_to_id.
add(
121 id_info.library_path,
132 auto validate_id_fn = [
this, &is_valid, &bmain, &bmain_id_map, &libraries_path_to_id](
134 ID *old_id = *(cb_data->id_pointer);
138 if (!this->old_ids_to_idinfo.
contains(old_id)) {
140 0,
"Missing entry in the old ID data of the node clipboard, should not happen");
153 bmain_id_map,
GS(id_info.
id_name.c_str()), id_info.
id_name.c_str() + 2, new_id_lib);
160 if (*(id_info.
new_id) ==
nullptr) {
178 bmain_id_map =
nullptr;
191 ID *old_id = *(cb_data->id_pointer);
195 if (!this->old_ids_to_idinfo.
contains(old_id)) {
197 0,
"Missing entry in the old ID data of the node clipboard, should not happen");
198 *(cb_data->id_pointer) =
nullptr;
206 "Unset new ID value for an old ID reference in the node clipboard, should not happen");
207 *(cb_data->id_pointer) =
nullptr;
210 *(cb_data->id_pointer) = *(id_info.
new_id);
235 node_map.
add_new(&node, new_node);
239 ID *old_id = *(cb_data->id_pointer);
242 if (this->old_ids_to_idinfo.
contains(old_id)) {
253 this->old_ids_to_idinfo.
add(old_id, std::move(id_info));
269 item.node = new_node;
271 this->nodes.
append(std::move(item));
298 for (
const bNode *node :
tree.all_nodes()) {
299 if (node->flag &
SELECT) {
306 if (new_node->parent) {
307 if (node_map.
contains(new_node->parent)) {
308 new_node->parent = node_map.
lookup(new_node->parent);
321 clipboard.
links.append({});
323 new_link.
flag = link->flag;
326 new_link.
to_socket = link->tosock->identifier;
337 ot->name =
"Copy to Clipboard";
338 ot->description =
"Copy the selected nodes to the internal clipboard";
339 ot->idname =
"NODE_OT_clipboard_copy";
360 if (clipboard.
nodes.is_empty()) {
368 "Some nodes references to other IDs could not be restored, will be left empty");
378 bNode *new_active_node =
nullptr;
383 const char *disabled_hint =
nullptr;
407 if (!new_node->
typeinfo->poll_instance ||
408 new_node->
typeinfo->poll_instance(new_node, &
tree, &disabled_hint))
410 node_map.
add_new(&node, new_node);
412 new_active_node = new_node;
419 "Cannot add node %s into node tree %s: %s",
427 "Cannot add node %s into node tree %s",
441 if (new_node->parent) {
442 if (node_map.
contains(new_node->parent)) {
443 new_node->parent = node_map.
lookup(new_node->parent);
448 if (new_active_node) {
460 center /= clipboard.
nodes.size();
467 new_node->location[0] += offset.x;
468 new_node->location[1] += offset.y;
482 if (!from_node || !to_node) {
494 tree.ensure_topology_cache();
520 ot->name =
"Paste from Clipboard";
521 ot->description =
"Paste nodes from the internal clipboard to the active node tree";
522 ot->idname =
"NODE_OT_clipboard_paste";
538 "The 2D view location for the center of the new nodes, or unchanged if not set",
SpaceNode * CTX_wm_space_node(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void BKE_library_foreach_subdata_id(Main *bmain, ID *owner_id, ID *self_id, blender::FunctionRef< void(LibraryForeachIDData *data)> subdata_foreach_id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, const LibraryForeachIDFlag flag)
IDNameLib_Map * BKE_main_idmap_create(Main *bmain, bool create_valid_ids_set, Main *old_bmain, int idmap_types) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BKE_main_idmap_destroy(IDNameLib_Map *id_map) ATTR_NONNULL()
ID * BKE_main_idmap_lookup_name(IDNameLib_Map *id_map, short id_type, const char *name, const Library *lib) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_msg(a, msg)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
void DEG_relations_tag_update(Main *bmain)
@ SOCK_DISPLAY_SHAPE_CIRCLE
void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
bool ED_operator_node_editable(bContext *C)
bool ED_operator_node_active(bContext *C)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
BMesh const char void * data
ValueIterator values() const &
bool add(const Key &key, const Value &value)
const Value & lookup(const Key &key) const
Value lookup_default(const Key &key, const Value &default_value) const
void add_new(const Key &key, const Value &value)
bool contains(const Key &key) const
void append(const T &value)
void ED_node_clipboard_free()
#define ID_IS_LINKED(_id)
Library * search_filepath_abs(ListBase *libraries, blender::StringRef filepath_abs)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, bool use_unique, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map)
void node_node_foreach_id(bNode *node, LibraryForeachIDData *data)
void node_free_node(bNodeTree *tree, bNode &node)
bool node_set_selected(bNode &node, bool select)
void node_detach_node(bNodeTree &ntree, bNode &node)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
bool node_declaration_ensure(bNodeTree &ntree, bNode &node)
void node_set_active(bNodeTree &ntree, bNode &node)
void NODE_OT_clipboard_copy(wmOperatorType *ot)
void node_select_paired(bNodeTree &node_tree)
bool node_deselect_all(bNodeTree &node_tree)
void NODE_OT_clipboard_paste(wmOperatorType *ot)
static wmOperatorStatus node_clipboard_paste_exec(bContext *C, wmOperator *op)
static wmOperatorStatus node_clipboard_copy_exec(bContext *C, wmOperator *)
void remap_node_pairing(bNodeTree &dst_tree, const Map< const bNode *, bNode * > &node_map)
static NodeClipboard & get_node_clipboard()
void update_multi_input_indices_for_removed_links(bNode &node)
static wmOperatorStatus node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
VecBase< float, 2 > float2
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
PropertyRNA * RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
LibraryRuntimeHandle * runtime
struct bNodeTree * edittree
bNodeTypeHandle * typeinfo
bNodeRuntimeHandle * runtime
std::optional< ID * > new_id
Vector< NodeClipboardItem > nodes
void paste_update_node_id_references(bNode &node)
bool paste_validate_id_references(Main &bmain)
Map< ID *, NodeClipboardItemIDInfo > old_ids_to_idinfo
Vector< ClipboardLink > links
void copy_add_node(const bNode &node, Map< const bNode *, bNode * > &node_map, Map< const bNodeSocket *, bNodeSocket * > &socket_map)
struct ReportList * reports