svn merge ^/trunk/blender -r50039:50044
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
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)
|
||||
|
||||
@@ -2018,47 +2018,69 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
|
||||
SpaceNode *snode = CTX_wm_space_node(C);
|
||||
bNodeTree *ntree = snode->edittree;
|
||||
bNode *gnode = node_tree_get_editgroup(snode->nodetree);
|
||||
float gnode_x = 0.0f, gnode_y = 0.0f;
|
||||
float gnode_center[2];
|
||||
const ListBase *clipboard_nodes_lb;
|
||||
const ListBase *clipboard_links_lb;
|
||||
bNode *node;
|
||||
bNodeLink *link;
|
||||
int num_nodes;
|
||||
float centerx, centery;
|
||||
float center[2];
|
||||
int is_clipboard_valid;
|
||||
|
||||
/* 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();
|
||||
|
||||
if (clipboard_nodes_lb->first == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (BKE_node_clipboard_get_type() != ntree->type) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* only warn */
|
||||
if (is_clipboard_valid == FALSE) {
|
||||
BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty");
|
||||
}
|
||||
|
||||
ED_preview_kill_jobs(C);
|
||||
|
||||
/* deselect old nodes */
|
||||
node_deselect_all(snode);
|
||||
|
||||
/* get group node offset */
|
||||
if (gnode)
|
||||
nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
|
||||
if (gnode) {
|
||||
nodeToView(gnode, 0.0f, 0.0f, &gnode_center[0], &gnode_center[1]);
|
||||
}
|
||||
else {
|
||||
zero_v2(gnode_center);
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
++num_nodes;
|
||||
centerx += 0.5f * (node->totr.xmin + node->totr.xmax);
|
||||
centery += 0.5f * (node->totr.ymin + node->totr.ymax);
|
||||
zero_v2(center);
|
||||
for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
|
||||
center[0] += 0.5f * (node->totr.xmin + node->totr.xmax);
|
||||
center[1] += 0.5f * (node->totr.ymin + node->totr.ymax);
|
||||
}
|
||||
centerx /= num_nodes;
|
||||
centery /= num_nodes;
|
||||
mul_v2_fl(center, 1.0 / 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;
|
||||
@@ -2066,12 +2088,12 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* place nodes around the mouse cursor. child nodes locations are relative to parent */
|
||||
if (!new_node->parent) {
|
||||
new_node->locx += snode->cursor[0] - centerx - gnode_x;
|
||||
new_node->locy += snode->cursor[1] - centery - gnode_y;
|
||||
new_node->locx += snode->cursor[0] - center[0] - gnode_center[0];
|
||||
new_node->locy += snode->cursor[1] - center[1] - gnode_center[1];
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user