svn merge ^/trunk/blender -r48409:48411
authorCampbell Barton <ideasman42@gmail.com>
Fri, 29 Jun 2012 14:39:38 +0000 (14:39 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 29 Jun 2012 14:39:38 +0000 (14:39 +0000)
13 files changed:
release/scripts/startup/bl_ui/space_node.py
source/blender/editors/include/ED_node.h
source/blender/editors/include/ED_transform.h
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_snap.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/intern/rna_scene.c

index d7f25a597eddd5fa2ce60787976ae3f6d8f7802d..bb29e415c1955e07b72b3176d1a709a96e39dc5c 100644 (file)
@@ -90,6 +90,9 @@ class NODE_HT_header(Header):
         # Snap
         row = layout.row(align=True)
         row.prop(toolsettings, "use_snap", text="")
+        row.prop(toolsettings, "snap_node_element", text="", icon_only=True)
+        if toolsettings.snap_node_element != 'INCREMENT':
+            row.prop(toolsettings, "snap_target", text="")
 
         layout.template_running_jobs()
 
index 0979e3ec92b14ab4a7e3a36ed6db210fe8ed2867..6f86d01fb98a8e7eb265b3e7a50eecbc3922a668 100644 (file)
@@ -41,10 +41,20 @@ struct bNodeTree;
 struct bNode;
 struct bNodeTree;
 struct ScrArea;
+struct View2D;
+
+typedef enum {
+       NODE_TOP    = 1,
+       NODE_BOTTOM = 2,
+       NODE_LEFT   = 4,
+       NODE_RIGHT  = 8
+} NodeBorder;
 
 /* drawnode.c */
 void ED_init_node_butfuncs(void);
 
+void drawnodesnap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
+
 /* node_draw.c */
 void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene);
 void ED_node_changed_update(struct ID *id, struct bNode *node);
index 608df8dd9b3026b4874d61d6045807b7330084a5..d7e9fc323a66da3882282aa9fce6defbef3cb250 100644 (file)
@@ -180,6 +180,8 @@ int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, cons
 int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
 int snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
 int snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
+int snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
+int snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
 
 #endif
 
index 99d3a32ece260f9b225d09d4eda788fbcfecf78c..9a3bf77843b57efab5782a7fa7ff311857bd4cc9 100644 (file)
@@ -3390,3 +3390,28 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
        node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
 //     node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
 }
+
+void drawnodesnap(View2D *v2d, const float cent[2], float size, NodeBorder border)
+{
+       glBegin(GL_LINES);
+       
+       if (border & (NODE_LEFT | NODE_RIGHT)) {
+               glVertex2f(cent[0], v2d->cur.ymin);
+               glVertex2f(cent[0], v2d->cur.ymax);
+       }
+       else {
+               glVertex2f(cent[0], cent[1] - size);
+               glVertex2f(cent[0], cent[1] + size);
+       }
+       
+       if (border & (NODE_TOP | NODE_BOTTOM)) {
+               glVertex2f(v2d->cur.xmin, cent[1]);
+               glVertex2f(v2d->cur.xmax, cent[1]);
+       }
+       else {
+               glVertex2f(cent[0] - size, cent[1]);
+               glVertex2f(cent[0] + size, cent[1]);
+       }
+       
+       glEnd();
+}
index f9aa0dfd582aa9dd58cec6904942da7eca5d0faf..17d7530d2a7858aacdc47190e783982430a3f6da 100644 (file)
@@ -65,6 +65,7 @@
 
 #include "ED_node.h"
 #include "ED_gpencil.h"
+#include "ED_space_api.h"
 
 #include "UI_interface.h"
 #include "UI_interface_icons.h"
@@ -1087,6 +1088,8 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
        
        //uiFreeBlocksWin(&sa->uiblocks, sa->win);
 
+       ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+
        /* only set once */
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_MAP1_VERTEX_3);
@@ -1139,6 +1142,8 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
        glDisable(GL_LINE_SMOOTH);
        glDisable(GL_BLEND);
        
