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:
Diffstat (limited to 'source/blender/editors/transform/transform_snap.c')
-rw-r--r--source/blender/editors/transform/transform_snap.c278
1 files changed, 250 insertions, 28 deletions
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 90b67951614..c49e1715f34 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -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;
@@ -459,7 +521,7 @@ void initSnapping(TransInfo *t, wmOperator *op)
}
/* use scene defaults only when transform is modal */
else if (t->flag & T_MODAL) {
- if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
+ if (ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
if (ts->snap_flag & SCE_SNAP) {
t->modifiers |= MOD_SNAP;
}
@@ -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);