Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-08-20 17:51:25 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-08-20 17:51:25 +0400
commit0f6a6c7499f0c1fa509355c5967f30a42cfa771e (patch)
tree0de8396d8dd554719f2103276ec14398b18ec298 /source/blender
parentad647b2767ea8b5cdc24cb3fae1173eca8a0da9b (diff)
fix for crash pasting nodes into a node tree when the ID pointer is lost.
also fix for ID user count on paste which wasn't increasing.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.c98
-rw-r--r--source/blender/editors/space_node/node_edit.c25
3 files changed, 119 insertions, 5 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 61845619452..c45afbe77a9 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -388,6 +388,7 @@ void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
void BKE_node_clipboard_clear(void);
+int BKE_node_clipboard_validate(void);
void BKE_node_clipboard_add_node(struct bNode *node);
void BKE_node_clipboard_add_link(struct bNodeLink *link);
const struct ListBase *BKE_node_clipboard_get_nodes(void);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 7cee9626c3f..dc2f3a1a2fa 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1425,13 +1425,37 @@ void nodeSocketSetType(bNodeSocket *sock, int type)
/* ************** Node Clipboard *********** */
+#define USE_NODE_CB_VALIDATE
+
+#ifdef USE_NODE_CB_VALIDATE
+/**
+ * This data structure is to validate the node on creation,
+ * otherwise we may reference missing data.
+ *
+ * Currently its only used for ID's, but nodes may one day
+ * referene other pointers which need validation.
+ */
+typedef struct bNodeClipboardExtraInfo {
+ struct bNodeClipboardExtraInfo *next, *prev;
+ ID *id;
+ char id_name[MAX_ID_NAME];
+ char library_name[FILE_MAX];
+} bNodeClipboardExtraInfo;
+#endif /* USE_NODE_CB_VALIDATE */
+
+
typedef struct bNodeClipboard {
ListBase nodes;
+
+#ifdef USE_NODE_CB_VALIDATE
+ ListBase nodes_extra_info;
+#endif
+
ListBase links;
int type;
} bNodeClipboard;
-bNodeClipboard node_clipboard;
+bNodeClipboard node_clipboard = {{0}};
void BKE_node_clipboard_init(struct bNodeTree *ntree)
{
@@ -1454,11 +1478,83 @@ void BKE_node_clipboard_clear(void)
nodeFreeNode(NULL, node);
}
node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
+
+#ifdef USE_NODE_CB_VALIDATE
+ BLI_freelistN(&node_clipboard.nodes_extra_info);
+#endif
+}
+
+/* return FALSE when one or more ID's are lost */
+int BKE_node_clipboard_validate(void)
+{
+ int ok = TRUE;
+
+#ifdef USE_NODE_CB_VALIDATE
+ bNodeClipboardExtraInfo *node_info;
+ bNode *node;
+
+
+ /* lists must be aligned */
+ BLI_assert(BLI_countlist(&node_clipboard.nodes) ==
+ BLI_countlist(&node_clipboard.nodes_extra_info));
+
+ for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first;
+ node;
+ node = node->next, node_info = node_info->next)
+ {
+ /* validate the node against the stored node info */
+
+ /* re-assign each loop since we may clear,
+ * open a new file where the ID is valid, and paste again */
+ node->id = node_info->id;
+
+ /* currently only validate the ID */
+ if (node->id) {
+ ListBase *lb = which_libbase(G.main, GS(node_info->id_name));
+ BLI_assert(lb != NULL);
+
+ if (BLI_findindex(lb, node_info->id) == -1) {
+ /* may assign NULL */
+ node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
+ printf("%s %p\n", node_info->id_name, node->id);
+ if (node->id == NULL) {
+ ok = FALSE;
+ }
+ }
+ }
+ }
+#endif /* USE_NODE_CB_VALIDATE */
+
+ return ok;
}
void BKE_node_clipboard_add_node(bNode *node)
{
+#ifdef USE_NODE_CB_VALIDATE
+ /* add extra info */
+ bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo));
+
+ node_info->id = node->id;
+ if (node->id) {
+ BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name));
+ if (node->id->lib) {
+ BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name));
+ }
+ else {
+ node_info->library_name[0] = '\0';
+ }
+ }
+ else {
+ node_info->id_name[0] = '\0';
+ node_info->library_name[0] = '\0';
+ }
+ BLI_addtail(&node_clipboard.nodes_extra_info, node_info);
+ /* end extra info */
+#endif /* USE_NODE_CB_VALIDATE */
+
+ /* add node */
BLI_addtail(&node_clipboard.nodes, node);
+
}
void BKE_node_clipboard_add_link(bNodeLink *link)
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index e4fc19fbd08..6d01fc83647 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2019,10 +2019,13 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bNodeTree *ntree = snode->edittree;
bNode *gnode = node_tree_get_editgroup(snode->nodetree);
float gnode_x = 0.0f, gnode_y = 0.0f;
+ const ListBase *clipboard_nodes_lb;
+ const ListBase *clipboard_links_lb;
bNode *node;
bNodeLink *link;
int num_nodes;
float centerx, centery;
+ int is_clipboard_valid;
if (BKE_node_clipboard_get_type() != ntree->type) {
BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
@@ -2038,10 +2041,17 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
if (gnode)
nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
+
+ /* validate pointers in the clipboard */
+ is_clipboard_valid = BKE_node_clipboard_validate();
+
+ clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
+ clipboard_links_lb = BKE_node_clipboard_get_links();
+
/* calculate "barycenter" for placing on mouse cursor */
num_nodes = 0;
centerx = centery = 0.0f;
- for (node = BKE_node_clipboard_get_nodes()->first; node; node = node->next) {
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
++num_nodes;
centerx += 0.5f * (node->totr.xmin + node->totr.xmax);
centery += 0.5f * (node->totr.ymin + node->totr.ymax);
@@ -2050,15 +2060,18 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
centery /= num_nodes;
/* copy nodes from clipboard */
- for (node = BKE_node_clipboard_get_nodes()->first; node; node = node->next) {
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
bNode *new_node = nodeCopyNode(ntree, node);
+ /* needed since nodeCopyNode() doesn't increase ID's */
+ id_us_plus(node->id);
+
/* pasted nodes are selected */
node_select(new_node);
}
/* reparent copied nodes */
- for (node = BKE_node_clipboard_get_nodes()->first; node; node = node->next) {
+ for (node = clipboard_nodes_lb->first; node; node = node->next) {
bNode *new_node = node->new_node;
if (new_node->parent)
new_node->parent = new_node->parent->new_node;
@@ -2071,7 +2084,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
}
}
- for (link = BKE_node_clipboard_get_links()->first; link; link = link->next) {
+ for (link = clipboard_links_lb->first; link; link = link->next) {
nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock,
link->tonode->new_node, link->tosock->new_sock);
}
@@ -2081,6 +2094,10 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
snode_notify(C, snode);
snode_dag_update(C, snode);
+ if (is_clipboard_valid == FALSE) {
+ BKE_report(op->reports, RPT_ERROR, "Some nodes ID references could not be found");
+ }
+
return OPERATOR_FINISHED;
}