+       ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+       
        /* draw grease-pencil ('canvas' strokes) */
        if (snode->nodetree)
                draw_gpencil_view2d(C, 1);
index a00376974a5a7fb74e0714089cc2fa3e02cbcc1e..1d70c6d68f2b1552699a6b2fd5d3b76b46dbb009 100644 (file)
@@ -1655,6 +1655,12 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
                unit_m3(t->spacemtx);
                t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
        }
+       else if (t->spacetype == SPACE_NODE) {
+               unit_m3(t->spacemtx);
+               /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/
+               t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+               /*t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);*/
+       }
        else
                unit_m3(t->spacemtx);
 
index fdc09c1bed0cde90ad1086080d35e78f7fe65044..3ab5bf7bbfb226a3504208c2cce3449bc9b0f16a 100644 (file)
@@ -86,6 +86,7 @@ typedef struct TransSnap {
        float   snapTarget[3]; /* to this point */
        float   snapNormal[3];
        float   snapTangent[3];
+       char    snapNodeBorder;
        ListBase points;
        TransSnapPoint  *selectedPoint;
        float   dist; // Distance from snapPoint to snapTarget
index f4c025f71be28a02efbc7534f4e5436596c5d7c7..8ca29864dff608c70fbd8114fccc38095dbb761c 100644 (file)
@@ -640,7 +640,7 @@ void drawConstraint(TransInfo *t)
 {
        TransCon *tc = &(t->con);
 
-       if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE))
+       if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
                return;
        if (!(tc->mode & CON_APPLY))
                return;
index f3a846daf29e04cfba97a6b9e6369b4601e6e663..af0b33d58aec1a34d4488ed272fe067d91cc0e61 100644 (file)
@@ -5516,8 +5516,11 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
        }
 
        td->loc = td2d->loc;
-       copy_v3_v3(td->center, td->loc);
        copy_v3_v3(td->iloc, td->loc);
+       /* use node center instead of origin (top-left corner) */
+       td->center[0] = node->locx + 0.5f * (node->totr.xmax - node->totr.xmin);
+       td->center[1] = node->locy - 0.5f * (node->totr.ymax - node->totr.ymin);        /* node height is used negative */
+       td->center[2] = 0.0f;
 
        memset(td->axismtx, 0, sizeof(td->axismtx));
        td->axismtx[2][2] = 1.0f;
@@ -5529,6 +5532,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
 
        unit_m3(td->mtx);
        unit_m3(td->smtx);
+
+       td->extra = node;
 }
 
 static void createTransNodeData(bContext *C, TransInfo *t)
