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')
-rw-r--r--source/blender/editors/transform/CMakeLists.txt4
-rw-r--r--source/blender/editors/transform/SConscript3
-rw-r--r--source/blender/editors/transform/transform.c1460
-rw-r--r--source/blender/editors/transform/transform.h28
-rw-r--r--source/blender/editors/transform/transform_constraints.c58
-rw-r--r--source/blender/editors/transform/transform_conversions.c971
-rw-r--r--source/blender/editors/transform/transform_generics.c78
-rw-r--r--source/blender/editors/transform/transform_manipulator.c17
-rw-r--r--source/blender/editors/transform/transform_ops.c53
-rw-r--r--source/blender/editors/transform/transform_snap.c151
10 files changed, 1807 insertions, 1016 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 0c360474b78..0bc38f81dd7 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -55,6 +55,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index e249856b747..1a2e9ab074a 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -50,4 +50,7 @@ defs = env['BF_GL_DEFINITIONS']
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
+
env.BlenderLib ( 'bf_editors_transform', sources, incs, defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 061d00424b8..68d77dec619 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -54,6 +54,7 @@
#include "BLI_memarena.h"
#include "BKE_nla.h"
+#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
@@ -98,11 +99,13 @@ static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg)
static void doEdgeSlide(TransInfo *t, float perc);
static void doVertSlide(TransInfo *t, float perc);
-static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
-static void drawVertSlide(const struct bContext *C, TransInfo *t);
+static void drawEdgeSlide(TransInfo *t);
+static void drawVertSlide(TransInfo *t);
static void len_v3_ensure(float v[3], const float length);
static void postInputRotation(TransInfo *t, float values[3]);
+static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short around);
+
/* Transform Callbacks */
static void initBend(TransInfo *t);
@@ -164,6 +167,7 @@ static void applyBoneEnvelope(TransInfo *t, const int mval[2]);
static void initBoneRoll(TransInfo *t);
static void applyBoneRoll(TransInfo *t, const int mval[2]);
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side);
static void initEdgeSlide(TransInfo *t);
static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
static void applyEdgeSlide(TransInfo *t, const int mval[2]);
@@ -235,6 +239,38 @@ void setTransformViewMatrices(TransInfo *t)
calculateCenter2D(t);
}
+void setTransformViewAspect(TransInfo *t, float r_aspect[3])
+{
+ copy_v3_fl(r_aspect, 1.0f);
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
+ else {
+ ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = t->sa->spacedata.first;
+
+ if (t->options & CTX_MOVIECLIP) {
+ ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ else {
+ ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]);
+ }
+ }
+ else if (t->spacetype == SPACE_IPO) {
+ /* depemds on context of usage */
+ }
+}
+
static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
{
float divx, divy;
@@ -288,25 +324,19 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
}
}
else if (t->spacetype == SPACE_IMAGE) {
- float aspx, aspy;
-
if (t->options & CTX_MASK) {
convertViewVec2D_mask(t->view, r_vec, dx, dy);
- ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
else if (t->options & CTX_PAINT_CURVE) {
r_vec[0] = dx;
r_vec[1] = dy;
-
- aspx = aspy = 1.0;
}
else {
convertViewVec2D(t->view, r_vec, dx, dy);
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
- r_vec[0] *= aspx;
- r_vec[1] *= aspy;
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
}
else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
convertViewVec2D(t->view, r_vec, dx, dy);
@@ -315,8 +345,6 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
}
else if (t->spacetype == SPACE_CLIP) {
- float aspx, aspy;
-
if (t->options & CTX_MASK) {
convertViewVec2D_mask(t->view, r_vec, dx, dy);
}
@@ -324,21 +352,8 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
convertViewVec2D(t->view, r_vec, dx, dy);
}
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy);
- }
- else if (t->options & CTX_MASK) {
- /* TODO - NOT WORKING, this isnt so bad since its only display aspect */
- ED_space_clip_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- else {
- /* should never happen, quiet warnings */
- BLI_assert(0);
- aspx = aspy = 1.0f;
- }
-
- r_vec[0] *= aspx;
- r_vec[1] *= aspy;
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
}
else {
printf("%s: called in an invalid context\n", __func__);
@@ -360,15 +375,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
SpaceImage *sima = t->sa->spacedata.first;
if (t->options & CTX_MASK) {
- float aspx, aspy;
float v[2];
- ED_space_image_get_aspect(sima, &aspx, &aspy);
-
- copy_v2_v2(v, vec);
-
- v[0] = v[0] / aspx;
- v[1] = v[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v);
@@ -382,11 +392,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[1] = vec[1];
}
else {
- float aspx, aspy, v[2];
+ float v[2];
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- v[0] = vec[0] / aspx;
- v[1] = vec[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
}
@@ -431,15 +440,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
MovieClip *clip = ED_space_clip_get_clip(sc);
if (clip) {
- float aspx, aspy;
float v[2];
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
-
- copy_v2_v2(v, vec);
-
- v[0] = v[0] / aspx;
- v[1] = v[1] / aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v);
@@ -454,13 +458,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
}
}
else if (t->options & CTX_MOVIECLIP) {
- float v[2], aspx, aspy;
-
- copy_v2_v2(v, vec);
- ED_space_clip_get_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy);
+ float v[2];
- v[0] /= aspx;
- v[1] /= aspy;
+ v[0] = vec[0] / t->aspect[0];
+ v[1] = vec[1] / t->aspect[1];
UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]);
}
@@ -516,7 +517,6 @@ void applyAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) {
SpaceImage *sima = t->sa->spacedata.first;
- float aspx, aspy;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -526,28 +526,13 @@ void applyAspectRatio(TransInfo *t, float vec[2])
vec[1] *= height;
}
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- vec[0] /= aspx;
- vec[1] /= aspy;
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
}
else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- SpaceClip *sc = t->sa->spacedata.first;
- float aspx, aspy;
-
-
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
-
- vec[0] /= aspx;
- vec[1] /= aspy;
- }
- else if (t->options & CTX_MASK) {
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
-
- vec[0] /= aspx;
- vec[1] /= aspy;
- }
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
}
}
}
@@ -556,7 +541,6 @@ void removeAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
SpaceImage *sima = t->sa->spacedata.first;
- float aspx, aspy;
if ((sima->flag & SI_COORDFLOATS) == 0) {
int width, height;
@@ -566,24 +550,13 @@ void removeAspectRatio(TransInfo *t, float vec[2])
vec[1] /= height;
}
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- vec[0] *= aspx;
- vec[1] *= aspy;
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
}
else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) {
if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- SpaceClip *sc = t->sa->spacedata.first;
- float aspx = 1.0f, aspy = 1.0f;
-
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
- }
- else if (t->options & CTX_MASK) {
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
- }
-
- vec[0] *= aspx;
- vec[1] *= aspy;
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
}
}
}
@@ -729,7 +702,6 @@ static void view_editmove(unsigned short UNUSED(event))
switch (event) {
case WHEELUPMOUSE:
-
if (G.qual & LR_SHIFTKEY) {
if (G.qual & LR_ALTKEY) {
G.qual &= ~LR_SHIFTKEY;
@@ -795,35 +767,38 @@ static void view_editmove(unsigned short UNUSED(event))
/* ************************************************* */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define TFM_MODAL_CANCEL 1
-#define TFM_MODAL_CONFIRM 2
-#define TFM_MODAL_TRANSLATE 3
-#define TFM_MODAL_ROTATE 4
-#define TFM_MODAL_RESIZE 5
-#define TFM_MODAL_SNAP_INV_ON 6
-#define TFM_MODAL_SNAP_INV_OFF 7
-#define TFM_MODAL_SNAP_TOGGLE 8
-#define TFM_MODAL_AXIS_X 9
-#define TFM_MODAL_AXIS_Y 10
-#define TFM_MODAL_AXIS_Z 11
-#define TFM_MODAL_PLANE_X 12
-#define TFM_MODAL_PLANE_Y 13
-#define TFM_MODAL_PLANE_Z 14
-#define TFM_MODAL_CONS_OFF 15
-#define TFM_MODAL_ADD_SNAP 16
-#define TFM_MODAL_REMOVE_SNAP 17
-/* 18 and 19 used by numinput, defined in transform.h
- * */
-#define TFM_MODAL_PROPSIZE_UP 20
-#define TFM_MODAL_PROPSIZE_DOWN 21
-#define TFM_MODAL_AUTOIK_LEN_INC 22
-#define TFM_MODAL_AUTOIK_LEN_DEC 23
-
-#define TFM_MODAL_EDGESLIDE_UP 24
-#define TFM_MODAL_EDGESLIDE_DOWN 25
+enum {
+ TFM_MODAL_CANCEL = 1,
+ TFM_MODAL_CONFIRM = 2,
+ TFM_MODAL_TRANSLATE = 3,
+ TFM_MODAL_ROTATE = 4,
+ TFM_MODAL_RESIZE = 5,
+ TFM_MODAL_SNAP_INV_ON = 6,
+ TFM_MODAL_SNAP_INV_OFF = 7,
+ TFM_MODAL_SNAP_TOGGLE = 8,
+ TFM_MODAL_AXIS_X = 9,
+ TFM_MODAL_AXIS_Y = 10,
+ TFM_MODAL_AXIS_Z = 11,
+ TFM_MODAL_PLANE_X = 12,
+ TFM_MODAL_PLANE_Y = 13,
+ TFM_MODAL_PLANE_Z = 14,
+ TFM_MODAL_CONS_OFF = 15,
+ TFM_MODAL_ADD_SNAP = 16,
+ TFM_MODAL_REMOVE_SNAP = 17,
+
+/* 18 and 19 used by numinput, defined in transform.h */
+
+ TFM_MODAL_PROPSIZE_UP = 20,
+ TFM_MODAL_PROPSIZE_DOWN = 21,
+ TFM_MODAL_AUTOIK_LEN_INC = 22,
+ TFM_MODAL_AUTOIK_LEN_DEC = 23,
+
+ TFM_MODAL_EDGESLIDE_UP = 24,
+ TFM_MODAL_EDGESLIDE_DOWN = 25,
/* for analog input, like trackpad */
-#define TFM_MODAL_PROPSIZE 26
+ TFM_MODAL_PROPSIZE = 26,
+};
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
@@ -868,8 +843,8 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
/* items for modal map */
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE);
WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE);
@@ -888,8 +863,12 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
+ WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP);
+ WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN);
+ WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP);
+ WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_DOWN);
WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP);
@@ -907,7 +886,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
{
if (!(t->flag & T_NO_CONSTRAINT)) {
int constraint_axis, constraint_plane;
- int edit_2d = (t->flag & T_2D_EDIT);
+ const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
const char *msg1 = "", *msg2 = "", *msg3 = "";
char axis;
@@ -1230,7 +1209,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_PROPSIZE_UP:
if (t->flag & T_PROP_EDIT) {
- t->prop_size *= 1.1f;
+ t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
calculatePropRatio(t);
@@ -1240,17 +1219,12 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_PROPSIZE_DOWN:
if (t->flag & T_PROP_EDIT) {
- t->prop_size *= 0.90909090f;
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
calculatePropRatio(t);
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
case TFM_MODAL_AUTOIK_LEN_INC:
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 1);
@@ -1265,6 +1239,9 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
break;
+ /* Those two are only handled in transform's own handler, see T44634! */
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN:
default:
break;
}
@@ -1413,7 +1390,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case PADPLUSKEY:
if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size *= 1.1f;
+ t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
calculatePropRatio(t);
@@ -1434,7 +1411,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case PADMINUS:
if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size *= 0.90909090f;
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
calculatePropRatio(t);
t->redraw = TREDRAW_HARD;
handled = true;
@@ -1571,7 +1548,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
if (cent3d) {
// Copy center from constraint center. Transform center can be local
- copy_v3_v3(cent3d, t->con.center);
+ copy_v3_v3(cent3d, t->center_global);
}
}
@@ -1824,8 +1801,8 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
drawSnapping(C, t);
/* edge slide, vert slide */
- drawEdgeSlide(C, t);
- drawVertSlide(C, t);
+ drawEdgeSlide(t);
+ drawVertSlide(t);
}
/* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */
@@ -1934,7 +1911,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
!RNA_property_is_set(op->ptr, prop))
{
- if (t->obedit)
+ if (t->spacetype == SPACE_IPO)
+ ts->proportional_fcurve = proportional;
+ else if (t->spacetype == SPACE_ACTION)
+ ts->proportional_action = proportional;
+ else if (t->obedit)
ts->proportional = proportional;
else if (t->options & CTX_MASK)
ts->proportional_mask = (proportional != PROP_EDIT_OFF);
@@ -1985,7 +1966,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
- RNA_property_boolean_set(op->ptr, prop, t->flag & T_MIRROR);
+ RNA_property_boolean_set(op->ptr, prop, (t->flag & T_MIRROR) != 0);
}
if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
@@ -2013,6 +1994,18 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
}
+
+ {
+ const char *prop_id = NULL;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) {
+
+ RNA_property_boolean_set(op->ptr, prop, (t->flag & T_ALT_TRANSFORM) != 0);
+ }
+ }
}
/* note: caller needs to free 't' on a 0 return */
@@ -2085,6 +2078,18 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
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 if (t->spacetype == SPACE_IPO) {
+ unit_m3(t->spacemtx);
+ t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+ t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ unit_m3(t->spacemtx);
+ t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
+ t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
+ }
else
unit_m3(t->spacemtx);
@@ -2184,18 +2189,28 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
case TFM_BONESIZE:
{ /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
bArmature *arm = t->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE)
+ if (arm->drawtype == ARM_ENVELOPE) {
initBoneEnvelope(t);
- else
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ }
+ else {
initBoneSize(t);
+ }
break;
}
case TFM_BONE_ENVELOPE:
initBoneEnvelope(t);
break;
+ case TFM_BONE_ENVELOPE_DIST:
+ initBoneEnvelope(t);
+ t->mode = TFM_BONE_ENVELOPE_DIST;
+ break;
case TFM_EDGE_SLIDE:
- initEdgeSlide(t);
+ {
+ const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
+ initEdgeSlide_ex(t, use_double_side);
break;
+ }
case TFM_VERT_SLIDE:
initVertSlide(t);
break;
@@ -2254,7 +2269,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
return 0;
}
-
/* overwrite initial values if operator supplied a non-null vector */
if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) {
float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */
@@ -2512,8 +2526,8 @@ static void protectedQuaternionBits(short protectflag, float quat[4], const floa
static void constraintTransLim(TransInfo *t, TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
- bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
+ const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
+ const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2528,7 +2542,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
/* Evaluate valid constraints */
for (con = td->con; con; con = con->next) {
- bConstraintTypeInfo *cti = NULL;
+ const bConstraintTypeInfo *cti = NULL;
ListBase targets = {NULL, NULL};
/* only consider constraint if enabled */
@@ -2615,7 +2629,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
bConstraintOb cob;
bConstraint *con;
bool do_limit = false;
@@ -2682,7 +2696,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
static void constraintSizeLim(TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
- bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
float size_sign[3], size_abs[3];
@@ -2806,10 +2820,11 @@ static void initBend(TransInfo *t)
t->num.unit_type[0] = B_UNIT_ROTATION;
t->num.unit_type[1] = B_UNIT_LENGTH;
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT | T_FREE_CUSTOMDATA;
//copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
calculateCenterCursor(t, t->center);
+ calculateCenterGlobal(t);
t->val = 0.0f;
@@ -2884,6 +2899,8 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
values.scale = values.scale / data->warp_init_dist;
}
+ copy_v2_v2(t->values, values.vector);
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
@@ -2901,8 +2918,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
WM_bool_as_string(is_clamp));
}
- copy_v2_v2(t->values, values.vector);
-
values.angle *= -1.0f;
values.scale *= data->warp_init_dist;
@@ -2957,6 +2972,13 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
add_v3_v3(vec, pivot);
mul_m3_v3(td->smtx, vec);
+
+ /* rotation */
+ if ((t->flag & T_POINTS) == 0) {
+ ElementRotation(t, td, mat, V3D_LOCAL);
+ }
+
+ /* location */
copy_v3_v3(td->loc, vec);
}
@@ -3052,6 +3074,8 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &value);
+ t->values[0] = value;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -3065,8 +3089,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext);
}
- t->values[0] = value;
-
unit_m3(smat);
// Custom data signals shear direction
@@ -3329,7 +3351,7 @@ static void applyResize(TransInfo *t, const int mval[2])
ratio = t->values[0];
}
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, ratio);
snapGridIncrement(t, size);
@@ -3435,12 +3457,10 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td;
float size[3], mat[3][3];
- float ratio;
int i;
char str[MAX_INFO_LEN];
- ratio = t->values[0];
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, t->values[0]);
snapGridIncrement(t, size);
@@ -3545,10 +3565,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
- if (ratio < 0)
- ratio = 0.0f;
- else if (ratio > 1)
- ratio = 1.0f;
+ CLAMP(ratio, 0.0f, 1.0f);
t->values[0] = ratio;
@@ -3917,6 +3934,8 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
final = angle_wrap_rad(final);
}
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -3933,8 +3952,6 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
- t->values[0] = final;
-
applyRotationValue(t, final, t->axis);
recalcData(t);
@@ -4006,7 +4023,9 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
char str[MAX_INFO_LEN];
size_t ofs = 0;
float axis1[3], axis2[3];
+#if 0 /* UNUSED */
float mat[3][3], totmat[3][3], smat[3][3];
+#endif
float phi[2];
copy_v3_v3(axis1, t->persinv[0]);
@@ -4014,13 +4033,14 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
normalize_v3(axis1);
normalize_v3(axis2);
- phi[0] = t->values[0];
- phi[1] = t->values[1];
+ copy_v2_v2(phi, t->values);
snapGridIncrement(t, phi);
applyNumInput(&t->num, phi);
+ copy_v2_v2(t->values, phi);
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
@@ -4038,6 +4058,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
+#if 0 /* UNUSED */
axis_angle_normalized_to_mat3(smat, axis1, phi[0]);
axis_angle_normalized_to_mat3(totmat, axis2, phi[1]);
@@ -4045,6 +4066,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
// TRANSFORM_FIX_ME
//copy_m3_m3(t->mat, mat); // used in manipulator
+#endif
applyTrackballValue(t, axis1, axis2, phi);
@@ -4370,6 +4392,8 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &distance);
+ t->values[0] = -distance;
+
/* header print for NumInput */
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
@@ -4397,9 +4421,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
/* done with header string */
-
- t->values[0] = -distance;
-
for (i = 0; i < t->total; i++, td++) {
float tdistance; /* temp dist */
if (td->flag & TD_NOACTION)
@@ -4466,6 +4487,8 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4543,6 +4566,8 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4621,6 +4646,8 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4719,6 +4746,8 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4791,6 +4820,8 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &distance);
+ t->values[0] = distance;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4804,8 +4835,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
}
- t->values[0] = distance;
-
if (t->con.applyRot && t->con.mode & CON_APPLY) {
t->con.applyRot(t, NULL, axis, NULL);
}
@@ -4878,12 +4907,14 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
weight = t->values[0];
- if (weight > 1.0f) weight = 1.0f;
+ CLAMP_MAX(weight, 1.0f);
snapGridIncrement(t, &weight);
applyNumInput(&t->num, &weight);
+ t->values[0] = weight;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -4956,12 +4987,14 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
crease = t->values[0];
- if (crease > 1.0f) crease = 1.0f;
+ CLAMP_MAX(crease, 1.0f);
snapGridIncrement(t, &crease);
applyNumInput(&t->num, &crease);
+ t->values[0] = crease;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -5095,7 +5128,7 @@ static void applyBoneSize(TransInfo *t, const int mval[2])
ratio = t->values[0];
}
- size[0] = size[1] = size[2] = ratio;
+ copy_v3_fl(size, ratio);
snapGridIncrement(t, size);
@@ -5103,6 +5136,8 @@ static void applyBoneSize(TransInfo *t, const int mval[2])
constraintNumInput(t, size);
}
+ copy_v3_v3(t->values, size);
+
size_to_mat3(mat, size);
if (t->con.applySize) {
@@ -5169,6 +5204,8 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &ratio);
+ t->values[0] = ratio;
+
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -5256,11 +5293,22 @@ static void slide_origdata_create_data_vert(
loop_weights = BLI_array_alloca(loop_weights, l_num);
for (j = 0; j < l_num; j++) {
BMLoop *l = BM_iter_step(&liter);
- if (!BLI_ghash_haskey(sod->origfaces, l->f)) {
+ BMLoop *l_prev, *l_next;
+ void **val_p;
+ if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) {
BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
- BLI_ghash_insert(sod->origfaces, l->f, f_copy);
+ *val_p = f_copy;
}
- loop_weights[j] = BM_loop_calc_face_angle(l);
+
+ if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
+ (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON)))
+ {
+ loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
+
}
/* store cd_loop_groups */
@@ -5328,6 +5376,13 @@ static void slide_origdata_interp_data_vert(
int j, l_num;
float *loop_weights;
const bool do_loop_weight = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+ const float *v_proj_axis = sv->v->no;
+ /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
+ float v_proj[3][3];
+
+ if (do_loop_weight) {
+ project_plane_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
+ }
// BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
@@ -5348,11 +5403,44 @@ static void slide_origdata_interp_data_vert(
/* weight the loop */
if (do_loop_weight) {
- const float *v_prev = slide_origdata_orig_vert_co(sod, l->prev->v);
- const float *v_next = slide_origdata_orig_vert_co(sod, l->next->v);
- const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, v_prev, sv->co_orig_3d, v_next, f_copy->no);
- const float eps = 0.00001f;
- loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ const float eps = 1.0e-8f;
+ const BMLoop *l_prev = l->prev;
+ const BMLoop *l_next = l->next;
+ const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ bool co_prev_ok;
+ bool co_next_ok;
+
+
+ /* In the unlikely case that we're next to a zero length edge - walk around the to the next.
+ * Since we only need to check if the vertex is in this corner,
+ * its not important _which_ loop - as long as its not overlapping 'sv->co_orig_3d', see: T45096. */
+ project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
+ ((l_prev = l_prev->prev) != l->next)))
+ {
+ co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
+ project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ }
+ project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
+ ((l_next = l_next->next) != l->prev)))
+ {
+ co_next = slide_origdata_orig_vert_co(sod, l_next->v);
+ project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ }
+
+ if (co_prev_ok && co_next_ok) {
+ const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, UNPACK3(v_proj), v_proj_axis);
+
+ loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps)));
+ if (UNLIKELY(!isfinite(loop_weights[j]))) {
+ loop_weights[j] = 0.0f;
+ }
+ }
+ else {
+ loop_weights[j] = 0.0f;
+ }
}
}
@@ -5423,6 +5511,19 @@ static void slide_origdata_free_date(
/** \name Transform Edge Slide
* \{ */
+static void calcEdgeSlideCustomPoints(struct TransInfo *t)
+{
+ EdgeSlideData *sld = t->customData;
+
+ setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediatly so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+}
+
+
static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
{
BMIter iter;
@@ -5438,7 +5539,7 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
}
/* interpoaltes along a line made up of 2 segments (used for edge slide) */
-static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t)
+static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], float t)
{
float t_mid, t_delta;
@@ -5446,17 +5547,28 @@ static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[
t_mid = line_point_factor_v3(v2, v1, v3);
t_delta = t - t_mid;
- if (fabsf(t_delta) < FLT_EPSILON) {
- copy_v3_v3(p, v2);
- }
- else if (t_delta < 0.0f) {
- interp_v3_v3v3(p, v1, v2, t / t_mid);
+ if (t_delta < 0.0f) {
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v2);
+ }
+ else {
+ interp_v3_v3v3(p, v1, v2, t / t_mid);
+ }
}
else {
- interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid));
+ t = t - t_mid;
+ t_mid = 1.0f - t_mid;
+
+ if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) {
+ copy_v3_v3(p, v3);
+ }
+ else {
+ interp_v3_v3v3(p, v2, v3, t / t_mid);
+ }
}
}
+
static void len_v3_ensure(float v[3], const float length)
{
normalize_v3(v);
@@ -5601,7 +5713,171 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l,
return NULL;
}
-static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2])
+/**
+ * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction.
+ */
+static void calcEdgeSlide_mval_range(
+ TransInfo *t, EdgeSlideData *sld, const int *sv_table, const int loop_nr,
+ const float mval[2], const bool use_btree_disp, const bool use_calc_direction)
+{
+ TransDataEdgeSlideVert *sv_array = sld->sv;
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ ARegion *ar = t->ar;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+ BMBVHTree *btree;
+
+ /* only for use_calc_direction */
+ float (*loop_dir)[3] = NULL, *loop_maxdist = NULL;
+
+ float mval_start[2], mval_end[2];
+ float mval_dir[3], dist_best_sq;
+ BMIter iter;
+ BMEdge *e;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ }
+
+ if (!rv3d) {
+ /* ok, let's try to survive this */
+ unit_m4(projectMat);
+ }
+ else {
+ ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
+ }
+
+ if (use_btree_disp) {
+ btree = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
+ }
+ else {
+ btree = NULL;
+ }
+
+ /* find mouse vectors, the global one, and one per loop in case we have
+ * multiple loops selected, in case they are oriented different */
+ zero_v3(mval_dir);
+ dist_best_sq = -1.0f;
+
+ if (use_calc_direction) {
+ loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir");
+ loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
+ copy_vn_fl(loop_maxdist, loop_nr, -1.0f);
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ int i;
+
+ /* search cross edges for visible edge to the mouse cursor,
+ * then use the shared vertex to calculate screen vector*/
+ for (i = 0; i < 2; i++) {
+ BMIter iter_other;
+ BMEdge *e_other;
+
+ BMVert *v = i ? e->v1 : e->v2;
+ BM_ITER_ELEM (e_other, &iter_other, v, BM_EDGES_OF_VERT) {
+ /* screen-space coords */
+ float sco_a[3], sco_b[3];
+ float dist_sq;
+ int j, l_nr;
+
+ if (BM_elem_flag_test(e_other, BM_ELEM_SELECT))
+ continue;
+
+ /* This test is only relevant if object is not wire-drawn! See [#32068]. */
+ if (use_btree_disp && !BMBVH_EdgeVisible(btree, e_other, ar, v3d, t->obedit)) {
+ continue;
+ }
+
+ BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
+ j = sv_table[BM_elem_index_get(v)];
+
+ if (sv_array[j].v_side[1]) {
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]);
+ ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat);
+ }
+
+ if (sv_array[j].v_side[0]) {
+ ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat);
+ }
+ else {
+ add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]);
+ ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat);
+ }
+
+ /* global direction */
+ dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a);
+ if ((dist_best_sq == -1.0f) ||
+ /* intentionally use 2d size on 3d vector */
+ (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f)))
+ {
+ dist_best_sq = dist_sq;
+ sub_v3_v3v3(mval_dir, sco_b, sco_a);
+ }
+
+ if (use_calc_direction) {
+ /* per loop direction */
+ l_nr = sv_array[j].loop_nr;
+ if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) {
+ loop_maxdist[l_nr] = dist_sq;
+ sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (use_calc_direction) {
+ int i;
+ sv_array = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv_array++) {
+ /* switch a/b if loop direction is different from global direction */
+ int l_nr = sv_array->loop_nr;
+ if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
+ swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]);
+ SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]);
+ }
+ }
+
+ MEM_freeN(loop_dir);
+ MEM_freeN(loop_maxdist);
+ }
+
+ /* possible all of the edge loops are pointing directly at the view */
+ if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
+ mval_dir[0] = 0.0f;
+ mval_dir[1] = 100.0f;
+ }
+
+ /* zero out start */
+ zero_v2(mval_start);
+
+ /* dir holds a vector along edge loop */
+ copy_v2_v2(mval_end, mval_dir);
+ mul_v2_fl(mval_end, 0.5f);
+
+ sld->mval_start[0] = t->mval[0] + mval_start[0];
+ sld->mval_start[1] = t->mval[1] + mval_start[1];
+
+ sld->mval_end[0] = t->mval[0] + mval_end[0];
+ sld->mval_end[1] = t->mval[1] + mval_end[1];
+
+ if (btree) {
+ BKE_bmbvh_free(btree);
+ }
+}
+
+static void calcEdgeSlide_non_proportional(
+ TransInfo *t, EdgeSlideData *sld, const float mval[2])
{
TransDataEdgeSlideVert *sv = sld->sv;
@@ -5631,7 +5907,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const
for (i = 0; i < sld->totsv; i++, sv++) {
/* Set length */
- sv->edge_len = len_v3v3(sv->dir_a, sv->dir_b);
+ sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]);
ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat);
dist_sq = len_squared_v2v2(mval, v_proj);
@@ -5646,7 +5922,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const
}
}
-static bool createEdgeSlideVerts(TransInfo *t)
+static bool createEdgeSlideVerts_double_side(TransInfo *t)
{
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
@@ -5655,24 +5931,13 @@ static bool createEdgeSlideVerts(TransInfo *t)
BMVert *v;
TransDataEdgeSlideVert *sv_array;
int sv_tot;
- BMBVHTree *btree;
int *sv_table; /* BMVert -> sv_array index */
EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int numsel, i, j, loop_nr;
+ bool use_btree_disp = false;
View3D *v3d = NULL;
RegionView3D *rv3d = NULL;
- ARegion *ar = t->ar;
- float projectMat[4][4];
- float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
- float mval_start[2], mval_end[2];
- float mval_dir[3], maxdist, (*loop_dir)[3], *loop_maxdist;
- int numsel, i, j, loop_nr, l_nr;
- int use_btree_disp;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = t->ar ? t->ar->regiondata : NULL;
- }
slide_origdata_init_flag(t, &sld->orig_data);
@@ -5680,14 +5945,6 @@ static bool createEdgeSlideVerts(TransInfo *t)
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
- }
-
/*ensure valid selection*/
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
@@ -5859,14 +6116,14 @@ static bool createEdgeSlideVerts(TransInfo *t)
if (l_a || l_a_prev) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
- sv->v_a = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_a, vec_a);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[0], vec_a);
}
if (l_b || l_b_prev) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v);
- sv->v_b = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_b, vec_b);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[1], vec_b);
}
v_prev = v;
@@ -5885,23 +6142,23 @@ static bool createEdgeSlideVerts(TransInfo *t)
if (l_a) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
- sv->v_a = BM_edge_other_vert(l_tmp->e, v);
+ sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v);
if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_a);
+ get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]);
}
else {
- sub_v3_v3v3(sv->dir_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
}
}
if (l_b) {
BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
- sv->v_b = BM_edge_other_vert(l_tmp->e, v);
+ sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v);
if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_b);
+ get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]);
}
else {
- sub_v3_v3v3(sv->dir_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
}
}
@@ -5972,142 +6229,228 @@ static bool createEdgeSlideVerts(TransInfo *t)
#undef EDGESLIDE_VERT_IS_INNER
}
- /* use for visibility checks */
- use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
- if (use_btree_disp) {
- btree = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
- }
- else {
- btree = NULL;
+ sld->sv = sv_array;
+ sld->totsv = sv_tot;
+
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
}
+ calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_btree_disp, true);
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(t, &sld->orig_data);
+ slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- sld->sv = sv_array;
- sld->totsv = sv_tot;
+ if (rv3d) {
+ calcEdgeSlide_non_proportional(t, sld, mval);
+ }
+
+ sld->em = em;
- /* find mouse vectors, the global one, and one per loop in case we have
- * multiple loops selected, in case they are oriented different */
- zero_v3(mval_dir);
- maxdist = -1.0f;
+ sld->perc = 0.0f;
+
+ t->customData = sld;
+
+ MEM_freeN(sv_table);
- loop_dir = MEM_callocN(sizeof(float) * 3 * loop_nr, "sv loop_dir");
- loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist");
- fill_vn_fl(loop_maxdist, loop_nr, -1.0f);
+ return true;
+}
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BMIter iter2;
- BMEdge *e2;
- float d;
+/**
+ * A simple version of #createEdgeSlideVerts
+ * Which assumes the longest unselected.
+ */
+static bool createEdgeSlideVerts_single_side(TransInfo *t)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v;
+ TransDataEdgeSlideVert *sv_array;
+ int sv_tot;
+ int *sv_table; /* BMVert -> sv_array index */
+ EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ float mval[2] = {(float)t->mval[0], (float)t->mval[1]};
+ int i, j, loop_nr;
+ bool use_btree_disp = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
- /* search cross edges for visible edge to the mouse cursor,
- * then use the shared vertex to calculate screen vector*/
- for (i = 0; i < 2; i++) {
- v = i ? e->v1 : e->v2;
- BM_ITER_ELEM (e2, &iter2, v, BM_EDGES_OF_VERT) {
- /* screen-space coords */
- float sco_a[3], sco_b[3];
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ }
- if (BM_elem_flag_test(e2, BM_ELEM_SELECT))
- continue;
+ slide_origdata_init_flag(t, &sld->orig_data);
- /* This test is only relevant if object is not wire-drawn! See [#32068]. */
- if (use_btree_disp && !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit)) {
- continue;
+ sld->is_proportional = true;
+ sld->curr_sv_index = 0;
+ /* heppans to be best for single-sided */
+ sld->flipped_vtx = true;
+
+ /* ensure valid selection */
+ j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ float len_sq_max = -1.0f;
+ BMIter iter2;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq > len_sq_max) {
+ len_sq_max = len_sq;
+ v->e = e;
}
+ }
+ }
- BLI_assert(sv_table[BM_elem_index_get(v)] != -1);
- j = sv_table[BM_elem_index_get(v)];
+ if (len_sq_max != -1.0f) {
+ j++;
+ }
+ }
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
- if (sv_array[j].v_b) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_b->co, sco_b, projectMat);
- }
- else {
- add_v3_v3v3(sco_b, v->co, sv_array[j].dir_b);
- ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat);
- }
-
- if (sv_array[j].v_a) {
- ED_view3d_project_float_v3_m4(ar, sv_array[j].v_a->co, sco_a, projectMat);
+ if (!j) {
+ return false;
+ }
+
+
+ sv_tot = j;
+ BLI_assert(sv_tot != 0);
+ /* over alloc */
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array");
+
+ /* same loop for all loops, weak but we dont connect loops in this case */
+ loop_nr = 1;
+
+ sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
+
+ j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ sv_table[i] = -1;
+ if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) {
+ if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) {
+ TransDataEdgeSlideVert *sv;
+ sv = &sv_array[j];
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->v_side[0] = BM_edge_other_vert(v->e, v);
+ sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co);
+ sv->loop_nr = 0;
+ sv_table[i] = j;
+ j += 1;
+ }
+ }
+ }
+
+ /* check for wire vertices,
+ * interpolate the directions of wire verts between non-wire verts */
+ if (sv_tot != bm->totvert) {
+ const int sv_tot_nowire = sv_tot;
+ TransDataEdgeSlideVert *sv_iter = sv_array;
+ int i;
+ for (i = 0; i < sv_tot_nowire; i++, sv_iter++) {
+ BMIter eiter;
+ BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) {
+ /* walk over wire */
+ TransDataEdgeSlideVert *sv_end = NULL;
+ BMEdge *e_step = e;
+ BMVert *v = sv_iter->v;
+
+ j = sv_tot;
+
+ while (1) {
+ BMVert *v_other = BM_edge_other_vert(e_step, v);
+ int endpoint = (
+ (sv_table[BM_elem_index_get(v_other)] != -1) +
+ (BM_vert_is_edge_pair(v_other) == false));
+
+ if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(v_other, BM_ELEM_SELECT)) &&
+ (endpoint == 0))
+ {
+ /* scan down the list */
+ TransDataEdgeSlideVert *sv;
+ BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1);
+ sv_table[BM_elem_index_get(v_other)] = j;
+ sv = &sv_array[j];
+ sv->v = v_other;
+ copy_v3_v3(sv->v_co_orig, v_other->co);
+ copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]);
+ j++;
+
+ /* advance! */
+ v = v_other;
+ e_step = BM_DISK_EDGE_NEXT(e_step, v_other);
}
else {
- add_v3_v3v3(sco_a, v->co, sv_array[j].dir_a);
- ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat);
- }
-
- /* global direction */
- d = dist_to_line_segment_v2(mval, sco_b, sco_a);
- if ((maxdist == -1.0f) ||
- /* intentionally use 2d size on 3d vector */
- (d < maxdist && (len_squared_v2v2(sco_b, sco_a) > 0.1f)))
- {
- maxdist = d;
- sub_v3_v3v3(mval_dir, sco_b, sco_a);
+ if ((endpoint == 2) && (sv_tot != j)) {
+ BLI_assert(BM_elem_index_get(v_other) != -1);
+ sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]];
+ }
+ break;
}
+ }
- /* per loop direction */
- l_nr = sv_array[j].loop_nr;
- if (loop_maxdist[l_nr] == -1.0f || d < loop_maxdist[l_nr]) {
- loop_maxdist[l_nr] = d;
- sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a);
+ if (sv_end) {
+ int sv_tot_prev = sv_tot;
+ const float *co_src = sv_iter->v->co;
+ const float *co_dst = sv_end->v->co;
+ const float *dir_src = sv_iter->dir_side[0];
+ const float *dir_dst = sv_end->dir_side[0];
+ sv_tot = j;
+
+ while (j-- != sv_tot_prev) {
+ float factor;
+ factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst);
+ interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor);
}
}
}
}
}
- /* possible all of the edge loops are pointing directly at the view */
- if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) {
- mval_dir[0] = 0.0f;
- mval_dir[1] = 100.0f;
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+
+ sld->sv = sv_array;
+ sld->totsv = sv_tot;
+
+ /* use for visibility checks */
+ if (t->spacetype == SPACE_VIEW3D) {
+ v3d = t->sa ? t->sa->spacedata.first : NULL;
+ rv3d = t->ar ? t->ar->regiondata : NULL;
+ use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
}
+ calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_btree_disp, false);
+
+ /* create copies of faces for customdata projection */
bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
slide_origdata_init_data(t, &sld->orig_data);
slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- /*create copies of faces for customdata projection*/
- sv_array = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv_array++) {
- /* switch a/b if loop direction is different from global direction */
- l_nr = sv_array->loop_nr;
- if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) {
- swap_v3_v3(sv_array->dir_a, sv_array->dir_b);
- SWAP(BMVert *, sv_array->v_a, sv_array->v_b);
- }
+ if (rv3d) {
+ calcEdgeSlide_non_proportional(t, sld, mval);
}
- if (rv3d)
- calcNonProportionalEdgeSlide(t, sld, mval);
-
sld->em = em;
- /*zero out start*/
- zero_v2(mval_start);
-
- /*dir holds a vector along edge loop*/
- copy_v2_v2(mval_end, mval_dir);
- mul_v2_fl(mval_end, 0.5f);
-
- sld->mval_start[0] = t->mval[0] + mval_start[0];
- sld->mval_start[1] = t->mval[1] + mval_start[1];
-
- sld->mval_end[0] = t->mval[0] + mval_end[0];
- sld->mval_end[1] = t->mval[1] + mval_end[1];
-
sld->perc = 0.0f;
-
+
t->customData = sld;
-
+
MEM_freeN(sv_table);
- if (btree) {
- BKE_bmbvh_free(btree);
- }
- MEM_freeN(loop_dir);
- MEM_freeN(loop_maxdist);
return true;
}
@@ -6148,15 +6491,23 @@ void freeEdgeSlideVerts(TransInfo *t)
recalcData(t);
}
-static void initEdgeSlide(TransInfo *t)
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side)
{
EdgeSlideData *sld;
+ bool ok;
t->mode = TFM_EDGE_SLIDE;
t->transform = applyEdgeSlide;
t->handleEvent = handleEventEdgeSlide;
- if (!createEdgeSlideVerts(t)) {
+ if (use_double_side) {
+ ok = createEdgeSlideVerts_double_side(t);
+ }
+ else {
+ ok = createEdgeSlideVerts_single_side(t);
+ }
+
+ if (!ok) {
t->state = TRANS_CANCEL;
return;
}
@@ -6169,7 +6520,7 @@ static void initEdgeSlide(TransInfo *t)
t->customFree = freeEdgeSlideVerts;
/* set custom point first if you want value to be initialized by init */
- setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+ calcEdgeSlideCustomPoints(t);
initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
t->idx_max = 0;
@@ -6185,6 +6536,11 @@ static void initEdgeSlide(TransInfo *t)
t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
+static void initEdgeSlide(TransInfo *t)
+{
+ initEdgeSlide_ex(t, true);
+}
+
static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_EDGE_SLIDE) {
@@ -6195,35 +6551,40 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
case EKEY:
if (event->val == KM_PRESS) {
sld->is_proportional = !sld->is_proportional;
+ calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
case FKEY:
- {
if (event->val == KM_PRESS) {
if (sld->is_proportional == false) {
sld->flipped_vtx = !sld->flipped_vtx;
}
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case CKEY:
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
- }
case EVT_MODAL_MAP:
- {
switch (event->val) {
case TFM_MODAL_EDGESLIDE_DOWN:
- {
sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
- break;
- }
+ return TREDRAW_HARD;
case TFM_MODAL_EDGESLIDE_UP:
- {
sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
- break;
- }
+ return TREDRAW_HARD;
}
break;
- }
+ case MOUSEMOVE:
+ calcEdgeSlideCustomPoints(t);
+ break;
default:
break;
}
@@ -6232,23 +6593,16 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_NOTHING;
}
-static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
+static void drawEdgeSlide(TransInfo *t)
{
- if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideData *sld = (EdgeSlideData *)t->customData;
+ if ((t->mode == TFM_EDGE_SLIDE) && t->customData) {
+ EdgeSlideData *sld = t->customData;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
/* Non-Prop mode */
- if (sld && sld->is_proportional == false) {
- View3D *v3d = CTX_wm_view3d(C);
- float co_a[3], co_b[3], co_mark[3];
- TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float fac = (sld->perc + 1.0f) / 2.0f;
- const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
- const float guide_size = ctrl_size - 0.5f;
+ if ((sld->is_proportional == false) || (is_clamp == false)) {
+ View3D *v3d = t->view;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
- const int alpha_shade = -30;
-
- add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a);
- add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b);
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
@@ -6261,42 +6615,88 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
glMultMatrixf(t->obedit->obmat);
- glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
- if (curr_sv->v_a) {
- glVertex3fv(curr_sv->v_a->co);
- glVertex3fv(curr_sv->v_co_orig);
- }
- if (curr_sv->v_b) {
- glVertex3fv(curr_sv->v_b->co);
- glVertex3fv(curr_sv->v_co_orig);
- }
- bglEnd();
+ if (sld->is_proportional == false) {
+ float co_a[3], co_b[3], co_mark[3];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (sld->perc + 1.0f) / 2.0f;
+ const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
+ const float guide_size = ctrl_size - 0.5f;
+ const int alpha_shade = -30;
+
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
+
+ glLineWidth(line_size);
+ UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ glBegin(GL_LINES);
+ if (curr_sv->v_side[0]) {
+ glVertex3fv(curr_sv->v_side[0]->co);
+ glVertex3fv(curr_sv->v_co_orig);
+ }
+ if (curr_sv->v_side[1]) {
+ glVertex3fv(curr_sv->v_side[1]->co);
+ glVertex3fv(curr_sv->v_co_orig);
+ }
+ glEnd();
+ UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ glPointSize(ctrl_size);
+ bglBegin(GL_POINTS);
+ if (sld->flipped_vtx) {
+ if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co);
+ }
+ else {
+ if (curr_sv->v_side[0]) bglVertex3fv(curr_sv->v_side[0]->co);
+ }
+ bglEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- glPointSize(ctrl_size);
- bglBegin(GL_POINTS);
- if (sld->flipped_vtx) {
- if (curr_sv->v_b) bglVertex3fv(curr_sv->v_b->co);
+ UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ glPointSize(guide_size);
+ bglBegin(GL_POINTS);
+#if 0
+ interp_v3_v3v3(co_mark, co_b, co_a, fac);
+ bglVertex3fv(co_mark);
+#endif
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ bglVertex3fv(co_mark);
+ bglEnd();
}
else {
- if (curr_sv->v_a) bglVertex3fv(curr_sv->v_a->co);
- }
- bglEnd();
+ if (is_clamp == false) {
+ const int side_index = sld->curr_side_unclamp;
+ TransDataEdgeSlideVert *sv;
+ int i;
+ const int alpha_shade = -160;
+
+ glLineWidth(line_size);
+ UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ glBegin(GL_LINES);
+
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(a, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(a, sv->dir_side[!side_index]);
+ }
- UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- glPointSize(guide_size);
- bglBegin(GL_POINTS);
-#if 0
- interp_v3_v3v3(co_mark, co_b, co_a, fac);
- bglVertex3fv(co_mark);
-#endif
- interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- bglVertex3fv(co_mark);
- bglEnd();
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->v_co_orig);
+ add_v3_v3(b, sv->v_co_orig);
+ glVertex3fv(a);
+ glVertex3fv(b);
+ }
+ glEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
glPopMatrix();
glPopAttrib();
@@ -6319,17 +6719,30 @@ static void doEdgeSlide(TransInfo *t, float perc)
sv = svlist;
if (sld->is_proportional == true) {
- for (i = 0; i < sld->totsv; i++, sv++) {
- float vec[3];
- if (perc > 0.0f) {
- copy_v3_v3(vec, sv->dir_a);
- mul_v3_fl(vec, perc);
- add_v3_v3v3(sv->v->co, sv->v_co_orig, vec);
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ const int side_index = (perc < 0.0f);
+ const float perc_final = fabsf(perc);
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
}
- else {
- copy_v3_v3(vec, sv->dir_b);
- mul_v3_fl(vec, -perc);
- add_v3_v3v3(sv->v->co, sv->v_co_orig, vec);
+
+ sld->curr_side_unclamp = side_index;
+ }
+ else {
+ const int side_index = sld->curr_side_unclamp;
+ const float perc_init = fabsf(perc) * ((sld->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float dir_flip[3];
+ float perc_final = perc_init;
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(dir_flip, sv->dir_side[side_index]);
+ }
+ else {
+ copy_v3_v3(dir_flip, sv->dir_side[!side_index]);
+ perc_final *= -1;
+ }
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final);
}
}
}
@@ -6339,7 +6752,7 @@ static void doEdgeSlide(TransInfo *t, float perc)
* a/b verts, this could be changed/improved so the distance is still met but the verts are moved along
* their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell
*
- * \note len_v3v3(curr_sv->dir_a, curr_sv->dir_b)
+ * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1])
* is the same as the distance between the original vert locations, same goes for the lines below.
*/
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
@@ -6352,8 +6765,8 @@ static void doEdgeSlide(TransInfo *t, float perc)
if (sv->edge_len > FLT_EPSILON) {
const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len;
- add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_a);
- add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b);
+ add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]);
+ add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
if (sld->flipped_vtx) {
interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
@@ -6371,46 +6784,43 @@ static void doEdgeSlide(TransInfo *t, float perc)
static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
{
char str[MAX_INFO_LEN];
+ size_t ofs = 0;
float final;
EdgeSlideData *sld = t->customData;
bool flipped = sld->flipped_vtx;
bool is_proportional = sld->is_proportional;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
final = t->values[0];
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
- CLAMP(final, -1.0f, 1.0f);
+ if (is_constrained) {
+ CLAMP(final, -1.0f, 1.0f);
+ }
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Edge Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
-
outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (is_proportional) {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"),
- &c[0], WM_bool_as_string(!is_proportional));
- }
- else {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"),
- &c[0], WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
- }
- }
- else if (is_proportional) {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s"),
- final, WM_bool_as_string(!is_proportional));
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs);
}
else {
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"),
- final, WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped));
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
}
-
- CLAMP(final, -1.0f, 1.0f);
-
- t->values[0] = final;
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional));
+ if (!is_proportional) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
/* do stuff here */
doEdgeSlide(t, final);
@@ -6432,10 +6842,20 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
{
VertSlideData *sld = t->customData;
TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
- const float *co_orig = sv->co_orig_2d;
- const float *co_curr = sv->co_link_orig_2d[sv->co_link_curr];
- const int mval_start[2] = {co_orig[0], co_orig[1]};
- const int mval_end[2] = {co_curr[0], co_curr[1]};
+
+ const float *co_orig_3d = sv->co_orig_3d;
+ const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr];
+
+ float co_curr_2d[2], co_orig_2d[2];
+
+ int mval_ofs[2], mval_start[2], mval_end[2];
+
+ ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat);
+ ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat);
+
+ ARRAY_SET_ITEMS(mval_ofs, t->imval[0] - co_orig_2d[0], t->imval[1] - co_orig_2d[1]);
+ ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
+ ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
if (sld->flipped_vtx && sld->is_proportional == false) {
setCustomPoints(t, &t->mouse, mval_start, mval_end);
@@ -6443,6 +6863,11 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
else {
setCustomPoints(t, &t->mouse, mval_end, mval_start);
}
+
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediatly so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
}
/**
@@ -6460,28 +6885,39 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
int i;
for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- dist_sq = len_squared_v2v2(mval_fl, sv->co_orig_2d);
+ float co_2d[2];
+
+ ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat);
+
+ dist_sq = len_squared_v2v2(mval_fl, co_2d);
if (dist_sq < dist_min_sq) {
dist_min_sq = dist_sq;
sld->curr_sv_index = i;
}
}
}
+
/**
* Run while moving the mouse to slide along the edge matching the mouse direction
*/
static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
{
VertSlideData *sld = t->customData;
- float mval_fl[2] = {UNPACK2(mval)};
+ float imval_fl[2] = {UNPACK2(t->imval)};
+ float mval_fl[2] = {UNPACK2(mval)};
- float dir[2];
+ float dir[3];
TransDataVertSlideVert *sv;
int i;
- /* first get the direction of the original vertex */
- sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl);
- normalize_v2(dir);
+ /* first get the direction of the original mouse position */
+ sub_v2_v2v2(dir, imval_fl, mval_fl);
+ ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac);
+
+ invert_m4_m4(t->obedit->imat, t->obedit->obmat);
+ mul_mat3_m4_v3(t->obedit->imat, dir);
+
+ normalize_v3(dir);
for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
if (sv->co_link_tot > 1) {
@@ -6490,11 +6926,14 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
int j;
for (j = 0; j < sv->co_link_tot; j++) {
- float tdir[2];
+ float tdir[3];
float dir_dot;
- sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]);
- normalize_v2(tdir);
- dir_dot = dot_v2v2(dir, tdir);
+
+ sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
+ project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
+
+ normalize_v3(tdir);
+ dir_dot = dot_v3v3(dir, tdir);
if (dir_dot > dir_dot_best) {
dir_dot_best = dir_dot;
co_link_curr_best = j;
@@ -6518,32 +6957,14 @@ static bool createVertSlideVerts(TransInfo *t)
BMVert *v;
TransDataVertSlideVert *sv_array;
VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
-// View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
- ARegion *ar = t->ar;
- float projectMat[4][4];
int j;
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
-// v3d = t->sa ? t->sa->spacedata.first : NULL;
- rv3d = ar ? ar->regiondata : NULL;
- }
-
slide_origdata_init_flag(t, &sld->orig_data);
sld->is_proportional = true;
sld->curr_sv_index = 0;
sld->flipped_vtx = false;
- if (!rv3d) {
- /* ok, let's try to survive this */
- unit_m4(projectMat);
- }
- else {
- ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
- }
-
j = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
bool ok = false;
@@ -6587,7 +7008,6 @@ static bool createVertSlideVerts(TransInfo *t)
}
sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__);
- sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__);
sv_array[j].co_link_tot = k;
k = 0;
@@ -6595,31 +7015,9 @@ static bool createVertSlideVerts(TransInfo *t)
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
BMVert *v_other = BM_edge_other_vert(e, v);
copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co);
- if (ar) {
- ED_view3d_project_float_v2_m4(ar,
- sv_array[j].co_link_orig_3d[k],
- sv_array[j].co_link_orig_2d[k],
- projectMat);
- }
- else {
- copy_v2_v2(sv_array[j].co_link_orig_2d[k],
- sv_array[j].co_link_orig_3d[k]);
- }
k++;
}
}
-
- if (ar) {
- ED_view3d_project_float_v2_m4(ar,
- sv_array[j].co_orig_3d,
- sv_array[j].co_orig_2d,
- projectMat);
- }
- else {
- copy_v2_v2(sv_array[j].co_orig_2d,
- sv_array[j].co_orig_3d);
- }
-
j++;
}
}
@@ -6637,7 +7035,19 @@ static bool createVertSlideVerts(TransInfo *t)
t->customData = sld;
- if (rv3d) {
+ /* most likely will be set below */
+ unit_m4(sld->proj_mat);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* view vars */
+ RegionView3D *rv3d = NULL;
+ ARegion *ar = t->ar;
+
+ rv3d = ar ? ar->regiondata : NULL;
+ if (rv3d) {
+ ED_view3d_ob_project_mat_get(rv3d, t->obedit, sld->proj_mat);
+ }
+
calcVertSlideMouseActiveVert(t, t->mval);
calcVertSlideMouseActiveEdges(t, t->mval);
}
@@ -6677,7 +7087,6 @@ void freeVertSlideVerts(TransInfo *t)
TransDataVertSlideVert *sv = sld->sv;
int i = 0;
for (i = 0; i < sld->totsv; i++, sv++) {
- MEM_freeN(sv->co_link_orig_2d);
MEM_freeN(sv->co_link_orig_3d);
}
}
@@ -6744,16 +7153,13 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
}
break;
case FKEY:
- {
if (event->val == KM_PRESS) {
sld->flipped_vtx = !sld->flipped_vtx;
calcVertSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
- }
case CKEY:
- {
/* use like a modifier key */
if (event->val == KM_PRESS) {
t->flag ^= T_ALT_TRANSFORM;
@@ -6761,23 +7167,17 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_HARD;
}
break;
- }
#if 0
case EVT_MODAL_MAP:
- {
switch (event->val) {
case TFM_MODAL_EDGESLIDE_DOWN:
- {
sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
break;
- }
case TFM_MODAL_EDGESLIDE_UP:
- {
sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
break;
- }
}
- }
+ break;
#endif
case MOUSEMOVE:
{
@@ -6797,19 +7197,20 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
return TREDRAW_NOTHING;
}
-static void drawVertSlide(const struct bContext *C, TransInfo *t)
+static void drawVertSlide(TransInfo *t)
{
- if (t->mode == TFM_VERT_SLIDE) {
- VertSlideData *sld = (VertSlideData *)t->customData;
+ if ((t->mode == TFM_VERT_SLIDE) && t->customData) {
+ VertSlideData *sld = t->customData;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
/* Non-Prop mode */
- if (sld) {
- View3D *v3d = CTX_wm_view3d(C);
+ {
+ View3D *v3d = t->view;
TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
TransDataVertSlideVert *sv;
const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
const int alpha_shade = -160;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
int i;
if (v3d && v3d->zbuf)
@@ -6857,11 +7258,40 @@ static void drawVertSlide(const struct bContext *C, TransInfo *t)
curr_sv->co_orig_3d);
bglEnd();
+ glDisable(GL_BLEND);
+
+ /* direction from active vertex! */
+ if ((t->mval[0] != t->imval[0]) ||
+ (t->mval[1] != t->imval[1]))
+ {
+ float zfac = ED_view3d_calc_zfac(t->ar->regiondata, curr_sv->co_orig_3d, NULL);
+ float mval_ofs[2];
+ float co_dest_3d[3];
+
+ mval_ofs[0] = t->mval[0] - t->imval[0];
+ mval_ofs[1] = t->mval[1] - t->imval[1];
+
+ ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
+
+ invert_m4_m4(t->obedit->imat, t->obedit->obmat);
+ mul_mat3_m4_v3(t->obedit->imat, co_dest_3d);
+
+ add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
+
+ glLineWidth(1);
+ setlinestyle(1);
+
+ cpack(0xffffff);
+ glBegin(GL_LINES);
+ glVertex3fv(curr_sv->co_orig_3d);
+ glVertex3fv(co_dest_3d);
+
+ glEnd();
+ }
+
glPopMatrix();
glPopAttrib();
- glDisable(GL_BLEND);
-
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
}
@@ -6933,6 +7363,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
/* header string */
ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
@@ -7001,6 +7433,8 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &final);
+ t->values[0] = final;
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -7273,7 +7707,7 @@ static void initSeqSlide(TransInfo *t)
t->num.idx_max = t->idx_max;
t->snap[0] = 0.0f;
- t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
+ t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
t->snap[2] = 10.0f;
copy_v3_fl(t->num.val_inc, t->snap[1]);
@@ -7307,40 +7741,28 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[MAX_INFO_L
WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
}
-static void applySeqSlideValue(TransInfo *t, const float val[2], int frame)
+static void applySeqSlideValue(TransInfo *t, const float val[2])
{
TransData *td = t->data;
int i;
- TransSeq *ts = t->customData;
for (i = 0; i < t->total; i++, td++) {
- float tvec[2];
-
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
- copy_v2_v2(tvec, val);
-
- mul_v2_fl(tvec, td->factor);
-
- if (t->modifiers & MOD_SNAP_INVERT) {
- td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min);
- }
- else {
- td->loc[0] = td->iloc[0] + tvec[0];
- }
-
- td->loc[1] = td->iloc[1] + tvec[1];
+ madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
}
}
static void applySeqSlide(TransInfo *t, const int mval[2])
{
char str[MAX_INFO_LEN];
- int snap_frame = 0;
+
+ snapSequenceBounds(t, mval);
+
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
float tvec[3];
@@ -7348,16 +7770,15 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
copy_v3_v3(t->values, tvec);
}
else {
- snap_frame = snapSequenceBounds(t, mval);
// snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}
- t->values[0] = floor(t->values[0] + 0.5f);
- t->values[1] = floor(t->values[1] + 0.5f);
+ t->values[0] = floorf(t->values[0] + 0.5f);
+ t->values[1] = floorf(t->values[1] + 0.5f);
headerSeqSlide(t, t->values, str);
- applySeqSlideValue(t, t->values, snap_frame);
+ applySeqSlideValue(t, t->values);
recalcData(t);
@@ -7520,6 +7941,7 @@ static void initTimeTranslate(TransInfo *t)
static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
{
char tvec[NUM_STR_REP_LEN * 3];
+ int ofs = 0;
/* if numeric input is active, use results from that, otherwise apply snapping to result */
if (hasNumInput(&t->num)) {
@@ -7555,10 +7977,14 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN])
BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
}
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]);
+ ofs += BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]);
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
-static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
+static void applyTimeTranslateValue(TransInfo *t)
{
TransData *td = t->data;
TransData2D *td2d = t->data2d;
@@ -7588,11 +8014,11 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- deltax = (float)(floor(deltax + 0.5f));
+ deltax = floorf(deltax + 0.5f);
}
val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
- val += deltax;
+ val += deltax * td->factor;
*(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
}
else {
@@ -7602,7 +8028,7 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
val = (float)(floor(((double)deltax / secf) + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- val = (float)(floor(val + 0.5f));
+ val = floorf(val + 0.5f);
}
*(td->val) = td->ival + val;
@@ -7616,15 +8042,17 @@ static void applyTimeTranslateValue(TransInfo *t, float UNUSED(sval))
static void applyTimeTranslate(TransInfo *t, const int mval[2])
{
View2D *v2d = (View2D *)t->view;
- float cval[2], sval[2];
char str[MAX_INFO_LEN];
/* calculate translation amount from mouse movement - in 'time-grid space' */
- UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
+ if (t->flag & T_MODAL) {
+ float cval[2], sval[2];
+ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
- /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
- t->values[0] = cval[0] - sval[0];
+ /* we only need to calculate effect for time (applyTimeTranslate only needs that) */
+ t->values[0] = cval[0] - sval[0];
+ }
/* handle numeric-input stuff */
t->vec[0] = t->values[0];
@@ -7632,7 +8060,7 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2])
t->values[0] = t->vec[0];
headerTimeTranslate(t, str);
- applyTimeTranslateValue(t, sval[0]);
+ applyTimeTranslateValue(t);
recalcData(t);
@@ -7765,7 +8193,7 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
/* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
// XXX Need to be able to repeat this
- t->values[0] = cval[0];
+ /* t->values[0] = cval[0]; */ /* UNUSED (reset again later). */
/* handle numeric-input stuff */
t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
@@ -7866,7 +8294,7 @@ static void applyTimeScaleValue(TransInfo *t)
fac = (float)(floor((double)fac / secf + 0.5) * secf);
}
else if (autosnap == SACTSNAP_STEP) {
- fac = (float)(floor(fac + 0.5f));
+ fac = floorf(fac + 0.5f);
}
/* check if any need to apply nla-mapping */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 8d6c693b14a..8863d337cff 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -39,9 +39,6 @@
#include "DNA_listBase.h"
-#include "BLI_smallhash.h"
-#include "BKE_editmesh.h"
-
/* ************************** Types ***************************** */
struct TransInfo;
@@ -107,8 +104,6 @@ typedef struct TransCon {
float mtx[3][3]; /* Matrix of the Constraint space */
float imtx[3][3]; /* Inverse Matrix of the Constraint space */
float pmtx[3][3]; /* Projection Constraint Matrix (same as imtx with some axis == 0) */
- float center[3]; /* transformation center to define where to draw the view widget
- * ALWAYS in global space. Unlike the transformation center */
int imval[2]; /* initial mouse value for visual calculation */
/* the one in TransInfo is not garanty to stay the same (Rotates change it) */
int mode; /* Mode flags of the Constraint */
@@ -216,10 +211,10 @@ typedef struct TransDataEdgeSlideVert {
float edge_len;
- struct BMVert *v_a, *v_b;
+ struct BMVert *v_side[2];
/* add origvert.co to get the original locations */
- float dir_a[3], dir_b[3];
+ float dir_side[2][3];
int loop_nr;
} TransDataEdgeSlideVert;
@@ -256,19 +251,20 @@ typedef struct EdgeSlideData {
bool flipped_vtx;
int curr_sv_index;
+
+ /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
+ int curr_side_unclamp;
} EdgeSlideData;
typedef struct TransDataVertSlideVert {
/* TransDataGenericSlideVert */
- BMVert *v;
+ struct BMVert *v;
struct LinkNode **cd_loop_groups;
float co_orig_3d[3];
/* end generic */
- float co_orig_2d[2];
float (*co_link_orig_3d)[3];
- float (*co_link_orig_2d)[2];
int co_link_tot;
int co_link_curr;
} TransDataVertSlideVert;
@@ -287,6 +283,9 @@ typedef struct VertSlideData {
bool flipped_vtx;
int curr_sv_index;
+
+ /* result of ED_view3d_ob_project_mat_get */
+ float proj_mat[4][4];
} VertSlideData;
typedef struct BoneInitData {
@@ -356,7 +355,10 @@ typedef struct TransInfo {
eRedrawFlag redraw; /* redraw flag */
float prop_size; /* proportional circle radius */
char proptext[20]; /* proportional falloff text */
- float center[3]; /* center of transformation */
+ float aspect[3]; /* spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
+ * use for conversion and snapping. */
+ float center[3]; /* center of transformation (in local-space) */
+ float center_global[3]; /* center of transformation (in global-space) */
float center2d[2]; /* center in screen coordinates */
int imval[2]; /* initial mouse position */
short event_type; /* event->type used to invoke transform */
@@ -541,6 +543,7 @@ void transformApply(struct bContext *C, TransInfo *t);
int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
+void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy);
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag);
void projectIntView(TransInfo *t, const float vec[3], int adr[2]);
@@ -626,7 +629,7 @@ typedef enum {
void snapGridIncrement(TransInfo *t, float *val);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
-int snapSequenceBounds(TransInfo *t, const int mval[2]);
+void snapSequenceBounds(TransInfo *t, const int mval[2]);
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);
@@ -690,6 +693,7 @@ void restoreTransObjects(TransInfo *t);
void recalcData(TransInfo *t);
void calculateCenter2D(TransInfo *t);
+void calculateCenterGlobal(TransInfo *t);
void calculateCenter(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index ccb81c7342b..3063ee22c55 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -46,6 +46,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_rect.h"
#include "BKE_context.h"
@@ -202,7 +203,7 @@ static void axisProjection(TransInfo *t, const float axis[3], const float in[3],
return;
}
- copy_v3_v3(t_con_center, t->con.center);
+ copy_v3_v3(t_con_center, t->center_global);
/* checks for center being too close to the view center */
viewAxisCorrectCenter(t, t_con_center);
@@ -276,7 +277,7 @@ static void planeProjection(TransInfo *t, const float in[3], float out[3])
{
float vec[3], factor, norm[3];
- add_v3_v3v3(vec, in, t->con.center);
+ add_v3_v3v3(vec, in, t->center_global);
getViewVector(t, vec, norm);
sub_v3_v3v3(vec, out, in);
@@ -309,7 +310,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3
mul_m3_v3(t->con.pmtx, out);
// With snap, a projection is alright, no need to correct for view alignment
- if (!(t->tsnap.mode != SCE_SNAP_MODE_INCREMENT && activeSnap(t))) {
+ if (ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) || activeSnap(t)) {
if (getConstraintSpaceDimension(t) == 2) {
if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
planeProjection(t, in, out);
@@ -687,11 +688,11 @@ void drawConstraint(TransInfo *t)
int depth_test_enabled;
convertViewVec(t, vec, (t->mval[0] - t->con.imval[0]), (t->mval[1] - t->con.imval[1]));
- add_v3_v3(vec, tc->center);
+ add_v3_v3(vec, t->center_global);
- drawLine(t, tc->center, tc->mtx[0], 'X', 0);
- drawLine(t, tc->center, tc->mtx[1], 'Y', 0);
- drawLine(t, tc->center, tc->mtx[2], 'Z', 0);
+ drawLine(t, t->center_global, tc->mtx[0], 'X', 0);
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', 0);
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', 0);
glColor3ubv((GLubyte *)col2);
@@ -701,7 +702,7 @@ void drawConstraint(TransInfo *t)
setlinestyle(1);
glBegin(GL_LINE_STRIP);
- glVertex3fv(tc->center);
+ glVertex3fv(t->center_global);
glVertex3fv(vec);
glEnd();
setlinestyle(0);
@@ -711,13 +712,13 @@ void drawConstraint(TransInfo *t)
}
if (tc->mode & CON_AXIS0) {
- drawLine(t, tc->center, tc->mtx[0], 'X', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
}
if (tc->mode & CON_AXIS1) {
- drawLine(t, tc->center, tc->mtx[1], 'Y', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
}
if (tc->mode & CON_AXIS2) {
- drawLine(t, tc->center, tc->mtx[2], 'Z', DRAWLIGHT);
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
}
}
}
@@ -728,7 +729,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
if (t->flag & T_PROP_EDIT) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float tmat[4][4], imat[4][4];
- float center[3];
int depth_test_enabled;
UI_ThemeColor(TH_GRID);
@@ -744,25 +744,21 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glPushMatrix();
- copy_v3_v3(center, t->center);
-
- if ((t->spacetype == SPACE_VIEW3D) && t->obedit) {
- mul_m4_v3(t->obedit->obmat, center); /* because t->center is in local space */
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* pass */
}
else if (t->spacetype == SPACE_IMAGE) {
- float aspx, aspy;
-
- if (t->options & CTX_MASK) {
- /* untested - mask aspect is TODO */
- ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- aspx = aspy = 1.0;
- }
- else {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- }
- glScalef(1.0f / aspx, 1.0f / aspy, 1.0);
+ glScalef(1.0f / t->aspect[0], 1.0f / t->aspect[1], 1.0f);
+ }
+ else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) {
+ /* only scale y */
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+ glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f);
}
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
@@ -770,7 +766,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glDisable(GL_DEPTH_TEST);
set_inverted_drawing(1);
- drawcircball(GL_LINE_LOOP, center, t->prop_size, imat);
+ drawcircball(GL_LINE_LOOP, t->center_global, t->prop_size, imat);
set_inverted_drawing(0);
if (depth_test_enabled)
@@ -961,7 +957,7 @@ static void setNearestAxis3d(TransInfo *t)
mul_v3_fl(axis, zfac);
/* now we can project to get window coordinate */
- add_v3_v3(axis, t->con.center);
+ add_v3_v3(axis, t->center_global);
projectFloatView(t, axis, axis_2d);
sub_v2_v2v2(axis, axis_2d, t->center2d);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index b50f56aae3e..c9e7e085a96 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
@@ -58,6 +59,7 @@
#include "BLI_linklist_stack.h"
#include "BLI_string.h"
#include "BLI_bitmap.h"
+#include "BLI_rect.h"
#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
@@ -340,20 +342,20 @@ static void createTransEdge(TransInfo *t)
BMIter iter;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
int cd_edge_float_offset;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
}
if (countsel == 0)
return;
- if (propmode) {
+ if (is_prop_edit) {
t->total = count;
}
else {
@@ -379,7 +381,7 @@ static void createTransEdge(TransInfo *t)
BLI_assert(cd_edge_float_offset != -1);
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
float *fl_ptr;
/* need to set center for center calculations */
mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
@@ -627,10 +629,10 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
mul_m3_m3m3(td->axismtx, omat, pmat);
normalize_m3(td->axismtx);
- if (t->mode == TFM_BONESIZE) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
bArmature *arm = t->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
td->loc = NULL;
td->val = &bone->dist;
td->ival = bone->dist;
@@ -717,7 +719,7 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob)
/* make sure no bone can be transformed when a parent is transformed */
/* since pchans are depsgraph sorted, the parents are in beginning of list */
- if (mode != TFM_BONESIZE) {
+ if (!ELEM(mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
if (bone->flag & BONE_TRANSFORM)
@@ -1124,7 +1126,7 @@ static void createTransArmatureVerts(TransInfo *t)
oldtot = t->total;
if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (t->mode == TFM_BONESIZE) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
if (ebo->flag & BONE_SELECTED)
t->total++;
}
@@ -1202,9 +1204,9 @@ static void createTransArmatureVerts(TransInfo *t)
}
}
- else if (t->mode == TFM_BONESIZE) {
+ else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
if (ebo->flag & BONE_SELECTED) {
- if (arm->drawtype == ARM_ENVELOPE) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
td->loc = NULL;
td->val = &ebo->dist;
td->ival = ebo->dist;
@@ -1329,18 +1331,18 @@ static void createTransMBallVerts(TransInfo *t)
TransDataExtension *tx;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
/* count totals */
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)");
@@ -1350,7 +1352,7 @@ static void createTransMBallVerts(TransInfo *t)
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (propmode || (ml->flag & SELECT)) {
+ if (is_prop_edit || (ml->flag & SELECT)) {
td->loc = &ml->x;
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
@@ -1463,7 +1465,7 @@ static void createTransCurveVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
ListBase *nurbs;
@@ -1478,13 +1480,13 @@ static void createTransCurveVerts(TransInfo *t)
if (bezt->hide == 0) {
if (hide_handles) {
if (bezt->f2 & SELECT) countsel += 3;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
else {
if (bezt->f1 & SELECT) countsel++;
if (bezt->f2 & SELECT) countsel++;
if (bezt->f3 & SELECT) countsel++;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
}
}
@@ -1492,7 +1494,7 @@ static void createTransCurveVerts(TransInfo *t)
else {
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode) count++;
+ if (is_prop_edit) count++;
if (bp->f1 & SELECT) countsel++;
}
}
@@ -1501,7 +1503,7 @@ static void createTransCurveVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
@@ -1536,7 +1538,7 @@ static void createTransCurveVerts(TransInfo *t)
}
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f1 & SELECT) && hide_handles == 0))
{
@@ -1570,7 +1572,7 @@ static void createTransCurveVerts(TransInfo *t)
}
/* This is the Curve Point, the other two are handles */
- if (propmode || (bezt->f2 & SELECT)) {
+ if (is_prop_edit || (bezt->f2 & SELECT)) {
copy_v3_v3(td->iloc, bezt->vec[1]);
td->loc = bezt->vec[1];
copy_v3_v3(td->center, td->loc);
@@ -1606,7 +1608,7 @@ static void createTransCurveVerts(TransInfo *t)
count++;
tail++;
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f3 & SELECT) && hide_handles == 0))
{
@@ -1643,12 +1645,12 @@ static void createTransCurveVerts(TransInfo *t)
(void)hdata; /* quiet warning */
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
/* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
@@ -1663,7 +1665,7 @@ static void createTransCurveVerts(TransInfo *t)
head = tail = td;
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
copy_v3_v3(td->center, td->loc);
@@ -1688,12 +1690,12 @@ static void createTransCurveVerts(TransInfo *t)
tail++;
}
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1709,14 +1711,14 @@ static void createTransLatticeVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
if (bp->hide == 0) {
if (bp->f1 & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
bp++;
}
@@ -1724,7 +1726,7 @@ static void createTransLatticeVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
@@ -1735,7 +1737,7 @@ static void createTransLatticeVerts(TransInfo *t)
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
if (bp->hide == 0) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
@@ -1776,7 +1778,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
float mat[4][4];
int i, k, transformparticle;
int count = 0, hasselected = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
@@ -1798,7 +1800,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
hasselected = 1;
transformparticle = 1;
}
- else if (propmode)
+ else if (is_prop_edit)
transformparticle = 1;
}
}
@@ -1848,7 +1850,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (key->flag & PEK_SELECT)
td->flag |= TD_SELECTED;
- else if (!propmode)
+ else if (!is_prop_edit)
td->flag |= TD_SKIP;
unit_m3(td->mtx);
@@ -1877,7 +1879,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
tx++;
tail++;
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1893,7 +1895,8 @@ void flushTransParticles(TransInfo *t)
PTCacheEditKey *key;
TransData *td;
float mat[4][4], imat[4][4], co[3];
- int i, k, propmode = t->flag & T_PROP_EDIT;
+ int i, k;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (psys)
psmd = psys_get_modifier(ob, psys);
@@ -1914,7 +1917,7 @@ void flushTransParticles(TransInfo *t)
/* optimization for proportional edit */
- if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
+ if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
copy_v3_v3(key->co, co);
point->flag |= PEP_EDIT_RECALC;
}
@@ -1972,17 +1975,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
int i;
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ float dist;
BM_elem_index_set(v, i); /* set_inline */
BM_elem_flag_disable(v, BM_ELEM_TAG);
if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- dists[i] = FLT_MAX;
+ dist = FLT_MAX;
}
else {
BLI_LINKSTACK_PUSH(queue, v);
-
- dists[i] = 0.0f;
+ dist = 0.0f;
}
+
+ dists[i] = dists_prev[i] = dist;
}
bm->elem_index_dirty &= ~BM_VERT;
}
@@ -1991,55 +1996,77 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
BMVert *v;
LinkNode *lnk;
+ /* this is correct but slow to do each iteration,
+ * instead sync the dist's while clearing BM_ELEM_TAG (below) */
+#if 0
memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
+#endif
while ((v = BLI_LINKSTACK_POP(queue))) {
- /* quick checks */
- bool has_edges = (v->e != NULL);
- bool has_faces = false;
+ BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
/* connected edge-verts */
- if (has_edges) {
- BMIter iter;
- BMEdge *e;
+ if (v->e != NULL) {
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- has_faces |= (BM_edge_is_wire(e) == false);
+ /* would normally use BM_EDGES_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == 0) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) {
+
+ /* edge distance */
+ BMVert *v_other = BM_edge_other_vert(e_iter, v);
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
}
}
- }
- }
- }
-
- /* imaginary edge diagonally across quad */
- if (has_faces) {
- BMIter iter;
- BMLoop *l;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if ((BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0) && (l->f->len == 4)) {
- BMVert *v_other = l->next->next->v;
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
- BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- BLI_LINKSTACK_PUSH(queue_next, v_other);
- }
+ /* face distance */
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ /**
+ * imaginary edge diagonally across quad,
+ * \note, this takes advantage of the rules of winding that we
+ * know 2 or more of a verts edges wont reference the same face twice.
+ * Also, if the edge is hidden, the face will be hidden too.
+ */
+ l_iter_radial = l_first_radial = e_iter->l;
+
+ do {
+ if ((l_iter_radial->v == v) &&
+ (l_iter_radial->f->len == 4) &&
+ (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
+ {
+ BMVert *v_other = l_iter_radial->next->next->v;
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
+ BM_elem_flag_enable(v_other, BM_ELEM_TAG);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
+ }
+ }
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
}
}
- }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
}
}
+
/* clear for the next loop */
for (lnk = queue_next; lnk; lnk = lnk->next) {
- BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG);
+ BMVert *v = lnk->link;
+ const int i = BM_elem_index_get(v);
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ /* keep in sync, avoid having to do full memcpy each iteration */
+ dists_prev[i] = dists[i];
}
BLI_LINKSTACK_SWAP(queue, queue_next);
@@ -2097,7 +2124,7 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r
vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
/* we shouldn't need this, but with incorrect selection flushing
* its possible we have a selected vertex thats not in a face, for now best not crash in that case. */
- fill_vn_i(vert_map, bm->totvert, -1);
+ copy_vn_i(vert_map, bm->totvert, -1);
BM_mesh_elem_table_ensure(bm, htype);
ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
@@ -2257,7 +2284,7 @@ static void createTransEditVerts(TransInfo *t)
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
float *dists = NULL;
int a;
- int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
+ const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
int mirror = 0;
int cd_vert_bweight_offset = -1;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
@@ -2297,7 +2324,7 @@ static void createTransEditVerts(TransInfo *t)
cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
}
- if (propmode) {
+ if (prop_mode) {
unsigned int count = 0;
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
@@ -2308,7 +2335,7 @@ static void createTransEditVerts(TransInfo *t)
t->total = count;
/* allocating scratch arrays */
- if (propmode & T_PROP_CONNECTED)
+ if (prop_mode & T_PROP_CONNECTED)
dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
}
else {
@@ -2330,7 +2357,7 @@ static void createTransEditVerts(TransInfo *t)
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode & T_PROP_CONNECTED) {
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
@@ -2359,7 +2386,7 @@ static void createTransEditVerts(TransInfo *t)
{
mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
- BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode);
+ BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
if (mappedcos)
MEM_freeN(mappedcos);
}
@@ -2384,7 +2411,7 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
&island_info[island_vert_map[a]] : NULL;
float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
@@ -2397,8 +2424,8 @@ static void createTransEditVerts(TransInfo *t)
if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
tob->flag |= TD_SELECTED;
- if (propmode) {
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode) {
+ if (prop_mode & T_PROP_CONNECTED) {
tob->dist = dists[a];
}
else {
@@ -2650,24 +2677,23 @@ void flushTransSeq(TransInfo *t)
/* ********************* UV ****************** */
-static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
+static void UVsToTransData(
+ const float aspect[2], TransData *td, TransData2D *td2d,
+ float *uv, const float *center, bool selected)
{
- float aspx, aspy;
-
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
-
/* uv coords are scaled by aspects. this is needed for rotations and
* proportional editing to be consistent with the stretched uv coords
* that are displayed. this also means that for display and numinput,
* and when the uv coords are flushed, these are converted each time */
- td2d->loc[0] = uv[0] * aspx;
- td2d->loc[1] = uv[1] * aspy;
+ td2d->loc[0] = uv[0] * aspect[0];
+ td2d->loc[1] = uv[1] * aspect[1];
td2d->loc[2] = 0.0f;
td2d->loc2d = uv;
td->flag = 0;
td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
+ copy_v2_v2(td->center, center ? center : td->loc);
+ td->center[2] = 0.0f;
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
@@ -2694,36 +2720,43 @@ static void createTransUVs(bContext *C, TransInfo *t)
ToolSettings *ts = CTX_data_tool_settings(C);
TransData *td = NULL;
TransData2D *td2d = NULL;
- MTexPoly *tf;
- MLoopUV *luv;
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMFace *efa;
- BMLoop *l;
BMIter iter, liter;
UvElementMap *elementmap = NULL;
BLI_bitmap *island_enabled = NULL;
+ struct { float co[2]; int co_num; } *island_center = NULL;
int count = 0, countsel = 0, count_rejected = 0;
- const bool propmode = (t->flag & T_PROP_EDIT) != 0;
- const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0;
-
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
+ const bool is_island_center = (t->around == V3D_LOCAL);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
- if (!ED_space_image_show_uvedit(sima, t->obedit)) return;
+ if (!ED_space_image_show_uvedit(sima, t->obedit))
+ return;
/* count */
- if (propconnected) {
+ if (is_prop_connected || is_island_center) {
/* create element map with island information */
- if (ts->uv_flag & UV_SYNC_SELECTION) {
- elementmap = BM_uv_element_map_create(em->bm, false, true);
+ const bool use_facesel = (ts->uv_flag & UV_SYNC_SELECTION) == 0;
+ elementmap = BM_uv_element_map_create(em->bm, use_facesel, false, true);
+ if (elementmap == NULL) {
+ return;
}
- else {
- elementmap = BM_uv_element_map_create(em->bm, true, true);
+
+ if (is_prop_connected) {
+ island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
+ }
+
+ if (is_island_center) {
+ island_center = MEM_callocN(sizeof(*island_center) * elementmap->totalIslands, __func__);
}
- island_enabled = BLI_BITMAP_NEW(elementmap->totalIslands, "TransIslandData(UV Editing)");
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+ BMLoop *l;
if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
@@ -2735,14 +2768,25 @@ static void createTransUVs(bContext *C, TransInfo *t)
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
countsel++;
- if (propconnected) {
+ if (is_prop_connected || island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
- BLI_BITMAP_ENABLE(island_enabled, element->island);
- }
+ if (is_prop_connected) {
+ BLI_BITMAP_ENABLE(island_enabled, element->island);
+ }
+
+ if (is_island_center) {
+ if (element->flag == false) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(island_center[element->island].co, luv->uv);
+ island_center[element->island].co_num++;
+ element->flag = true;
+ }
+ }
+ }
}
- if (propmode) {
+ if (is_prop_edit) {
count++;
}
}
@@ -2750,13 +2794,19 @@ static void createTransUVs(bContext *C, TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) {
- if (propconnected) {
- MEM_freeN(island_enabled);
+ goto finally;
+ }
+
+ if (is_island_center) {
+ int i;
+
+ for (i = 0; i < elementmap->totalIslands; i++) {
+ mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
+ mul_v2_v2(island_center[i].co, t->aspect);
}
- return;
}
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -2769,56 +2819,88 @@ static void createTransUVs(bContext *C, TransInfo *t)
td2d = t->data2d;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l;
+
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
+ const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ MLoopUV *luv;
+ const float *center = NULL;
+
+ if (!is_prop_edit && !selected)
continue;
- if (propconnected) {
+ if (is_prop_connected || is_island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
- if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
- count_rejected++;
- continue;
+
+ if (is_prop_connected) {
+ if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
+ count_rejected++;
+ continue;
+ }
+ }
+
+ if (is_island_center) {
+ center = island_center[element->island].co;
}
}
+ BM_elem_flag_enable(l, BM_ELEM_TAG);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
+ UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, selected);
}
}
- if (propconnected) {
+ if (is_prop_connected) {
t->total -= count_rejected;
- BM_uv_element_map_free(elementmap);
- MEM_freeN(island_enabled);
}
if (sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
+
+
+finally:
+ if (is_prop_connected || is_island_center) {
+ BM_uv_element_map_free(elementmap);
+
+ if (is_prop_connected) {
+ MEM_freeN(island_enabled);
+ }
+
+ if (island_center) {
+ MEM_freeN(island_center);
+ }
+ }
}
void flushTransUVs(TransInfo *t)
{
SpaceImage *sima = t->sa->spacedata.first;
TransData2D *td;
- int a, width, height;
- float aspx, aspy, invx, invy;
+ int a;
+ float aspect_inv[2], size[2];
+ const bool use_pixel_snap = ((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL));
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- ED_space_image_get_size(sima, &width, &height);
- invx = 1.0f / aspx;
- invy = 1.0f / aspy;
+ aspect_inv[0] = 1.0f / t->aspect[0];
+ aspect_inv[1] = 1.0f / t->aspect[1];
+
+ if (use_pixel_snap) {
+ int size_i[2];
+ ED_space_image_get_size(sima, &size_i[0], &size_i[1]);
+ size[0] = size_i[0];
+ size[1] = size_i[1];
+ }
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data2d; a < t->total; a++, td++) {
- td->loc2d[0] = td->loc[0] * invx;
- td->loc2d[1] = td->loc[1] * invy;
+ td->loc2d[0] = td->loc[0] * aspect_inv[0];
+ td->loc2d[1] = td->loc[1] * aspect_inv[1];
- if ((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
- td->loc2d[0] = roundf(width * td->loc2d[0]) / width;
- td->loc2d[1] = roundf(height * td->loc2d[1]) / height;
+ if (use_pixel_snap) {
+ td->loc2d[0] = roundf(td->loc2d[0] * size[0]) / size[0];
+ td->loc2d[1] = roundf(td->loc2d[1] * size[1]) / size[1];
}
}
}
@@ -2826,44 +2908,45 @@ void flushTransUVs(TransInfo *t)
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
TransData *td;
- int a, clipx = 1, clipy = 1;
- float aspx, aspy, min[2], max[2];
+ int a;
+ bool clipx = true, clipy = true;
+ float min[2], max[2];
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
min[0] = min[1] = 0.0f;
- max[0] = aspx; max[1] = aspy;
+ max[0] = t->aspect[0];
+ max[1] = t->aspect[1];
for (a = 0, td = t->data; a < t->total; a++, td++) {
minmax_v2v2_v2(min, max, td->loc);
}
if (resize) {
- if (min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx * 0.5f)
+ if (min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < t->aspect[0] * 0.5f)
vec[0] *= t->center[0] / (t->center[0] - min[0]);
- else if (max[0] > aspx && t->center[0] < aspx)
- vec[0] *= (t->center[0] - aspx) / (t->center[0] - max[0]);
+ else if (max[0] > t->aspect[0] && t->center[0] < t->aspect[0])
+ vec[0] *= (t->center[0] - t->aspect[0]) / (t->center[0] - max[0]);
else
clipx = 0;
- if (min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy * 0.5f)
+ if (min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < t->aspect[1] * 0.5f)
vec[1] *= t->center[1] / (t->center[1] - min[1]);
- else if (max[1] > aspy && t->center[1] < aspy)
- vec[1] *= (t->center[1] - aspy) / (t->center[1] - max[1]);
+ else if (max[1] > t->aspect[1] && t->center[1] < t->aspect[1])
+ vec[1] *= (t->center[1] - t->aspect[1]) / (t->center[1] - max[1]);
else
clipy = 0;
}
else {
if (min[0] < 0.0f)
vec[0] -= min[0];
- else if (max[0] > aspx)
- vec[0] -= max[0] - aspx;
+ else if (max[0] > t->aspect[0])
+ vec[0] -= max[0] - t->aspect[0];
else
clipx = 0;
if (min[1] < 0.0f)
vec[1] -= min[1];
- else if (max[1] > aspy)
- vec[1] -= max[1] - aspy;
+ else if (max[1] > t->aspect[1])
+ vec[1] -= max[1] - t->aspect[1];
else
clipy = 0;
}
@@ -2875,9 +2958,6 @@ void clipUVData(TransInfo *t)
{
TransData *td = NULL;
int a;
- float aspx, aspy;
-
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
for (a = 0, td = t->data; a < t->total; a++, td++) {
if (td->flag & TD_NOACTION)
@@ -2886,8 +2966,8 @@ void clipUVData(TransInfo *t)
if ((td->flag & TD_SKIP) || (!td->loc))
continue;
- td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), aspx);
- td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), aspy);
+ td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
+ td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
}
}
@@ -3161,7 +3241,7 @@ static void posttrans_gpd_clean(bGPdata *gpd)
bGPDframe *gpf, *gpfn;
bool is_double = false;
- BLI_listbase_sort_r(&gpl->frames, &is_double, gpf_cmp_frame);
+ BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
if (is_double) {
for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
@@ -3188,7 +3268,7 @@ static void posttrans_mask_clean(Mask *mask)
MaskLayerShape *masklay_shape, *masklay_shape_next;
bool is_double = false;
- BLI_listbase_sort_r(&masklay->splines_shapes, &is_double, masklay_shape_cmp_frame);
+ BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
if (is_double) {
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
@@ -3304,76 +3384,90 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
/* ----------------------------- */
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
+static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit)
{
BezTriple *bezt;
- int i, count = 0;
+ int i, count = 0, count_all = 0;
if (ELEM(NULL, fcu, fcu->bezt))
return count;
/* only include points that occur on the right side of cfra */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (bezt->f2 & SELECT) {
+ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
/* no need to adjust the handle selection since they are assumed
* selected (like graph editor with SIPO_NOHANDLES) */
- if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- count += 1;
- }
+ if (bezt->f2 & SELECT)
+ count++;
+
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
+static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit)
{
bGPDframe *gpf;
- int count = 0;
+ int count = 0, count_all = 0;
if (gpl == NULL)
return count;
/* only include points that occur on the right side of cfra */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
- if (FrameOnMouseSide(side, (float)gpf->framenum, cfra))
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ if (gpf->flag & GP_FRAME_SELECT)
count++;
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra)
+static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit)
{
MaskLayerShape *masklayer_shape;
- int count = 0;
+ int count = 0, count_all = 0;
if (masklay == NULL)
return count;
/* only include points that occur on the right side of cfra */
for (masklayer_shape = masklay->splines_shapes.first; masklayer_shape; masklayer_shape = masklayer_shape->next) {
- if (masklayer_shape->flag & MASK_SHAPE_SELECT) {
- if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra))
+ if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
+ if (masklayer_shape->flag & MASK_SHAPE_SELECT)
count++;
+ count_all++;
}
}
- return count;
+ if (is_prop_edit && count > 0)
+ return count_all;
+ else
+ return count;
}
/* This function assigns the information to transdata */
-static void TimeToTransData(TransData *td, float *time, AnimData *adt)
+static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypos)
{
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = time;
td->ival = *(time);
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
/* store the AnimData where this keyframe exists as a keyframe of the
* active action as td->extra.
*/
@@ -3387,7 +3481,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra)
+static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos)
{
BezTriple *bezt;
TransData2D *td2d = *td2dv;
@@ -3398,11 +3492,14 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* only add selected keyframes (for now, proportional edit is not enabled) */
- if (bezt->f2 & SELECT) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */
+ if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */
/* only add if on the right 'side' of the current frame */
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
- TimeToTransData(td, bezt->vec[1], adt);
+ TimeToTransData(td, bezt->vec[1], adt, ypos);
+ if (bezt->f2 & SELECT)
+ td->flag |= TD_SELECTED;
+
/*set flags to move handles as necessary*/
td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2;
td2d->h1 = bezt->vec[0];
@@ -3453,19 +3550,22 @@ void flushTransIntFrameActionData(TransInfo *t)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra)
+static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos)
{
bGPDframe *gpf;
int count = 0;
/* check for select frames on right side of current frame */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (gpf->flag & GP_FRAME_SELECT) {
+ if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) {
if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
td->ival = (float)gpf->framenum;
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
tfd->val = (float)gpf->framenum;
tfd->sdata = &gpf->framenum;
@@ -3481,19 +3581,22 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl,
}
/* refer to comment above #GPLayerToTransData, this is the same but for masks */
-static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra)
+static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos)
{
MaskLayerShape *masklay_shape;
int count = 0;
/* check for select frames on right side of current frame */
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
td->ival = (float)masklay_shape->frame;
+ td->center[0] = td->ival;
+ td->center[1] = ypos;
+
tfd->val = (float)masklay_shape->frame;
tfd->sdata = &masklay_shape->frame;
@@ -3515,15 +3618,25 @@ static void createTransActionData(bContext *C, TransInfo *t)
TransData *td = NULL;
TransData2D *td2d = NULL;
tGPFtransdata *tfd = NULL;
-
+
+ rcti *mask = &t->ar->v2d.mask;
+ rctf *datamask = &t->ar->v2d.cur;
+
+ float xsize = BLI_rctf_size_x(datamask);
+ float ysize = BLI_rctf_size_y(datamask);
+ float xmask = BLI_rcti_size_x(mask);
+ float ymask = BLI_rcti_size_y(mask);
+
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
int count = 0;
float cfra;
-
+ float ypos = 1.0f / ((ysize / xsize) * (xmask / ymask)) * BLI_rctf_cent_y(&t->ar->v2d.cur);
+
/* determine what type of data we are operating on */
if (ANIM_animdata_get_context(C, &ac) == 0)
return;
@@ -3551,7 +3664,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
/* loop 1: fully select ipo-keys and count how many BezTriples are selected */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
-
+ int adt_count = 0;
/* convert current-frame to action-time (slightly less accurate, especially under
* higher scaling ratios, but is faster than converting all points)
*/
@@ -3560,14 +3673,19 @@ static void createTransActionData(bContext *C, TransInfo *t)
else
cfra = (float)CFRA;
- if (ale->type == ANIMTYPE_FCURVE)
- count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
+ if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
+ adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_GPLAYER)
- count += count_gplayer_frames(ale->data, t->frame_side, cfra);
+ adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_MASKLAYER)
- count += count_masklayer_frames(ale->data, t->frame_side, cfra);
+ adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else
BLI_assert(0);
+
+ if (adt_count > 0) {
+ count += adt_count;
+ ale->tag = true;
+ }
}
/* stop if trying to build list if nothing selected */
@@ -3604,11 +3722,22 @@ static void createTransActionData(bContext *C, TransInfo *t)
/* loop 2: build transdata array */
for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt;
+
+ if (is_prop_edit && !ale->tag)
+ continue;
+
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
if (ale->type == ANIMTYPE_GPLAYER) {
bGPDlayer *gpl = (bGPDlayer *)ale->data;
int i;
- i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra);
+ i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3616,7 +3745,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
MaskLayer *masklay = (MaskLayer *)ale->data;
int i;
- i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra);
+ i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3624,15 +3753,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- /* convert current-frame to action-time (slightly less accurate, especially under
- * higher scaling ratios, but is faster than converting all points)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
-
- td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra);
+ td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
}
}
@@ -3661,6 +3782,109 @@ static void createTransActionData(bContext *C, TransInfo *t)
*((float *)(t->customData) + 1) = max;
}
+ /* calculate distances for proportional editing */
+ if (is_prop_edit) {
+ td = t->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt;
+
+ /* F-Curve may not have any keyframes */
+ if (!ale->tag)
+ continue;
+
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ bGPDframe *gpf;
+
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (gpf->flag & GP_FRAME_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ bGPDframe *gpf_iter;
+ int min = INT_MAX;
+ for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) {
+ if (gpf_iter->flag & GP_FRAME_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) {
+ int val = abs(gpf->framenum - gpf_iter->framenum);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ MaskLayerShape *masklay_shape;
+
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_shape->frame, cfra)) {
+ if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ MaskLayerShape *masklay_iter;
+ int min = INT_MAX;
+ for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) {
+ if (masklay_iter->flag & MASK_SHAPE_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) {
+ int val = abs(masklay_shape->frame - masklay_iter->frame);
+ if (val < min) {
+ min = val;
+ }
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ else {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ BezTriple *bezt;
+ int i;
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ if (bezt->f2 & SELECT) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ BezTriple *bezt_iter;
+ int j;
+ float min = FLT_MAX;
+ for (j = 0, bezt_iter = fcu->bezt; j < fcu->totvert; j++, bezt_iter++) {
+ if (bezt_iter->f2 & SELECT) {
+ if (FrameOnMouseSide(t->frame_side, (float)bezt_iter->vec[1][0], cfra)) {
+ float val = fabs(bezt->vec[1][0] - bezt_iter->vec[1][0]);
+ if (val < min)
+ min = val;
+ }
+ }
+ }
+ td->dist = td->rdist = min;
+ }
+ td++;
+ }
+ }
+ }
+ }
+ }
+
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
}
@@ -3669,6 +3893,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
typedef struct TransDataGraph {
float unit_scale;
+ float offset;
} TransDataGraph;
/* Helper function for createTransGraphEditData, which is responsible for associating
@@ -3677,7 +3902,7 @@ typedef struct TransDataGraph {
static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg,
AnimData *adt, BezTriple *bezt,
int bi, bool selected, bool ishandle, bool intvals,
- float mtx[3][3], float smtx[3][3], float unit_scale)
+ float mtx[3][3], float smtx[3][3], float unit_scale, float offset)
{
float *loc = bezt->vec[bi];
const float *cent = bezt->vec[1];
@@ -3691,26 +3916,26 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
if (adt) {
td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
- td2d->loc[1] = loc[1] * unit_scale;
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
td2d->loc[2] = 0.0f;
td2d->loc2d = loc;
td->loc = td2d->loc;
td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
- td->center[1] = cent[1] * unit_scale;
+ td->center[1] = (cent[1] + offset) * unit_scale;
td->center[2] = 0.0f;
copy_v3_v3(td->iloc, td->loc);
}
else {
td2d->loc[0] = loc[0];
- td2d->loc[1] = loc[1] * unit_scale;
+ td2d->loc[1] = (loc[1] + offset) * unit_scale;
td2d->loc[2] = 0.0f;
td2d->loc2d = loc;
td->loc = td2d->loc;
copy_v3_v3(td->center, cent);
- td->center[1] *= unit_scale;
+ td->center[1] = (td->center[1] + offset) * unit_scale;
copy_v3_v3(td->iloc, td->loc);
}
@@ -3750,6 +3975,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
copy_m3_m3(td->smtx, smtx);
tdg->unit_scale = unit_scale;
+ tdg->offset = offset;
}
static bool graph_edit_is_translation_mode(TransInfo *t)
@@ -3762,6 +3988,29 @@ static bool graph_edit_use_local_center(TransInfo *t)
return (t->around == V3D_LOCAL) && !graph_edit_is_translation_mode(t);
}
+
+static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
+{
+ int j = 0;
+ TransData *td_iter = td_start;
+
+ td->dist = FLT_MAX;
+ for (; j < fcu->totvert; j++) {
+ BezTriple *bezt = fcu->bezt + j;
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (sel1 || sel2 || sel3) {
+ td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
+ }
+
+ td_iter += 3;
+ }
+ }
+}
+
static void createTransGraphEditData(bContext *C, TransInfo *t)
{
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
@@ -3784,6 +4033,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
const bool is_translation_mode = graph_edit_is_translation_mode(t);
const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
const bool use_local_center = graph_edit_use_local_center(t);
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
/* determine what type of data we are operating on */
@@ -3815,6 +4065,8 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float cfra;
+ int curvecount = 0;
+ bool selected = false;
/* F-Curve may not have any keyframes */
if (fcu->bezt == NULL)
@@ -3835,20 +4087,34 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- count++;
+ if (is_prop_edit) {
+ curvecount += 3;
+ if (sel2 || sel1 || sel3)
+ selected = true;
+ }
+ else {
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ count++;
+ }
+
+ if (sel3) {
+ count++;
+ }
}
- if (sel3) {
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
count++;
}
}
+ }
+ }
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- count++;
- }
+ if (is_prop_edit) {
+ if (selected) {
+ count += curvecount;
+ ale->tag = true;
}
}
}
@@ -3897,11 +4163,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
- float unit_scale;
+ float unit_scale, offset;
float cfra;
/* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL)
+ if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0))
continue;
/* convert current-frame to action-time (slightly less accurate, especially under
@@ -3912,7 +4178,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
else
cfra = (float)CFRA;
- unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag);
+ unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
@@ -3924,66 +4190,135 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
TransDataCurveHandleFlags *hdata = NULL;
/* short h1=1, h2=1; */ /* UNUSED */
- /* only include handles if selected, irrespective of the interpolation modes.
- * also, only treat handles specially if the center point isn't selected.
- */
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale);
+ if (is_prop_edit) {
+ bool is_sel = (sel2 || sel1 || sel3);
+ /* we always select all handles for proportional editing if central handle is selected */
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale, offset);
+ initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* only include handles if selected, irrespective of the interpolation modes.
+ * also, only treat handles specially if the center point isn't selected.
+ */
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* h1 = 0; */ /* UNUSED */
+ }
+
+ if (sel3) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale, offset);
+ }
+ else {
+ /* h2 = 0; */ /* UNUSED */
+ }
}
- else {
- /* h1 = 0; */ /* UNUSED */
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ /* move handles relative to center */
+ if (is_translation_mode) {
+ if (sel1) td->flag |= TD_MOVEHANDLE1;
+ if (sel3) td->flag |= TD_MOVEHANDLE2;
+ }
+
+ /* if handles were not selected, store their selection status */
+ if (!(sel1) || !(sel3)) {
+ if (hdata == NULL)
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale, offset);
+
}
-
- if (sel3) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale);
+ /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
+ * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
+ * then check if we're using auto-handles.
+ * - If so, change them auto-handles to aligned handles so that handles get affected too
+ */
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) &&
+ ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
+ ELEM(t->mode, TFM_ROTATION, TFM_RESIZE))
+ {
+ if (hdata && (sel1) && (sel3)) {
+ bezt->h1 = HD_ALIGN;
+ bezt->h2 = HD_ALIGN;
+ }
+ }
+ }
+ }
+ }
+
+ /* Sets handles based on the selection */
+ testhandles_fcurve(fcu, use_handle);
+ }
+
+ if (is_prop_edit) {
+ /* loop 2: build transdata arrays */
+ td = t->data;
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ TransData *td_start = td;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (ale->tag == 0))
+ continue;
+
+ /* convert current-frame to action-time (slightly less accurate, especially under
+ * higher scaling ratios, but is faster than converting all points)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
+ const bool sel2 = (bezt->f2 & SELECT) != 0;
+ const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
+ const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
+
+ if (sel1 || sel2) {
+ td->dist = td->rdist = 0.0f;
}
else {
- /* h2 = 0; */ /* UNUSED */
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
- }
-
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- /* move handles relative to center */
- if (is_translation_mode) {
- if (sel1) td->flag |= TD_MOVEHANDLE1;
- if (sel3) td->flag |= TD_MOVEHANDLE2;
+ td++;
+
+ if (sel2) {
+ td->dist = td->rdist = 0.0f;
}
-
- /* if handles were not selected, store their selection status */
- if (!(sel1) || !(sel3)) {
- if (hdata == NULL)
- hdata = initTransDataCurveHandles(td, bezt);
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
-
- bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale);
-
- }
- /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
- * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
- * then check if we're using auto-handles.
- * - If so, change them auto-handles to aligned handles so that handles get affected too
- */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
- ELEM(t->mode, TFM_ROTATION, TFM_RESIZE))
- {
- if (hdata && (sel1) && (sel3)) {
- bezt->h1 = HD_ALIGN;
- bezt->h2 = HD_ALIGN;
+ td++;
+
+ if (sel3 || sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
}
+ td++;
}
}
}
-
- /* Sets handles based on the selection */
- testhandles_fcurve(fcu, use_handle);
}
-
+
/* cleanup temp list */
ANIM_animdata_freelist(&anim_data);
}
@@ -4267,7 +4602,7 @@ void flushTransGraphData(TransInfo *t)
if (td->flag & TD_INTVALUES)
td2d->loc2d[1] = floorf(td2d->loc[1] + 0.5f);
else
- td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale;
+ td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
@@ -5080,7 +5415,9 @@ static void set_trans_object_base_flags(TransInfo *t)
}
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
+#ifdef WITH_LEGACY_DEPSGRAPH
DAG_scene_flush_update(G.main, t->scene, -1, 0);
+#endif
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
@@ -5157,7 +5494,9 @@ static int count_proportional_objects(TransInfo *t)
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
DAG_scene_relations_update(G.main, t->scene);
+#ifdef WITH_LEGACY_DEPSGRAPH
DAG_scene_flush_update(G.main, t->scene, -1, 0);
+#endif
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
@@ -6039,7 +6378,7 @@ static void createTransObject(bContext *C, TransInfo *t)
TransData *td = NULL;
TransDataExtension *tx;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
set_trans_object_base_flags(t);
@@ -6052,7 +6391,7 @@ static void createTransObject(bContext *C, TransInfo *t)
return;
}
- if (propmode) {
+ if (is_prop_edit) {
t->total += count_proportional_objects(t);
}
@@ -6085,7 +6424,7 @@ static void createTransObject(bContext *C, TransInfo *t)
}
CTX_DATA_END;
- if (propmode) {
+ if (is_prop_edit) {
View3D *v3d = t->view;
Base *base;
@@ -6239,22 +6578,22 @@ typedef struct TransDataTracking {
static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int area, float loc[2], float rel[2], const float off[2], float aspx, float aspy)
+ int area, float loc[2], float rel[2], const float off[2], const float aspect[2])
{
int anchor = area == TRACK_AREA_POINT && off;
tdt->mode = transDataTracking_ModeTracks;
if (anchor) {
- td2d->loc[0] = rel[0] * aspx; /* hold original location */
- td2d->loc[1] = rel[1] * aspy;
+ td2d->loc[0] = rel[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = rel[1] * aspect[1];
tdt->loc = loc;
td2d->loc2d = loc; /* current location */
}
else {
- td2d->loc[0] = loc[0] * aspx; /* hold original location */
- td2d->loc[1] = loc[1] * aspy;
+ td2d->loc[0] = loc[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = loc[1] * aspect[1];
td2d->loc2d = loc; /* current location */
}
@@ -6269,8 +6608,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
if (rel) {
if (!anchor) {
- td2d->loc[0] += rel[0] * aspx;
- td2d->loc[1] += rel[1] * aspy;
+ td2d->loc[0] += rel[0] * aspect[0];
+ td2d->loc[1] += rel[1] * aspect[1];
}
copy_v2_v2(tdt->srelative, rel);
@@ -6285,8 +6624,8 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
//copy_v3_v3(td->center, td->loc);
td->flag |= TD_INDIVIDUAL_SCALE;
- td->center[0] = marker->pos[0] * aspx;
- td->center[1] = marker->pos[1] * aspy;
+ td->center[0] = marker->pos[0] * aspect[0];
+ td->center[1] = marker->pos[1] * aspect[1];
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
@@ -6301,8 +6640,9 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
unit_m3(td->smtx);
}
-static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy)
+static void trackToTransData(
+ const int framenr, TransData *td, TransData2D *td2d,
+ TransDataTracking *tdt, MovieTrackingTrack *track, const float aspect[2])
{
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
@@ -6310,11 +6650,11 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- track->offset, marker->pos, track->offset, aspx, aspy);
+ track->offset, marker->pos, track->offset, aspect);
if (track->flag & SELECT) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- marker->pos, NULL, NULL, aspx, aspy);
+ marker->pos, NULL, NULL, aspect);
}
if (track->pat_flag & SELECT) {
@@ -6322,28 +6662,28 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
for (a = 0; a < 4; a++) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT,
- marker->pattern_corners[a], marker->pos, NULL, aspx, aspy);
+ marker->pattern_corners[a], marker->pos, NULL, aspect);
}
}
if (track->search_flag & SELECT) {
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_min, marker->pos, NULL, aspx, aspy);
+ marker->search_min, marker->pos, NULL, aspect);
markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_max, marker->pos, NULL, aspx, aspy);
+ marker->search_max, marker->pos, NULL, aspect);
}
}
static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
MovieTrackingPlaneTrack *plane_track, float corner[2],
- float aspx, float aspy)
+ const float aspect[2])
{
tdt->mode = transDataTracking_ModePlaneTracks;
tdt->plane_track = plane_track;
- td2d->loc[0] = corner[0] * aspx; /* hold original location */
- td2d->loc[1] = corner[1] * aspy;
+ td2d->loc[0] = corner[0] * aspect[0]; /* hold original location */
+ td2d->loc[1] = corner[1] * aspect[1];
td2d->loc2d = corner; /* current location */
td2d->loc[2] = 0.0f;
@@ -6368,7 +6708,7 @@ static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDa
static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
- float aspx, float aspy)
+ const float aspect[2])
{
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
int i;
@@ -6377,7 +6717,7 @@ static void planeTrackToTransData(const int framenr, TransData *td, TransData2D
plane_marker->flag &= ~PLANE_MARKER_TRACKED;
for (i = 0; i < 4; i++) {
- planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspx, aspy);
+ planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
}
}
@@ -6406,7 +6746,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
MovieTrackingPlaneTrack *plane_track;
TransDataTracking *tdt;
int framenr = ED_space_clip_get_clip_frame_number(sc);
- float aspx, aspy;
/* count */
t->total = 0;
@@ -6441,8 +6780,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
if (t->total == 0)
return;
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
-
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransTracking TransData");
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransTracking TransData2D");
tdt = t->customData = MEM_callocN(t->total * sizeof(TransDataTracking), "TransTracking TransDataTracking");
@@ -6453,7 +6790,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = tracksbase->first;
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- trackToTransData(framenr, td, td2d, tdt, track, aspx, aspy);
+ trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
/* offset */
td++;
@@ -6487,7 +6824,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
plane_track = plane_track->next)
{
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- planeTrackToTransData(framenr, td, td2d, tdt, plane_track, aspx, aspy);
+ planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
td += 4;
td2d += 4;
tdt += 4;
@@ -6699,14 +7036,10 @@ static void cancelTransTracking(TransInfo *t)
void flushTransTracking(TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
TransData *td;
TransData2D *td2d;
TransDataTracking *tdt;
int a;
- float aspx, aspy;
-
- ED_space_clip_get_aspect_dimension_aware(sc, &aspx, &aspy);
if (t->state == TRANS_CANCEL)
cancelTransTracking(t);
@@ -6720,8 +7053,8 @@ void flushTransTracking(TransInfo *t)
continue;
}
- loc2d[0] = td2d->loc[0] / aspx;
- loc2d[1] = td2d->loc[1] / aspy;
+ loc2d[0] = td2d->loc[0] / t->aspect[0];
+ loc2d[1] = td2d->loc[1] / t->aspect[1];
if (t->flag & T_ALT_TRANSFORM) {
if (t->mode == TFM_RESIZE) {
@@ -6763,8 +7096,8 @@ void flushTransTracking(TransInfo *t)
td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
}
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
- td2d->loc2d[0] = td2d->loc[0] / aspx;
- td2d->loc2d[1] = td2d->loc[1] / aspy;
+ td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
+ td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
}
}
}
@@ -6842,9 +7175,10 @@ static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which
}
}
-static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
- const int propmode, const float asp[2])
+static void MaskPointToTransData(
+ Scene *scene, MaskSplinePoint *point,
+ TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+ const bool is_prop_edit, const float asp[2])
{
BezTriple *bezt = &point->bezt;
const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point);
@@ -6854,7 +7188,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
invert_m3_m3(parent_inverse_matrix, parent_matrix);
- if (propmode || is_sel_point) {
+ if (is_prop_edit || is_sel_point) {
int i;
tdm->point = point;
@@ -6974,7 +7308,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
TransData2D *td2d = NULL;
TransDataMasking *tdm = NULL;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT);
float asp[2];
t->total = 0;
@@ -7024,7 +7358,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
}
}
- if (propmode)
+ if (is_prop_edit)
count += 3;
}
}
@@ -7037,7 +7371,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mask Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -7060,10 +7394,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
- if (propmode || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp);
+ if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
+ MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
- if (propmode || MASKPOINT_ISSEL_KNOT(point)) {
+ if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
td += 3;
td2d += 3;
tdm += 3;
@@ -7306,8 +7640,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
const Scene *scene = CTX_data_scene(C);
const int cfra = CFRA;
- const int propedit = (t->flag & T_PROP_EDIT);
- const int propedit_connected = (t->flag & T_PROP_CONNECTED);
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
/* == Grease Pencil Strokes to Transform Data ==
@@ -7338,9 +7672,9 @@ static void createTransGPencil(bContext *C, TransInfo *t)
continue;
}
- if (propedit) {
+ if (is_prop_edit) {
/* Proportional Editing... */
- if (propedit_connected) {
+ if (is_prop_edit_connected) {
/* connected only - so only if selected */
if (gps->flag & GP_STROKE_SELECT)
t->total += gps->totpoints;
@@ -7447,8 +7781,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
}
/* What we need to include depends on proportional editing settings... */
- if (propedit) {
- if (propedit_connected) {
+ if (is_prop_edit) {
+ if (is_prop_edit_connected) {
/* A) "Connected" - Only those in selected strokes */
stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
}
@@ -7467,7 +7801,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bGPDspoint *pt;
int i;
-#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or propedit breaks */
+#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */
const float ninv = 1.0f / gps->totpoints;
float center[3] = {0.0f};
@@ -7482,7 +7816,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bool point_ok;
/* include point? */
- if (propedit) {
+ if (is_prop_edit) {
/* Always all points in strokes that get included */
point_ok = true;
}
@@ -7525,7 +7859,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
}
/* March over these points, and calculate the proportional editing distances */
- if (propedit && (head != tail)) {
+ if (is_prop_edit && (head != tail)) {
/* XXX: for now, we are similar enough that this works... */
calc_distanceCurveVerts(head, tail - 1);
}
@@ -7594,6 +7928,12 @@ void createTransData(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_ACTION) {
t->flag |= T_POINTS | T_2D_EDIT;
createTransActionData(C, t);
+
+ if (t->data && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ //set_prop_dist(t, false); /* don't do that, distance has been set in createTransActionData already */
+ sort_trans_data_dist(t);
+ }
}
else if (t->spacetype == SPACE_NLA) {
t->flag |= T_POINTS | T_2D_EDIT;
@@ -7607,13 +7947,12 @@ void createTransData(bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_IPO) {
t->flag |= T_POINTS | T_2D_EDIT;
createTransGraphEditData(C, t);
-#if 0
+
if (t->data && (t->flag & T_PROP_EDIT)) {
sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
+ set_prop_dist(t, false); /* don't do that, distance has been set in createTransGraphEditData already */
sort_trans_data_dist(t);
}
-#endif
}
else if (t->spacetype == SPACE_NODE) {
t->flag |= T_POINTS | T_2D_EDIT;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 5f02fa1b05f..90c806a2d05 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -80,6 +80,7 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
+#include "BKE_utildefines.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -808,10 +809,14 @@ static void recalcData_objects(TransInfo *t)
ebo->rad_head *= ebo->length / ebo->oldlength;
ebo->rad_tail *= ebo->length / ebo->oldlength;
ebo->oldlength = ebo->length;
+
+ if (ebo_parent) {
+ ebo_parent->rad_tail = ebo->rad_head;
+ }
}
}
- if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
+ if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
/* fix roll */
for (i = 0; i < t->total; i++, td++) {
if (td->extra) {
@@ -1065,6 +1070,8 @@ static int initTransInfo_edit_pet_to_flag(const int proportional)
* Setup internal data, mouse, vectors
*
* \note \a op and \a event can be NULL
+ *
+ * \see #saveTransform does the reverse.
*/
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
@@ -1121,6 +1128,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
zero_v3(t->vec);
zero_v3(t->center);
+ zero_v3(t->center_global);
unit_m3(t->mat);
@@ -1156,6 +1164,19 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->spacetype = sa->spacetype;
}
+ /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
+ if (op) {
+ const char *prop_id = NULL;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ }
+
+ if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) &&
+ RNA_property_is_set(op->ptr, prop))
+ {
+ BKE_BIT_TEST_SET(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
+ }
+ }
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = sa->spacedata.first;
@@ -1316,7 +1337,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* use settings from scene only if modal */
if (t->flag & T_MODAL) {
if ((t->options & CTX_NO_PET) == 0) {
- if (t->obedit) {
+ if (t->spacetype == SPACE_IPO) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
+ }
+ else if (t->obedit) {
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
}
else if (t->options & CTX_GPENCIL_STROKES) {
@@ -1375,6 +1402,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
#endif
setTransformViewMatrices(t);
+ setTransformViewAspect(t, t->aspect);
initNumInput(&t->num);
}
@@ -1541,6 +1569,19 @@ void calculateCenter2D(TransInfo *t)
}
}
+void calculateCenterGlobal(TransInfo *t)
+{
+ /* setting constraint center */
+ /* note, init functions may over-ride t->center */
+ if (t->flag & (T_EDIT | T_POSE)) {
+ Object *ob = t->obedit ? t->obedit : t->poseobj;
+ mul_v3_m4v3(t->center_global, ob->obmat, t->center);
+ }
+ else {
+ copy_v3_v3(t->center_global, t->center);
+ }
+}
+
void calculateCenterCursor(TransInfo *t, float r_center[3])
{
const float *cursor;
@@ -1569,30 +1610,17 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
{
- float aspx = 1.0, aspy = 1.0;
const float *cursor = NULL;
if (t->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- if (t->options & CTX_MASK) {
- ED_space_image_get_aspect(sima, &aspx, &aspy);
- }
- else {
- ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
- }
cursor = sima->cursor;
}
else if (t->spacetype == SPACE_CLIP) {
SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
- if (t->options & CTX_MOVIECLIP) {
- ED_space_clip_get_aspect_dimension_aware(space_clip, &aspx, &aspy);
- }
- else {
- ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
- }
cursor = space_clip->cursor;
}
-
+
if (cursor) {
if (t->options & CTX_MASK) {
float co[2];
@@ -1609,8 +1637,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
BLI_assert(!"Shall not happen");
}
- r_center[0] = co[0] * aspx;
- r_center[1] = co[1] * aspy;
+ r_center[0] = co[0] * t->aspect[0];
+ r_center[1] = co[1] * t->aspect[1];
}
else if (t->options & CTX_PAINT_CURVE) {
if (t->spacetype == SPACE_IMAGE) {
@@ -1619,8 +1647,8 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
}
}
else {
- r_center[0] = cursor[0] * aspx;
- r_center[1] = cursor[1] * aspy;
+ r_center[0] = cursor[0] * t->aspect[0];
+ r_center[1] = cursor[1] * t->aspect[1];
}
}
}
@@ -1755,14 +1783,8 @@ void calculateCenter(TransInfo *t)
}
calculateCenter2D(t);
+ calculateCenterGlobal(t);
- /* setting constraint center */
- copy_v3_v3(t->con.center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, t->con.center);
- }
-
/* for panning from cameraview */
if (t->flag & T_OBJECT) {
if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
@@ -1783,7 +1805,7 @@ void calculateCenter(TransInfo *t)
/* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
if (t->mode == TFM_TRANSLATION) {
copy_v3_v3(t->center, axis);
- copy_v3_v3(t->con.center, t->center);
+ copy_v3_v3(t->center_global, t->center);
}
}
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index fc8e6cd0286..acc6108f264 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -512,7 +512,7 @@ static int calc_manipulator_stats(const bContext *C)
for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
if (ek->flag & PEK_SELECT) {
- calc_tw_center(scene, ek->flag & PEK_USE_WCO ? ek->world_co : ek->co);
+ calc_tw_center(scene, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
totsel++;
}
}
@@ -895,6 +895,11 @@ static void postOrtho(const bool ortho)
}
}
+BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags)
+{
+ return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z));
+}
+
static void draw_manipulator_rotate(
View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo,
const bool is_moving, const bool is_picksel)
@@ -908,8 +913,8 @@ static void draw_manipulator_rotate(
const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB;
bool ortho;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
/* Init stuff */
glDisable(GL_DEPTH_TEST);
@@ -1051,8 +1056,6 @@ static void draw_manipulator_rotate(
glRotatef(90.0, 1.0, 0.0, 0.0);
postOrtho(ortho);
}
-
- if (arcs) glDisable(GL_CLIP_PLANE0);
}
// donut arcs
if (arcs) {
@@ -1448,8 +1451,8 @@ static void draw_manipulator_rotate_cyl(
int axis_order[3] = {2, 0, 1};
int i;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
manipulator_axis_order(rv3d, axis_order);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index e33bc19fc92..013e47886eb 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -38,6 +38,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_editmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -63,23 +64,23 @@ typedef struct TransformModeItem {
static const float VecOne[3] = {1, 1, 1};
-static char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
-static char OP_ROTATION[] = "TRANSFORM_OT_rotate";
-static char OP_TOSPHERE[] = "TRANSFORM_OT_tosphere";
-static char OP_RESIZE[] = "TRANSFORM_OT_resize";
-static char OP_SKIN_RESIZE[] = "TRANSFORM_OT_skin_resize";
-static char OP_SHEAR[] = "TRANSFORM_OT_shear";
-static char OP_BEND[] = "TRANSFORM_OT_bend";
-static char OP_SHRINK_FATTEN[] = "TRANSFORM_OT_shrink_fatten";
-static char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
-static char OP_TILT[] = "TRANSFORM_OT_tilt";
-static char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
-static char OP_MIRROR[] = "TRANSFORM_OT_mirror";
-static char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
-static char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
-static char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
-static char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
-static char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
+static const char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
+static const char OP_ROTATION[] = "TRANSFORM_OT_rotate";
+static const char OP_TOSPHERE[] = "TRANSFORM_OT_tosphere";
+static const char OP_RESIZE[] = "TRANSFORM_OT_resize";
+static const char OP_SKIN_RESIZE[] = "TRANSFORM_OT_skin_resize";
+static const char OP_SHEAR[] = "TRANSFORM_OT_shear";
+static const char OP_BEND[] = "TRANSFORM_OT_bend";
+static const char OP_SHRINK_FATTEN[] = "TRANSFORM_OT_shrink_fatten";
+static const char OP_PUSH_PULL[] = "TRANSFORM_OT_push_pull";
+static const char OP_TILT[] = "TRANSFORM_OT_tilt";
+static const char OP_TRACKBALL[] = "TRANSFORM_OT_trackball";
+static const char OP_MIRROR[] = "TRANSFORM_OT_mirror";
+static const char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide";
+static const char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide";
+static const char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease";
+static const char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight";
+static const char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide";
static void TRANSFORM_OT_translate(struct wmOperatorType *ot);
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot);
@@ -140,6 +141,7 @@ EnumPropertyItem transform_mode_types[] =
{TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
{TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
{TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
+ {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
{TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
{TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
{TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
@@ -488,7 +490,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* add temp handler */
WM_event_add_modal_handler(C, op);
- op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only?
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only?
return OPERATOR_RUNNING_MODAL;
}
}
@@ -790,6 +792,8 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
@@ -834,6 +838,8 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Edge Slide";
ot->description = "Slide an edge loop along a mesh";
@@ -845,9 +851,12 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
- RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+
+ prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
@@ -865,7 +874,7 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_editmesh_region_view3d;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
@@ -1118,7 +1127,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_node_element");
break;
case SPACE_SEQ:
WM_keymap_add_item(keymap, OP_SEQ_SLIDE, GKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 4a2927ace00..1b0256bdeed 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -454,7 +454,7 @@ void applySnapping(TransInfo *t, float *vec)
t->tsnap.applySnap(t, vec);
}
- else if ((t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) && activeSnap(t)) {
+ else if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t)) {
double current = PIL_check_seconds_timer();
// Time base quirky code to go around findnearest slowness
@@ -577,6 +577,10 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
}
+ else if (t->spacetype == SPACE_SEQ) {
+ /* We do our own snapping currently, so nothing here */
+ t->tsnap.mode = SCE_SNAP_MODE_GRID; /* Dummy, should we rather add a NOP mode? */
+ }
else {
/* Always grid outside of 3D view */
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
@@ -837,16 +841,10 @@ static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const f
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float angle, start[3], end[3], center[3];
-
- copy_v3_v3(center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, center);
- }
+ float angle, start[3], end[3];
- sub_v3_v3v3(start, p1, center);
- sub_v3_v3v3(end, p2, center);
+ sub_v3_v3v3(start, p1, t->center_global);
+ sub_v3_v3v3(end, p2, t->center_global);
// Angle around a constraint axis (error prone, will need debug)
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
@@ -893,16 +891,10 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float d1[3], d2[3], center[3], len_d1;
-
- copy_v3_v3(center, t->center);
- if (t->flag & (T_EDIT | T_POSE)) {
- Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_m4_v3(ob->obmat, center);
- }
+ float d1[3], d2[3], len_d1;
- sub_v3_v3v3(d1, p1, center);
- sub_v3_v3v3(d2, p2, center);
+ sub_v3_v3v3(d1, p1, t->center_global);
+ sub_v3_v3v3(d2, p2, t->center_global);
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
mul_m3_v3(t->con.pmtx, d1);
@@ -949,9 +941,9 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
// last_p = LAST_SNAP_POINT;
// }
// else
-// {
+ {
last_p = t->tsnap.snapPoint;
-// }
+ }
for (p1 = depth_peels.first; p1; p1 = p1->next) {
@@ -1041,14 +1033,13 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
else if (t->spacetype == SPACE_IMAGE && t->obedit != NULL && t->obedit->type == OB_MESH) {
/* same as above but for UV's */
Image *ima = ED_space_image(t->sa->spacedata.first);
- float aspx, aspy, co[2];
+ float co[2];
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
if (ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint)) {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
- t->tsnap.snapPoint[0] *= aspx;
- t->tsnap.snapPoint[1] *= aspy;
+ t->tsnap.snapPoint[0] *= t->aspect[0];
+ t->tsnap.snapPoint[1] *= t->aspect[1];
t->tsnap.status |= POINT_INIT;
}
@@ -1109,13 +1100,7 @@ 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);
- }
-
+ copy_v3_v3(t->tsnap.snapTarget, t->center_global);
TargetSnapOffset(t, NULL);
t->tsnap.status |= TARGET_INIT;
@@ -1396,11 +1381,8 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
if (arm->edbo) {
EditBone *eBone;
@@ -1758,11 +1740,8 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
switch (snap_mode) {
case SCE_SNAP_MODE_VERTEX:
@@ -2107,12 +2086,8 @@ static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4],
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
/* If number of vert is more than an arbitrary limit,
* test against boundbox first
@@ -2418,8 +2393,8 @@ void snapGridIncrement(TransInfo *t, float *val)
{
GearsType action;
- // Only do something if using Snap to Grid
- if (t->tsnap.mode != SCE_SNAP_MODE_INCREMENT)
+ /* only do something if using absolute or incremental grid snapping */
+ if (!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))
return;
action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
@@ -2431,7 +2406,7 @@ void snapGridIncrement(TransInfo *t, float *val)
snapGridIncrementAction(t, val, action);
}
-int snapSequenceBounds(TransInfo *t, const int mval[2])
+void snapSequenceBounds(TransInfo *t, const int mval[2])
{
float xmouse, ymouse;
int frame;
@@ -2439,7 +2414,7 @@ int snapSequenceBounds(TransInfo *t, const int mval[2])
TransSeq *ts = t->customData;
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
if (!(t->modifiers & MOD_SNAP_INVERT))
- return 0;
+ return;
/* convert to frame range */
UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
@@ -2450,50 +2425,58 @@ int snapSequenceBounds(TransInfo *t, const int mval[2])
if (!ts->snap_left)
frame = frame - (ts->max - ts->min);
- return frame;
+ t->values[0] = frame - ts->min;
}
static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
{
+ float asp_local[3] = {1, 1, 1};
+ const bool use_aspect = ELEM(t->mode, TFM_TRANSLATION);
+ const float *asp = use_aspect ? t->aspect : asp_local;
int i;
- float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3)
- if (max_index > 2) {
- printf("applyGridIncrement: invalid index %d, clamping\n", max_index);
- max_index = 2;
- }
+ BLI_assert(ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID));
+ BLI_assert(max_index <= 2);
- // Early bailing out if no need to snap
- if (fac[action] == 0.0f)
+ /* Early bailing out if no need to snap */
+ if (fac[action] == 0.0f) {
return;
-
- /* evil hack - snapping needs to be adapted for image aspect ratio */
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
- if (t->options & CTX_MASK) {
- ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- asp[0] = asp[1] = 1.0;
- }
- else {
- ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
- }
}
- else if ((t->spacetype == SPACE_IPO) && (t->mode == TFM_TRANSLATION)) {
- View2D *v2d = &t->ar->v2d;
- View2DGrid *grid;
- SpaceIpo *sipo = t->sa->spacedata.first;
- int unity = V2D_UNIT_VALUES;
- int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
- /* grid */
- grid = UI_view2d_grid_calc(t->scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, t->ar->winx, t->ar->winy);
+ if (use_aspect) {
+ /* custom aspect for fcurve */
+ if (t->spacetype == SPACE_IPO) {
+ View2D *v2d = &t->ar->v2d;
+ View2DGrid *grid;
+ SpaceIpo *sipo = t->sa->spacedata.first;
+ int unity = V2D_UNIT_VALUES;
+ int unitx = (sipo->flag & SIPO_DRAWTIME) ? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
+
+ /* grid */
+ grid = UI_view2d_grid_calc(t->scene, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, t->ar->winx, t->ar->winy);
+
+ UI_view2d_grid_size(grid, &asp_local[0], &asp_local[1]);
+ UI_view2d_grid_free(grid);
- UI_view2d_grid_size(grid, &asp[0], &asp[1]);
- UI_view2d_grid_free(grid);
+ asp = asp_local;
+ }
}
- for (i = 0; i <= max_index; i++) {
- val[i] = fac[action] * asp[i] * floorf(val[i] / (fac[action] * asp[i]) + 0.5f);
+ /* absolute snapping on grid based on global center */
+ if ((t->tsnap.mode == SCE_SNAP_MODE_GRID) && (t->mode == TFM_TRANSLATION)) {
+ for (i = 0; i <= max_index; i++) {
+ /* do not let unconstrained axis jump to absolute grid increments */
+ if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) {
+ const float iter_fac = fac[action] * asp[i];
+ val[i] = iter_fac * roundf((val[i] + t->center_global[i]) / iter_fac) - t->center_global[i];
+ }
+ }
+ }
+ else {
+ /* relative snapping in fixed increments */
+ for (i = 0; i <= max_index; i++) {
+ const float iter_fac = fac[action] * asp[i];
+ val[i] = iter_fac * roundf(val[i] / iter_fac);
+ }
}
}