diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_blender.h | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_icons.h | 6 | ||||
-rw-r--r-- | source/blender/editors/interface/resources.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.c | 13 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 355 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 44 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_space_types.h | 26 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_space.c | 20 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_userdef.c | 6 |
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) |