@@ -6324,7 +6329,7 @@ void createTransData(bContext *C, TransInfo *t)
 #endif
        }
        else if (t->spacetype == SPACE_NODE) {
-               t->flag |= T_2D_EDIT | T_POINTS;
+               t->flag |= T_POINTS | T_2D_EDIT;
                createTransNodeData(C, t);
                if (t->data && (t->flag & T_PROP_EDIT)) {
                        sort_trans_data(t); // makes selected become first in array
index d485b886ea701f1fa11dba150b725256075e9d9d..c49e1715f34544aeb705105041db0b067fa5c6df 100644 (file)
@@ -42,6 +42,7 @@
 #include "DNA_object_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes
+#include "DNA_node_types.h"
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_view3d_types.h"
@@ -74,6 +75,7 @@
 #include "ED_armature.h"
 #include "ED_image.h"
 #include "ED_mesh.h"
+#include "ED_node.h"
 #include "ED_uvedit.h"
 #include "ED_view3d.h"
 
@@ -113,6 +115,9 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
 
 /****************** IMPLEMENTATIONS *********************/
 
+static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode);
+static NodeBorder snapNodeBorder(int snap_node_mode);
+
 #if 0
 int BIF_snappingSupported(Object *obedit)
 {
@@ -140,19 +145,22 @@ int activeSnap(TransInfo *t)
 
 void drawSnapping(const struct bContext *C, TransInfo *t)
 {
-       if (validSnap(t) && activeSnap(t)) {
-               
-               unsigned char col[4], selectedCol[4], activeCol[4];
-               UI_GetThemeColor3ubv(TH_TRANSFORM, col);
-               col[3] = 128;
-               
-               UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
-               selectedCol[3] = 128;
-
-               UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
-               activeCol[3] = 192;
-
-               if (t->spacetype == SPACE_VIEW3D) {
+       unsigned char col[4], selectedCol[4], activeCol[4];
+       
+       if (!activeSnap(t))
+               return;
+       
+       UI_GetThemeColor3ubv(TH_TRANSFORM, col);
+       col[3] = 128;
+       
+       UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
+       selectedCol[3] = 128;
+       
+       UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
+       activeCol[3] = 192;
+       
+       if (t->spacetype == SPACE_VIEW3D) {
+               if (validSnap(t)) {
                        TransSnapPoint *p;
                        View3D *v3d = CTX_wm_view3d(C);
                        RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -160,11 +168,11 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
                        float size;
                        
                        glDisable(GL_DEPTH_TEST);
-       
+                       
                        size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
-
+                       
                        invert_m4_m4(imat, rv3d->viewmat);
-
+                       
                        for (p = t->tsnap.points.first; p; p = p->next) {
                                if (p == t->tsnap.selectedPoint) {
                                        glColor4ubv(selectedCol);
@@ -172,20 +180,20 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
                                else {
                                        glColor4ubv(col);
                                }
-
+                               
                                drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat);
                        }
-
+                       
                        if (t->tsnap.status & POINT_INIT) {
                                glColor4ubv(activeCol);
-
+                               
                                drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat);
                        }
                        
                        /* draw normal if needed */
                        if (usingSnappingNormal(t) && validSnappingNormal(t)) {
                                glColor4ubv(activeCol);
-
+                               
                                glBegin(GL_LINES);
                                glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
                                glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
@@ -197,7 +205,9 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
                        if (v3d->zbuf)
                                glEnable(GL_DEPTH_TEST);
                }
-               else if (t->spacetype == SPACE_IMAGE) {
+       }
+       else if (t->spacetype == SPACE_IMAGE) {
+               if (validSnap(t)) {
                        /* This will not draw, and Im nor sure why - campbell */
 #if 0
                        float xuser_asp, yuser_asp;
@@ -228,7 +238,36 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
                        glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
                        setlinestyle(0);
 #endif
+               }
+       }
+       else if (t->spacetype == SPACE_NODE) {
+               if (validSnap(t)) {
+                       ARegion *ar = CTX_wm_region(C);
+                       TransSnapPoint *p;
+                       float size;
+                       
+                       size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+                       
+                       glEnable(GL_BLEND);
                        
+                       for (p = t->tsnap.points.first; p; p = p->next) {
+                               if (p == t->tsnap.selectedPoint) {
+                                       glColor4ubv(selectedCol);
+                               }
+                               else {
+                                       glColor4ubv(col);
+                               }
+                               
+                               drawnodesnap(&ar->v2d, p->co, size, 0);
+                       }
+                       
+                       if (t->tsnap.status & POINT_INIT) {
+                               glColor4ubv(activeCol);
+                               
+                               drawnodesnap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder);
+                       }
+                       
+                       glDisable(GL_BLEND);
                }
        }
 }
@@ -349,6 +388,8 @@ void resetSnapping(TransInfo *t)
        t->tsnap.snapNormal[0] = 0;
        t->tsnap.snapNormal[1] = 0;
        t->tsnap.snapNormal[2] = 0;
+       
+       t->tsnap.snapNodeBorder = 0;
 }
 
 int usingSnappingNormal(TransInfo *t)
@@ -373,12 +414,20 @@ static void initSnappingMode(TransInfo *t)
        Object *obedit = t->obedit;
        Scene *scene = t->scene;
 
-       /* force project off when not supported */
-       if (ts->snap_mode != SCE_SNAP_MODE_FACE) {
+       if (t->spacetype == SPACE_NODE) {
+               /* force project off when not supported */
                t->tsnap.project = 0;
+               
+               t->tsnap.mode = ts->snap_node_mode;
+       }
+       else {
+               /* force project off when not supported */
+               if (ts->snap_mode != SCE_SNAP_MODE_FACE) {
+                       t->tsnap.project = 0;
+               }
+               
+               t->tsnap.mode = ts->snap_mode;
        }
-
-       t->tsnap.mode = ts->snap_mode;
 
        if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) &&  /* Only 3D view or UV */
            (t->flag & T_CAMERA) == 0)  /* Not with camera selected in camera view */
@@ -414,6 +463,19 @@ static void initSnappingMode(TransInfo *t)
                        t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
                }
        }
