99 this->nodes.clear_and_shrink();
101 this->old_ids_to_idinfo.
clear();
115 bool is_valid =
true;
123 id_info.new_id.reset();
124 if (!id_info.packed_id_hash.has_value() && !id_info.library_path.empty() &&
125 !libraries_path_to_id.
contains(id_info.library_path))
127 libraries_path_to_id.
add(
128 id_info.library_path,
151 auto validate_id_fn =
152 [
this, &is_valid, &bmain, &bmain_id_map, &libraries_path_to_id, &packed_id_by_hash](
154 ID *old_id = *(cb_data->id_pointer);
158 if (!this->old_ids_to_idinfo.
contains(old_id)) {
160 0,
"Missing entry in the old ID data of the node clipboard, should not happen");
188 if (*(id_info.
new_id) ==
nullptr) {
206 bmain_id_map =
nullptr;
219 ID *old_id = *(cb_data->id_pointer);
223 if (!this->old_ids_to_idinfo.
contains(old_id)) {
225 0,
"Missing entry in the old ID data of the node clipboard, should not happen");
226 *(cb_data->id_pointer) =
nullptr;
234 "Unset new ID value for an old ID reference in the node clipboard, should not happen");
235 *(cb_data->id_pointer) =
nullptr;
238 *(cb_data->id_pointer) = *(id_info.
new_id);
268 node_map.
add_new(&node, new_node);
272 ID *old_id = *(cb_data->id_pointer);
276 if (this->old_ids_to_idinfo.
contains(old_id)) {
290 this->old_ids_to_idinfo.
add(old_id, std::move(id_info));
306 item.node = new_node;
308 this->nodes.
append(std::move(item));
335 for (
const bNode *node :
tree.all_nodes()) {
336 if (node->flag &
SELECT) {
343 if (new_node->parent) {
344 if (node_map.
contains(new_node->parent)) {
345 new_node->parent = node_map.
lookup(new_node->parent);
358 clipboard.
links.append({});
360 new_link.
flag = link->flag;
363 new_link.
to_socket = link->tosock->identifier;
374 ot->name =
"Copy to Clipboard";
375 ot->description =
"Copy the selected nodes to the internal clipboard";
376 ot->idname =
"NODE_OT_clipboard_copy";
397 if (clipboard.
nodes.is_empty()) {
405 "Some nodes references to other IDs could not be restored, will be left empty");
415 bNode *new_active_node =
nullptr;
420 const char *disabled_hint =
nullptr;
444 if (!new_node->
typeinfo->poll_instance ||
445 new_node->
typeinfo->poll_instance(new_node, &
tree, &disabled_hint))
447 node_map.
add_new(&node, new_node);
449 new_active_node = new_node;
456 "Cannot add node %s into node tree %s: %s",
464 "Cannot add node %s into node tree %s",
478 if (new_node->parent) {
479 if (node_map.
contains(new_node->parent)) {
480 new_node->parent = node_map.
lookup(new_node->parent);
485 if (new_active_node) {
497 center /= clipboard.
nodes.size();
504 new_node->location[0] += offset.x;
505 new_node->location[1] += offset.y;
519 if (!from_node || !to_node) {
531 tree.ensure_topology_cache();
557 ot->name =
"Paste from Clipboard";
558 ot->description =
"Paste nodes from the internal clipboard to the active node tree";
559 ot->idname =
"NODE_OT_clipboard_paste";
575 "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)
#define FOREACH_MAIN_ID_END
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
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)
#define ID_IS_PACKED(_id)
#define ID_IS_LINKED(_id)
@ LIBRARY_FLAG_IS_ARCHIVE
@ 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()
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()
Library * search_filepath_abs(ListBase *libraries, blender::StringRef filepath_abs)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
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)
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, std::optional< StringRefNull > dst_unique_name, std::optional< int > dst_unique_identifier, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map, bool allow_duplicate_names=false)
bool node_declaration_ensure(bNodeTree &ntree, bNode &node)
void node_set_active(bNodeTree &ntree, bNode &node)
void NODE_OT_clipboard_copy(wmOperatorType *ot)
NodeLinkData data[NODELINK_GROUP_SIZE]
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
std::optional< IDHash > packed_id_hash
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