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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/include/UI_icons.h6
-rw-r--r--source/blender/editors/interface/resources.c4
-rw-r--r--source/blender/editors/space_node/node_intern.h2
-rw-r--r--source/blender/editors/space_node/node_ops.c13
-rw-r--r--source/blender/editors/space_node/node_relationships.c355
-rw-r--r--source/blender/editors/transform/transform.c44
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h26
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_space.c20
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c6
13 files changed, 464 insertions, 20 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 14048ba4c65..2a9583b99d2 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 275
-#define BLENDER_SUBVERSION 3
+#define BLENDER_SUBVERSION 4
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index f497c5db4f0..cc84a899856 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6772,6 +6772,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
link_list(fd, &snode->treepath);
snode->edittree = NULL;
+ snode->iofsd = NULL;
BLI_listbase_clear(&snode->linkdrag);
}
else if (sl->spacetype == SPACE_TEXT) {
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index b5fb24affe4..32f45b222aa 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -462,8 +462,10 @@ DEF_ICON(FORCE_SMOKEFLOW)
DEF_ICON(BLANK690) /* XXX 'Temperature' icon! */
DEF_ICON(BLANK691) /* XXX 'Temperature' icon! */
DEF_ICON(BLANK692) /* XXX 'Gear' icon! */
- DEF_ICON(BLANK693)
- DEF_ICON(BLANK694)
+#endif
+DEF_ICON(NODE_INSERT_ON)
+DEF_ICON(NODE_INSERT_OFF)
+#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK695)
DEF_ICON(BLANK696)
DEF_ICON(BLANK697)
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index a7eb33561b4..5eaee734789 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -2635,6 +2635,10 @@ void init_userdef_do_versions(void)
U.ndof_deadzone = 0.1;
}
+ if (!USER_VERSION_ATLEAST(275, 4)) {
+ U.node_margin = 80;
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 6b1d947bfca..b08c9b10eeb 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -167,6 +167,8 @@ void NODE_OT_detach(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
+void NODE_OT_insert_offset(wmOperatorType *ot);
+
/* node_edit.c */
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 474ad4db4af..7464fb77d90 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -92,6 +92,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_link_viewer);
+ WM_operatortype_append(NODE_OT_insert_offset);
+
WM_operatortype_append(NODE_OT_read_renderlayers);
WM_operatortype_append(NODE_OT_read_fullsamplelayers);
WM_operatortype_append(NODE_OT_render_changed);
@@ -147,6 +149,17 @@ void ED_operatormacros_node(void)
mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(mot->ptr, "release_confirm", true);
WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
+
+ /* NODE_OT_translate_attach with remove_on_canel set to true */
+ ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", "Move and Attach",
+ "Move nodes and attach to frame",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(mot->ptr, "release_confirm", true);
+ RNA_boolean_set(mot->ptr, "remove_on_cancel", true);
+ WM_operatortype_macro_define(ot, "NODE_OT_attach");
+ WM_operatortype_macro_define(ot, "NODE_OT_insert_offset");
/* Note: Currently not in a default keymap or menu due to messy keymaps
* and tricky invoke functionality.
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index c8951a1172e..8af4b8c4b8d 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_easing.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -45,6 +46,7 @@
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_render.h"
+#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -53,6 +55,7 @@
#include "WM_types.h"
#include "UI_view2d.h"
+#include "UI_resources.h"
#include "BLF_translation.h"
@@ -66,6 +69,17 @@ typedef struct bNodeListItem {
struct bNode *node;
} bNodeListItem;
+typedef struct NodeInsertOfsData {
+ bNodeTree *ntree;
+ bNode *insert; /* inserted node */
+ bNode *prev, *next; /* prev/next node in the chain */
+ bNode *insert_parent;
+
+ wmTimer *anim_timer;
+
+ float offset_x; /* offset to apply to node chain */
+} NodeInsertOfsData;
+
static int sort_nodes_locx(const void *a, const void *b)
{
const bNodeListItem *nli1 = a;
@@ -1099,25 +1113,33 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
-static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static bNode *node_find_frame_to_attach(ARegion *ar, const bNodeTree *ntree, const int mouse_xy[2])
{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree = snode->edittree;
bNode *frame;
float cursor[2];
-
+
/* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
- if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1]))
- break;
+ if (BLI_rctf_isect_pt_v(&frame->totr, cursor))
+ return frame;
}
+
+ return NULL;
+}
+
+static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *frame = node_find_frame_to_attach(ar, ntree, event->mval);
+
if (frame) {
bNode *node, *parent;
for (node = ntree->nodes.last; node; node = node->prev) {
@@ -1371,6 +1393,312 @@ static bNodeSocket *socket_best_match(ListBase *sockets)
return NULL;
}
+static bool node_parents_offset_flag_enable_cb(bNode *parent, void *UNUSED(userdata))
+{
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ parent->flag |= NODE_TEST;
+
+ return true;
+}
+
+static void node_offset_apply(bNode *node, const float offset_x)
+{
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ if ((node->flag & NODE_TEST) == 0) {
+ node->anim_init_locx = node->locx;
+ node->anim_ofsx = (offset_x / UI_DPI_FAC);
+ node->flag |= NODE_TEST;
+ }
+}
+
+static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, const float offset_x)
+{
+ bNode *node;
+
+ node_offset_apply(parent, offset_x);
+
+ /* flag all childs as offset to prevent them from being offset
+ * separately (they've already moved with the parent) */
+ for (node = data->ntree->nodes.first; node; node = node->next) {
+ if (nodeIsChildOf(parent, node)) {
+ /* NODE_TEST is used to flag nodes that shouldn't be offset (again) */
+ node->flag |= NODE_TEST;
+ }
+ }
+}
+
+#define NODE_INSOFS_ANIM_DURATION 0.25f
+
+/**
+ * Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similiar
+ * to node_link_insert_offset_output_chain_cb below, but with slightly different logic
+ */
+static bool node_link_insert_offset_frame_chain_cb(
+ bNode *fromnode, bNode *tonode,
+ void *userdata,
+ const bool reversed)
+{
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
+
+ if (ofs_node->parent && ofs_node->parent != data->insert_parent) {
+ node_offset_apply(ofs_node->parent, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ return true;
+}
+
+/**
+ * Applies NodeInsertOfsData.offset_x to all childs of \a parent
+ */
+static void node_link_insert_offset_frame_chains(
+ const bNodeTree *ntree, const bNode *parent,
+ NodeInsertOfsData *data,
+ const bool reversed)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (nodeIsChildOf(parent, node)) {
+ nodeChainIter(ntree, node, node_link_insert_offset_frame_chain_cb, data, reversed);
+ }
+ }
+}
+
+/**
+ * Callback that applies NodeInsertOfsData.offset_x to a node or its parent,
+ * considering the logic needed for offseting nodes after link insert
+ */
+static bool node_link_insert_offset_chain_cb(
+ bNode *fromnode, bNode *tonode,
+ void *userdata,
+ const bool reversed)
+{
+ NodeInsertOfsData *data = userdata;
+ bNode *ofs_node = reversed ? fromnode : tonode;
+
+ if (data->insert_parent) {
+ if (ofs_node->parent && (ofs_node->parent->flag & NODE_TEST) == 0) {
+ node_parent_offset_apply(data, ofs_node->parent, data->offset_x);
+ node_link_insert_offset_frame_chains(data->ntree, ofs_node->parent, data, reversed);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ if (nodeIsChildOf(data->insert_parent, ofs_node) == false) {
+ data->insert_parent = NULL;
+ }
+ }
+ else if (ofs_node->parent) {
+ bNode *node = nodeFindRootParent(ofs_node);
+ node_offset_apply(node, data->offset_x);
+ }
+ else {
+ node_offset_apply(ofs_node, data->offset_x);
+ }
+
+ return true;
+}
+
+static void node_link_insert_offset_ntree(
+ NodeInsertOfsData *iofsd, ARegion *ar,
+ const int mouse_xy[2], const bool right_alignment)
+{
+ bNodeTree *ntree = iofsd->ntree;
+ bNode *insert = iofsd->insert;
+ bNode *prev = iofsd->prev, *next = iofsd->next;
+ bNode *init_parent = insert->parent; /* store old insert->parent for restoring later */
+ rctf totr_insert;
+
+ const float min_margin = U.node_margin * UI_DPI_FAC;
+ const float width = NODE_WIDTH(insert);
+ const bool needs_alignment = (next->totr.xmin - prev->totr.xmax) < (width + (min_margin * 2.0f));
+
+ float margin = width;
+ float dist, addval;
+
+
+ /* NODE_TEST will be used later, so disable for all nodes */
+ ntreeNodeFlagSet(ntree, NODE_TEST, false);
+
+ /* insert->totr isn't updated yet, so totr_insert is used to get the correct worldspace coords */
+ node_to_updated_rect(insert, &totr_insert);
+
+ /* frame attachement was't handled yet so we search the frame that the node will be attached to later */
+ insert->parent = node_find_frame_to_attach(ar, ntree, mouse_xy);
+
+ /* this makes sure nodes are also correctly offset when inserting a node on top of a frame
+ * without actually making it a part of the frame (because mouse isn't intersecting it)
+ * - logic here is similar to node_find_frame_to_attach */
+ if (!insert->parent ||
+ (prev->parent && (prev->parent == next->parent) && (prev->parent != insert->parent)))
+ {
+ bNode *frame;
+ rctf totr_frame;
+
+ /* check nodes front to back */
+ for (frame = ntree->nodes.last; frame; frame = frame->prev) {
+ /* skip selected, those are the nodes we want to attach */
+ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
+ continue;
+
+ /* for some reason frame y coords aren't correct yet */
+ node_to_updated_rect(frame, &totr_frame);
+
+ if (BLI_rctf_isect_x(&totr_frame, totr_insert.xmin) &&
+ BLI_rctf_isect_x(&totr_frame, totr_insert.xmax))
+ {
+ if (BLI_rctf_isect_y(&totr_frame, totr_insert.ymin) ||
+ BLI_rctf_isect_y(&totr_frame, totr_insert.ymax))
+ {
+ /* frame isn't insert->parent actually, but this is needed to make offsetting
+ * nodes work correctly for above checked cases (it is restored later) */
+ insert->parent = frame;
+ break;
+ }
+ }
+ }
+ }
+
+
+ /* *** ensure offset at the left (or right for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? totr_insert.xmin - prev->totr.xmax : next->totr.xmin - totr_insert.xmax;
+ /* distance between insert_node and prev is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+
+ node_offset_apply(insert, addval);
+
+ totr_insert.xmin += addval;
+ totr_insert.xmax += addval;
+ margin += min_margin;
+ }
+
+ /* *** ensure offset at the right (or left for right_alignment case) of insert_node *** */
+
+ dist = right_alignment ? next->totr.xmin - totr_insert.xmax : totr_insert.xmin - prev->totr.xmax;
+ /* distance between insert_node and next is smaller than min margin */
+ if (dist < min_margin) {
+ addval = (min_margin - dist) * (right_alignment ? 1.0f : -1.0f);
+ if (needs_alignment) {
+ bNode *offs_node = right_alignment ? next : prev;
+ if (!offs_node->parent ||
+ offs_node->parent == insert->parent ||
+ nodeIsChildOf(offs_node->parent, insert))
+ {
+ node_offset_apply(offs_node, addval);
+ }
+ else if (!insert->parent && offs_node->parent) {
+ node_offset_apply(offs_node->parent, addval);
+ }
+ margin = addval;
+ }
+ /* enough room is available, but we want to ensure the min margin at the right */
+ else {
+ /* offset inserted node so that min margin is kept at the right */
+ node_offset_apply(insert, -addval);
+ }
+ }
+
+
+ if (needs_alignment) {
+ iofsd->insert_parent = insert->parent;
+ iofsd->offset_x = margin;
+
+ /* flag all parents of insert as offset to prevent them from being offset */
+ nodeParentsIter(insert, node_parents_offset_flag_enable_cb, NULL);
+ /* iterate over entire chain and apply offsets */
+ nodeChainIter(ntree, right_alignment ? next : prev, node_link_insert_offset_chain_cb, iofsd, !right_alignment);
+ }
+
+ insert->parent = init_parent;
+}
+
+/**
+ * Modal handler for insert offset animation
+ */
+static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
+ bNode *node;
+ const float duration = (float)iofsd->anim_timer->duration;
+
+ if (!snode || event->type != TIMER || iofsd->anim_timer != event->customdata)
+ return OPERATOR_PASS_THROUGH;
+
+ /* end timer + free insert offset data */
+ if (duration > NODE_INSOFS_ANIM_DURATION) {
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
+
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ node->anim_init_locx = node->anim_ofsx = 0.0f;
+ }
+
+ snode->iofsd = NULL;
+ MEM_freeN(iofsd);
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ /* handle animation */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->anim_ofsx) {
+ node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
+ NODE_INSOFS_ANIM_DURATION);
+ }
+ }
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+#undef NODE_INSOFS_ANIM_DURATION
+
+static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const SpaceNode *snode = CTX_wm_space_node(C);
+ NodeInsertOfsData *iofsd = snode->iofsd;
+
+ if (!iofsd || !iofsd->insert)
+ return OPERATOR_CANCELLED;
+
+ BLI_assert((snode->flag & SNODE_SKIP_INSOFFSET) == 0);
+
+ iofsd->ntree = snode->edittree;
+ iofsd->anim_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.02);
+
+ node_link_insert_offset_ntree(
+ iofsd, CTX_wm_region(C),
+ event->mval, (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT));
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void NODE_OT_insert_offset(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Insert Offset";
+ ot->description = "Automatically offset nodes on insertion";
+ ot->idname = "NODE_OT_insert_offset";
+
+ /* callbacks */
+ ot->invoke = node_insert_offset_invoke;
+ ot->modal = node_insert_offset_modal;
+ ot->poll = ED_operator_node_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
+
/* assumes link with NODE_LINKFLAG_HILITE set */
void ED_node_link_insert(ScrArea *sa)
{
@@ -1401,6 +1729,17 @@ void ED_node_link_insert(ScrArea *sa)
nodeAddLink(snode->edittree, select, best_output, node, sockto);
+ /* set up insert offset data, it needs stuff from here */
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ NodeInsertOfsData *iofsd = MEM_callocN(sizeof(NodeInsertOfsData), __func__);
+
+ iofsd->insert = select;
+ iofsd->prev = link->fromnode;
+ iofsd->next = node;
+
+ snode->iofsd = iofsd;
+ }
+
ntreeUpdateTree(G.main, snode->edittree); /* needed for pointers */
snode_update(snode, select);
ED_node_tag_update_id(snode->id);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index adef32dd4ca..a889faba9a4 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -799,6 +799,8 @@ enum {
/* for analog input, like trackpad */
TFM_MODAL_PROPSIZE = 26,
+/* node editor insert offset (aka auto-offset) direction toggle */
+ TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
};
/* called in transform_ops.c, on each regeneration of keymaps */
@@ -831,6 +833,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
{TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
{TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
+ {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -879,7 +882,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC);
-
+
+ /* node editor only */
+ WM_modalkeymap_add_item(keymap, TKEY, KM_PRESS, 0, 0, TFM_MODAL_INSERTOFS_TOGGLE_DIR);
+
return keymap;
}
@@ -1240,6 +1246,25 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ BLI_assert(t->sa->spacetype == t->spacetype);
+
+ if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
+ }
+ else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ t->redraw |= TREDRAW_SOFT;
+ }
+ break;
/* Those two are only handled in transform's own handler, see T44634! */
case TFM_MODAL_EDGESLIDE_UP:
case TFM_MODAL_EDGESLIDE_DOWN:
@@ -4246,6 +4271,23 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[MAX_INF
if (t->flag & T_PROP_EDIT_ALL) {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
+
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ const char *str_old = BLI_strdup(str);
+ const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? "right" : "left";
+ char str_km[MAX_INFO_LEN];
+
+ WM_modalkeymap_items_to_string(t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, sizeof(str_km), str_km);
+
+ ofs += BLI_snprintf(str, MAX_INFO_LEN, "Auto-offset set to %s - press %s to toggle direction | %s",
+ str_dir, str_km, str_old);
+
+ MEM_freeN((void *)str_old);
+ }
+ }
}
static void applyTranslationValue(TransInfo *t, const float vec[3])
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 1bbd0ab8416..17b0dbca51c 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -191,6 +191,8 @@ typedef struct bNode {
float width, height; /* node custom width and height */
float miniwidth; /* node width if hidden */
float offsetx, offsety; /* additional offset from loc */
+ float anim_init_locx; /* initial locx for insert offset animation */
+ float anim_ofsx; /* offset that will be added to locx for insert offset animation */
int update; /* update flags */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index ab19273f087..2a066726d96 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -985,12 +985,17 @@ typedef struct SpaceNode {
int treetype DNA_DEPRECATED; /* treetype: as same nodetree->type */
int pad3;
- short texfrom; /* texfrom object, world or brush */
- short shaderfrom; /* shader from object or world */
- short recalc; /* currently on 0/1, for auto compo */
- short pad4;
- ListBase linkdrag; /* temporary data for modal linking operator */
-
+ short texfrom; /* texfrom object, world or brush */
+ short shaderfrom; /* shader from object or world */
+ short recalc; /* currently on 0/1, for auto compo */
+
+ char insert_ofs_dir; /* direction for offsetting nodes on insertion */
+ char pad4;
+
+ ListBase linkdrag; /* temporary data for modal linking operator */
+ /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */
+ struct NodeInsertOfsData *iofsd; /* temporary data for node insert offset (in UI called Auto-offset) */
+
struct bGPdata *gpd; /* grease-pencil data */
} SpaceNode;
@@ -1006,8 +1011,9 @@ typedef enum eSpaceNode_Flag {
SNODE_AUTO_RENDER = (1 << 5),
SNODE_SHOW_HIGHLIGHT = (1 << 6),
// SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013
- SNODE_NEW_SHADERS = (1 << 11),
+ SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
+ SNODE_SKIP_INSOFFSET = (1 << 13), /* automatically offset following nodes in a chain on insertion */
} eSpaceNode_Flag;
/* snode->texfrom */
@@ -1025,6 +1031,12 @@ typedef enum eSpaceNode_ShaderFrom {
SNODE_SHADER_LINESTYLE = 2,
} eSpaceNode_ShaderFrom;
+/* snode->insert_ofs_dir */
+enum {
+ SNODE_INSERTOFS_DIR_RIGHT = 0,
+ SNODE_INSERTOFS_DIR_LEFT = 1,
+};
+
/* Game Logic Editor ===================================== */
/* Logic Editor */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 803c2922ed9..bc2c7463e7f 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -465,7 +465,8 @@ typedef struct UserDef {
int scrollback; /* console scrollback limit */
int dpi; /* range 48-128? */
- char pad2[2];
+ char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
+ char pad2;
short transopts;
short menuthreshold1, menuthreshold2;
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 838465f1517..4df0b8df0f7 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -4095,6 +4095,12 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem insert_ofs_dir_items[] = {
+ {SNODE_INSERTOFS_DIR_RIGHT, "RIGHT", 0, "Right"},
+ {SNODE_INSERTOFS_DIR_LEFT, "LEFT", 0, "Left"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem dummy_items[] = {
{0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}};
@@ -4208,6 +4214,20 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+ /* insert offset (called "Auto-offset" in UI) */
+ prop = RNA_def_property(srna, "use_insert_offset", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNODE_SKIP_INSOFFSET);
+ RNA_def_property_ui_text(prop, "Auto-offset", "Automatically offset the following or previous nodes in a "
+ "chain when inserting a new node");
+ RNA_def_property_ui_icon(prop, ICON_NODE_INSERT_ON, 1);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
+ prop = RNA_def_property(srna, "insert_offset_direction", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "insert_ofs_dir");
+ RNA_def_property_enum_items(prop, insert_ofs_dir_items);
+ RNA_def_property_ui_text(prop, "Auto-offset Direction", "Direction to offset nodes on insertion");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
RNA_api_space_node(srna);
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 5bf8fe76c91..b4ae82290fd 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3848,6 +3848,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_duplicate_particle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_PSYS);
RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object");
+
+ /* currently only used for insert offset (aka auto-offset), maybe also be useful for later stuff though */
+ prop = RNA_def_property(srna, "node_margin", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "node_margin");
+ RNA_def_property_ui_text(prop, "Auto-offset Margin", "Minimum distance between nodes for Auto-offsetting nodes");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_system(BlenderRNA *brna)