+       else if (t->spacetype == SPACE_NODE)
+       {
+               setSnappingCallback(t);
+               
+               if (t->tsnap.applySnap != NULL)
+               {
+                       t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+               }
+               else {
+                       /* Grid if snap is not possible */
+                       t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+               }
+       }
        else {
                /* Always grid outside of 3D view */
                t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
@@ -624,7 +686,17 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
 {
        float point[3];
        getSnapPoint(t, point);
-       sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
+
+       if (t->spacetype == SPACE_NODE) {
+               char border = t->tsnap.snapNodeBorder;
+               if (border & (NODE_LEFT | NODE_RIGHT))
+                       vec[0] = point[0] - t->tsnap.snapTarget[0];
+               if (border & (NODE_BOTTOM | NODE_TOP))
+                       vec[1] = point[1] - t->tsnap.snapTarget[1];
+       }
+       else {
+               sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
+       }
 }
 
 static void ApplySnapRotation(TransInfo *t, float *value)
@@ -879,20 +951,57 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
                        t->tsnap.status &= ~POINT_INIT;
                }
        }
+       else if (t->spacetype == SPACE_NODE) {
+               float loc[2];
+               int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+               char node_border;
+               
+               if (snapNodesTransform(t, t->mval, &dist, loc, &node_border, t->tsnap.modeSelect)) {
+                       copy_v2_v2(t->tsnap.snapPoint, loc);
+                       t->tsnap.snapNodeBorder = node_border;
+                       
+                       t->tsnap.status |=  POINT_INIT;
+               }
+               else {
+                       t->tsnap.status &= ~POINT_INIT;
+               }
+       }
 }
 
 /********************** TARGET **************************/
 
+static void TargetSnapOffset(TransInfo *t, TransData *td)
+{
+       if (t->spacetype == SPACE_NODE && td != NULL) {
+               bNode *node = td->extra;
+               char border = t->tsnap.snapNodeBorder;
+               float width = node->totr.xmax - node->totr.xmin;
+               float height = node->totr.ymax - node->totr.ymin;
+               
+               if (border & NODE_LEFT)
+                       t->tsnap.snapTarget[0] -= 0.5f * width;
+               if (border & NODE_RIGHT)
+                       t->tsnap.snapTarget[0] += 0.5f * width;
+               if (border & NODE_BOTTOM)
+                       t->tsnap.snapTarget[1] -= 0.5f * height;
+               if (border & NODE_TOP)
+                       t->tsnap.snapTarget[1] += 0.5f * height;
+       }
+}
+
 static void TargetSnapCenter(TransInfo *t)
 {
        /* Only need to calculate once */
        if ((t->tsnap.status & TARGET_INIT) == 0) {
                copy_v3_v3(t->tsnap.snapTarget, t->center);     
+               
                if (t->flag & (T_EDIT | T_POSE)) {
                        Object *ob = t->obedit ? t->obedit : t->poseobj;
                        mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
                }
                
+               TargetSnapOffset(t, NULL);
+               
                t->tsnap.status |= TARGET_INIT;         
        }
 }
@@ -914,12 +1023,14 @@ static void TargetSnapActive(TransInfo *t)
 
                if (active_td) {
                        copy_v3_v3(t->tsnap.snapTarget, active_td->center);
-                               
+                       
                        if (t->flag & (T_EDIT | T_POSE)) {
                                Object *ob = t->obedit ? t->obedit : t->poseobj;
                                mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
                        }
                        
+                       TargetSnapOffset(t, active_td);
+                       
                        t->tsnap.status |= TARGET_INIT;
                }
                /* No active, default to median */
@@ -953,6 +1064,8 @@ static void TargetSnapMedian(TransInfo *t)
                        mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
                }
                
+               TargetSnapOffset(t, NULL);
+               
                t->tsnap.status |= TARGET_INIT;         
        }
 }
@@ -1029,6 +1142,8 @@ static void TargetSnapClosest(TransInfo *t)
                        }
                }
                
+               TargetSnapOffset(t, closest);
+               
                t->tsnap.status |= TARGET_INIT;
        }
 }
@@ -1876,6 +1991,113 @@ int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2],
        return peelObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), depth_peels, mval, mode);
 }
 
+/******************** NODES ***********************************/
+
+static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode)
+{
+       /* node is use for snapping only if a) snap mode matches and b) node is inside the view */
+       return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
+               (mode == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
+               (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
+                node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
+}
+
+static NodeBorder snapNodeBorder(int snap_node_mode)
+{
+       switch (snap_node_mode) {
+               case SCE_SNAP_MODE_NODE_X:
+                       return NODE_LEFT | NODE_RIGHT;
+               case SCE_SNAP_MODE_NODE_Y:
+                       return NODE_TOP | NODE_BOTTOM;
+               case SCE_SNAP_MODE_NODE_XY:
+                       return NODE_LEFT | NODE_RIGHT | NODE_TOP | NODE_BOTTOM;
+       }
+       return 0;
+}
+
+static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
+                    float r_loc[2], int *r_dist, char *r_node_border)
+{
+       View2D *v2d = &ar->v2d;
+       NodeBorder border = snapNodeBorder(ts->snap_node_mode);
+       int retval = 0;
+       rcti totr;
+       int new_dist;
+       
+       UI_view2d_to_region_no_clip(v2d, node->totr.xmin, node->totr.ymin, &totr.xmin, &totr.ymin);
+       UI_view2d_to_region_no_clip(v2d, node->totr.xmax, node->totr.ymax, &totr.xmax, &totr.ymax);
+       
+       if (border & NODE_LEFT) {
+               new_dist = abs(totr.xmin - mval[0]);
+               if (new_dist < *r_dist) {
+                       UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
+                       *r_dist = new_dist;
+                       *r_node_border = NODE_LEFT;
+                       retval = 1;
+               }
+       }
+       
+       if (border & NODE_RIGHT) {
+               new_dist = abs(totr.xmax - mval[0]);
+               if (new_dist < *r_dist) {
+                       UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
+                       *r_dist = new_dist;
+                       *r_node_border = NODE_RIGHT;
+                       retval = 1;
+               }
+       }
+       
+       if (border & NODE_BOTTOM) {
+               new_dist = abs(totr.ymin - mval[1]);
+               if (new_dist < *r_dist) {
+                       UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
+                       *r_dist = new_dist;
+                       *r_node_border = NODE_BOTTOM;
+                       retval = 1;
+               }
+       }
+       
+       if (border & NODE_TOP) {
+               new_dist = abs(totr.ymax - mval[1]);
+               if (new_dist < *r_dist) {
+                       UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
+                       *r_dist = new_dist;
+                       *r_node_border = NODE_TOP;
+                       retval = 1;
+               }
+       }
+       
+       return retval;
+}
+
+static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2],
+                     int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+{
+       bNodeTree *ntree = snode->edittree;
+       bNode *node;
+       int retval = 0;
+       
+       *r_node_border = 0;
+       
+       for (node = ntree->nodes.first; node; node = node->next) {
+               if (snapNodeTest(&ar->v2d, node, mode))
+                       retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist, r_node_border);
+       }
+       
+       return retval;
+}
+
+int snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+{
+       return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode);
+}
+
+int snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+{
+       Scene *scene = CTX_data_scene(C);
+       return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode);
+}
+
 /*================================================================*/
 
 static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
index 6a8022c07a5cafec635fe356b3cc87baa4976c95..02a7d0da3258bf0727809a0943a42e73528489b9 100644 (file)
@@ -899,7 +899,7 @@ typedef struct ToolSettings {
 
        /* Subdivide Settings */
        short cornertype;
-       short pad3;
+       short pad1;
        /*Triangle to Quad conversion threshold*/
        float jointrilimit;
        /* Editmode Tools */
@@ -995,12 +995,13 @@ typedef struct ToolSettings {
        char edge_mode_live_unwrap;
 
        /* Transform */
-       char snap_mode;
+       char snap_mode, snap_node_mode;
+       char pad3;
        short snap_flag, snap_target;
        short proportional, prop_mode;
        char proportional_objects; /* proportional edit, object mode */
        char proportional_mask; /* proportional edit, object mode */
-       char pad[4];
+       char pad4[2];
 
        char auto_normalize; /*auto normalizing mode in wpaint*/
        char multipaint; /* paint multiple bones in wpaint */
@@ -1012,7 +1013,7 @@ typedef struct ToolSettings {
        int uv_relax_method;
        /* XXX: these sculpt_paint_* fields are deprecated, use the
         * unified_paint_settings field instead! */
-       short sculpt_paint_settings DNA_DEPRECATED;     short pad1;
+       short sculpt_paint_settings DNA_DEPRECATED;     short pad5;
        int sculpt_paint_unified_size DNA_DEPRECATED;
        float sculpt_paint_unified_unprojected_radius DNA_DEPRECATED;
        float sculpt_paint_unified_alpha DNA_DEPRECATED;
@@ -1370,6 +1371,9 @@ typedef struct Scene {
 #define SCE_SNAP_MODE_EDGE             2
 #define SCE_SNAP_MODE_FACE             3
 #define SCE_SNAP_MODE_VOLUME   4
+#define SCE_SNAP_MODE_NODE_X   5
+#define SCE_SNAP_MODE_NODE_Y   6
+#define SCE_SNAP_MODE_NODE_XY  7
 
 /* toolsettings->selectmode */
 #define SCE_SELECT_VERTEX      1 /* for mesh */
index a8d176db7679c4893b9c70f1e0f545d588cb4c75..a0614a9d82a7cfef0118b27e8cfe9b2daa121c4b 100644 (file)
@@ -45,6 +45,7 @@ extern EnumPropertyItem proportional_falloff_curve_only_items[];
 extern EnumPropertyItem proportional_editing_items[];
 extern EnumPropertyItem snap_target_items[];
 extern EnumPropertyItem snap_element_items[];
+extern EnumPropertyItem snap_node_element_items[];
 extern EnumPropertyItem mesh_select_mode_items[];
 extern EnumPropertyItem space_type_items[];
 extern EnumPropertyItem region_type_items[];
index 7a2f0736e983f6bf24173d87ceb70108342683cc..4c0d6eb30d2031dd24faa886ff79c293cbba7d95 100644 (file)
@@ -136,6 +136,14 @@ EnumPropertyItem snap_element_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+EnumPropertyItem snap_node_element_items[] = {
+       {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"},
+       {SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
+       {SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
+       {SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},
+       {0, NULL, 0, NULL, NULL}
+};
+
 
 /* workaround for duplice enums,
  * have each enum line as a defne then conditionally set it or not
@@ -1626,6 +1634,13 @@ static void rna_def_tool_settings(BlenderRNA  *brna)
        RNA_def_property_enum_items(prop, snap_element_items);
        RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to");
        RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+       
+       /* node editor uses own set of snap modes */
+       prop = RNA_def_property(srna, "snap_node_element", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "snap_node_mode");
+       RNA_def_property_enum_items(prop, snap_node_element_items);
+       RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
 
        prop = RNA_def_property(srna, "snap_target", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "snap_target");
@@ -1651,7 +1666,7 @@ static void rna_def_tool_settings(BlenderRNA  *brna)
        RNA_def_property_ui_text(prop, "Project to Self", "Snap onto itself (editmode)");
        RNA_def_property_ui_icon(prop, ICON_ORTHO, 0);
        RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
-       
+
        /* Grease Pencil */
        prop = RNA_def_property(srna, "use_grease_pencil_sessions", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_PAINTSESSIONS_ON);