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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/transform
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/CMakeLists.txt72
-rw-r--r--source/blender/editors/transform/transform.c15383
-rw-r--r--source/blender/editors/transform/transform.h1398
-rw-r--r--source/blender/editors/transform/transform_constraints.c1768
-rw-r--r--source/blender/editors/transform/transform_conversions.c16167
-rw-r--r--source/blender/editors/transform/transform_generics.c4171
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c525
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c3969
-rw-r--r--source/blender/editors/transform/transform_gizmo_extrude_3d.c761
-rw-r--r--source/blender/editors/transform/transform_input.c651
-rw-r--r--source/blender/editors/transform/transform_ops.c1774
-rw-r--r--source/blender/editors/transform/transform_orientations.c1930
-rw-r--r--source/blender/editors/transform/transform_snap.c2441
-rw-r--r--source/blender/editors/transform/transform_snap_object.c4654
14 files changed, 28250 insertions, 27414 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index c475a9e4e3d..05e0659637b 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -16,55 +16,55 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenfont
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../gpu
- ../../ikplugin
- ../../makesdna
- ../../makesrna
- ../../render/extern/include
- ../../windowmanager
- ../../depsgraph
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenfont
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../gpu
+ ../../ikplugin
+ ../../makesdna
+ ../../makesrna
+ ../../render/extern/include
+ ../../windowmanager
+ ../../depsgraph
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- transform.c
- transform_constraints.c
- transform_conversions.c
- transform_generics.c
- transform_gizmo_2d.c
- transform_gizmo_3d.c
- transform_gizmo_extrude_3d.c
- transform_input.c
- transform_ops.c
- transform_orientations.c
- transform_snap.c
- transform_snap_object.c
+ transform.c
+ transform_constraints.c
+ transform_conversions.c
+ transform_generics.c
+ transform_gizmo_2d.c
+ transform_gizmo_3d.c
+ transform_gizmo_extrude_3d.c
+ transform_input.c
+ transform_ops.c
+ transform_orientations.c
+ transform_snap.c
+ transform_snap_object.c
- transform.h
+ transform.h
)
set(LIB
- bf_blenfont
- bf_blenkernel
- bf_blenlib
- bf_bmesh
- bf_editor_mask
- bf_gpu
+ bf_blenfont
+ bf_blenkernel
+ bf_blenlib
+ bf_bmesh
+ bf_editor_mask
+ bf_gpu
)
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
add_definitions(${GL_DEFINITIONS})
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 1358b526bca..944c6436dfb 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -35,7 +35,7 @@
#include "DNA_mask_types.h"
#include "DNA_mesh_types.h"
#include "DNA_movieclip_types.h"
-#include "DNA_scene_types.h" /* PET modes */
+#include "DNA_scene_types.h" /* PET modes */
#include "DNA_workspace_types.h"
#include "DNA_gpencil_types.h"
@@ -107,7 +107,8 @@ static void drawEdgeSlide(TransInfo *t);
static void drawVertSlide(TransInfo *t);
static void postInputRotation(TransInfo *t, float values[3]);
-static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
+static void ElementRotation(
+ TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around);
static void initSnapSpatial(TransInfo *t, float r_snap[3]);
static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm);
@@ -175,7 +176,8 @@ 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, bool use_even, bool flipped, bool use_clamp);
+static void initEdgeSlide_ex(
+ TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp);
static void initEdgeSlide(TransInfo *t);
static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
static void applyEdgeSlide(TransInfo *t, const int mval[2]);
@@ -210,496 +212,489 @@ static void initGPOpacity(TransInfo *t);
static void applyGPOpacity(TransInfo *t, const int mval[2]);
/* end transform callbacks */
-
static bool transdata_check_local_center(TransInfo *t, short around)
{
- return ((around == V3D_AROUND_LOCAL_ORIGINS) && (
- (t->flag & (T_OBJECT | T_POSE)) ||
- /* implicit: (t->flag & T_EDIT) */
- (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) ||
- (t->spacetype == SPACE_GRAPH) ||
- (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))
- );
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
+ ((t->flag & (T_OBJECT | T_POSE)) ||
+ /* implicit: (t->flag & T_EDIT) */
+ (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) ||
+ (t->spacetype == SPACE_GRAPH) ||
+ (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))));
}
bool transdata_check_local_islands(TransInfo *t, short around)
{
- return ((around == V3D_AROUND_LOCAL_ORIGINS) && (
- (ELEM(t->obedit_type, OB_MESH))));
+ return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH))));
}
/* ************************** SPACE DEPENDENT CODE **************************** */
void setTransformViewMatrices(TransInfo *t)
{
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = t->ar->regiondata;
+ if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->ar->regiondata;
- copy_m4_m4(t->viewmat, rv3d->viewmat);
- copy_m4_m4(t->viewinv, rv3d->viewinv);
- copy_m4_m4(t->persmat, rv3d->persmat);
- copy_m4_m4(t->persinv, rv3d->persinv);
- t->persp = rv3d->persp;
- }
- else {
- unit_m4(t->viewmat);
- unit_m4(t->viewinv);
- unit_m4(t->persmat);
- unit_m4(t->persinv);
- t->persp = RV3D_ORTHO;
- }
+ copy_m4_m4(t->viewmat, rv3d->viewmat);
+ copy_m4_m4(t->viewinv, rv3d->viewinv);
+ copy_m4_m4(t->persmat, rv3d->persmat);
+ copy_m4_m4(t->persinv, rv3d->persinv);
+ t->persp = rv3d->persp;
+ }
+ else {
+ unit_m4(t->viewmat);
+ unit_m4(t->viewinv);
+ unit_m4(t->persmat);
+ unit_m4(t->persinv);
+ t->persp = RV3D_ORTHO;
+ }
- calculateCenter2D(t);
- calculateCenterLocal(t, t->center_global);
+ calculateCenter2D(t);
+ calculateCenterLocal(t, t->center_global);
}
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_GRAPH) {
- /* depemds on context of usage */
- }
+ 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_GRAPH) {
+ /* depemds on context of usage */
+ }
}
static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy)
{
- float divx = BLI_rcti_size_x(&v2d->mask);
- float divy = BLI_rcti_size_y(&v2d->mask);
+ float divx = BLI_rcti_size_x(&v2d->mask);
+ float divy = BLI_rcti_size_y(&v2d->mask);
- r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
- r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
- r_vec[2] = 0.0f;
+ r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx;
+ r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy;
+ r_vec[2] = 0.0f;
}
static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
{
- float divx = BLI_rcti_size_x(&v2d->mask);
- float divy = BLI_rcti_size_y(&v2d->mask);
+ float divx = BLI_rcti_size_x(&v2d->mask);
+ float divy = BLI_rcti_size_y(&v2d->mask);
- float mulx = BLI_rctf_size_x(&v2d->cur);
- float muly = BLI_rctf_size_y(&v2d->cur);
+ float mulx = BLI_rctf_size_x(&v2d->cur);
+ float muly = BLI_rctf_size_y(&v2d->cur);
- /* difference with convertViewVec2D */
- /* clamp w/h, mask only */
- if (mulx / divx < muly / divy) {
- divy = divx;
- muly = mulx;
- }
- else {
- divx = divy;
- mulx = muly;
- }
- /* end difference */
+ /* difference with convertViewVec2D */
+ /* clamp w/h, mask only */
+ if (mulx / divx < muly / divy) {
+ divy = divx;
+ muly = mulx;
+ }
+ else {
+ divx = divy;
+ mulx = muly;
+ }
+ /* end difference */
- r_vec[0] = mulx * dx / divx;
- r_vec[1] = muly * dy / divy;
- r_vec[2] = 0.0f;
+ r_vec[0] = mulx * dx / divx;
+ r_vec[1] = muly * dy / divy;
+ r_vec[2] = 0.0f;
}
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy)
{
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- if (t->options & CTX_PAINT_CURVE) {
- r_vec[0] = dx;
- r_vec[1] = dy;
- }
- else {
- const float mval_f[2] = {(float)dx, (float)dy};
- ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- convertViewVec2D_mask(t->view, r_vec, dx, dy);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- r_vec[0] = dx;
- r_vec[1] = dy;
- }
- else {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
-
- r_vec[0] *= t->aspect[0];
- r_vec[1] *= t->aspect[1];
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
- else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
- convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
- }
- else if (t->spacetype == SPACE_CLIP) {
- if (t->options & CTX_MASK) {
- convertViewVec2D_mask(t->view, r_vec, dx, dy);
- }
- else {
- convertViewVec2D(t->view, r_vec, dx, dy);
- }
-
- r_vec[0] *= t->aspect[0];
- r_vec[1] *= t->aspect[1];
- }
- else {
- printf("%s: called in an invalid context\n", __func__);
- zero_v3(r_vec);
- }
+ if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+ }
+ else {
+ const float mval_f[2] = {(float)dx, (float)dy};
+ ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ convertViewVec2D_mask(t->view, r_vec, dx, dy);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+ }
+ else {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+ else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
+ convertViewVec2D(&t->ar->v2d, r_vec, dx, dy);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ if (t->options & CTX_MASK) {
+ convertViewVec2D_mask(t->view, r_vec, dx, dy);
+ }
+ else {
+ convertViewVec2D(t->view, r_vec, dx, dy);
+ }
+
+ r_vec[0] *= t->aspect[0];
+ r_vec[1] *= t->aspect[1];
+ }
+ else {
+ printf("%s: called in an invalid context\n", __func__);
+ zero_v3(r_vec);
+ }
}
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag)
{
- if (t->spacetype == SPACE_VIEW3D) {
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
- /* this is what was done in 2.64, perhaps we can be smarter? */
- adr[0] = (int)2140000000.0f;
- adr[1] = (int)2140000000.0f;
- }
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
-
- if (t->options & CTX_MASK) {
- float v[2];
-
- 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);
-
- ED_image_point_pos__reverse(sima, t->ar, v, v);
-
- adr[0] = v[0];
- adr[1] = v[1];
- }
- else if (t->options & CTX_PAINT_CURVE) {
- adr[0] = vec[0];
- adr[1] = vec[1];
- }
- else {
- float v[2];
-
- 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]);
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- int out[2] = {0, 0};
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
+ /* this is what was done in 2.64, perhaps we can be smarter? */
+ adr[0] = (int)2140000000.0f;
+ adr[1] = (int)2140000000.0f;
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ float v[2];
+
+ 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);
+
+ ED_image_point_pos__reverse(sima, t->ar, v, v);
+
+ adr[0] = v[0];
+ adr[1] = v[1];
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else {
+ float v[2];
+
+ 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]);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ int out[2] = {0, 0};
#if 0
- SpaceAction *sact = t->sa->spacedata.first;
-
- if (sact->flag & SACTION_DRAWTIME) {
- //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
- /* same as below */
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- }
- else
+ SpaceAction *sact = t->sa->spacedata.first;
+
+ if (sact->flag & SACTION_DRAWTIME) {
+ //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
+ /* same as below */
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ }
+ else
#endif
- {
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- }
-
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
- int out[2] = {0, 0};
-
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */
- int out[2] = {0, 0};
-
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
- adr[0] = out[0];
- adr[1] = out[1];
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
-
- if (t->options & CTX_MASK) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (clip) {
- float v[2];
-
- 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);
-
- ED_clip_point_stable_pos__reverse(sc, t->ar, v, v);
-
- adr[0] = v[0];
- adr[1] = v[1];
- }
- else {
- adr[0] = 0;
- adr[1] = 0;
- }
- }
- else if (t->options & CTX_MOVIECLIP) {
- float v[2];
-
- 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]);
- }
- else {
- BLI_assert(0);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]);
- }
+ {
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ }
+
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) {
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */
+ int out[2] = {0, 0};
+
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]);
+ adr[0] = out[0];
+ adr[1] = out[1];
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+
+ if (t->options & CTX_MASK) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip) {
+ float v[2];
+
+ 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);
+
+ ED_clip_point_stable_pos__reverse(sc, t->ar, v, v);
+
+ adr[0] = v[0];
+ adr[1] = v[1];
+ }
+ else {
+ adr[0] = 0;
+ adr[1] = 0;
+ }
+ }
+ else if (t->options & CTX_MOVIECLIP) {
+ float v[2];
+
+ 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]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]);
+ }
}
void projectIntView(TransInfo *t, const float vec[3], int adr[2])
{
- projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+ projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
}
void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag)
{
- switch (t->spacetype) {
- case SPACE_VIEW3D:
- {
- if (t->options & CTX_PAINT_CURVE) {
- adr[0] = vec[0];
- adr[1] = vec[1];
- }
- else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- /* allow points behind the view [#33643] */
- if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
- /* XXX, 2.64 and prior did this, weak! */
- adr[0] = t->ar->winx / 2.0f;
- adr[1] = t->ar->winy / 2.0f;
- }
- return;
- }
- break;
- }
- default:
- {
- int a[2] = {0, 0};
- projectIntView(t, vec, a);
- adr[0] = a[0];
- adr[1] = a[1];
- break;
- }
- }
+ switch (t->spacetype) {
+ case SPACE_VIEW3D: {
+ if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ /* allow points behind the view [#33643] */
+ if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
+ /* XXX, 2.64 and prior did this, weak! */
+ adr[0] = t->ar->winx / 2.0f;
+ adr[1] = t->ar->winy / 2.0f;
+ }
+ return;
+ }
+ break;
+ }
+ default: {
+ int a[2] = {0, 0};
+ projectIntView(t, vec, a);
+ adr[0] = a[0];
+ adr[1] = a[1];
+ break;
+ }
+ }
}
void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
{
- projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+ projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
}
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;
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) &&
+ !(t->options & CTX_PAINT_CURVE)) {
+ SpaceImage *sima = t->sa->spacedata.first;
- if ((sima->flag & SI_COORDFLOATS) == 0) {
- int width, height;
- ED_space_image_get_size(sima, &width, &height);
+ if ((sima->flag & SI_COORDFLOATS) == 0) {
+ int width, height;
+ ED_space_image_get_size(sima, &width, &height);
- vec[0] *= width;
- vec[1] *= height;
- }
+ vec[0] *= width;
+ vec[1] *= height;
+ }
- 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)) {
- vec[0] /= t->aspect[0];
- vec[1] /= t->aspect[1];
- }
- }
+ 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)) {
+ vec[0] /= t->aspect[0];
+ vec[1] /= t->aspect[1];
+ }
+ }
}
void removeAspectRatio(TransInfo *t, float vec[2])
{
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
- SpaceImage *sima = t->sa->spacedata.first;
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
+ SpaceImage *sima = t->sa->spacedata.first;
- if ((sima->flag & SI_COORDFLOATS) == 0) {
- int width, height;
- ED_space_image_get_size(sima, &width, &height);
+ if ((sima->flag & SI_COORDFLOATS) == 0) {
+ int width, height;
+ ED_space_image_get_size(sima, &width, &height);
- vec[0] /= width;
- vec[1] /= height;
- }
+ vec[0] /= width;
+ vec[1] /= height;
+ }
- 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)) {
- vec[0] *= t->aspect[0];
- vec[1] *= t->aspect[1];
- }
- }
+ 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)) {
+ vec[0] *= t->aspect[0];
+ vec[1] *= t->aspect[1];
+ }
+ }
}
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- if (gpd) {
- DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
- }
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
- }
- else if (t->spacetype == SPACE_VIEW3D) {
- if (t->options & CTX_PAINT_CURVE) {
- wmWindow *window = CTX_wm_window(C);
- WM_paint_cursor_tag_redraw(window, t->ar);
- }
- else {
- /* Do we need more refined tags? */
- if (t->flag & T_POSE)
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- else
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- /* For real-time animation record - send notifiers recognized by animation editors */
- // XXX: is this notifier a lame duck?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- //SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
- }
- else if (t->spacetype == SPACE_NLA) {
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- }
- else if (t->spacetype == SPACE_NODE) {
- //ED_area_tag_redraw(t->sa);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
- }
- else if (t->spacetype == SPACE_SEQ) {
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- Mask *mask = CTX_data_edit_mask(C);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- wmWindow *window = CTX_wm_window(C);
- WM_paint_cursor_tag_redraw(window, t->ar);
- }
- else if (t->flag & T_CURSOR) {
- ED_area_tag_redraw(t->sa);
- }
- else {
- // XXX how to deal with lock?
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- if (sima->lock) {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data);
- }
- else {
- ED_area_tag_redraw(t->sa);
- }
- }
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first;
-
- if (ED_space_clip_check_show_trackedit(sc)) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- /* objects could be parented to tracking data, so send this for viewport refresh */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- }
- else if (ED_space_clip_check_show_maskedit(sc)) {
- Mask *mask = CTX_data_edit_mask(C);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- }
- }
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+ }
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
+ else {
+ /* Do we need more refined tags? */
+ if (t->flag & T_POSE)
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ else
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* For real-time animation record - send notifiers recognized by animation editors */
+ // XXX: is this notifier a lame duck?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ //SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ //ED_area_tag_redraw(t->sa);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ Mask *mask = CTX_data_edit_mask(C);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
+ else if (t->flag & T_CURSOR) {
+ ED_area_tag_redraw(t->sa);
+ }
+ else {
+ // XXX how to deal with lock?
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ if (sima->lock) {
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data);
+ }
+ else {
+ ED_area_tag_redraw(t->sa);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first;
+
+ if (ED_space_clip_check_show_trackedit(sc)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ /* objects could be parented to tracking data, so send this for viewport refresh */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ }
+ else if (ED_space_clip_check_show_maskedit(sc)) {
+ Mask *mask = CTX_data_edit_mask(C);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ }
+ }
}
static void viewRedrawPost(bContext *C, TransInfo *t)
{
- ED_area_status_text(t->sa, NULL);
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* if autokeying is enabled, send notifiers that keyframes were added */
- if (IS_AUTOKEY_ON(t->scene))
- WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
-
- /* redraw UV editor */
- if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
- (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
- {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
- }
-
- /* XXX temp, first hack to get auto-render in compositor work (ton) */
- WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
-
- }
-
-#if 0 // TRANSFORM_FIX_ME
- if (t->spacetype == SPACE_VIEW3D) {
- allqueue(REDRAWBUTSOBJECT, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- allqueue(REDRAWIMAGE, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
- else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) {
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWTIME, 0);
- allqueue(REDRAWBUTSOBJECT, 0);
- }
-
- scrarea_queue_headredraw(curarea);
+ ED_area_status_text(t->sa, NULL);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* if autokeying is enabled, send notifiers that keyframes were added */
+ if (IS_AUTOKEY_ON(t->scene))
+ WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+
+ /* redraw UV editor */
+ if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
+ (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+ }
+
+ /* XXX temp, first hack to get auto-render in compositor work (ton) */
+ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C));
+ }
+
+#if 0 // TRANSFORM_FIX_ME
+ if (t->spacetype == SPACE_VIEW3D) {
+ allqueue(REDRAWBUTSOBJECT, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) {
+ allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWNLA, 0);
+ allqueue(REDRAWIPO, 0);
+ allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
+ }
+
+ scrarea_queue_headredraw(curarea);
#endif
}
@@ -707,81 +702,81 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
static void view_editmove(unsigned short UNUSED(event))
{
-#if 0 // TRANSFORM_FIX_ME
- int refresh = 0;
- /* Regular: Zoom in */
- /* Shift: Scroll up */
- /* Ctrl: Scroll right */
- /* Alt-Shift: Rotate up */
- /* Alt-Ctrl: Rotate right */
-
- /* only work in 3D window for now
- * In the end, will have to send to event to a 2D window handler instead
- */
- if (Trans.flag & T_2D_EDIT)
- return;
-
- switch (event) {
- case WHEELUPMOUSE:
- if (G.qual & LR_SHIFTKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_SHIFTKEY;
- persptoetsen(PAD2);
- G.qual |= LR_SHIFTKEY;
- }
- else {
- persptoetsen(PAD2);
- }
- }
- else if (G.qual & LR_CTRLKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_CTRLKEY;
- persptoetsen(PAD4);
- G.qual |= LR_CTRLKEY;
- }
- else {
- persptoetsen(PAD4);
- }
- }
- else if (U.uiflag & USER_WHEELZOOMDIR)
- persptoetsen(PADMINUS);
- else
- persptoetsen(PADPLUSKEY);
-
- refresh = 1;
- break;
- case WHEELDOWNMOUSE:
- if (G.qual & LR_SHIFTKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_SHIFTKEY;
- persptoetsen(PAD8);
- G.qual |= LR_SHIFTKEY;
- }
- else {
- persptoetsen(PAD8);
- }
- }
- else if (G.qual & LR_CTRLKEY) {
- if (G.qual & LR_ALTKEY) {
- G.qual &= ~LR_CTRLKEY;
- persptoetsen(PAD6);
- G.qual |= LR_CTRLKEY;
- }
- else {
- persptoetsen(PAD6);
- }
- }
- else if (U.uiflag & USER_WHEELZOOMDIR)
- persptoetsen(PADPLUSKEY);
- else
- persptoetsen(PADMINUS);
-
- refresh = 1;
- break;
- }
-
- if (refresh)
- setTransformViewMatrices(&Trans);
+#if 0 // TRANSFORM_FIX_ME
+ int refresh = 0;
+ /* Regular: Zoom in */
+ /* Shift: Scroll up */
+ /* Ctrl: Scroll right */
+ /* Alt-Shift: Rotate up */
+ /* Alt-Ctrl: Rotate right */
+
+ /* only work in 3D window for now
+ * In the end, will have to send to event to a 2D window handler instead
+ */
+ if (Trans.flag & T_2D_EDIT)
+ return;
+
+ switch (event) {
+ case WHEELUPMOUSE:
+ if (G.qual & LR_SHIFTKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD2);
+ G.qual |= LR_SHIFTKEY;
+ }
+ else {
+ persptoetsen(PAD2);
+ }
+ }
+ else if (G.qual & LR_CTRLKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD4);
+ G.qual |= LR_CTRLKEY;
+ }
+ else {
+ persptoetsen(PAD4);
+ }
+ }
+ else if (U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADMINUS);
+ else
+ persptoetsen(PADPLUSKEY);
+
+ refresh = 1;
+ break;
+ case WHEELDOWNMOUSE:
+ if (G.qual & LR_SHIFTKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_SHIFTKEY;
+ persptoetsen(PAD8);
+ G.qual |= LR_SHIFTKEY;
+ }
+ else {
+ persptoetsen(PAD8);
+ }
+ }
+ else if (G.qual & LR_CTRLKEY) {
+ if (G.qual & LR_ALTKEY) {
+ G.qual &= ~LR_CTRLKEY;
+ persptoetsen(PAD6);
+ G.qual |= LR_CTRLKEY;
+ }
+ else {
+ persptoetsen(PAD6);
+ }
+ }
+ else if (U.uiflag & USER_WHEELZOOMDIR)
+ persptoetsen(PADPLUSKEY);
+ else
+ persptoetsen(PADMINUS);
+
+ refresh = 1;
+ break;
+ }
+
+ if (refresh)
+ setTransformViewMatrices(&Trans);
#endif
}
@@ -789,885 +784,898 @@ 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 */
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 */
- TFM_MODAL_PROPSIZE = 26,
-/* node editor insert offset (aka auto-offset) direction toggle */
- TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
+ 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 */
+ TFM_MODAL_PROPSIZE = 26,
+ /* node editor insert offset (aka auto-offset) direction toggle */
+ TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
};
static bool transform_modal_item_poll(const wmOperator *op, int value)
{
- const TransInfo *t = op->customdata;
- switch (value) {
- case TFM_MODAL_CANCEL:
- {
- if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) {
- return false;
- }
- break;
- }
- case TFM_MODAL_PROPSIZE:
- case TFM_MODAL_PROPSIZE_UP:
- case TFM_MODAL_PROPSIZE_DOWN:
- {
- if ((t->flag & T_PROP_EDIT) == 0) {
- return false;
- }
- break;
- }
- case TFM_MODAL_ADD_SNAP:
- case TFM_MODAL_REMOVE_SNAP:
- {
- if (t->spacetype != SPACE_VIEW3D) {
- return false;
- }
- else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) {
- return false;
- }
- else if (!validSnap(t)) {
- return false;
- }
- break;
- }
- case TFM_MODAL_AXIS_X:
- case TFM_MODAL_AXIS_Y:
- case TFM_MODAL_AXIS_Z:
- case TFM_MODAL_PLANE_X:
- case TFM_MODAL_PLANE_Y:
- case TFM_MODAL_PLANE_Z:
- {
- if (t->flag & T_NO_CONSTRAINT) {
- return false;
- }
- if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) {
- if (t->flag & T_2D_EDIT) {
- return false;
- }
- }
- break;
- }
- case TFM_MODAL_CONS_OFF:
- {
- if ((t->con.mode & CON_APPLY) == 0) {
- return false;
- }
- break;
- }
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- {
- if (t->mode != TFM_EDGE_SLIDE) {
- return false;
- }
- break;
- }
- case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
- {
- if (t->spacetype != SPACE_NODE) {
- return false;
- }
- break;
- }
- case TFM_MODAL_AUTOIK_LEN_INC:
- case TFM_MODAL_AUTOIK_LEN_DEC:
- {
- if ((t->flag & T_AUTOIK) == 0) {
- return false;
- }
- break;
- }
- }
- return true;
+ const TransInfo *t = op->customdata;
+ switch (value) {
+ case TFM_MODAL_CANCEL: {
+ if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_PROPSIZE:
+ case TFM_MODAL_PROPSIZE_UP:
+ case TFM_MODAL_PROPSIZE_DOWN: {
+ if ((t->flag & T_PROP_EDIT) == 0) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_ADD_SNAP:
+ case TFM_MODAL_REMOVE_SNAP: {
+ if (t->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+ else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) {
+ return false;
+ }
+ else if (!validSnap(t)) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_AXIS_X:
+ case TFM_MODAL_AXIS_Y:
+ case TFM_MODAL_AXIS_Z:
+ case TFM_MODAL_PLANE_X:
+ case TFM_MODAL_PLANE_Y:
+ case TFM_MODAL_PLANE_Z: {
+ if (t->flag & T_NO_CONSTRAINT) {
+ return false;
+ }
+ if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) {
+ if (t->flag & T_2D_EDIT) {
+ return false;
+ }
+ }
+ break;
+ }
+ case TFM_MODAL_CONS_OFF: {
+ if ((t->con.mode & CON_APPLY) == 0) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN: {
+ if (t->mode != TFM_EDGE_SLIDE) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR: {
+ if (t->spacetype != SPACE_NODE) {
+ return false;
+ }
+ break;
+ }
+ case TFM_MODAL_AUTOIK_LEN_INC:
+ case TFM_MODAL_AUTOIK_LEN_DEC: {
+ if ((t->flag & T_AUTOIK) == 0) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
}
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{
- static const EnumPropertyItem modal_items[] = {
- {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
- {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
- {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""},
- {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""},
- {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""},
- {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""},
- {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""},
- {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""},
- {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
- {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
- {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
- {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
- {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
- {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
- {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
- {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
- {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
- {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""},
- {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
- {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
- {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
- {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
- {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
- {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""},
- {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""},
- {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
- {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map");
-
- keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
- keymap->poll_modal_item = transform_modal_item_poll;
-
- return keymap;
+ static const EnumPropertyItem modal_items[] = {
+ {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""},
+ {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""},
+ {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""},
+ {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""},
+ {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""},
+ {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""},
+ {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""},
+ {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""},
+ {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""},
+ {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""},
+ {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""},
+ {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""},
+ {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
+ {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
+ {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
+ {TFM_MODAL_PROPSIZE_DOWN,
+ "PROPORTIONAL_SIZE_DOWN",
+ 0,
+ "Decrease Proportional Influence",
+ ""},
+ {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
+ {TFM_MODAL_AUTOIK_LEN_DEC,
+ "AUTOIK_CHAIN_LEN_DOWN",
+ 0,
+ "Decrease Max AutoIK Chain Length",
+ ""},
+ {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""},
+ {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""},
+ {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""},
+ {TFM_MODAL_INSERTOFS_TOGGLE_DIR,
+ "INSERTOFS_TOGGLE_DIR",
+ 0,
+ "Toggle Direction for Node Auto-offset",
+ ""},
+ {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""},
+ {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map");
+
+ keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
+ keymap->poll_modal_item = transform_modal_item_poll;
+
+ return keymap;
}
static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cmode, bool is_plane)
{
- if (!(t->flag & T_NO_CONSTRAINT)) {
- int constraint_axis, constraint_plane;
- const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
- const char *msg1 = "", *msg2 = "", *msg3 = "";
- char axis;
-
- /* Initialize */
- switch (key_type) {
- case XKEY:
- msg1 = IFACE_("along X");
- msg2 = IFACE_("along %s X");
- msg3 = IFACE_("locking %s X");
- axis = 'X';
- constraint_axis = CON_AXIS0;
- break;
- case YKEY:
- msg1 = IFACE_("along Y");
- msg2 = IFACE_("along %s Y");
- msg3 = IFACE_("locking %s Y");
- axis = 'Y';
- constraint_axis = CON_AXIS1;
- break;
- case ZKEY:
- msg1 = IFACE_("along Z");
- msg2 = IFACE_("along %s Z");
- msg3 = IFACE_("locking %s Z");
- axis = 'Z';
- constraint_axis = CON_AXIS2;
- break;
- default:
- /* Invalid key */
- return;
- }
- constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
-
- if (edit_2d && (key_type != ZKEY)) {
- if (cmode == axis) {
- stopConstraint(t);
- }
- else {
- setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1);
- }
- }
- else if (!edit_2d) {
- if (cmode != axis) {
- /* First press, constraint to an axis. */
- t->orientation.index = 0;
- const short *orientation_ptr = t->orientation.types[t->orientation.index];
- const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
- if (is_plane == false) {
- setUserConstraint(t, orientation, constraint_axis, msg2);
- }
- else {
- setUserConstraint(t, orientation, constraint_plane, msg3);
- }
- }
- else {
- /* Successive presses on existing axis, cycle orientation modes. */
- t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
-
- if (t->orientation.index == 0) {
- stopConstraint(t);
- }
- else {
- const short *orientation_ptr = t->orientation.types[t->orientation.index];
- const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
- if (is_plane == false) {
- setUserConstraint(t, orientation, constraint_axis, msg2);
- }
- else {
- setUserConstraint(t, orientation, constraint_plane, msg3);
- }
- }
- }
- }
- t->redraw |= TREDRAW_HARD;
- }
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ int constraint_axis, constraint_plane;
+ const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
+ const char *msg1 = "", *msg2 = "", *msg3 = "";
+ char axis;
+
+ /* Initialize */
+ switch (key_type) {
+ case XKEY:
+ msg1 = IFACE_("along X");
+ msg2 = IFACE_("along %s X");
+ msg3 = IFACE_("locking %s X");
+ axis = 'X';
+ constraint_axis = CON_AXIS0;
+ break;
+ case YKEY:
+ msg1 = IFACE_("along Y");
+ msg2 = IFACE_("along %s Y");
+ msg3 = IFACE_("locking %s Y");
+ axis = 'Y';
+ constraint_axis = CON_AXIS1;
+ break;
+ case ZKEY:
+ msg1 = IFACE_("along Z");
+ msg2 = IFACE_("along %s Z");
+ msg3 = IFACE_("locking %s Z");
+ axis = 'Z';
+ constraint_axis = CON_AXIS2;
+ break;
+ default:
+ /* Invalid key */
+ return;
+ }
+ constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
+
+ if (edit_2d && (key_type != ZKEY)) {
+ if (cmode == axis) {
+ stopConstraint(t);
+ }
+ else {
+ setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1);
+ }
+ }
+ else if (!edit_2d) {
+ if (cmode != axis) {
+ /* First press, constraint to an axis. */
+ t->orientation.index = 0;
+ const short *orientation_ptr = t->orientation.types[t->orientation.index];
+ const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
+ if (is_plane == false) {
+ setUserConstraint(t, orientation, constraint_axis, msg2);
+ }
+ else {
+ setUserConstraint(t, orientation, constraint_plane, msg3);
+ }
+ }
+ else {
+ /* Successive presses on existing axis, cycle orientation modes. */
+ t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types);
+
+ if (t->orientation.index == 0) {
+ stopConstraint(t);
+ }
+ else {
+ const short *orientation_ptr = t->orientation.types[t->orientation.index];
+ const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL;
+ if (is_plane == false) {
+ setUserConstraint(t, orientation, constraint_axis, msg2);
+ }
+ else {
+ setUserConstraint(t, orientation, constraint_plane, msg3);
+ }
+ }
+ }
+ }
+ t->redraw |= TREDRAW_HARD;
+ }
}
int transformEvent(TransInfo *t, const wmEvent *event)
{
- char cmode = constraintModeToChar(t);
- bool handled = false;
- const int modifiers_prev = t->modifiers;
-
- t->redraw |= handleMouseInput(t, &t->mouse, event);
-
- /* Handle modal numinput events first, if already activated. */
- if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
- hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event))
- {
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (event->type == MOUSEMOVE) {
- if (t->modifiers & MOD_CONSTRAINT_SELECT)
- t->con.mode |= CON_SELECT;
-
- copy_v2_v2_int(t->mval, event->mval);
-
- /* Use this for soft redraw. Might cause flicker in object mode */
- // t->redraw |= TREDRAW_SOFT;
- t->redraw |= TREDRAW_HARD;
-
- if (t->state == TRANS_STARTING) {
- t->state = TRANS_RUNNING;
- }
-
- applyMouseInput(t, &t->mouse, t->mval, t->values);
-
- // Snapping mouse move events
- t->redraw |= handleSnapping(t, event);
- handled = true;
- }
- /* handle modal keymap first */
- else if (event->type == EVT_MODAL_MAP) {
- switch (event->val) {
- case TFM_MODAL_CANCEL:
- t->state = TRANS_CANCEL;
- handled = true;
- break;
- case TFM_MODAL_CONFIRM:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
- case TFM_MODAL_TRANSLATE:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initTranslation(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- WM_event_add_mousemove(t->context);
- handled = true;
- }
- else if (t->mode == TFM_SEQ_SLIDE) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else {
- if (t->obedit_type == OB_MESH) {
- if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- /* first try edge slide */
- initEdgeSlide(t);
- /* if that fails, do vertex slide */
- if (t->state == TRANS_CANCEL) {
- resetTransModal(t);
- t->state = TRANS_STARTING;
- initVertSlide(t);
- }
- /* vert slide can fail on unconnected vertices (rare but possible) */
- if (t->state == TRANS_CANCEL) {
- resetTransModal(t);
- t->mode = TFM_TRANSLATION;
- t->state = TRANS_STARTING;
- restoreTransObjects(t);
- resetTransRestrictions(t);
- initTranslation(t);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- WM_event_add_mousemove(t->context);
- }
- }
- else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- if (t->mode == TFM_TRANSLATION) {
- restoreTransObjects(t);
-
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- }
- break;
- case TFM_MODAL_ROTATE:
- /* only switch when... */
- if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- if (t->mode == TFM_ROTATION) {
- initTrackball(t);
- }
- else {
- initRotation(t);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case TFM_MODAL_RESIZE:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
-
- /* Scale isn't normally very useful after extrude along normals, see T39756 */
- if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) {
- stopConstraint(t);
- }
-
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initResize(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (t->mode == TFM_SHRINKFATTEN) {
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- else if (t->mode == TFM_RESIZE) {
- if (t->options & CTX_MOVIECLIP) {
- restoreTransObjects(t);
-
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
-
- case TFM_MODAL_SNAP_INV_ON:
- t->modifiers |= MOD_SNAP_INVERT;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_SNAP_INV_OFF:
- t->modifiers &= ~MOD_SNAP_INVERT;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_SNAP_TOGGLE:
- t->modifiers ^= MOD_SNAP;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_AXIS_X:
- if (!(t->flag & T_NO_CONSTRAINT)) {
- transform_event_xyz_constraint(t, XKEY, cmode, false);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AXIS_Y:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- transform_event_xyz_constraint(t, YKEY, cmode, false);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AXIS_Z:
- if ((t->flag & (T_NO_CONSTRAINT)) == 0) {
- transform_event_xyz_constraint(t, ZKEY, cmode, false);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PLANE_X:
- if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, XKEY, cmode, true);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PLANE_Y:
- if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, YKEY, cmode, true);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PLANE_Z:
- if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
- transform_event_xyz_constraint(t, ZKEY, cmode, true);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_CONS_OFF:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- stopConstraint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_ADD_SNAP:
- addSnapPoint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_REMOVE_SNAP:
- removeSnapPoint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
- case TFM_MODAL_PROPSIZE:
- /* MOUSEPAN usage... */
- if (t->flag & T_PROP_EDIT) {
- float fac = 1.0f + 0.005f *(event->y - event->prevy);
- t->prop_size *= fac;
- if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
- t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end), T_PROP_SIZE_MIN);
- }
- else {
- t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN);
- }
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PROPSIZE_UP:
- if (t->flag & T_PROP_EDIT) {
- 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)->clip_end);
- }
- else {
- t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX);
- }
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_PROPSIZE_DOWN:
- if (t->flag & T_PROP_EDIT) {
- t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
- t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN);
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AUTOIK_LEN_INC:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, 1);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_AUTOIK_LEN_DEC:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, -1);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
- if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
-
- BLI_assert(t->sa->spacetype == t->spacetype);
-
- if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
- snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
- }
- else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
- snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
- }
- else {
- BLI_assert(0);
- }
-
- t->redraw |= TREDRAW_SOFT;
- }
- break;
- /* Those two are only handled in transform's own handler, see T44634! */
- case TFM_MODAL_EDGESLIDE_UP:
- case TFM_MODAL_EDGESLIDE_DOWN:
- default:
- break;
- }
- }
- /* else do non-mapped events */
- else if (event->val == KM_PRESS) {
- switch (event->type) {
- case RIGHTMOUSE:
- t->state = TRANS_CANCEL;
- handled = true;
- break;
- /* enforce redraw of transform when modifiers are used */
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- t->modifiers |= MOD_CONSTRAINT_PLANE;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
-
- case SPACEKEY:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
-
- case MIDDLEMOUSE:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- /* exception for switching to dolly, or trackball, in camera view */
- if (t->flag & T_CAMERA) {
- if (t->mode == TFM_TRANSLATION)
- setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
- else if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
- initTrackball(t);
- }
- }
- else {
- t->modifiers |= MOD_CONSTRAINT_SELECT;
- if (t->con.mode & CON_APPLY) {
- stopConstraint(t);
- }
- else {
- if (event->shift) {
- /* bit hackish... but it prevents mmb select to print the
- * orientation from menu */
- float mati[3][3];
- strcpy(t->spacename, "global");
- unit_m3(mati);
- initSelectConstraint(t, mati);
- }
- else {
- initSelectConstraint(t, t->spacemtx);
- }
- postSelectConstraint(t);
- }
- }
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case ESCKEY:
- t->state = TRANS_CANCEL;
- handled = true;
- break;
- case PADENTER:
- case RETKEY:
- t->state = TRANS_CONFIRM;
- handled = true;
- break;
- case GKEY:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initTranslation(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case SKEY:
- /* only switch when... */
- if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initResize(t);
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case RKEY:
- /* only switch when... */
- if (!(t->options & CTX_TEXTURE)) {
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
-
- if (t->mode == TFM_ROTATION) {
- initTrackball(t);
- }
- else {
- initRotation(t);
- }
- initSnapping(t, NULL); // need to reinit after mode change
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case CKEY:
- if (event->alt) {
- if (!(t->options & CTX_NO_PET)) {
- t->flag ^= T_PROP_CONNECTED;
- sort_trans_data_dist(t);
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- case OKEY:
- if (t->flag & T_PROP_EDIT && event->shift) {
- t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
- calculatePropRatio(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case PADPLUSKEY:
- if (event->alt && t->flag & T_PROP_EDIT) {
- 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)->clip_end);
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- break;
- case PAGEUPKEY:
- case WHEELDOWNMOUSE:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, 1);
- }
- else {
- view_editmove(event->type);
- }
- t->redraw = TREDRAW_HARD;
- handled = true;
- break;
- case PADMINUS:
- if (event->alt && t->flag & T_PROP_EDIT) {
- t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
- calculatePropRatio(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- break;
- case PAGEDOWNKEY:
- case WHEELUPMOUSE:
- if (t->flag & T_AUTOIK) {
- transform_autoik_update(t, -1);
- }
- else {
- view_editmove(event->type);
- }
- t->redraw = TREDRAW_HARD;
- handled = true;
- break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
- if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
- t->flag |= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case NKEY:
- if (ELEM(t->mode, TFM_ROTATION)) {
- if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
- restoreTransObjects(t);
- resetTransModal(t);
- resetTransRestrictions(t);
- initNormalRotation(t);
- t->redraw = TREDRAW_HARD;
- handled = true;
- }
- }
- break;
- default:
- break;
- }
-
- /* Snapping key events */
- t->redraw |= handleSnapping(t, event);
- }
- else if (event->val == KM_RELEASE) {
- switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- t->modifiers &= ~MOD_CONSTRAINT_PLANE;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- break;
-
- case MIDDLEMOUSE:
- if ((t->flag & T_NO_CONSTRAINT) == 0) {
- t->modifiers &= ~MOD_CONSTRAINT_SELECT;
- postSelectConstraint(t);
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- case LEFTALTKEY:
- case RIGHTALTKEY:
- if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
- t->flag &= ~T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
- break;
- default:
- break;
- }
-
- /* confirm transform if launch key is released after mouse move */
- if (t->flag & T_RELEASE_CONFIRM) {
- /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */
- if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) {
- t->state = TRANS_CONFIRM;
- }
- }
- }
-
- /* if we change snap options, get the unsnapped values back */
- if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
- (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT)))
- {
- applyMouseInput(t, &t->mouse, t->mval, t->values);
- }
-
- /* Per transform event, if present */
- if (t->handleEvent &&
- (!handled ||
- /* Needed for vertex slide, see [#38756] */
- (event->type == MOUSEMOVE)))
- {
- t->redraw |= t->handleEvent(t, event);
- }
-
- /* Try to init modal numinput now, if possible. */
- if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
- handleNumInput(t->context, &(t->num), event))
- {
- t->redraw |= TREDRAW_HARD;
- handled = true;
- }
-
- if (t->redraw &&
- !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))
- {
- WM_window_status_area_tag_redraw(CTX_wm_window(t->context));
- }
-
- if (handled || t->redraw) {
- return 0;
- }
- else {
- return OPERATOR_PASS_THROUGH;
- }
+ char cmode = constraintModeToChar(t);
+ bool handled = false;
+ const int modifiers_prev = t->modifiers;
+
+ t->redraw |= handleMouseInput(t, &t->mouse, event);
+
+ /* Handle modal numinput events first, if already activated. */
+ if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) &&
+ handleNumInput(t->context, &(t->num), event)) {
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (event->type == MOUSEMOVE) {
+ if (t->modifiers & MOD_CONSTRAINT_SELECT)
+ t->con.mode |= CON_SELECT;
+
+ copy_v2_v2_int(t->mval, event->mval);
+
+ /* Use this for soft redraw. Might cause flicker in object mode */
+ // t->redraw |= TREDRAW_SOFT;
+ t->redraw |= TREDRAW_HARD;
+
+ if (t->state == TRANS_STARTING) {
+ t->state = TRANS_RUNNING;
+ }
+
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+
+ // Snapping mouse move events
+ t->redraw |= handleSnapping(t, event);
+ handled = true;
+ }
+ /* handle modal keymap first */
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case TFM_MODAL_CANCEL:
+ t->state = TRANS_CANCEL;
+ handled = true;
+ break;
+ case TFM_MODAL_CONFIRM:
+ t->state = TRANS_CONFIRM;
+ handled = true;
+ break;
+ case TFM_MODAL_TRANSLATE:
+ /* only switch when... */
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TRACKBALL,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initTranslation(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ WM_event_add_mousemove(t->context);
+ handled = true;
+ }
+ else if (t->mode == TFM_SEQ_SLIDE) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else {
+ if (t->obedit_type == OB_MESH) {
+ if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ /* first try edge slide */
+ initEdgeSlide(t);
+ /* if that fails, do vertex slide */
+ if (t->state == TRANS_CANCEL) {
+ resetTransModal(t);
+ t->state = TRANS_STARTING;
+ initVertSlide(t);
+ }
+ /* vert slide can fail on unconnected vertices (rare but possible) */
+ if (t->state == TRANS_CANCEL) {
+ resetTransModal(t);
+ t->mode = TFM_TRANSLATION;
+ t->state = TRANS_STARTING;
+ restoreTransObjects(t);
+ resetTransRestrictions(t);
+ initTranslation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ WM_event_add_mousemove(t->context);
+ }
+ }
+ else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
+ if (t->mode == TFM_TRANSLATION) {
+ restoreTransObjects(t);
+
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ }
+ break;
+ case TFM_MODAL_ROTATE:
+ /* only switch when... */
+ if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TRACKBALL,
+ TFM_TRANSLATION,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ if (t->mode == TFM_ROTATION) {
+ initTrackball(t);
+ }
+ else {
+ initRotation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case TFM_MODAL_RESIZE:
+ /* only switch when... */
+ if (ELEM(t->mode,
+ TFM_ROTATION,
+ TFM_TRANSLATION,
+ TFM_TRACKBALL,
+ TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE)) {
+
+ /* Scale isn't normally very useful after extrude along normals, see T39756 */
+ if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) {
+ stopConstraint(t);
+ }
+
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initResize(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ else if (t->mode == TFM_RESIZE) {
+ if (t->options & CTX_MOVIECLIP) {
+ restoreTransObjects(t);
+
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+
+ case TFM_MODAL_SNAP_INV_ON:
+ t->modifiers |= MOD_SNAP_INVERT;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_SNAP_INV_OFF:
+ t->modifiers &= ~MOD_SNAP_INVERT;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_SNAP_TOGGLE:
+ t->modifiers ^= MOD_SNAP;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_AXIS_X:
+ if (!(t->flag & T_NO_CONSTRAINT)) {
+ transform_event_xyz_constraint(t, XKEY, cmode, false);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AXIS_Y:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ transform_event_xyz_constraint(t, YKEY, cmode, false);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AXIS_Z:
+ if ((t->flag & (T_NO_CONSTRAINT)) == 0) {
+ transform_event_xyz_constraint(t, ZKEY, cmode, false);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PLANE_X:
+ if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
+ transform_event_xyz_constraint(t, XKEY, cmode, true);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PLANE_Y:
+ if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
+ transform_event_xyz_constraint(t, YKEY, cmode, true);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PLANE_Z:
+ if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) {
+ transform_event_xyz_constraint(t, ZKEY, cmode, true);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_CONS_OFF:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ stopConstraint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_ADD_SNAP:
+ addSnapPoint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_REMOVE_SNAP:
+ removeSnapPoint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+ case TFM_MODAL_PROPSIZE:
+ /* MOUSEPAN usage... */
+ if (t->flag & T_PROP_EDIT) {
+ float fac = 1.0f + 0.005f * (event->y - event->prevy);
+ t->prop_size *= fac;
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
+ t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end),
+ T_PROP_SIZE_MIN);
+ }
+ else {
+ t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN);
+ }
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PROPSIZE_UP:
+ if (t->flag & T_PROP_EDIT) {
+ 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)->clip_end);
+ }
+ else {
+ t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX);
+ }
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_PROPSIZE_DOWN:
+ if (t->flag & T_PROP_EDIT) {
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
+ t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN);
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AUTOIK_LEN_INC:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, 1);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_AUTOIK_LEN_DEC:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, -1);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case TFM_MODAL_INSERTOFS_TOGGLE_DIR:
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ BLI_assert(t->sa->spacetype == t->spacetype);
+
+ if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT;
+ }
+ else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) {
+ snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ t->redraw |= TREDRAW_SOFT;
+ }
+ break;
+ /* Those two are only handled in transform's own handler, see T44634! */
+ case TFM_MODAL_EDGESLIDE_UP:
+ case TFM_MODAL_EDGESLIDE_DOWN:
+ default:
+ break;
+ }
+ }
+ /* else do non-mapped events */
+ else if (event->val == KM_PRESS) {
+ switch (event->type) {
+ case RIGHTMOUSE:
+ t->state = TRANS_CANCEL;
+ handled = true;
+ break;
+ /* enforce redraw of transform when modifiers are used */
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ t->modifiers |= MOD_CONSTRAINT_PLANE;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+
+ case SPACEKEY:
+ t->state = TRANS_CONFIRM;
+ handled = true;
+ break;
+
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ /* exception for switching to dolly, or trackball, in camera view */
+ if (t->flag & T_CAMERA) {
+ if (t->mode == TFM_TRANSLATION)
+ setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
+ else if (t->mode == TFM_ROTATION) {
+ restoreTransObjects(t);
+ initTrackball(t);
+ }
+ }
+ else {
+ t->modifiers |= MOD_CONSTRAINT_SELECT;
+ if (t->con.mode & CON_APPLY) {
+ stopConstraint(t);
+ }
+ else {
+ if (event->shift) {
+ /* bit hackish... but it prevents mmb select to print the
+ * orientation from menu */
+ float mati[3][3];
+ strcpy(t->spacename, "global");
+ unit_m3(mati);
+ initSelectConstraint(t, mati);
+ }
+ else {
+ initSelectConstraint(t, t->spacemtx);
+ }
+ postSelectConstraint(t);
+ }
+ }
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case ESCKEY:
+ t->state = TRANS_CANCEL;
+ handled = true;
+ break;
+ case PADENTER:
+ case RETKEY:
+ t->state = TRANS_CONFIRM;
+ handled = true;
+ break;
+ case GKEY:
+ /* only switch when... */
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initTranslation(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case SKEY:
+ /* only switch when... */
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initResize(t);
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case RKEY:
+ /* only switch when... */
+ if (!(t->options & CTX_TEXTURE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+
+ if (t->mode == TFM_ROTATION) {
+ initTrackball(t);
+ }
+ else {
+ initRotation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case CKEY:
+ if (event->alt) {
+ if (!(t->options & CTX_NO_PET)) {
+ t->flag ^= T_PROP_CONNECTED;
+ sort_trans_data_dist(t);
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ case OKEY:
+ if (t->flag & T_PROP_EDIT && event->shift) {
+ t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX;
+ calculatePropRatio(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case PADPLUSKEY:
+ if (event->alt && t->flag & T_PROP_EDIT) {
+ 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)->clip_end);
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case PAGEUPKEY:
+ case WHEELDOWNMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, 1);
+ }
+ else {
+ view_editmove(event->type);
+ }
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ break;
+ case PADMINUS:
+ if (event->alt && t->flag & T_PROP_EDIT) {
+ t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f;
+ calculatePropRatio(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case PAGEDOWNKEY:
+ case WHEELUPMOUSE:
+ if (t->flag & T_AUTOIK) {
+ transform_autoik_update(t, -1);
+ }
+ else {
+ view_editmove(event->type);
+ }
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ break;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
+ t->flag |= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case NKEY:
+ if (ELEM(t->mode, TFM_ROTATION)) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+ restoreTransObjects(t);
+ resetTransModal(t);
+ resetTransRestrictions(t);
+ initNormalRotation(t);
+ t->redraw = TREDRAW_HARD;
+ handled = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Snapping key events */
+ t->redraw |= handleSnapping(t, event);
+ }
+ else if (event->val == KM_RELEASE) {
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ t->modifiers &= ~MOD_CONSTRAINT_PLANE;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ break;
+
+ case MIDDLEMOUSE:
+ if ((t->flag & T_NO_CONSTRAINT) == 0) {
+ t->modifiers &= ~MOD_CONSTRAINT_SELECT;
+ postSelectConstraint(t);
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ case LEFTALTKEY:
+ case RIGHTALTKEY:
+ if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
+ t->flag &= ~T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* confirm transform if launch key is released after mouse move */
+ if (t->flag & T_RELEASE_CONFIRM) {
+ /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */
+ if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) {
+ t->state = TRANS_CONFIRM;
+ }
+ }
+ }
+
+ /* if we change snap options, get the unsnapped values back */
+ if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) !=
+ (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT))) {
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
+ }
+
+ /* Per transform event, if present */
+ if (t->handleEvent && (!handled ||
+ /* Needed for vertex slide, see [#38756] */
+ (event->type == MOUSEMOVE))) {
+ t->redraw |= t->handleEvent(t, event);
+ }
+
+ /* Try to init modal numinput now, if possible. */
+ if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) &&
+ handleNumInput(t->context, &(t->num), event)) {
+ t->redraw |= TREDRAW_HARD;
+ handled = true;
+ }
+
+ if (t->redraw && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ WM_window_status_area_tag_redraw(CTX_wm_window(t->context));
+ }
+
+ if (handled || t->redraw) {
+ return 0;
+ }
+ else {
+ return OPERATOR_PASS_THROUGH;
+ }
}
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
{
- TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
- bool success;
-
- t->context = C;
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
+ bool success;
- t->state = TRANS_RUNNING;
+ t->context = C;
- /* avoid calculating PET */
- t->options = CTX_NO_PET;
+ t->state = TRANS_RUNNING;
- t->mode = TFM_DUMMY;
+ /* avoid calculating PET */
+ t->options = CTX_NO_PET;
- initTransInfo(C, t, NULL, NULL);
+ t->mode = TFM_DUMMY;
- /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */
- t->around = V3D_AROUND_CENTER_BOUNDS;
+ initTransInfo(C, t, NULL, NULL);
- createTransData(C, t); // make TransData structs from selection
+ /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */
+ t->around = V3D_AROUND_CENTER_BOUNDS;
- t->around = centerMode; // override userdefined mode
+ createTransData(C, t); // make TransData structs from selection
- if (t->data_len_all == 0) {
- success = false;
- }
- else {
- success = true;
+ t->around = centerMode; // override userdefined mode
- calculateCenter(t);
+ if (t->data_len_all == 0) {
+ success = false;
+ }
+ else {
+ success = true;
- if (cent2d) {
- copy_v2_v2(cent2d, t->center2d);
- }
+ calculateCenter(t);
- if (cent3d) {
- // Copy center from constraint center. Transform center can be local
- copy_v3_v3(cent3d, t->center_global);
- }
- }
+ if (cent2d) {
+ copy_v2_v2(cent2d, t->center2d);
+ }
+ if (cent3d) {
+ // Copy center from constraint center. Transform center can be local
+ copy_v3_v3(cent3d, t->center_global);
+ }
+ }
- /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
- special_aftertrans_update(C, t);
+ /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
+ special_aftertrans_update(C, t);
- postTrans(C, t);
+ postTrans(C, t);
- MEM_freeN(t);
+ MEM_freeN(t);
- return success;
+ return success;
}
typedef enum {
- UP,
- DOWN,
- LEFT,
- RIGHT,
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT,
} ArrowDirection;
#define POS_INDEX 0
@@ -1677,382 +1685,384 @@ typedef enum {
static void drawArrow(ArrowDirection d, short offset, short length, short size)
{
- immBegin(GPU_PRIM_LINES, 6);
-
- switch (d) {
- case LEFT:
- offset = -offset;
- length = -length;
- size = -size;
- ATTR_FALLTHROUGH;
- case RIGHT:
- immVertex2f(POS_INDEX, offset, 0);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length - size, -size);
- immVertex2f(POS_INDEX, offset + length, 0);
- immVertex2f(POS_INDEX, offset + length - size, size);
- break;
-
- case DOWN:
- offset = -offset;
- length = -length;
- size = -size;
- ATTR_FALLTHROUGH;
- case UP:
- immVertex2f(POS_INDEX, 0, offset);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, -size, offset + length - size);
- immVertex2f(POS_INDEX, 0, offset + length);
- immVertex2f(POS_INDEX, size, offset + length - size);
- break;
- }
-
- immEnd();
+ immBegin(GPU_PRIM_LINES, 6);
+
+ switch (d) {
+ case LEFT:
+ offset = -offset;
+ length = -length;
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case RIGHT:
+ immVertex2f(POS_INDEX, offset, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, -size);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, size);
+ break;
+
+ case DOWN:
+ offset = -offset;
+ length = -length;
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case UP:
+ immVertex2f(POS_INDEX, 0, offset);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, -size, offset + length - size);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, size, offset + length - size);
+ break;
+ }
+
+ immEnd();
}
static void drawArrowHead(ArrowDirection d, short size)
{
- immBegin(GPU_PRIM_LINES, 4);
-
- switch (d) {
- case LEFT:
- size = -size;
- ATTR_FALLTHROUGH;
- case RIGHT:
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, -size);
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, size);
- break;
-
- case DOWN:
- size = -size;
- ATTR_FALLTHROUGH;
- case UP:
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, -size, -size);
- immVertex2f(POS_INDEX, 0, 0);
- immVertex2f(POS_INDEX, size, -size);
- break;
- }
-
- immEnd();
+ immBegin(GPU_PRIM_LINES, 4);
+
+ switch (d) {
+ case LEFT:
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case RIGHT:
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, size);
+ break;
+
+ case DOWN:
+ size = -size;
+ ATTR_FALLTHROUGH;
+ case UP:
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, size, -size);
+ break;
+ }
+
+ immEnd();
}
static void drawArc(float size, float angle_start, float angle_end, int segments)
{
- float delta = (angle_end - angle_start) / segments;
- float angle;
- int a;
+ float delta = (angle_end - angle_start) / segments;
+ float angle;
+ int a;
- immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
+ immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
- for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
- immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
- }
- immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
+ for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
+ immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
+ }
+ immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
- immEnd();
+ immEnd();
}
static bool helpline_poll(bContext *C)
{
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype == RGN_TYPE_WINDOW)
- return 1;
- return 0;
+ if (ar && ar->regiontype == RGN_TYPE_WINDOW)
+ return 1;
+ return 0;
}
static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
{
- TransInfo *t = (TransInfo *)customdata;
-
- if (t->helpline != HLP_NONE) {
- float cent[2];
- float mval[3] = {
- x,
- y,
- 0.0f,
- };
- float tmval[2] = {
- (float)t->mval[0],
- (float)t->mval[1],
- };
-
- projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
- /* Offset the values for the area region. */
- const float offset[2] = {
- t->ar->winrct.xmin,
- t->ar->winrct.ymin,
- };
-
- for (int i = 0; i < 2; i++) {
- cent[i] += offset[i];
- tmval[i] += offset[i];
- }
-
- GPU_matrix_push();
-
- /* Dashed lines first. */
- if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
- BLI_assert(shdr_pos == POS_INDEX);
-
- GPU_line_width(1.0f);
+ TransInfo *t = (TransInfo *)customdata;
+
+ if (t->helpline != HLP_NONE) {
+ float cent[2];
+ float mval[3] = {
+ x,
+ y,
+ 0.0f,
+ };
+ float tmval[2] = {
+ (float)t->mval[0],
+ (float)t->mval[1],
+ };
+
+ projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO);
+ /* Offset the values for the area region. */
+ const float offset[2] = {
+ t->ar->winrct.xmin,
+ t->ar->winrct.ymin,
+ };
+
+ for (int i = 0; i < 2; i++) {
+ cent[i] += offset[i];
+ tmval[i] += offset[i];
+ }
+
+ GPU_matrix_push();
+
+ /* Dashed lines first. */
+ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
+ BLI_assert(shdr_pos == POS_INDEX);
+
+ GPU_line_width(1.0f);
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_VIEW_OVERLAY);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex2fv(POS_INDEX, cent);
- immVertex2f(POS_INDEX, tmval[0], tmval[1]);
- immEnd();
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- immUnbindProgram();
- }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2fv(POS_INDEX, cent);
+ immVertex2f(POS_INDEX, tmval[0], tmval[1]);
+ immEnd();
- /* And now, solid lines. */
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- UNUSED_VARS_NDEBUG(pos); /* silence warning */
- BLI_assert(pos == POS_INDEX);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUnbindProgram();
+ }
- switch (t->helpline) {
- case HLP_SPRING:
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ /* And now, solid lines. */
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ UNUSED_VARS_NDEBUG(pos); /* silence warning */
+ BLI_assert(pos == POS_INDEX);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- GPU_matrix_translate_3fv(mval);
- GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
+ switch (t->helpline) {
+ case HLP_SPRING:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- case HLP_HARROW:
- immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_matrix_translate_3fv(mval);
+ GPU_matrix_translate_3fv(mval);
+ GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z');
- GPU_line_width(3.0f);
- drawArrow(RIGHT, 5, 10, 5);
- drawArrow(LEFT, 5, 10, 5);
- break;
- case HLP_VARROW:
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_line_width(3.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ case HLP_HARROW:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_translate_3fv(mval);
- GPU_matrix_translate_3fv(mval);
+ GPU_line_width(3.0f);
+ drawArrow(RIGHT, 5, 10, 5);
+ drawArrow(LEFT, 5, 10, 5);
+ break;
+ case HLP_VARROW:
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- case HLP_CARROW:
- {
- /* Draw arrow based on direction defined by custom-points. */
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_translate_3fv(mval);
- GPU_matrix_translate_3fv(mval);
+ GPU_line_width(3.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ case HLP_CARROW: {
+ /* Draw arrow based on direction defined by custom-points. */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
+ GPU_matrix_translate_3fv(mval);
- const int *data = t->mouse.data;
- const float dx = data[2] - data[0], dy = data[3] - data[1];
- const float angle = -atan2f(dx, dy);
+ GPU_line_width(3.0f);
- GPU_matrix_push();
+ const int *data = t->mouse.data;
+ const float dx = data[2] - data[0], dy = data[3] - data[1];
+ const float angle = -atan2f(dx, dy);
- GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z');
+ GPU_matrix_push();
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z');
- GPU_matrix_pop();
- break;
- }
- case HLP_ANGLE:
- {
- float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1];
- float angle = atan2f(dy, dx);
- float dist = hypotf(dx, dy);
- float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
- float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
- immUniformThemeColor(TH_VIEW_OVERLAY);
+ GPU_matrix_pop();
+ break;
+ }
+ case HLP_ANGLE: {
+ float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1];
+ float angle = atan2f(dy, dx);
+ float dist = hypotf(dx, dy);
+ float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
+ float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
- GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- GPU_line_width(3.0f);
- drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
- drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
+ GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0);
- GPU_matrix_push();
+ GPU_line_width(3.0f);
+ drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
+ drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
- GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
- GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z');
+ GPU_matrix_push();
- drawArrowHead(DOWN, 5);
+ GPU_matrix_translate_3f(
+ cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z');
- GPU_matrix_pop();
+ drawArrowHead(DOWN, 5);
- GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
- GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z');
+ GPU_matrix_pop();
- drawArrowHead(UP, 5);
- break;
- }
- case HLP_TRACKBALL:
- {
- unsigned char col[3], col2[3];
- UI_GetThemeColor3ubv(TH_GRID, col);
+ GPU_matrix_translate_3f(
+ cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+ GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z');
- GPU_matrix_translate_3fv(mval);
+ drawArrowHead(UP, 5);
+ break;
+ }
+ case HLP_TRACKBALL: {
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
- GPU_line_width(3.0f);
+ GPU_matrix_translate_3fv(mval);
- UI_make_axis_color(col, col2, 'X');
- immUniformColor3ubv(col2);
+ GPU_line_width(3.0f);
- drawArrow(RIGHT, 5, 10, 5);
- drawArrow(LEFT, 5, 10, 5);
+ UI_make_axis_color(col, col2, 'X');
+ immUniformColor3ubv(col2);
- UI_make_axis_color(col, col2, 'Y');
- immUniformColor3ubv(col2);
+ drawArrow(RIGHT, 5, 10, 5);
+ drawArrow(LEFT, 5, 10, 5);
- drawArrow(UP, 5, 10, 5);
- drawArrow(DOWN, 5, 10, 5);
- break;
- }
- }
+ UI_make_axis_color(col, col2, 'Y');
+ immUniformColor3ubv(col2);
- immUnbindProgram();
- GPU_matrix_pop();
- }
+ drawArrow(UP, 5, 10, 5);
+ drawArrow(DOWN, 5, 10, 5);
+ break;
+ }
+ }
+
+ immUnbindProgram();
+ GPU_matrix_pop();
+ }
}
static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *ar)
{
- /* Don't show overlays when not the active view and when overlay is disabled: T57139 */
- bool ok = false;
- if (ar == t->ar) {
- ok = true;
- }
- else {
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
- ok = true;
- }
- }
- }
- return ok;
+ /* Don't show overlays when not the active view and when overlay is disabled: T57139 */
+ bool ok = false;
+ if (ar == t->ar) {
+ ok = true;
+ }
+ else {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) {
+ ok = true;
+ }
+ }
+ }
+ return ok;
}
static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg)
{
- TransInfo *t = arg;
+ TransInfo *t = arg;
- if (!transinfo_show_overlay(C, t, ar)) {
- return;
- }
+ if (!transinfo_show_overlay(C, t, ar)) {
+ return;
+ }
- GPU_line_width(1.0f);
+ GPU_line_width(1.0f);
- drawConstraint(t);
- drawPropCircle(C, t);
- drawSnapping(C, t);
+ drawConstraint(t);
+ drawPropCircle(C, t);
+ drawSnapping(C, t);
- if (ar == t->ar) {
- /* edge slide, vert slide */
- drawEdgeSlide(t);
- drawVertSlide(t);
+ if (ar == t->ar) {
+ /* edge slide, vert slide */
+ drawEdgeSlide(t);
+ drawVertSlide(t);
- /* Rotation */
- drawDial3d(t);
- }
+ /* Rotation */
+ drawDial3d(t);
+ }
}
/* just draw a little warning message in the top-right corner of the viewport
* to warn that autokeying is enabled */
static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
{
- rcti rect;
- const char *printable = IFACE_("Auto Keying On");
- float printable_size[2];
- int xco, yco;
+ rcti rect;
+ const char *printable = IFACE_("Auto Keying On");
+ float printable_size[2];
+ int xco, yco;
- ED_region_visible_rect(ar, &rect);
+ ED_region_visible_rect(ar, &rect);
- const int font_id = BLF_default();
- BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
+ const int font_id = BLF_default();
+ BLF_width_and_height(
+ font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
- xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
- yco = (rect.ymax - U.widget_unit);
+ xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ yco = (rect.ymax - U.widget_unit);
- /* warning text (to clarify meaning of overlays)
- * - original color was red to match the icon, but that clashes badly with a less nasty border
- */
- unsigned char color[3];
- UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
- BLF_color3ubv(font_id, color);
+ /* warning text (to clarify meaning of overlays)
+ * - original color was red to match the icon, but that clashes badly with a less nasty border
+ */
+ unsigned char color[3];
+ UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color);
+ BLF_color3ubv(font_id, color);
#ifdef WITH_INTERNATIONAL
- BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#else
- BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#endif
- /* autokey recording icon... */
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_blend(true);
+ /* autokey recording icon... */
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
- xco -= U.widget_unit;
- yco -= (int)printable_size[1] / 2;
+ xco -= U.widget_unit;
+ yco -= (int)printable_size[1] / 2;
- UI_icon_draw(xco, yco, ICON_REC);
+ UI_icon_draw(xco, yco, ICON_REC);
- GPU_blend(false);
+ GPU_blend(false);
}
static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
{
- TransInfo *t = arg;
-
- if (!transinfo_show_overlay(C, t, ar)) {
- return;
- }
-
- if (ar == t->ar) {
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
-
- /* draw auto-key-framing hint in the corner
- * - only draw if enabled (advanced users may be distracted/annoyed),
- * for objects that will be autokeyframed (no point otherwise),
- * AND only for the active region (as showing all is too overwhelming)
- */
- if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) {
- if (ar == t->ar) {
- if (t->flag & (T_OBJECT | T_POSE)) {
- if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) {
- drawAutoKeyWarning(t, ar);
- }
- }
- }
- }
- }
+ TransInfo *t = arg;
+
+ if (!transinfo_show_overlay(C, t, ar)) {
+ return;
+ }
+
+ if (ar == t->ar) {
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+
+ /* draw auto-key-framing hint in the corner
+ * - only draw if enabled (advanced users may be distracted/annoyed),
+ * for objects that will be autokeyframed (no point otherwise),
+ * AND only for the active region (as showing all is too overwhelming)
+ */
+ if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) {
+ if (ar == t->ar) {
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) {
+ drawAutoKeyWarning(t, ar);
+ }
+ }
+ }
+ }
+ }
}
/**
@@ -2060,235 +2070,231 @@ static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg)
*/
void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- int proportional = 0;
- PropertyRNA *prop;
-
- // Save back mode in case we're in the generic operator
- if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
- RNA_property_enum_set(op->ptr, prop, t->mode);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "value"))) {
- float values[4];
-
- copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values);
-
- if (RNA_property_array_check(prop)) {
- RNA_property_float_set_array(op->ptr, prop, values);
- }
- else {
- RNA_property_float_set(op->ptr, prop, values[0]);
- }
- }
-
- /* convert flag to enum */
- switch (t->flag & T_PROP_EDIT_ALL) {
- case T_PROP_EDIT:
- proportional = PROP_EDIT_ON;
- break;
- case (T_PROP_EDIT | T_PROP_CONNECTED):
- proportional = PROP_EDIT_CONNECTED;
- break;
- case (T_PROP_EDIT | T_PROP_PROJECTED):
- proportional = PROP_EDIT_PROJECTED;
- break;
- default:
- proportional = PROP_EDIT_OFF;
- break;
- }
-
- // If modal, save settings back in scene if not set as operator argument
- if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
- /* save settings if not set in operator */
-
- /* skip saving proportional edit if it was not actually used */
- if (!(t->options & CTX_NO_PET)) {
- if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- if (t->spacetype == SPACE_GRAPH)
- ts->proportional_fcurve = proportional;
- else if (t->spacetype == SPACE_ACTION)
- ts->proportional_action = proportional;
- else if (t->obedit_type != -1)
- ts->proportional = proportional;
- else if (t->options & CTX_MASK)
- ts->proportional_mask = (proportional != PROP_EDIT_OFF);
- else
- ts->proportional_objects = (proportional != PROP_EDIT_OFF);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) {
- ts->proportional_size =
- RNA_property_is_set(op->ptr, prop) ? RNA_property_float_get(op->ptr, prop) : t->prop_size;
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->prop_mode = t->prop_mode;
- }
- }
-
- /* do we check for parameter? */
- if (transformModeUseSnap(t)) {
- if (t->modifiers & MOD_SNAP) {
- ts->snap_flag |= SCE_SNAP;
- }
- else {
- ts->snap_flag &= ~SCE_SNAP;
- }
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
- !RNA_property_is_set(op->ptr, prop) &&
- (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX))
- {
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
- orient_slot->type = t->orientation.user;
- BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) ||
- (BKE_scene_transform_orientation_get_index(
- t->scene, t->orientation.custom) == orient_slot->index_custom));
- }
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
- RNA_property_enum_set(op->ptr, prop, proportional);
- RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
- RNA_float_set(op->ptr, "proportional_size", t->prop_size);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
- RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
- }
-
- /* Orientation used for redo. */
- const bool use_orient_axis = (
- t->orient_matrix_is_set &&
- (RNA_struct_find_property(op->ptr, "orient_axis") != NULL));
- short orientation;
- if (t->con.mode & CON_APPLY) {
- orientation = t->con.orientation;
- if (orientation == V3D_ORIENT_CUSTOM) {
- const int orientation_index_custom = BKE_scene_transform_orientation_get_index(
- t->scene, t->orientation.custom);
- /* Maybe we need a t->con.custom_orientation?
- * Seems like it would always match t->orientation.custom. */
- orientation = V3D_ORIENT_CUSTOM + orientation_index_custom;
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- }
- }
- else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) &&
- (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")))
- {
- orientation = RNA_property_enum_get(op->ptr, prop);
- }
- else if (use_orient_axis) {
- /* We're not using an orientation, use the fallback. */
- orientation = t->orientation.unset;
- }
- else {
- orientation = V3D_ORIENT_GLOBAL;
- }
-
-
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
- if (t->flag & T_MODAL) {
- if (t->con.mode & CON_APPLY) {
- int orient_axis = constraintModeToIndex(t);
- if (orient_axis != -1) {
- RNA_property_enum_set(op->ptr, prop, orient_axis);
- }
- }
- else {
- RNA_property_enum_set(op->ptr, prop, t->orient_axis);
- }
- }
- }
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
- if (t->flag & T_MODAL) {
- RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho);
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) {
- if (t->flag & T_MODAL) {
- if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
- if (t->flag & T_MODAL) {
- RNA_enum_set(op->ptr, "orient_matrix_type", orientation);
- }
- }
- if (t->con.mode & CON_APPLY) {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]);
- }
- else if (use_orient_axis) {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]);
- }
- else {
- RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
- }
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) {
- /* constraint orientation can be global, even if user selects something else
- * so use the orientation in the constraint if set */
-
- /* Use 'orient_matrix' instead. */
- if (t->flag & T_MODAL) {
- if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
- RNA_property_enum_set(op->ptr, prop, orientation);
- }
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
- bool constraint_axis[3] = {false, false, false};
- if (t->flag & T_MODAL) {
- /* Only set if needed, so we can hide in the UI when nothing is set.
- * See 'transform_poll_property'. */
- if (t->con.mode & CON_APPLY) {
- if (t->con.mode & CON_AXIS0) {
- constraint_axis[0] = true;
- }
- if (t->con.mode & CON_AXIS1) {
- constraint_axis[1] = true;
- }
- if (t->con.mode & CON_AXIS2) {
- constraint_axis[2] = true;
- }
- }
- if (ELEM(true, UNPACK3(constraint_axis))) {
- RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
- }
- }
- }
-
- {
- const char *prop_id = NULL;
- bool prop_state = true;
- if (t->mode == TFM_SHRINKFATTEN) {
- prop_id = "use_even_offset";
- prop_state = false;
- }
-
- 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) == prop_state);
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
- RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
- }
-
- if (t->mode == TFM_SHEAR) {
- prop = RNA_struct_find_property(op->ptr, "shear_axis");
- t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
- RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data));
- }
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ int proportional = 0;
+ PropertyRNA *prop;
+
+ // Save back mode in case we're in the generic operator
+ if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
+ RNA_property_enum_set(op->ptr, prop, t->mode);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "value"))) {
+ float values[4];
+
+ copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values);
+
+ if (RNA_property_array_check(prop)) {
+ RNA_property_float_set_array(op->ptr, prop, values);
+ }
+ else {
+ RNA_property_float_set(op->ptr, prop, values[0]);
+ }
+ }
+
+ /* convert flag to enum */
+ switch (t->flag & T_PROP_EDIT_ALL) {
+ case T_PROP_EDIT:
+ proportional = PROP_EDIT_ON;
+ break;
+ case (T_PROP_EDIT | T_PROP_CONNECTED):
+ proportional = PROP_EDIT_CONNECTED;
+ break;
+ case (T_PROP_EDIT | T_PROP_PROJECTED):
+ proportional = PROP_EDIT_PROJECTED;
+ break;
+ default:
+ proportional = PROP_EDIT_OFF;
+ break;
+ }
+
+ // If modal, save settings back in scene if not set as operator argument
+ if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
+ /* save settings if not set in operator */
+
+ /* skip saving proportional edit if it was not actually used */
+ if (!(t->options & CTX_NO_PET)) {
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
+ !RNA_property_is_set(op->ptr, prop)) {
+ if (t->spacetype == SPACE_GRAPH)
+ ts->proportional_fcurve = proportional;
+ else if (t->spacetype == SPACE_ACTION)
+ ts->proportional_action = proportional;
+ else if (t->obedit_type != -1)
+ ts->proportional = proportional;
+ else if (t->options & CTX_MASK)
+ ts->proportional_mask = (proportional != PROP_EDIT_OFF);
+ else
+ ts->proportional_objects = (proportional != PROP_EDIT_OFF);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) {
+ ts->proportional_size = RNA_property_is_set(op->ptr, prop) ?
+ RNA_property_float_get(op->ptr, prop) :
+ t->prop_size;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ !RNA_property_is_set(op->ptr, prop)) {
+ ts->prop_mode = t->prop_mode;
+ }
+ }
+
+ /* do we check for parameter? */
+ if (transformModeUseSnap(t)) {
+ if (t->modifiers & MOD_SNAP) {
+ ts->snap_flag |= SCE_SNAP;
+ }
+ else {
+ ts->snap_flag &= ~SCE_SNAP;
+ }
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
+ !RNA_property_is_set(op->ptr, prop) &&
+ (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) {
+ TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+ orient_slot->type = t->orientation.user;
+ BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) ||
+ (BKE_scene_transform_orientation_get_index(t->scene, t->orientation.custom) ==
+ orient_slot->index_custom));
+ }
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ RNA_property_enum_set(op->ptr, prop, proportional);
+ RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
+ RNA_float_set(op->ptr, "proportional_size", t->prop_size);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
+ RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
+ }
+
+ /* Orientation used for redo. */
+ const bool use_orient_axis = (t->orient_matrix_is_set &&
+ (RNA_struct_find_property(op->ptr, "orient_axis") != NULL));
+ short orientation;
+ if (t->con.mode & CON_APPLY) {
+ orientation = t->con.orientation;
+ if (orientation == V3D_ORIENT_CUSTOM) {
+ const int orientation_index_custom = BKE_scene_transform_orientation_get_index(
+ t->scene, t->orientation.custom);
+ /* Maybe we need a t->con.custom_orientation?
+ * Seems like it would always match t->orientation.custom. */
+ orientation = V3D_ORIENT_CUSTOM + orientation_index_custom;
+ BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
+ }
+ }
+ else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) &&
+ (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) {
+ orientation = RNA_property_enum_get(op->ptr, prop);
+ }
+ else if (use_orient_axis) {
+ /* We're not using an orientation, use the fallback. */
+ orientation = t->orientation.unset;
+ }
+ else {
+ orientation = V3D_ORIENT_GLOBAL;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
+ if (t->flag & T_MODAL) {
+ if (t->con.mode & CON_APPLY) {
+ int orient_axis = constraintModeToIndex(t);
+ if (orient_axis != -1) {
+ RNA_property_enum_set(op->ptr, prop, orient_axis);
+ }
+ }
+ else {
+ RNA_property_enum_set(op->ptr, prop, t->orient_axis);
+ }
+ }
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
+ if (t->flag & T_MODAL) {
+ RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho);
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) {
+ if (t->flag & T_MODAL) {
+ if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
+ if (t->flag & T_MODAL) {
+ RNA_enum_set(op->ptr, "orient_matrix_type", orientation);
+ }
+ }
+ if (t->con.mode & CON_APPLY) {
+ RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]);
+ }
+ else if (use_orient_axis) {
+ RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]);
+ }
+ else {
+ RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]);
+ }
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) {
+ /* constraint orientation can be global, even if user selects something else
+ * so use the orientation in the constraint if set */
+
+ /* Use 'orient_matrix' instead. */
+ if (t->flag & T_MODAL) {
+ if (orientation != V3D_ORIENT_CUSTOM_MATRIX) {
+ RNA_property_enum_set(op->ptr, prop, orientation);
+ }
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
+ bool constraint_axis[3] = {false, false, false};
+ if (t->flag & T_MODAL) {
+ /* Only set if needed, so we can hide in the UI when nothing is set.
+ * See 'transform_poll_property'. */
+ if (t->con.mode & CON_APPLY) {
+ if (t->con.mode & CON_AXIS0) {
+ constraint_axis[0] = true;
+ }
+ if (t->con.mode & CON_AXIS1) {
+ constraint_axis[1] = true;
+ }
+ if (t->con.mode & CON_AXIS2) {
+ constraint_axis[2] = true;
+ }
+ }
+ if (ELEM(true, UNPACK3(constraint_axis))) {
+ RNA_property_boolean_set_array(op->ptr, prop, constraint_axis);
+ }
+ }
+ }
+
+ {
+ const char *prop_id = NULL;
+ bool prop_state = true;
+ if (t->mode == TFM_SHRINKFATTEN) {
+ prop_id = "use_even_offset";
+ prop_state = false;
+ }
+
+ 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) == prop_state);
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
+ RNA_property_boolean_set(
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ }
+
+ if (t->mode == TFM_SHEAR) {
+ prop = RNA_struct_find_property(op->ptr, "shear_axis");
+ t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
+ RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data));
+ }
}
/**
@@ -2298,896 +2304,896 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
*/
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
{
- int options = 0;
- PropertyRNA *prop;
-
- t->context = C;
-
- /* added initialize, for external calls to set stuff in TransInfo, like undo string */
-
- t->state = TRANS_STARTING;
-
- if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_CURSOR;
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_TEXTURE;
- }
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- options |= CTX_GPENCIL_STROKES;
- }
- }
-
- t->options = options;
-
- t->mode = mode;
-
- /* Needed to translate tweak events to mouse buttons. */
- t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1;
-
- // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0)
- // For gizmo only, so assume LEFTMOUSE
- if (t->launch_event == 0) {
- t->launch_event = LEFTMOUSE;
- }
-
- unit_m3(t->spacemtx);
-
- initTransInfo(C, t, op, event);
- initTransformOrientation(C, t);
-
- if (t->spacetype == SPACE_VIEW3D) {
- t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
- t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_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),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- 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),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_CLIP) {
- 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),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_NODE) {
- /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/
- t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- 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),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
- else if (t->spacetype == SPACE_ACTION) {
- 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),
- SPACE_TYPE_ANY, RGN_TYPE_ANY,
- helpline_poll, drawHelpline, t);
- }
-
- createTransData(C, t); // make TransData structs from selection
-
- if (t->data_len_all == 0) {
- postTrans(C, t);
- return 0;
- }
-
- if (event) {
- /* keymap for shortcut header prints */
- t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
-
- /* Stupid code to have Ctrl-Click on gizmo work ok.
- *
- * Do this only for translation/rotation/resize because only these
- * modes are available from gizmo and doing such check could
- * lead to keymap conflicts for other modes (see #31584)
- */
- if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
- wmKeyMapItem *kmi;
-
- for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
- if (kmi->flag & KMI_INACTIVE) {
- continue;
- }
-
- if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) {
- if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) ||
- (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) ||
- (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) ||
- ((kmi->type == OSKEY) && event->oskey) )
- {
- t->modifiers |= MOD_SNAP_INVERT;
- }
- break;
- }
- }
- }
- }
-
- initSnapping(t, op); // Initialize snapping data AFTER mode flags
-
- initSnapSpatial(t, t->snap_spatial);
-
- /* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
- * will be removed (ton) */
-
- /* EVIL2: we gave as argument also texture space context bit... was cleared */
-
- /* EVIL3: extend mode for animation editors also switches modes...
- * but is best way to avoid duplicate code */
- mode = t->mode;
-
- calculatePropRatio(t);
- calculateCenter(t);
-
- /* Overwrite initial values if operator supplied a non-null vector.
- *
- * Run before init functions so 'values_modal_offset' can be applied on mouse input.
- */
- BLI_assert(is_zero_v4(t->values_modal_offset));
- 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 */
-
- if (RNA_property_array_check(prop)) {
- RNA_float_get_array(op->ptr, "value", values);
- }
- else {
- values[0] = RNA_float_get(op->ptr, "value");
- }
-
- copy_v4_v4(t->values, values);
-
- if (t->flag & T_MODAL) {
- copy_v4_v4(t->values_modal_offset, values);
- t->redraw = TREDRAW_HARD;
- }
- else {
- copy_v4_v4(t->auto_values, values);
- t->flag |= T_AUTOVALUES;
- }
- }
-
- if (event) {
- /* Initialize accurate transform to settings requested by keymap. */
- bool use_accurate = false;
- if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- use_accurate = true;
- }
- }
- initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate);
- }
-
- switch (mode) {
- case TFM_TRANSLATION:
- initTranslation(t);
- break;
- case TFM_ROTATION:
- initRotation(t);
- break;
- case TFM_RESIZE:
- initResize(t);
- break;
- case TFM_SKIN_RESIZE:
- initSkinResize(t);
- break;
- case TFM_TOSPHERE:
- initToSphere(t);
- break;
- case TFM_SHEAR:
- prop = RNA_struct_find_property(op->ptr, "shear_axis");
- t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
- initShear(t);
- break;
- case TFM_BEND:
- initBend(t);
- break;
- case TFM_SHRINKFATTEN:
- initShrinkFatten(t);
- break;
- case TFM_TILT:
- initTilt(t);
- break;
- case TFM_CURVE_SHRINKFATTEN:
- initCurveShrinkFatten(t);
- break;
- case TFM_MASK_SHRINKFATTEN:
- initMaskShrinkFatten(t);
- break;
- case TFM_GPENCIL_SHRINKFATTEN:
- initGPShrinkFatten(t);
- break;
- case TFM_TRACKBALL:
- initTrackball(t);
- break;
- case TFM_PUSHPULL:
- initPushPull(t);
- break;
- case TFM_CREASE:
- initCrease(t);
- break;
- case TFM_BONESIZE:
- { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
- /* Note: we have to pick one, use the active object. */
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
- bArmature *arm = tc->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE) {
- initBoneEnvelope(t);
- 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:
- case TFM_VERT_SLIDE:
- {
- const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false);
- const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false);
- const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true);
- if (mode == TFM_EDGE_SLIDE) {
- const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
- initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp);
- }
- else {
- initVertSlide_ex(t, use_even, flipped, use_clamp);
- }
- break;
- }
- case TFM_BONE_ROLL:
- initBoneRoll(t);
- break;
- case TFM_TIME_TRANSLATE:
- initTimeTranslate(t);
- break;
- case TFM_TIME_SLIDE:
- initTimeSlide(t);
- break;
- case TFM_TIME_SCALE:
- initTimeScale(t);
- break;
- case TFM_TIME_DUPLICATE:
- /* same as TFM_TIME_EXTEND, but we need the mode info for later
- * so that duplicate-culling will work properly
- */
- if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA))
- initTranslation(t);
- else
- initTimeTranslate(t);
- t->mode = mode;
- break;
- case TFM_TIME_EXTEND:
- /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
- * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
- * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement)
- * depending on which editor this was called from
- */
- if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA))
- initTranslation(t);
- else
- initTimeTranslate(t);
- break;
- case TFM_BAKE_TIME:
- initBakeTime(t);
- break;
- case TFM_MIRROR:
- initMirror(t);
- break;
- case TFM_BWEIGHT:
- initBevelWeight(t);
- break;
- case TFM_ALIGN:
- initAlign(t);
- break;
- case TFM_SEQ_SLIDE:
- initSeqSlide(t);
- break;
- case TFM_NORMAL_ROTATION:
- initNormalRotation(t);
- break;
- case TFM_GPENCIL_OPACITY:
- initGPOpacity(t);
- break;
- }
-
- if (t->state == TRANS_CANCEL) {
- postTrans(C, t);
- return 0;
- }
-
- /* Transformation axis from operator */
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) &&
- RNA_property_is_set(op->ptr, prop))
- {
- t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) &&
- RNA_property_is_set(op->ptr, prop))
- {
- t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
- }
-
- /* Constraint init from operator */
- if ((t->flag & T_MODAL) ||
- /* For mirror operator the constraint axes are effectively the values. */
- (RNA_struct_find_property(op->ptr, "values") == NULL))
- {
- if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) &&
- RNA_property_is_set(op->ptr, prop))
- {
- bool constraint_axis[3];
-
- RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
-
- if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
- t->con.mode |= CON_APPLY;
-
- if (constraint_axis[0]) {
- t->con.mode |= CON_AXIS0;
- }
- if (constraint_axis[1]) {
- t->con.mode |= CON_AXIS1;
- }
- if (constraint_axis[2]) {
- t->con.mode |= CON_AXIS2;
- }
-
- setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
- }
- }
- }
- else {
- /* So we can adjust in non global orientation. */
- if (t->orientation.user != V3D_ORIENT_GLOBAL) {
- t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2;
- setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
- }
- }
-
- /* Don't write into the values when non-modal because they are already set from operator redo values. */
- if (t->flag & T_MODAL) {
- /* Setup the mouse input with initial values. */
- applyMouseInput(t, &t->mouse, t->mouse.imval, t->values);
- }
-
- if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
- if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) {
- BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit);
- bool do_skip = false;
-
- /* Currently only used for two of three most frequent transform ops,
- * can include more ops.
- * Note that scaling cannot be included here,
- * non-uniform scaling will affect normals. */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) {
- if (em->bm->totvertsel == em->bm->totvert) {
- /* No need to invalidate if whole mesh is selected. */
- do_skip = true;
- }
- }
-
- if (t->flag & T_MODAL) {
- RNA_property_boolean_set(op->ptr, prop, false);
- }
- else if (!do_skip) {
- const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
- if (preserve_clnor) {
- BKE_editmesh_lnorspace_update(em);
- t->flag |= T_CLNOR_REBUILD;
- }
- BM_lnorspace_invalidate(em->bm, true);
- }
- }
- }
- }
- }
-
- t->context = NULL;
-
- return 1;
+ int options = 0;
+ PropertyRNA *prop;
+
+ t->context = C;
+
+ /* added initialize, for external calls to set stuff in TransInfo, like undo string */
+
+ t->state = TRANS_STARTING;
+
+ if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_CURSOR;
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_TEXTURE;
+ }
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ options |= CTX_GPENCIL_STROKES;
+ }
+ }
+
+ t->options = options;
+
+ t->mode = mode;
+
+ /* Needed to translate tweak events to mouse buttons. */
+ t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1;
+
+ // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0)
+ // For gizmo only, so assume LEFTMOUSE
+ if (t->launch_event == 0) {
+ t->launch_event = LEFTMOUSE;
+ }
+
+ unit_m3(t->spacemtx);
+
+ initTransInfo(C, t, op, event);
+ initTransformOrientation(C, t);
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ t->draw_handle_apply = ED_region_draw_cb_activate(
+ t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
+ t->draw_handle_view = ED_region_draw_cb_activate(
+ t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->draw_handle_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), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ 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), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ 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), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/
+ t->draw_handle_view = ED_region_draw_cb_activate(
+ t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ 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), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ 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), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t);
+ }
+
+ createTransData(C, t); // make TransData structs from selection
+
+ if (t->data_len_all == 0) {
+ postTrans(C, t);
+ return 0;
+ }
+
+ if (event) {
+ /* keymap for shortcut header prints */
+ t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
+
+ /* Stupid code to have Ctrl-Click on gizmo work ok.
+ *
+ * Do this only for translation/rotation/resize because only these
+ * modes are available from gizmo and doing such check could
+ * lead to keymap conflicts for other modes (see #31584)
+ */
+ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
+ wmKeyMapItem *kmi;
+
+ for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
+ if (kmi->flag & KMI_INACTIVE) {
+ continue;
+ }
+
+ if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) {
+ if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) ||
+ (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) ||
+ (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) ||
+ ((kmi->type == OSKEY) && event->oskey)) {
+ t->modifiers |= MOD_SNAP_INVERT;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ initSnapping(t, op); // Initialize snapping data AFTER mode flags
+
+ initSnapSpatial(t, t->snap_spatial);
+
+ /* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
+ * will be removed (ton) */
+
+ /* EVIL2: we gave as argument also texture space context bit... was cleared */
+
+ /* EVIL3: extend mode for animation editors also switches modes...
+ * but is best way to avoid duplicate code */
+ mode = t->mode;
+
+ calculatePropRatio(t);
+ calculateCenter(t);
+
+ /* Overwrite initial values if operator supplied a non-null vector.
+ *
+ * Run before init functions so 'values_modal_offset' can be applied on mouse input.
+ */
+ BLI_assert(is_zero_v4(t->values_modal_offset));
+ 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 */
+
+ if (RNA_property_array_check(prop)) {
+ RNA_float_get_array(op->ptr, "value", values);
+ }
+ else {
+ values[0] = RNA_float_get(op->ptr, "value");
+ }
+
+ copy_v4_v4(t->values, values);
+
+ if (t->flag & T_MODAL) {
+ copy_v4_v4(t->values_modal_offset, values);
+ t->redraw = TREDRAW_HARD;
+ }
+ else {
+ copy_v4_v4(t->auto_values, values);
+ t->flag |= T_AUTOVALUES;
+ }
+ }
+
+ if (event) {
+ /* Initialize accurate transform to settings requested by keymap. */
+ bool use_accurate = false;
+ if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ use_accurate = true;
+ }
+ }
+ initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate);
+ }
+
+ switch (mode) {
+ case TFM_TRANSLATION:
+ initTranslation(t);
+ break;
+ case TFM_ROTATION:
+ initRotation(t);
+ break;
+ case TFM_RESIZE:
+ initResize(t);
+ break;
+ case TFM_SKIN_RESIZE:
+ initSkinResize(t);
+ break;
+ case TFM_TOSPHERE:
+ initToSphere(t);
+ break;
+ case TFM_SHEAR:
+ prop = RNA_struct_find_property(op->ptr, "shear_axis");
+ t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop));
+ initShear(t);
+ break;
+ case TFM_BEND:
+ initBend(t);
+ break;
+ case TFM_SHRINKFATTEN:
+ initShrinkFatten(t);
+ break;
+ case TFM_TILT:
+ initTilt(t);
+ break;
+ case TFM_CURVE_SHRINKFATTEN:
+ initCurveShrinkFatten(t);
+ break;
+ case TFM_MASK_SHRINKFATTEN:
+ initMaskShrinkFatten(t);
+ break;
+ case TFM_GPENCIL_SHRINKFATTEN:
+ initGPShrinkFatten(t);
+ break;
+ case TFM_TRACKBALL:
+ initTrackball(t);
+ break;
+ case TFM_PUSHPULL:
+ initPushPull(t);
+ break;
+ case TFM_CREASE:
+ initCrease(t);
+ break;
+ case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
+ /* Note: we have to pick one, use the active object. */
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ bArmature *arm = tc->poseobj->data;
+ if (arm->drawtype == ARM_ENVELOPE) {
+ initBoneEnvelope(t);
+ 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:
+ case TFM_VERT_SLIDE: {
+ const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false);
+ const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false);
+ const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true);
+ if (mode == TFM_EDGE_SLIDE) {
+ const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
+ initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp);
+ }
+ else {
+ initVertSlide_ex(t, use_even, flipped, use_clamp);
+ }
+ break;
+ }
+ case TFM_BONE_ROLL:
+ initBoneRoll(t);
+ break;
+ case TFM_TIME_TRANSLATE:
+ initTimeTranslate(t);
+ break;
+ case TFM_TIME_SLIDE:
+ initTimeSlide(t);
+ break;
+ case TFM_TIME_SCALE:
+ initTimeScale(t);
+ break;
+ case TFM_TIME_DUPLICATE:
+ /* same as TFM_TIME_EXTEND, but we need the mode info for later
+ * so that duplicate-culling will work properly
+ */
+ if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA))
+ initTranslation(t);
+ else
+ initTimeTranslate(t);
+ t->mode = mode;
+ break;
+ case TFM_TIME_EXTEND:
+ /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation
+ * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION
+ * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement)
+ * depending on which editor this was called from
+ */
+ if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA))
+ initTranslation(t);
+ else
+ initTimeTranslate(t);
+ break;
+ case TFM_BAKE_TIME:
+ initBakeTime(t);
+ break;
+ case TFM_MIRROR:
+ initMirror(t);
+ break;
+ case TFM_BWEIGHT:
+ initBevelWeight(t);
+ break;
+ case TFM_ALIGN:
+ initAlign(t);
+ break;
+ case TFM_SEQ_SLIDE:
+ initSeqSlide(t);
+ break;
+ case TFM_NORMAL_ROTATION:
+ initNormalRotation(t);
+ break;
+ case TFM_GPENCIL_OPACITY:
+ initGPOpacity(t);
+ break;
+ }
+
+ if (t->state == TRANS_CANCEL) {
+ postTrans(C, t);
+ return 0;
+ }
+
+ /* Transformation axis from operator */
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ t->orient_axis = RNA_property_enum_get(op->ptr, prop);
+ }
+ if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ /* Constraint init from operator */
+ if ((t->flag & T_MODAL) ||
+ /* For mirror operator the constraint axes are effectively the values. */
+ (RNA_struct_find_property(op->ptr, "values") == NULL)) {
+ if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ bool constraint_axis[3];
+
+ RNA_property_boolean_get_array(op->ptr, prop, constraint_axis);
+
+ if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) {
+ t->con.mode |= CON_APPLY;
+
+ if (constraint_axis[0]) {
+ t->con.mode |= CON_AXIS0;
+ }
+ if (constraint_axis[1]) {
+ t->con.mode |= CON_AXIS1;
+ }
+ if (constraint_axis[2]) {
+ t->con.mode |= CON_AXIS2;
+ }
+
+ setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
+ }
+ }
+ }
+ else {
+ /* So we can adjust in non global orientation. */
+ if (t->orientation.user != V3D_ORIENT_GLOBAL) {
+ t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2;
+ setUserConstraint(t, t->orientation.user, t->con.mode, "%s");
+ }
+ }
+
+ /* Don't write into the values when non-modal because they are already set from operator redo values. */
+ if (t->flag & T_MODAL) {
+ /* Setup the mouse input with initial values. */
+ applyMouseInput(t, &t->mouse, t->mouse.imval, t->values);
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) {
+ if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) {
+ BMEditMesh *em = NULL; // BKE_editmesh_from_object(t->obedit);
+ bool do_skip = false;
+
+ /* Currently only used for two of three most frequent transform ops,
+ * can include more ops.
+ * Note that scaling cannot be included here,
+ * non-uniform scaling will affect normals. */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) {
+ if (em->bm->totvertsel == em->bm->totvert) {
+ /* No need to invalidate if whole mesh is selected. */
+ do_skip = true;
+ }
+ }
+
+ if (t->flag & T_MODAL) {
+ RNA_property_boolean_set(op->ptr, prop, false);
+ }
+ else if (!do_skip) {
+ const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop);
+ if (preserve_clnor) {
+ BKE_editmesh_lnorspace_update(em);
+ t->flag |= T_CLNOR_REBUILD;
+ }
+ BM_lnorspace_invalidate(em->bm, true);
+ }
+ }
+ }
+ }
+ }
+
+ t->context = NULL;
+
+ return 1;
}
void transformApply(bContext *C, TransInfo *t)
{
- t->context = C;
+ t->context = C;
- if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
- selectConstraint(t);
- if (t->transform) {
- t->transform(t, t->mval); // calls recalcData()
- viewRedrawForce(C, t);
- }
- t->redraw = TREDRAW_NOTHING;
- }
- else if (t->redraw & TREDRAW_SOFT) {
- viewRedrawForce(C, t);
- }
+ if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
+ selectConstraint(t);
+ if (t->transform) {
+ t->transform(t, t->mval); // calls recalcData()
+ viewRedrawForce(C, t);
+ }
+ t->redraw = TREDRAW_NOTHING;
+ }
+ else if (t->redraw & TREDRAW_SOFT) {
+ viewRedrawForce(C, t);
+ }
- /* If auto confirm is on, break after one pass */
- if (t->options & CTX_AUTOCONFIRM) {
- t->state = TRANS_CONFIRM;
- }
+ /* If auto confirm is on, break after one pass */
+ if (t->options & CTX_AUTOCONFIRM) {
+ t->state = TRANS_CONFIRM;
+ }
- t->context = NULL;
+ t->context = NULL;
}
static void drawTransformApply(const bContext *C, ARegion *UNUSED(ar), void *arg)
{
- TransInfo *t = arg;
+ TransInfo *t = arg;
- if (t->redraw & TREDRAW_SOFT) {
- t->redraw |= TREDRAW_HARD;
- transformApply((bContext *)C, t);
- }
+ if (t->redraw & TREDRAW_SOFT) {
+ t->redraw |= TREDRAW_HARD;
+ transformApply((bContext *)C, t);
+ }
}
int transformEnd(bContext *C, TransInfo *t)
{
- int exit_code = OPERATOR_RUNNING_MODAL;
+ int exit_code = OPERATOR_RUNNING_MODAL;
- t->context = C;
+ t->context = C;
- if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) {
- /* handle restoring objects */
- if (t->state == TRANS_CANCEL) {
- /* exception, edge slide transformed UVs too */
- if (t->mode == TFM_EDGE_SLIDE) {
- doEdgeSlide(t, 0.0f);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- doVertSlide(t, 0.0f);
- }
+ if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) {
+ /* handle restoring objects */
+ if (t->state == TRANS_CANCEL) {
+ /* exception, edge slide transformed UVs too */
+ if (t->mode == TFM_EDGE_SLIDE) {
+ doEdgeSlide(t, 0.0f);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ doVertSlide(t, 0.0f);
+ }
- exit_code = OPERATOR_CANCELLED;
- restoreTransObjects(t); // calls recalcData()
- }
- else {
- if (t->flag & T_CLNOR_REBUILD) {
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BM_lnorspace_rebuild(em->bm, true);
- }
- }
- exit_code = OPERATOR_FINISHED;
- }
+ exit_code = OPERATOR_CANCELLED;
+ restoreTransObjects(t); // calls recalcData()
+ }
+ else {
+ if (t->flag & T_CLNOR_REBUILD) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BM_lnorspace_rebuild(em->bm, true);
+ }
+ }
+ exit_code = OPERATOR_FINISHED;
+ }
- /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
- special_aftertrans_update(C, t);
+ /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */
+ special_aftertrans_update(C, t);
- /* free data */
- postTrans(C, t);
+ /* free data */
+ postTrans(C, t);
- /* send events out for redraws */
- viewRedrawPost(C, t);
+ /* send events out for redraws */
+ viewRedrawPost(C, t);
- viewRedrawForce(C, t);
- }
+ viewRedrawForce(C, t);
+ }
- t->context = NULL;
+ t->context = NULL;
- return exit_code;
+ return exit_code;
}
/* ************************** TRANSFORM LOCKS **************************** */
static void protectedTransBits(short protectflag, float vec[3])
{
- if (protectflag & OB_LOCK_LOCX)
- vec[0] = 0.0f;
- if (protectflag & OB_LOCK_LOCY)
- vec[1] = 0.0f;
- if (protectflag & OB_LOCK_LOCZ)
- vec[2] = 0.0f;
+ if (protectflag & OB_LOCK_LOCX)
+ vec[0] = 0.0f;
+ if (protectflag & OB_LOCK_LOCY)
+ vec[1] = 0.0f;
+ if (protectflag & OB_LOCK_LOCZ)
+ vec[2] = 0.0f;
}
static void protectedSizeBits(short protectflag, float size[3])
{
- if (protectflag & OB_LOCK_SCALEX)
- size[0] = 1.0f;
- if (protectflag & OB_LOCK_SCALEY)
- size[1] = 1.0f;
- if (protectflag & OB_LOCK_SCALEZ)
- size[2] = 1.0f;
+ if (protectflag & OB_LOCK_SCALEX)
+ size[0] = 1.0f;
+ if (protectflag & OB_LOCK_SCALEY)
+ size[1] = 1.0f;
+ if (protectflag & OB_LOCK_SCALEZ)
+ size[2] = 1.0f;
}
static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3])
{
- if (protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
+ if (protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
}
-
/* this function only does the delta rotation */
/* axis-angle is usually internally stored as quats... */
-static void protectedAxisAngleBits(short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle)
-{
- /* check that protection flags are set */
- if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0)
- return;
-
- if (protectflag & OB_LOCK_ROT4D) {
- /* axis-angle getting limited as 4D entities that they are... */
- if (protectflag & OB_LOCK_ROTW)
- *angle = oldAngle;
- if (protectflag & OB_LOCK_ROTX)
- axis[0] = oldAxis[0];
- if (protectflag & OB_LOCK_ROTY)
- axis[1] = oldAxis[1];
- if (protectflag & OB_LOCK_ROTZ)
- axis[2] = oldAxis[2];
- }
- else {
- /* axis-angle get limited with euler... */
- float eul[3], oldeul[3];
-
- axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle);
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle);
-
- if (protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT);
-
- /* when converting to axis-angle, we need a special exception for the case when there is no axis */
- if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
- /* for now, rotate around y-axis then (so that it simply becomes the roll) */
- axis[1] = 1.0f;
- }
- }
+static void protectedAxisAngleBits(
+ short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle)
+{
+ /* check that protection flags are set */
+ if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0)
+ return;
+
+ if (protectflag & OB_LOCK_ROT4D) {
+ /* axis-angle getting limited as 4D entities that they are... */
+ if (protectflag & OB_LOCK_ROTW)
+ *angle = oldAngle;
+ if (protectflag & OB_LOCK_ROTX)
+ axis[0] = oldAxis[0];
+ if (protectflag & OB_LOCK_ROTY)
+ axis[1] = oldAxis[1];
+ if (protectflag & OB_LOCK_ROTZ)
+ axis[2] = oldAxis[2];
+ }
+ else {
+ /* axis-angle get limited with euler... */
+ float eul[3], oldeul[3];
+
+ axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle);
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle);
+
+ if (protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT);
+
+ /* when converting to axis-angle, we need a special exception for the case when there is no axis */
+ if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) {
+ /* for now, rotate around y-axis then (so that it simply becomes the roll) */
+ axis[1] = 1.0f;
+ }
+ }
}
/* this function only does the delta rotation */
static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4])
{
- /* check that protection flags are set */
- if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0)
- return;
-
- if (protectflag & OB_LOCK_ROT4D) {
- /* quaternions getting limited as 4D entities that they are... */
- if (protectflag & OB_LOCK_ROTW)
- quat[0] = oldquat[0];
- if (protectflag & OB_LOCK_ROTX)
- quat[1] = oldquat[1];
- if (protectflag & OB_LOCK_ROTY)
- quat[2] = oldquat[2];
- if (protectflag & OB_LOCK_ROTZ)
- quat[3] = oldquat[3];
- }
- else {
- /* quaternions get limited with euler... (compatibility mode) */
- float eul[3], oldeul[3], nquat[4], noldquat[4];
- float qlen;
-
- qlen = normalize_qt_qt(nquat, quat);
- normalize_qt_qt(noldquat, oldquat);
-
- quat_to_eul(eul, nquat);
- quat_to_eul(oldeul, noldquat);
-
- if (protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- eul_to_quat(quat, eul);
-
- /* restore original quat size */
- mul_qt_fl(quat, qlen);
-
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((nquat[0] < 0.0f && quat[0] > 0.0f) ||
- (nquat[0] > 0.0f && quat[0] < 0.0f))
- {
- mul_qt_fl(quat, -1.0f);
- }
- }
+ /* check that protection flags are set */
+ if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0)
+ return;
+
+ if (protectflag & OB_LOCK_ROT4D) {
+ /* quaternions getting limited as 4D entities that they are... */
+ if (protectflag & OB_LOCK_ROTW)
+ quat[0] = oldquat[0];
+ if (protectflag & OB_LOCK_ROTX)
+ quat[1] = oldquat[1];
+ if (protectflag & OB_LOCK_ROTY)
+ quat[2] = oldquat[2];
+ if (protectflag & OB_LOCK_ROTZ)
+ quat[3] = oldquat[3];
+ }
+ else {
+ /* quaternions get limited with euler... (compatibility mode) */
+ float eul[3], oldeul[3], nquat[4], noldquat[4];
+ float qlen;
+
+ qlen = normalize_qt_qt(nquat, quat);
+ normalize_qt_qt(noldquat, oldquat);
+
+ quat_to_eul(eul, nquat);
+ quat_to_eul(oldeul, noldquat);
+
+ if (protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ eul_to_quat(quat, eul);
+
+ /* restore original quat size */
+ mul_qt_fl(quat, qlen);
+
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((nquat[0] < 0.0f && quat[0] > 0.0f) || (nquat[0] > 0.0f && quat[0] < 0.0f)) {
+ mul_qt_fl(quat, -1.0f);
+ }
+ }
}
/* ******************* TRANSFORM LIMITS ********************** */
static void constraintTransLim(TransInfo *t, TransData *td)
{
- if (td->con) {
- 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;
- float ctime = (float)(t->scene->r.cfra);
-
- /* Make a temporary bConstraintOb for using these limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- unit_m4(cob.matrix);
- copy_v3_v3(cob.matrix[3], td->loc);
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- const bConstraintTypeInfo *cti = NULL;
- ListBase targets = {NULL, NULL};
-
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
- if (con->enforce == 0.0f) continue;
-
- /* only use it if it's tagged for this purpose (and the right type) */
- if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
- bLocLimitConstraint *data = con->data;
-
- if ((data->flag2 & LIMIT_TRANSFORM) == 0)
- continue;
- cti = ctiLoc;
- }
- else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
- bDistLimitConstraint *data = con->data;
-
- if ((data->flag & LIMITDIST_TRANSFORM) == 0)
- continue;
- cti = ctiDist;
- }
-
- if (cti) {
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
- else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
- /* skip... incompatible spacetype */
- continue;
- }
-
- /* get constraint targets if needed */
- BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime);
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, &targets);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
-
- /* free targets list */
- BLI_freelistN(&targets);
- }
- }
-
- /* copy results from cob->matrix */
- copy_v3_v3(td->loc, cob.matrix[3]);
- }
+ if (td->con) {
+ 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;
+ float ctime = (float)(t->scene->r.cfra);
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ unit_m4(cob.matrix);
+ copy_v3_v3(cob.matrix[3], td->loc);
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ const bConstraintTypeInfo *cti = NULL;
+ ListBase targets = {NULL, NULL};
+
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
+ continue;
+ if (con->enforce == 0.0f)
+ continue;
+
+ /* only use it if it's tagged for this purpose (and the right type) */
+ if (con->type == CONSTRAINT_TYPE_LOCLIMIT) {
+ bLocLimitConstraint *data = con->data;
+
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0)
+ continue;
+ cti = ctiLoc;
+ }
+ else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
+ bDistLimitConstraint *data = con->data;
+
+ if ((data->flag & LIMITDIST_TRANSFORM) == 0)
+ continue;
+ cti = ctiDist;
+ }
+
+ if (cti) {
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatible spacetype */
+ continue;
+ }
+
+ /* get constraint targets if needed */
+ BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime);
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, &targets);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+
+ /* free targets list */
+ BLI_freelistN(&targets);
+ }
+ }
+
+ /* copy results from cob->matrix */
+ copy_v3_v3(td->loc, cob.matrix[3]);
+ }
}
static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
{
- /* Make a temporary bConstraintOb for use by limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- memset(cob, 0, sizeof(bConstraintOb));
- if (td->ext) {
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- /* quats */
- /* objects and bones do normalization first too, otherwise
- * we don't necessarily end up with a rotation matrix, and
- * then conversion back to quat gives a different result */
- float quat[4];
- normalize_qt_qt(quat, td->ext->quat);
- quat_to_mat4(cob->matrix, quat);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* axis angle */
- axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle);
- }
- else {
- /* eulers */
- eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder);
- }
- }
+ /* Make a temporary bConstraintOb for use by limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ memset(cob, 0, sizeof(bConstraintOb));
+ if (td->ext) {
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ /* quats */
+ /* objects and bones do normalization first too, otherwise
+ * we don't necessarily end up with a rotation matrix, and
+ * then conversion back to quat gives a different result */
+ float quat[4];
+ normalize_qt_qt(quat, td->ext->quat);
+ quat_to_mat4(cob->matrix, quat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* axis angle */
+ axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle);
+ }
+ else {
+ /* eulers */
+ eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder);
+ }
+ }
}
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
{
- if (td->con) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
- bConstraintOb cob;
- bConstraint *con;
- bool do_limit = false;
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
- if (con->enforce == 0.0f) continue;
-
- /* we're only interested in Limit-Rotation constraints */
- if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
- bRotLimitConstraint *data = con->data;
-
- /* only use it if it's tagged for this purpose */
- if ((data->flag2 & LIMIT_TRANSFORM) == 0)
- continue;
-
- /* skip incompatible spacetypes */
- if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL))
- continue;
-
- /* only do conversion if necessary, to preserve quats and eulers */
- if (do_limit == false) {
- constraintob_from_transdata(&cob, td);
- do_limit = true;
- }
-
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, NULL);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
- }
- }
-
- if (do_limit) {
- /* copy results from cob->matrix */
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- /* quats */
- mat4_to_quat(td->ext->quat, cob.matrix);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* axis angle */
- mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix);
- }
- else {
- /* eulers */
- mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix);
- }
- }
- }
+ if (td->con) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT);
+ bConstraintOb cob;
+ bConstraint *con;
+ bool do_limit = false;
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
+ continue;
+ if (con->enforce == 0.0f)
+ continue;
+
+ /* we're only interested in Limit-Rotation constraints */
+ if (con->type == CONSTRAINT_TYPE_ROTLIMIT) {
+ bRotLimitConstraint *data = con->data;
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0)
+ continue;
+
+ /* skip incompatible spacetypes */
+ if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL))
+ continue;
+
+ /* only do conversion if necessary, to preserve quats and eulers */
+ if (do_limit == false) {
+ constraintob_from_transdata(&cob, td);
+ do_limit = true;
+ }
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+ }
+ }
+
+ if (do_limit) {
+ /* copy results from cob->matrix */
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ /* quats */
+ mat4_to_quat(td->ext->quat, cob.matrix);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* axis angle */
+ mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix);
+ }
+ else {
+ /* eulers */
+ mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix);
+ }
+ }
+ }
}
static void constraintSizeLim(TransInfo *t, TransData *td)
{
- if (td->con && td->ext) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
- bConstraintOb cob = {NULL};
- bConstraint *con;
- float size_sign[3], size_abs[3];
- int i;
-
- /* Make a temporary bConstraintOb for using these limit constraints
- * - they only care that cob->matrix is correctly set ;-)
- * - current space should be local
- */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- return; // TODO: fix this case
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE)
- return;
-
- /* separate out sign to apply back later */
- for (i = 0; i < 3; i++) {
- size_sign[i] = signf(td->ext->size[i]);
- size_abs[i] = fabsf(td->ext->size[i]);
- }
-
- size_to_mat4(cob.matrix, size_abs);
- }
-
- /* Evaluate valid constraints */
- for (con = td->con; con; con = con->next) {
- /* only consider constraint if enabled */
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
- if (con->enforce == 0.0f) continue;
-
- /* we're only interested in Limit-Scale constraints */
- if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
- bSizeLimitConstraint *data = con->data;
-
- /* only use it if it's tagged for this purpose */
- if ((data->flag2 & LIMIT_TRANSFORM) == 0)
- continue;
-
- /* do space conversions */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->mtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
- }
- else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
- /* skip... incompatible spacetype */
- continue;
- }
-
- /* do constraint */
- cti->evaluate_constraint(con, &cob, NULL);
-
- /* convert spaces again */
- if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
- /* just multiply by td->smtx (this should be ok) */
- mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
- }
- }
- }
-
- /* copy results from cob->matrix */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- return; // TODO: fix this case
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE)
- return;
-
- /* extrace scale from matrix and apply back sign */
- mat4_to_size(td->ext->size, cob.matrix);
- mul_v3_v3(td->ext->size, size_sign);
- }
- }
+ if (td->con && td->ext) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
+ bConstraintOb cob = {NULL};
+ bConstraint *con;
+ float size_sign[3], size_abs[3];
+ int i;
+
+ /* Make a temporary bConstraintOb for using these limit constraints
+ * - they only care that cob->matrix is correctly set ;-)
+ * - current space should be local
+ */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ return;
+
+ /* separate out sign to apply back later */
+ for (i = 0; i < 3; i++) {
+ size_sign[i] = signf(td->ext->size[i]);
+ size_abs[i] = fabsf(td->ext->size[i]);
+ }
+
+ size_to_mat4(cob.matrix, size_abs);
+ }
+
+ /* Evaluate valid constraints */
+ for (con = td->con; con; con = con->next) {
+ /* only consider constraint if enabled */
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
+ continue;
+ if (con->enforce == 0.0f)
+ continue;
+
+ /* we're only interested in Limit-Scale constraints */
+ if (con->type == CONSTRAINT_TYPE_SIZELIMIT) {
+ bSizeLimitConstraint *data = con->data;
+
+ /* only use it if it's tagged for this purpose */
+ if ((data->flag2 & LIMIT_TRANSFORM) == 0)
+ continue;
+
+ /* do space conversions */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->mtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix);
+ }
+ else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) {
+ /* skip... incompatible spacetype */
+ continue;
+ }
+
+ /* do constraint */
+ cti->evaluate_constraint(con, &cob, NULL);
+
+ /* convert spaces again */
+ if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
+ /* just multiply by td->smtx (this should be ok) */
+ mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix);
+ }
+ }
+ }
+
+ /* copy results from cob->matrix */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ return; // TODO: fix this case
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ return;
+
+ /* extrace scale from matrix and apply back sign */
+ mat4_to_size(td->ext->size, cob.matrix);
+ mul_v3_v3(td->ext->size, size_sign);
+ }
+ }
}
-
/* -------------------------------------------------------------------- */
/* Transform (Bend) */
@@ -3195,246 +3201,258 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
* \{ */
struct BendCustomData {
- /* All values are in global space. */
- float warp_sta[3];
- float warp_end[3];
+ /* All values are in global space. */
+ float warp_sta[3];
+ float warp_end[3];
- float warp_nor[3];
- float warp_tan[3];
+ float warp_nor[3];
+ float warp_tan[3];
- /* for applying the mouse distance */
- float warp_init_dist;
+ /* for applying the mouse distance */
+ float warp_init_dist;
};
static void initBend(TransInfo *t)
{
- const float mval_fl[2] = {UNPACK2(t->mval)};
- const float *curs;
- float tvec[3];
- struct BendCustomData *data;
+ const float mval_fl[2] = {UNPACK2(t->mval)};
+ const float *curs;
+ float tvec[3];
+ struct BendCustomData *data;
- t->mode = TFM_BEND;
- t->transform = Bend;
- t->handleEvent = handleEventBend;
+ t->mode = TFM_BEND;
+ t->transform = Bend;
+ t->handleEvent = handleEventBend;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
- t->idx_max = 1;
- t->num.idx_max = 1;
- t->snap[0] = 0.0f;
- t->snap[1] = SNAP_INCREMENTAL_ANGLE;
- t->snap[2] = t->snap[1] * 0.2;
+ t->idx_max = 1;
+ t->num.idx_max = 1;
+ t->snap[0] = 0.0f;
+ t->snap[1] = SNAP_INCREMENTAL_ANGLE;
+ t->snap[2] = t->snap[1] * 0.2;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
- t->num.unit_type[1] = B_UNIT_LENGTH;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ 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;
- //copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- calculateCenterCursor(t, t->center_global);
- }
- calculateCenterLocal(t, t->center_global);
+ //copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenterCursor(t, t->center_global);
+ }
+ calculateCenterLocal(t, t->center_global);
- t->val = 0.0f;
+ t->val = 0.0f;
- data = MEM_callocN(sizeof(*data), __func__);
+ data = MEM_callocN(sizeof(*data), __func__);
- curs = t->scene->cursor.location;
- copy_v3_v3(data->warp_sta, curs);
- ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end);
+ curs = t->scene->cursor.location;
+ copy_v3_v3(data->warp_sta, curs);
+ ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end);
- copy_v3_v3(data->warp_nor, t->viewinv[2]);
- normalize_v3(data->warp_nor);
+ copy_v3_v3(data->warp_nor, t->viewinv[2]);
+ normalize_v3(data->warp_nor);
- /* tangent */
- sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
- cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
- normalize_v3(data->warp_tan);
+ /* tangent */
+ sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
+ cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
+ normalize_v3(data->warp_tan);
- data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
+ data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
- t->custom.mode.data = data;
- t->custom.mode.use_free = true;
+ t->custom.mode.data = data;
+ t->custom.mode.use_free = true;
}
static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- status = TREDRAW_HARD;
- }
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ status = TREDRAW_HARD;
+ }
- return status;
+ return status;
}
static void Bend(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3];
- float pivot_global[3];
- float warp_end_radius_global[3];
- int i;
- char str[UI_MAX_DRAW_STR];
- const struct BendCustomData *data = t->custom.mode.data;
- const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
+ float vec[3];
+ float pivot_global[3];
+ float warp_end_radius_global[3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ const struct BendCustomData *data = t->custom.mode.data;
+ const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
- union {
- struct { float angle, scale; };
- float vector[2];
- } values;
+ union {
+ struct {
+ float angle, scale;
+ };
+ float vector[2];
+ } values;
- /* amount of radians for bend */
- copy_v2_v2(values.vector, t->values);
+ /* amount of radians for bend */
+ copy_v2_v2(values.vector, t->values);
#if 0
- snapGrid(t, angle_rad);
+ snapGrid(t, angle_rad);
#else
- /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
- * this isnt essential but nicer to give reasonable snapping values for radius */
- if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
- const float radius_snap = 0.1f;
- const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
- values.scale *= snap_hack;
- snapGridIncrement(t, values.vector);
- values.scale /= snap_hack;
- }
+ /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
+ * this isnt essential but nicer to give reasonable snapping values for radius */
+ if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
+ const float radius_snap = 0.1f;
+ const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
+ values.scale *= snap_hack;
+ snapGridIncrement(t, values.vector);
+ values.scale /= snap_hack;
+ }
#endif
- if (applyNumInput(&t->num, values.vector)) {
- 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];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
- &c[0], &c[NUM_STR_REP_LEN],
- WM_bool_as_string(is_clamp));
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
- RAD2DEGF(values.angle), values.scale * data->warp_init_dist,
- WM_bool_as_string(is_clamp));
- }
-
- values.angle *= -1.0f;
- values.scale *= data->warp_init_dist;
-
- /* calc 'data->warp_end' from 'data->warp_end_init' */
- copy_v3_v3(warp_end_radius_global, data->warp_end);
- dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale);
- /* done */
-
- /* calculate pivot */
- copy_v3_v3(pivot_global, data->warp_sta);
- if (values.angle > 0.0f) {
- madd_v3_v3fl(pivot_global, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
- }
- else {
- madd_v3_v3fl(pivot_global, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
- }
-
- /* TODO(campbell): xform, compensate object center. */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
-
- float warp_sta_local[3];
- float warp_end_local[3];
- float warp_end_radius_local[3];
- float pivot_local[3];
-
- if (tc->use_local_mat) {
- sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]);
- sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]);
- sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
- sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
- }
- else {
- copy_v3_v3(warp_sta_local, data->warp_sta);
- copy_v3_v3(warp_end_local, data->warp_end);
- copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
- copy_v3_v3(pivot_local, pivot_global);
- }
-
- for (i = 0; i < tc->data_len; i++, td++) {
- float mat[3][3];
- float delta[3];
- float fac, fac_scaled;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if (UNLIKELY(values.angle == 0.0f)) {
- copy_v3_v3(td->loc, td->iloc);
- continue;
- }
-
- copy_v3_v3(vec, td->iloc);
- mul_m3_v3(td->mtx, vec);
-
- fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
- if (is_clamp) {
- CLAMP(fac, 0.0f, 1.0f);
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
- }
- else {
- fac_scaled = fac * td->factor;
- }
- }
- else {
- fac_scaled = fac * td->factor;
- }
-
- axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
- interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
- sub_v3_v3(delta, warp_sta_local);
-
- /* delta is subtracted, rotation adds back this offset */
- sub_v3_v3(vec, delta);
-
- sub_v3_v3(vec, pivot_local);
- mul_m3_v3(mat, vec);
- add_v3_v3(vec, pivot_local);
-
- mul_m3_v3(td->smtx, vec);
-
- /* rotation */
- if ((t->flag & T_POINTS) == 0) {
- ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS);
- }
-
- /* location */
- copy_v3_v3(td->loc, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ if (applyNumInput(&t->num, values.vector)) {
+ 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];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str,
+ sizeof(str),
+ IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
+ &c[0],
+ &c[NUM_STR_REP_LEN],
+ WM_bool_as_string(is_clamp));
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str,
+ sizeof(str),
+ IFACE_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
+ RAD2DEGF(values.angle),
+ values.scale * data->warp_init_dist,
+ WM_bool_as_string(is_clamp));
+ }
+
+ values.angle *= -1.0f;
+ values.scale *= data->warp_init_dist;
+
+ /* calc 'data->warp_end' from 'data->warp_end_init' */
+ copy_v3_v3(warp_end_radius_global, data->warp_end);
+ dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale);
+ /* done */
+
+ /* calculate pivot */
+ copy_v3_v3(pivot_global, data->warp_sta);
+ if (values.angle > 0.0f) {
+ madd_v3_v3fl(pivot_global,
+ data->warp_tan,
+ -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
+ }
+ else {
+ madd_v3_v3fl(pivot_global,
+ data->warp_tan,
+ +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
+ }
+
+ /* TODO(campbell): xform, compensate object center. */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+
+ float warp_sta_local[3];
+ float warp_end_local[3];
+ float warp_end_radius_local[3];
+ float pivot_local[3];
+
+ if (tc->use_local_mat) {
+ sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]);
+ sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]);
+ sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
+ sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
+ }
+ else {
+ copy_v3_v3(warp_sta_local, data->warp_sta);
+ copy_v3_v3(warp_end_local, data->warp_end);
+ copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
+ copy_v3_v3(pivot_local, pivot_global);
+ }
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float mat[3][3];
+ float delta[3];
+ float fac, fac_scaled;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (UNLIKELY(values.angle == 0.0f)) {
+ copy_v3_v3(td->loc, td->iloc);
+ continue;
+ }
+
+ copy_v3_v3(vec, td->iloc);
+ mul_m3_v3(td->mtx, vec);
+
+ fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
+ if (is_clamp) {
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
+ }
+ else {
+ fac_scaled = fac * td->factor;
+ }
+ }
+ else {
+ fac_scaled = fac * td->factor;
+ }
+
+ axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
+ interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
+ sub_v3_v3(delta, warp_sta_local);
+
+ /* delta is subtracted, rotation adds back this offset */
+ sub_v3_v3(vec, delta);
+
+ sub_v3_v3(vec, pivot_local);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, pivot_local);
+
+ mul_m3_v3(td->smtx, vec);
+
+ /* rotation */
+ if ((t->flag & T_POINTS) == 0) {
+ ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS);
+ }
+
+ /* location */
+ copy_v3_v3(td->loc, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Shear) */
@@ -3443,192 +3461,195 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
static void initShear_mouseInputMode(TransInfo *t)
{
- float dir[3];
+ float dir[3];
- if (t->custom.mode.data == NULL) {
- copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
- }
- else {
- cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]);
- }
+ if (t->custom.mode.data == NULL) {
+ copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
+ }
+ else {
+ cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]);
+ }
- /* Without this, half the gizmo handles move in the opposite direction. */
- if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
- negate_v3(dir);
- }
+ /* Without this, half the gizmo handles move in the opposite direction. */
+ if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) {
+ negate_v3(dir);
+ }
- mul_mat3_m4_v3(t->viewmat, dir);
- if (normalize_v2(dir) == 0.0f) {
- dir[0] = 1.0f;
- }
- setCustomPointsFromDirection(t, &t->mouse, dir);
+ mul_mat3_m4_v3(t->viewmat, dir);
+ if (normalize_v2(dir) == 0.0f) {
+ dir[0] = 1.0f;
+ }
+ setCustomPointsFromDirection(t, &t->mouse, dir);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
}
static void initShear(TransInfo *t)
{
- t->mode = TFM_SHEAR;
- t->transform = applyShear;
- t->handleEvent = handleEventShear;
+ t->mode = TFM_SHEAR;
+ t->transform = applyShear;
+ t->handleEvent = handleEventShear;
- if (t->orient_axis == t->orient_axis_ortho) {
- t->orient_axis = 2;
- t->orient_axis_ortho = 1;
- }
+ if (t->orient_axis == t->orient_axis_ortho) {
+ t->orient_axis = 2;
+ t->orient_axis_ortho = 1;
+ }
- initShear_mouseInputMode(t);
+ initShear_mouseInputMode(t);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- /* Use custom.mode.data pointer to signal Shear direction */
- if (t->custom.mode.data == NULL) {
- t->custom.mode.data = (void *)1;
- }
- else {
- t->custom.mode.data = NULL;
- }
- initShear_mouseInputMode(t);
+ if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
+ /* Use custom.mode.data pointer to signal Shear direction */
+ if (t->custom.mode.data == NULL) {
+ t->custom.mode.data = (void *)1;
+ }
+ else {
+ t->custom.mode.data = NULL;
+ }
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
- else if (event->type == XKEY && event->val == KM_PRESS) {
- t->custom.mode.data = NULL;
- initShear_mouseInputMode(t);
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == XKEY && event->val == KM_PRESS) {
+ t->custom.mode.data = NULL;
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
- else if (event->type == YKEY && event->val == KM_PRESS) {
- t->custom.mode.data = (void *)1;
- initShear_mouseInputMode(t);
+ status = TREDRAW_HARD;
+ }
+ else if (event->type == YKEY && event->val == KM_PRESS) {
+ t->custom.mode.data = (void *)1;
+ initShear_mouseInputMode(t);
- status = TREDRAW_HARD;
- }
+ status = TREDRAW_HARD;
+ }
- return status;
+ return status;
}
-
static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3];
- float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
- float value;
- int i;
- char str[UI_MAX_DRAW_STR];
- const bool is_local_center = transdata_check_local_center(t, t->around);
-
- value = t->values[0];
-
- snapGridIncrement(t, &value);
-
- applyNumInput(&t->num, &value);
-
- t->values[0] = value;
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- BLI_snprintf(str, sizeof(str), IFACE_("Shear: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext);
- }
-
- unit_m3(smat);
-
- // Custom data signals shear direction
- if (t->custom.mode.data == NULL)
- smat[1][0] = value;
- else
- smat[0][1] = value;
-
- copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]);
- copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]);
- cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]);
- invert_m3_m3(axismat, axismat_inv);
-
- mul_m3_series(totmat, axismat_inv, smat, axismat);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- const float *center, *co;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if (t->flag & T_EDIT) {
- mul_m3_series(tmat, td->smtx, totmat, td->mtx);
- }
- else {
- copy_m3_m3(tmat, totmat);
- }
-
- if (is_local_center) {
- center = td->center;
- co = td->loc;
- }
- else {
- center = tc->center_local;
- co = td->center;
- }
-
- sub_v3_v3v3(vec, co, center);
-
- mul_m3_v3(tmat, vec);
-
- add_v3_v3(vec, center);
- sub_v3_v3(vec, co);
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
-
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ float vec[3];
+ float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3];
+ float value;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ const bool is_local_center = transdata_check_local_center(t, t->around);
+
+ value = t->values[0];
+
+ snapGridIncrement(t, &value);
+
+ applyNumInput(&t->num, &value);
+
+ t->values[0] = value;
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ BLI_snprintf(str, sizeof(str), IFACE_("Shear: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str,
+ sizeof(str),
+ IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"),
+ value,
+ t->proptext);
+ }
+
+ unit_m3(smat);
+
+ // Custom data signals shear direction
+ if (t->custom.mode.data == NULL)
+ smat[1][0] = value;
+ else
+ smat[0][1] = value;
+
+ copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]);
+ copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]);
+ cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]);
+ invert_m3_m3(axismat, axismat_inv);
+
+ mul_m3_series(totmat, axismat_inv, smat, axismat);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ const float *center, *co;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (t->flag & T_EDIT) {
+ mul_m3_series(tmat, td->smtx, totmat, td->mtx);
+ }
+ else {
+ copy_m3_m3(tmat, totmat);
+ }
+
+ if (is_local_center) {
+ center = td->center;
+ co = td->loc;
+ }
+ else {
+ center = tc->center_local;
+ co = td->center;
+ }
+
+ sub_v3_v3v3(vec, co, center);
+
+ mul_m3_v3(tmat, vec);
+
+ add_v3_v3(vec, center);
+ sub_v3_v3(vec, co);
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Resize) */
@@ -3637,81 +3658,108 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
static void initResize(TransInfo *t)
{
- t->mode = TFM_RESIZE;
- t->transform = applyResize;
+ t->mode = TFM_RESIZE;
+ t->transform = applyResize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
- t->num.val_flag[1] |= NUM_NO_ZERO;
- t->num.val_flag[2] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[1] |= NUM_NO_ZERO;
+ t->num.val_flag[2] |= NUM_NO_ZERO;
#endif
- }
+ }
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
}
static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
{
- char tvec[NUM_STR_REP_LEN * 3];
- size_t ofs = 0;
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
- }
-
- if (t->con.mode & CON_APPLY) {
- switch (t->num.idx_max) {
- case 0:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s%s %s"),
- &tvec[0], t->con.text, t->proptext);
- break;
- case 1:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s : %s%s %s"),
- &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext);
- break;
- case 2:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0],
- &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
- break;
- }
- }
- else {
- if (t->flag & T_2D_EDIT) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale X: %s Y: %s%s %s"),
- &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale X: %s Y: %s Z: %s%s %s"),
- &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
- }
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ char tvec[NUM_STR_REP_LEN * 3];
+ size_t ofs = 0;
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
+ }
+
+ if (t->con.mode & CON_APPLY) {
+ switch (t->num.idx_max) {
+ case 0:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Scale: %s%s %s"),
+ &tvec[0],
+ t->con.text,
+ t->proptext);
+ break;
+ case 1:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Scale: %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ t->con.text,
+ t->proptext);
+ break;
+ case 2:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Scale: %s : %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ break;
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Scale X: %s Y: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Scale X: %s Y: %s Z: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
/**
@@ -3721,227 +3769,228 @@ static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_
*/
static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3])
{
- float rmat[3][3];
+ float rmat[3][3];
- mat3_to_rot_size(rmat, size, mat);
+ mat3_to_rot_size(rmat, size, mat);
- /* first tried with dotproduct... but the sign flip is crucial */
- if (dot_v3v3(rmat[0], smat[0]) < 0.0f) size[0] = -size[0];
- if (dot_v3v3(rmat[1], smat[1]) < 0.0f) size[1] = -size[1];
- if (dot_v3v3(rmat[2], smat[2]) < 0.0f) size[2] = -size[2];
+ /* first tried with dotproduct... but the sign flip is crucial */
+ if (dot_v3v3(rmat[0], smat[0]) < 0.0f)
+ size[0] = -size[0];
+ if (dot_v3v3(rmat[1], smat[1]) < 0.0f)
+ size[1] = -size[1];
+ if (dot_v3v3(rmat[2], smat[2]) < 0.0f)
+ size[2] = -size[2];
}
static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
{
- float tmat[3][3], smat[3][3], center[3];
- float vec[3];
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
- }
- else {
- copy_m3_m3(tmat, mat);
- }
-
- if (t->con.applySize) {
- t->con.applySize(t, tc, td, tmat);
- }
-
- /* local constraint shouldn't alter center */
- if (transdata_check_local_center(t, t->around)) {
- copy_v3_v3(center, td->center);
- }
- else if (t->options & CTX_MOVIECLIP) {
- if (td->flag & TD_INDIVIDUAL_SCALE) {
- copy_v3_v3(center, td->center);
- }
- else {
- copy_v3_v3(center, tc->center_local);
- }
- }
- else {
- copy_v3_v3(center, tc->center_local);
- }
-
- /* Size checked needed since the 3D cursor only uses rotation fields. */
- if (td->ext && td->ext->size) {
- float fsize[3];
-
- if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) {
- float obsizemat[3][3];
- /* Reorient the size mat to fit the oriented object. */
- mul_m3_m3m3(obsizemat, tmat, td->axismtx);
- /* print_m3("obsizemat", obsizemat); */
- TransMat3ToSize(obsizemat, td->axismtx, fsize);
- /* print_v3("fsize", fsize); */
- }
- else {
- mat3_to_size(fsize, tmat);
- }
-
- protectedSizeBits(td->protectflag, fsize);
-
- if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */
- if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
- /* scale val and reset size */
- *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor);
-
- td->ext->size[0] = td->ext->isize[0];
- td->ext->size[1] = td->ext->isize[1];
- td->ext->size[2] = td->ext->isize[2];
- }
- else {
- /* Reset val if SINGLESIZE but using a constraint */
- if (td->flag & TD_SINGLESIZE)
- *td->val = td->ival;
-
- td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
- td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
- td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor);
- }
- }
-
- constraintSizeLim(t, td);
- }
-
- /* For individual element center, Editmode need to use iloc */
- if (t->flag & T_POINTS)
- sub_v3_v3v3(vec, td->iloc, center);
- else
- sub_v3_v3v3(vec, td->center, center);
-
- mul_m3_v3(tmat, vec);
-
- add_v3_v3(vec, center);
- if (t->flag & T_POINTS)
- sub_v3_v3(vec, td->iloc);
- else
- sub_v3_v3(vec, td->center);
-
- /* grease pencil falloff */
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
-
- /* scale stroke thickness */
- if (td->val) {
- snapGridIncrement(t, t->values);
- applyNumInput(&t->num, t->values);
-
- float ratio = t->values[0];
- *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
- CLAMP_MIN(*td->val, 0.001f);
- }
-
- }
- else {
- mul_v3_fl(vec, td->factor);
- }
-
- if (t->flag & (T_OBJECT | T_POSE)) {
- mul_m3_v3(td->smtx, vec);
- }
-
- protectedTransBits(td->protectflag, vec);
- if (td->loc) {
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
-
- constraintTransLim(t, td);
+ float tmat[3][3], smat[3][3], center[3];
+ float vec[3];
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+ }
+ else {
+ copy_m3_m3(tmat, mat);
+ }
+
+ if (t->con.applySize) {
+ t->con.applySize(t, tc, td, tmat);
+ }
+
+ /* local constraint shouldn't alter center */
+ if (transdata_check_local_center(t, t->around)) {
+ copy_v3_v3(center, td->center);
+ }
+ else if (t->options & CTX_MOVIECLIP) {
+ if (td->flag & TD_INDIVIDUAL_SCALE) {
+ copy_v3_v3(center, td->center);
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+
+ /* Size checked needed since the 3D cursor only uses rotation fields. */
+ if (td->ext && td->ext->size) {
+ float fsize[3];
+
+ if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) {
+ float obsizemat[3][3];
+ /* Reorient the size mat to fit the oriented object. */
+ mul_m3_m3m3(obsizemat, tmat, td->axismtx);
+ /* print_m3("obsizemat", obsizemat); */
+ TransMat3ToSize(obsizemat, td->axismtx, fsize);
+ /* print_v3("fsize", fsize); */
+ }
+ else {
+ mat3_to_size(fsize, tmat);
+ }
+
+ protectedSizeBits(td->protectflag, fsize);
+
+ if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */
+ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) {
+ /* scale val and reset size */
+ *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor);
+
+ td->ext->size[0] = td->ext->isize[0];
+ td->ext->size[1] = td->ext->isize[1];
+ td->ext->size[2] = td->ext->isize[2];
+ }
+ else {
+ /* Reset val if SINGLESIZE but using a constraint */
+ if (td->flag & TD_SINGLESIZE)
+ *td->val = td->ival;
+
+ td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
+ td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
+ td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor);
+ }
+ }
+
+ constraintSizeLim(t, td);
+ }
+
+ /* For individual element center, Editmode need to use iloc */
+ if (t->flag & T_POINTS)
+ sub_v3_v3v3(vec, td->iloc, center);
+ else
+ sub_v3_v3v3(vec, td->center, center);
+
+ mul_m3_v3(tmat, vec);
+
+ add_v3_v3(vec, center);
+ if (t->flag & T_POINTS)
+ sub_v3_v3(vec, td->iloc);
+ else
+ sub_v3_v3(vec, td->center);
+
+ /* grease pencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff);
+
+ /* scale stroke thickness */
+ if (td->val) {
+ snapGridIncrement(t, t->values);
+ applyNumInput(&t->num, t->values);
+
+ float ratio = t->values[0];
+ *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff;
+ CLAMP_MIN(*td->val, 0.001f);
+ }
+ }
+ else {
+ mul_v3_fl(vec, td->factor);
+ }
+
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ mul_m3_v3(td->smtx, vec);
+ }
+
+ protectedTransBits(td->protectflag, vec);
+ if (td->loc) {
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+
+ constraintTransLim(t, td);
}
static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
{
- float mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
-
- if (t->flag & T_AUTOVALUES) {
- copy_v3_v3(t->values, t->auto_values);
- }
- else {
- float ratio = t->values[0];
-
- copy_v3_fl(t->values, ratio);
-
- snapGridIncrement(t, t->values);
-
- if (applyNumInput(&t->num, t->values)) {
- constraintNumInput(t, t->values);
- }
-
- applySnapping(t, t->values);
- }
-
- size_to_mat3(mat, t->values);
- if (t->con.mode & CON_APPLY) {
- t->con.applySize(t, NULL, NULL, mat);
-
- /* Only so we have re-usable value with redo. */
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- int j = 0;
- for (i = 0; i < 3; i++) {
- if (!(t->con.mode & (CON_AXIS0 << i))) {
- t->values[i] = 1.0f;
- }
- else {
- pvec[j++] = t->values[i];
- }
- }
- headerResize(t, pvec, str);
- }
- else {
- headerResize(t, t->values, str);
- }
-
- copy_m3_m3(t->mat, mat); // used in gizmo
-
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- ElementResize(t, tc, td, mat);
- }
- }
-
- /* evil hack - redo resize if cliping needed */
- if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 1)) {
- size_to_mat3(mat, t->values);
-
- if (t->con.mode & CON_APPLY) {
- t->con.applySize(t, NULL, NULL, mat);
- }
-
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++)
- ElementResize(t, tc, td, mat);
-
- /* In proportional edit it can happen that */
- /* vertices in the radius of the brush end */
- /* outside the clipping area */
- /* XXX HACK - dg */
- if (t->flag & T_PROP_EDIT_ALL) {
- clipUVData(t);
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ float mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
+
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(t->values, t->auto_values);
+ }
+ else {
+ float ratio = t->values[0];
+
+ copy_v3_fl(t->values, ratio);
+
+ snapGridIncrement(t, t->values);
+
+ if (applyNumInput(&t->num, t->values)) {
+ constraintNumInput(t, t->values);
+ }
+
+ applySnapping(t, t->values);
+ }
+
+ size_to_mat3(mat, t->values);
+ if (t->con.mode & CON_APPLY) {
+ t->con.applySize(t, NULL, NULL, mat);
+
+ /* Only so we have re-usable value with redo. */
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ int j = 0;
+ for (i = 0; i < 3; i++) {
+ if (!(t->con.mode & (CON_AXIS0 << i))) {
+ t->values[i] = 1.0f;
+ }
+ else {
+ pvec[j++] = t->values[i];
+ }
+ }
+ headerResize(t, pvec, str);
+ }
+ else {
+ headerResize(t, t->values, str);
+ }
+
+ copy_m3_m3(t->mat, mat); // used in gizmo
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ ElementResize(t, tc, td, mat);
+ }
+ }
+
+ /* evil hack - redo resize if cliping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 1)) {
+ size_to_mat3(mat, t->values);
+
+ if (t->con.mode & CON_APPLY) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++)
+ ElementResize(t, tc, td, mat);
+
+ /* In proportional edit it can happen that */
+ /* vertices in the radius of the brush end */
+ /* outside the clipping area */
+ /* XXX HACK - dg */
+ if (t->flag & T_PROP_EDIT_ALL) {
+ clipUVData(t);
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Skin) */
@@ -3950,101 +3999,101 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
static void initSkinResize(TransInfo *t)
{
- t->mode = TFM_SKIN_RESIZE;
- t->transform = applySkinResize;
+ t->mode = TFM_SKIN_RESIZE;
+ t->transform = applySkinResize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
- t->num.val_flag[1] |= NUM_NO_ZERO;
- t->num.val_flag[2] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[1] |= NUM_NO_ZERO;
+ t->num.val_flag[2] |= NUM_NO_ZERO;
#endif
- }
+ }
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
}
static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
{
- float size[3], mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
+ float size[3], mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- copy_v3_fl(size, t->values[0]);
+ copy_v3_fl(size, t->values[0]);
- snapGridIncrement(t, size);
+ snapGridIncrement(t, size);
- if (applyNumInput(&t->num, size)) {
- constraintNumInput(t, size);
- }
+ if (applyNumInput(&t->num, size)) {
+ constraintNumInput(t, size);
+ }
- applySnapping(t, size);
+ applySnapping(t, size);
- if (t->flag & T_AUTOVALUES) {
- copy_v3_v3(size, t->auto_values);
- }
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(size, t->auto_values);
+ }
- copy_v3_v3(t->values, size);
+ copy_v3_v3(t->values, size);
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- headerResize(t, size, str);
+ headerResize(t, size, str);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tmat[3][3], smat[3][3];
- float fsize[3];
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tmat[3][3], smat[3][3];
+ float fsize[3];
- if (td->flag & TD_NOACTION)
- break;
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
- }
- else {
- copy_m3_m3(tmat, mat);
- }
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
+ }
+ else {
+ copy_m3_m3(tmat, mat);
+ }
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, tmat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, tmat);
+ }
- mat3_to_size(fsize, tmat);
- td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
- td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
- }
- }
+ mat3_to_size(fsize, tmat);
+ td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor);
+ td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (ToSphere) */
@@ -4053,96 +4102,97 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
static void initToSphere(TransInfo *t)
{
- int i;
+ int i;
- t->mode = TFM_TOSPHERE;
- t->transform = applyToSphere;
+ t->mode = TFM_TOSPHERE;
+ t->transform = applyToSphere;
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
- t->flag |= T_NO_CONSTRAINT;
+ t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE;
+ t->flag |= T_NO_CONSTRAINT;
- // Calculate average radius
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- t->val += len_v3v3(tc->center_local, td->iloc);
- }
- }
+ // Calculate average radius
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ t->val += len_v3v3(tc->center_local, td->iloc);
+ }
+ }
- t->val /= (float)t->data_len_all;
+ t->val /= (float)t->data_len_all;
}
static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3];
- float ratio, radius;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float vec[3];
+ float ratio, radius;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- CLAMP(ratio, 0.0f, 1.0f);
+ CLAMP(ratio, 0.0f, 1.0f);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext);
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tratio;
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tratio;
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- sub_v3_v3v3(vec, td->iloc, tc->center_local);
+ sub_v3_v3v3(vec, td->iloc, tc->center_local);
- radius = normalize_v3(vec);
+ radius = normalize_v3(vec);
- tratio = ratio * td->factor;
+ tratio = ratio * td->factor;
- mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
+ mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio);
- add_v3_v3v3(td->loc, tc->center_local, vec);
- }
- }
+ add_v3_v3v3(td->loc, tc->center_local, vec);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Rotation) */
@@ -4151,56 +4201,66 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
static void postInputRotation(TransInfo *t, float values[3])
{
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, values);
- }
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, values);
+ }
}
static void initRotation(TransInfo *t)
{
- t->mode = TFM_ROTATION;
- t->transform = applyRotation;
+ t->mode = TFM_ROTATION;
+ t->transform = applyRotation;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
- if (t->flag & T_2D_EDIT)
- t->flag |= T_NO_CONSTRAINT;
+ if (t->flag & T_2D_EDIT)
+ t->flag |= T_NO_CONSTRAINT;
}
/* Used by Transform Rotation and Transform Normal Rotation */
static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
{
- size_t ofs = 0;
+ size_t ofs = 0;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"),
- RAD2DEGF(final), t->con.text, t->proptext);
- }
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Rot: %s %s %s"),
+ &c[0],
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_("Rot: %.2f%s %s"),
+ RAD2DEGF(final),
+ t->con.text,
+ t->proptext);
+ }
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
/**
@@ -4209,309 +4269,314 @@ static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final)
*
* Protected axis and other transform settings are taken into account.
*/
-static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const float *center)
-{
- float vec[3], totmat[3][3], smat[3][3];
- float eul[3], fmat[3][3], quat[4];
-
- if (t->flag & T_POINTS) {
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, totmat);
-
- /* apply gpencil falloff */
- if (t->options & CTX_GPENCIL_STROKES) {
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- float sx = smat[0][0];
- float sy = smat[1][1];
- float sz = smat[2][2];
-
- mul_m3_fl(smat, gps->runtime.multi_frame_falloff);
- /* fix scale */
- smat[0][0] = sx;
- smat[1][1] = sy;
- smat[2][2] = sz;
- }
-
- sub_v3_v3v3(vec, td->iloc, center);
- mul_m3_v3(smat, vec);
-
- add_v3_v3v3(td->loc, vec, center);
-
- sub_v3_v3v3(vec, td->loc, td->iloc);
- protectedTransBits(td->protectflag, vec);
- add_v3_v3v3(td->loc, td->iloc, vec);
-
-
- if (td->flag & TD_USEQUAT) {
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
-
- if (td->ext->quat) {
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
-
- /* is there a reason not to have this here? -jahka */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
- }
- }
- }
- /**
- * HACK WARNING
- *
- * This is some VERY ugly special case to deal with pose mode.
- *
- * The problem is that mtx and smtx include each bone orientation.
- *
- * That is needed to rotate each bone properly, HOWEVER, to calculate
- * the translation component, we only need the actual armature object's
- * matrix (and inverse). That is not all though. Once the proper translation
- * has been computed, it has to be converted back into the bone's space.
- */
- else if (t->flag & T_POSE) {
- // Extract and invert armature object matrix
-
- if ((td->flag & TD_NO_LOC) == 0) {
- sub_v3_v3v3(vec, td->center, center);
-
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(mat, vec); // Applying rotation
- mul_m3_v3(tc->imat3, vec); // To Local space
-
- add_v3_v3(vec, center);
- /* vec now is the location where the object has to be */
-
- sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
-
- /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
- if (td->flag & TD_PBONE_LOCAL_MTX_P) {
- /* do nothing */
- }
- else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location)
- }
- else {
- mul_m3_v3(tc->mat3, vec); // To Global space
- mul_m3_v3(td->smtx, vec); // To Pose space
- }
-
- protectedTransBits(td->protectflag, vec);
-
- add_v3_v3v3(td->loc, td->iloc, vec);
-
- constraintTransLim(t, td);
- }
-
- /* rotation */
- /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same,
- * and ElementRotation() might be called in Translation context (with align snapping),
- * we need to be sure to actually use the *rotation* matrix here...
- * So no other way than storing it in some dedicated members of td->ext! */
- if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
- /* euler or quaternion/axis-angle? */
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
-
- mat3_to_quat(quat, fmat); /* Actual transform */
-
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
- /* this function works on end result */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
-
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* calculate effect based on quats */
- float iquat[4], tquat[4];
-
- axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
-
- mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
- mat3_to_quat(quat, fmat); /* Actual transform */
- mul_qt_qtqt(tquat, quat, iquat);
-
- quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
-
- /* this function works on end result */
- protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis,
- td->ext->irotAngle);
- }
- else {
- float eulmat[3][3];
-
- mul_m3_m3m3(totmat, mat, td->ext->r_mtx);
- mul_m3_m3m3(smat, td->ext->r_smtx, totmat);
-
- /* calculate the total rotatation in eulers */
- copy_v3_v3(eul, td->ext->irot);
- eulO_to_mat3(eulmat, eul, td->ext->rotOrder);
-
- /* mat = transform, obmat = bone rotation */
- mul_m3_m3m3(fmat, smat, eulmat);
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* and apply (to end result only) */
- protectedRotateBits(td->protectflag, eul, td->ext->irot);
- copy_v3_v3(td->ext->rot, eul);
- }
-
- constraintRotLim(t, td);
- }
- }
- else {
- if ((td->flag & TD_NO_LOC) == 0) {
- /* translation */
- sub_v3_v3v3(vec, td->center, center);
- mul_m3_v3(mat, vec);
- add_v3_v3(vec, center);
- /* vec now is the location where the object has to be */
- sub_v3_v3(vec, td->center);
- mul_m3_v3(td->smtx, vec);
-
- protectedTransBits(td->protectflag, vec);
-
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
-
-
- constraintTransLim(t, td);
-
- /* rotation */
- if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself
- /* euler or quaternion? */
- if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
- /* can be called for texture space translate for example, then opt out */
- if (td->ext->quat) {
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
-
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
- /* this function works on end result */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
- }
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- /* calculate effect based on quats */
- float iquat[4], tquat[4];
-
- axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
-
- mul_m3_series(fmat, td->smtx, mat, td->mtx);
- mat3_to_quat(quat, fmat); // Actual transform
- mul_qt_qtqt(tquat, quat, iquat);
-
- quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
-
- /* this function works on end result */
- protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis,
- td->ext->irotAngle);
- }
- else {
- float obmat[3][3];
-
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, totmat);
-
- /* calculate the total rotatation in eulers */
- add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */
- eulO_to_mat3(obmat, eul, td->ext->rotOrder);
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* correct back for delta rot */
- sub_v3_v3v3(eul, eul, td->ext->drot);
-
- /* and apply */
- protectedRotateBits(td->protectflag, eul, td->ext->irot);
- copy_v3_v3(td->ext->rot, eul);
- }
-
- constraintRotLim(t, td);
- }
- }
-}
-
-static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
+static void ElementRotation_ex(
+ TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const float *center)
+{
+ float vec[3], totmat[3][3], smat[3][3];
+ float eul[3], fmat[3][3], quat[4];
+
+ if (t->flag & T_POINTS) {
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* apply gpencil falloff */
+ if (t->options & CTX_GPENCIL_STROKES) {
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ float sx = smat[0][0];
+ float sy = smat[1][1];
+ float sz = smat[2][2];
+
+ mul_m3_fl(smat, gps->runtime.multi_frame_falloff);
+ /* fix scale */
+ smat[0][0] = sx;
+ smat[1][1] = sy;
+ smat[2][2] = sz;
+ }
+
+ sub_v3_v3v3(vec, td->iloc, center);
+ mul_m3_v3(smat, vec);
+
+ add_v3_v3v3(td->loc, vec, center);
+
+ sub_v3_v3v3(vec, td->loc, td->iloc);
+ protectedTransBits(td->protectflag, vec);
+ add_v3_v3v3(td->loc, td->iloc, vec);
+
+ if (td->flag & TD_USEQUAT) {
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+
+ if (td->ext->quat) {
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+
+ /* is there a reason not to have this here? -jahka */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ }
+ }
+ /**
+ * HACK WARNING
+ *
+ * This is some VERY ugly special case to deal with pose mode.
+ *
+ * The problem is that mtx and smtx include each bone orientation.
+ *
+ * That is needed to rotate each bone properly, HOWEVER, to calculate
+ * the translation component, we only need the actual armature object's
+ * matrix (and inverse). That is not all though. Once the proper translation
+ * has been computed, it has to be converted back into the bone's space.
+ */
+ else if (t->flag & T_POSE) {
+ // Extract and invert armature object matrix
+
+ if ((td->flag & TD_NO_LOC) == 0) {
+ sub_v3_v3v3(vec, td->center, center);
+
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(mat, vec); // Applying rotation
+ mul_m3_v3(tc->imat3, vec); // To Local space
+
+ add_v3_v3(vec, center);
+ /* vec now is the location where the object has to be */
+
+ sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
+
+ /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
+ if (td->flag & TD_PBONE_LOCAL_MTX_P) {
+ /* do nothing */
+ }
+ else if (td->flag & TD_PBONE_LOCAL_MTX_C) {
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location)
+ }
+ else {
+ mul_m3_v3(tc->mat3, vec); // To Global space
+ mul_m3_v3(td->smtx, vec); // To Pose space
+ }
+
+ protectedTransBits(td->protectflag, vec);
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+
+ constraintTransLim(t, td);
+ }
+
+ /* rotation */
+ /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same,
+ * and ElementRotation() might be called in Translation context (with align snapping),
+ * we need to be sure to actually use the *rotation* matrix here...
+ * So no other way than storing it in some dedicated members of td->ext! */
+ if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
+ /* euler or quaternion/axis-angle? */
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
+
+ mat3_to_quat(quat, fmat); /* Actual transform */
+
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* calculate effect based on quats */
+ float iquat[4], tquat[4];
+
+ axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
+
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
+ mat3_to_quat(quat, fmat); /* Actual transform */
+ mul_qt_qtqt(tquat, quat, iquat);
+
+ quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
+
+ /* this function works on end result */
+ protectedAxisAngleBits(td->protectflag,
+ td->ext->rotAxis,
+ td->ext->rotAngle,
+ td->ext->irotAxis,
+ td->ext->irotAngle);
+ }
+ else {
+ float eulmat[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->ext->r_mtx);
+ mul_m3_m3m3(smat, td->ext->r_smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ copy_v3_v3(eul, td->ext->irot);
+ eulO_to_mat3(eulmat, eul, td->ext->rotOrder);
+
+ /* mat = transform, obmat = bone rotation */
+ mul_m3_m3m3(fmat, smat, eulmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* and apply (to end result only) */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ copy_v3_v3(td->ext->rot, eul);
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+ else {
+ if ((td->flag & TD_NO_LOC) == 0) {
+ /* translation */
+ sub_v3_v3v3(vec, td->center, center);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, center);
+ /* vec now is the location where the object has to be */
+ sub_v3_v3(vec, td->center);
+ mul_m3_v3(td->smtx, vec);
+
+ protectedTransBits(td->protectflag, vec);
+
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+
+ constraintTransLim(t, td);
+
+ /* rotation */
+ if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself
+ /* euler or quaternion? */
+ if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
+ /* can be called for texture space translate for example, then opt out */
+ if (td->ext->quat) {
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ /* calculate effect based on quats */
+ float iquat[4], tquat[4];
+
+ axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
+
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
+ mat3_to_quat(quat, fmat); // Actual transform
+ mul_qt_qtqt(tquat, quat, iquat);
+
+ quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
+
+ /* this function works on end result */
+ protectedAxisAngleBits(td->protectflag,
+ td->ext->rotAxis,
+ td->ext->rotAngle,
+ td->ext->irotAxis,
+ td->ext->irotAngle);
+ }
+ else {
+ float obmat[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */
+ eulO_to_mat3(obmat, eul, td->ext->rotOrder);
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* correct back for delta rot */
+ sub_v3_v3v3(eul, eul, td->ext->drot);
+
+ /* and apply */
+ protectedRotateBits(td->protectflag, eul, td->ext->irot);
+ copy_v3_v3(td->ext->rot, eul);
+ }
+
+ constraintRotLim(t, td);
+ }
+ }
+}
+
+static void ElementRotation(
+ TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
{
- const float *center;
-
- /* local constraint shouldn't alter center */
- if (transdata_check_local_center(t, around)) {
- center = td->center;
- }
- else {
- center = tc->center_local;
- }
-
- ElementRotation_ex(t, tc, td, mat, center);
+ const float *center;
+
+ /* local constraint shouldn't alter center */
+ if (transdata_check_local_center(t, around)) {
+ center = td->center;
+ }
+ else {
+ center = tc->center_local;
+ }
+
+ ElementRotation_ex(t, tc, td, mat, center);
}
static void applyRotationValue(TransInfo *t, float angle, float axis[3])
{
- float mat[3][3];
- int i;
+ float mat[3][3];
+ int i;
- axis_angle_normalized_to_mat3(mat, axis, angle);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (t->con.applyRot) {
- t->con.applyRot(t, tc, td, axis, NULL);
- axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
- }
- else if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
- }
+ if (t->con.applyRot) {
+ t->con.applyRot(t, tc, td, axis, NULL);
+ axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+ }
+ else if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ }
}
static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, NULL);
- }
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, NULL);
+ }
- applySnapping(t, &final);
+ applySnapping(t, &final);
- /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */
- applyNumInput(&t->num, &final);
+ /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- headerRotation(t, str, final);
+ headerRotation(t, str, final);
- applyRotationValue(t, final, axis_final);
+ applyRotationValue(t, final, axis_final);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Rotation - Trackball) */
@@ -4520,115 +4585,127 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
static void initTrackball(TransInfo *t)
{
- t->mode = TFM_TRACKBALL;
- t->transform = applyTrackball;
+ t->mode = TFM_TRACKBALL;
+ t->transform = applyTrackball;
- initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
+ initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL);
- t->idx_max = 1;
- t->num.idx_max = 1;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
+ t->idx_max = 1;
+ t->num.idx_max = 1;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
- t->num.unit_type[1] = B_UNIT_ROTATION;
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
+ t->num.unit_type[1] = B_UNIT_ROTATION;
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
-static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2])
+static void applyTrackballValue(TransInfo *t,
+ const float axis1[3],
+ const float axis2[3],
+ float angles[2])
{
- float mat[3][3];
- float axis[3];
- float angle;
- int i;
+ float mat[3][3];
+ float axis[3];
+ float angle;
+ int i;
- mul_v3_v3fl(axis, axis1, angles[0]);
- madd_v3_v3fl(axis, axis2, angles[1]);
- angle = normalize_v3(axis);
- axis_angle_normalized_to_mat3(mat, axis, angle);
+ mul_v3_v3fl(axis, axis1, angles[0]);
+ madd_v3_v3fl(axis, axis2, angles[1]);
+ angle = normalize_v3(axis);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (t->flag & T_PROP_EDIT) {
- axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
- }
+ if (t->flag & T_PROP_EDIT) {
+ axis_angle_normalized_to_mat3(mat, axis, td->factor * angle);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- }
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ }
}
static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float axis1[3], axis2[3];
-#if 0 /* UNUSED */
- float mat[3][3], totmat[3][3], smat[3][3];
+ char str[UI_MAX_DRAW_STR];
+ 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];
+ float phi[2];
- copy_v3_v3(axis1, t->persinv[0]);
- copy_v3_v3(axis2, t->persinv[1]);
- normalize_v3(axis1);
- normalize_v3(axis2);
+ copy_v3_v3(axis1, t->persinv[0]);
+ copy_v3_v3(axis2, t->persinv[1]);
+ normalize_v3(axis1);
+ normalize_v3(axis2);
- copy_v2_v2(phi, t->values);
+ copy_v2_v2(phi, t->values);
- snapGridIncrement(t, phi);
+ snapGridIncrement(t, phi);
- applyNumInput(&t->num, phi);
+ applyNumInput(&t->num, phi);
- copy_v2_v2(t->values, phi);
+ copy_v2_v2(t->values, phi);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN * 2];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN * 2];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %s %s %s"),
- &c[0], &c[NUM_STR_REP_LEN], t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %.2f %.2f %s"),
- RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext);
- }
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ IFACE_("Trackball: %s %s %s"),
+ &c[0],
+ &c[NUM_STR_REP_LEN],
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ IFACE_("Trackball: %.2f %.2f %s"),
+ RAD2DEGF(phi[0]),
+ RAD2DEGF(phi[1]),
+ t->proptext);
+ }
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - 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]);
+#if 0 /* UNUSED */
+ axis_angle_normalized_to_mat3(smat, axis1, phi[0]);
+ axis_angle_normalized_to_mat3(totmat, axis2, phi[1]);
- mul_m3_m3m3(mat, smat, totmat);
+ mul_m3_m3m3(mat, smat, totmat);
- // TRANSFORM_FIX_ME
- //copy_m3_m3(t->mat, mat); // used in gizmo
+ // TRANSFORM_FIX_ME
+ //copy_m3_m3(t->mat, mat); // used in gizmo
#endif
- applyTrackballValue(t, axis1, axis2, phi);
+ applyTrackballValue(t, axis1, axis2, phi);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Normal Rotation) */
@@ -4637,153 +4714,154 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm)
{
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
- // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+ // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- tc->custom.mode.data = lnors_ed_arr;
- tc->custom.mode.free_cb = freeCustomNormalArray;
+ tc->custom.mode.data = lnors_ed_arr;
+ tc->custom.mode.free_cb = freeCustomNormalArray;
}
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data;
+ BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data;
- if (t->state == TRANS_CANCEL) {
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
+ if (t->state == TRANS_CANCEL) {
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
- /* Restore custom loop normal on cancel */
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data);
- }
- }
+ /* Restore custom loop normal on cancel */
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data);
+ }
+ }
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
- tc->custom.mode.data = NULL;
- tc->custom.mode.free_cb = NULL;
+ tc->custom.mode.data = NULL;
+ tc->custom.mode.free_cb = NULL;
}
static void initNormalRotation(TransInfo *t)
{
- t->mode = TFM_NORMAL_ROTATION;
- t->transform = applyNormalRotation;
+ t->mode = TFM_NORMAL_ROTATION;
+ t->transform = applyNormalRotation;
- setInputPostFct(&t->mouse, postInputRotation);
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
- BKE_editmesh_lnorspace_update(em);
+ BKE_editmesh_lnorspace_update(em);
- storeCustomLNorValue(tc, bm);
- }
+ storeCustomLNorValue(tc, bm);
+ }
}
/* Works by getting custom normal from clnor_data, transform, then store */
static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
+ char str[UI_MAX_DRAW_STR];
- float axis_final[3];
- copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
+ float axis_final[3];
+ copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]);
- if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
- t->con.applyRot(t, NULL, NULL, axis_final, NULL);
- }
+ if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
+ t->con.applyRot(t, NULL, NULL, axis_final, NULL);
+ }
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
- BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data;
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data;
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- float axis[3];
- float mat[3][3];
- float angle = t->values[0];
- copy_v3_v3(axis, axis_final);
+ float axis[3];
+ float mat[3][3];
+ float angle = t->values[0];
+ copy_v3_v3(axis, axis_final);
- snapGridIncrement(t, &angle);
+ snapGridIncrement(t, &angle);
- applySnapping(t, &angle);
+ applySnapping(t, &angle);
- applyNumInput(&t->num, &angle);
+ applyNumInput(&t->num, &angle);
- headerRotation(t, str, angle);
+ headerRotation(t, str, angle);
- axis_angle_normalized_to_mat3(mat, axis, angle);
+ axis_angle_normalized_to_mat3(mat, axis, angle);
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
- }
- }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Translation) */
static void initSnapSpatial(TransInfo *t, float r_snap[3])
{
- if (t->spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = t->ar->regiondata;
-
- if (rv3d) {
- View3D *v3d = t->sa->spacedata.first;
- r_snap[0] = 0.0f;
- r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f;
- r_snap[2] = r_snap[1] * 0.1f;
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- r_snap[0] = 0.0f;
- r_snap[1] = 0.0625f;
- r_snap[2] = 0.03125f;
- }
- else if (t->spacetype == SPACE_CLIP) {
- r_snap[0] = 0.0f;
- r_snap[1] = 0.125f;
- r_snap[2] = 0.0625f;
- }
- else if (t->spacetype == SPACE_NODE) {
- r_snap[0] = 0.0f;
- r_snap[1] = ED_node_grid_size();
- r_snap[2] = ED_node_grid_size();
- }
- else if (t->spacetype == SPACE_GRAPH) {
- r_snap[0] = 0.0f;
- r_snap[1] = 1.0;
- r_snap[2] = 0.1f;
- }
- else {
- r_snap[0] = 0.0f;
- r_snap[1] = r_snap[2] = 1.0f;
- }
+ if (t->spacetype == SPACE_VIEW3D) {
+ RegionView3D *rv3d = t->ar->regiondata;
+
+ if (rv3d) {
+ View3D *v3d = t->sa->spacedata.first;
+ r_snap[0] = 0.0f;
+ r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f;
+ r_snap[2] = r_snap[1] * 0.1f;
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.0625f;
+ r_snap[2] = 0.03125f;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.125f;
+ r_snap[2] = 0.0625f;
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = ED_node_grid_size();
+ r_snap[2] = ED_node_grid_size();
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 1.0;
+ r_snap[2] = 0.1f;
+ }
+ else {
+ r_snap[0] = 0.0f;
+ r_snap[1] = r_snap[2] = 1.0f;
+ }
}
/** \name Transform Translation
@@ -4791,304 +4869,355 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3])
static void initTranslation(TransInfo *t)
{
- if (t->spacetype == SPACE_ACTION) {
- /* this space uses time translate */
- BKE_report(t->reports, RPT_ERROR,
- "Use 'Time_Translate' transform mode instead of 'Translation' mode "
- "for translating keyframes in Dope Sheet Editor");
- t->state = TRANS_CANCEL;
- }
-
- t->mode = TFM_TRANSLATION;
- t->transform = applyTranslation;
-
- initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
-
- t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- copy_v3_v3(t->snap, t->snap_spatial);
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- if (t->spacetype == SPACE_VIEW3D) {
- /* Handling units makes only sense in 3Dview... See T38877. */
- t->num.unit_type[0] = B_UNIT_LENGTH;
- t->num.unit_type[1] = B_UNIT_LENGTH;
- t->num.unit_type[2] = B_UNIT_LENGTH;
- }
- else {
- /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
- }
+ if (t->spacetype == SPACE_ACTION) {
+ /* this space uses time translate */
+ BKE_report(t->reports,
+ RPT_ERROR,
+ "Use 'Time_Translate' transform mode instead of 'Translation' mode "
+ "for translating keyframes in Dope Sheet Editor");
+ t->state = TRANS_CANCEL;
+ }
+
+ t->mode = TFM_TRANSLATION;
+ t->transform = applyTranslation;
+
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+
+ t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ copy_v3_v3(t->snap, t->snap_spatial);
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* Handling units makes only sense in 3Dview... See T38877. */
+ t->num.unit_type[0] = B_UNIT_LENGTH;
+ t->num.unit_type[1] = B_UNIT_LENGTH;
+ t->num.unit_type[2] = B_UNIT_LENGTH;
+ }
+ else {
+ /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
+ }
}
static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
{
- size_t ofs = 0;
- char tvec[NUM_STR_REP_LEN * 3];
- char distvec[NUM_STR_REP_LEN];
- char autoik[NUM_STR_REP_LEN];
- float dist;
-
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- dist = len_v3(t->num.val);
- }
- else {
- float dvec[3];
-
- copy_v3_v3(dvec, vec);
- applyAspectRatio(t, dvec);
-
- dist = len_v3(vec);
- if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- int i;
-
- for (i = 0; i < 3; i++) {
- bUnit_AsString2(
- &tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length,
- 4, B_UNIT_LENGTH, &t->scene->unit, true);
- }
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]);
- }
- }
-
- if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
- bUnit_AsString2(
- distvec, sizeof(distvec), dist * t->scene->unit.scale_length,
- 4, B_UNIT_LENGTH, &t->scene->unit, false);
- }
- else if (dist > 1e10f || dist < -1e10f) {
- /* prevent string buffer overflow */
- BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
- }
- else {
- BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist);
- }
-
- if (t->flag & T_AUTOIK) {
- short chainlen = t->settings->autoik_chainlen;
-
- if (chainlen)
- BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen);
- else
- autoik[0] = '\0';
- }
- else
- autoik[0] = '\0';
-
- if (t->con.mode & CON_APPLY) {
- switch (t->num.idx_max) {
- case 0:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s (%s)%s %s %s",
- &tvec[0], distvec, t->con.text, t->proptext, autoik);
- break;
- case 1:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s D: %s (%s)%s %s %s",
- &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext, autoik);
- break;
- case 2:
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s D: %s D: %s (%s)%s %s %s",
- &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec,
- t->con.text, t->proptext, autoik);
- break;
- }
- }
- else {
- if (t->flag & T_2D_EDIT) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "Dx: %s Dy: %s (%s)%s %s",
- &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext);
- }
- else {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s",
- &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text,
- t->proptext, autoik);
- }
- }
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
-
- if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
-
- if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
- const char *str_old = BLI_strdup(str);
- const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? IFACE_("right") : IFACE_("left");
- char str_km[64];
-
- WM_modalkeymap_items_to_string(t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km));
-
- ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("Auto-offset set to %s - press %s to toggle direction | %s"),
- str_dir, str_km, str_old);
-
- MEM_freeN((void *)str_old);
- }
- }
+ size_t ofs = 0;
+ char tvec[NUM_STR_REP_LEN * 3];
+ char distvec[NUM_STR_REP_LEN];
+ char autoik[NUM_STR_REP_LEN];
+ float dist;
+
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ dist = len_v3(t->num.val);
+ }
+ else {
+ float dvec[3];
+
+ copy_v3_v3(dvec, vec);
+ applyAspectRatio(t, dvec);
+
+ dist = len_v3(vec);
+ if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ bUnit_AsString2(&tvec[NUM_STR_REP_LEN * i],
+ NUM_STR_REP_LEN,
+ dvec[i] * t->scene->unit.scale_length,
+ 4,
+ B_UNIT_LENGTH,
+ &t->scene->unit,
+ true);
+ }
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]);
+ }
+ }
+
+ if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) {
+ bUnit_AsString2(distvec,
+ sizeof(distvec),
+ dist * t->scene->unit.scale_length,
+ 4,
+ B_UNIT_LENGTH,
+ &t->scene->unit,
+ false);
+ }
+ else if (dist > 1e10f || dist < -1e10f) {
+ /* prevent string buffer overflow */
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
+ }
+ else {
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist);
+ }
+
+ if (t->flag & T_AUTOIK) {
+ short chainlen = t->settings->autoik_chainlen;
+
+ if (chainlen)
+ BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen);
+ else
+ autoik[0] = '\0';
+ }
+ else
+ autoik[0] = '\0';
+
+ if (t->con.mode & CON_APPLY) {
+ switch (t->num.idx_max) {
+ case 0:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s (%s)%s %s %s",
+ &tvec[0],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ case 1:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s D: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ case 2:
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "D: %s D: %s D: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ break;
+ }
+ }
+ else {
+ if (t->flag & T_2D_EDIT) {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "Dx: %s Dy: %s (%s)%s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ distvec,
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ "Dx: %s Dy: %s Dz: %s (%s)%s %s %s",
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ distvec,
+ t->con.text,
+ t->proptext,
+ autoik);
+ }
+ }
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
+
+ if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+
+ if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
+ const char *str_old = BLI_strdup(str);
+ const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ?
+ IFACE_("right") :
+ IFACE_("left");
+ char str_km[64];
+
+ WM_modalkeymap_items_to_string(
+ t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km));
+
+ ofs += BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ IFACE_("Auto-offset set to %s - press %s to toggle direction | %s"),
+ str_dir,
+ str_km,
+ str_old);
+
+ MEM_freeN((void *)str_old);
+ }
+ }
}
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
- const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT);
- float tvec[3];
-
- /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
- * so, maybe inside this function is not the best place to apply this rotation.
- * but you need "handle snapping rotation before doing the translation" (really?) */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- float pivot[3];
- if (apply_snap_align_rotation) {
- copy_v3_v3(pivot, t->tsnap.snapTarget);
- /* The pivot has to be in local-space (see T49494) */
- if (tc->use_local_mat) {
- mul_m4_v3(tc->imat, pivot);
- }
- }
-
- TransData *td = tc->data;
- for (int i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- float rotate_offset[3] = {0};
- bool use_rotate_offset = false;
-
- /* handle snapping rotation before doing the translation */
- if (apply_snap_align_rotation) {
- float mat[3][3];
-
- if (validSnappingNormal(t)) {
- const float *original_normal;
-
- /* In pose mode, we want to align normals with Y axis of bones... */
- if (t->flag & T_POSE)
- original_normal = td->axismtx[1];
- else
- original_normal = td->axismtx[2];
-
- rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
- }
- else {
- unit_m3(mat);
- }
-
- ElementRotation_ex(t, tc, td, mat, pivot);
-
- if (td->loc) {
- use_rotate_offset = true;
- sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
- }
- }
-
- if (t->con.applyVec) {
- float pvec[3];
- t->con.applyVec(t, tc, td, vec, tvec, pvec);
- }
- else {
- copy_v3_v3(tvec, vec);
- }
-
- if (use_rotate_offset) {
- add_v3_v3(tvec, rotate_offset);
- }
-
- mul_m3_v3(td->smtx, tvec);
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* grease pencil multiframe falloff */
- bGPDstroke *gps = (bGPDstroke *)td->extra;
- if (gps != NULL) {
- mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
- }
- else {
- mul_v3_fl(tvec, td->factor);
- }
- }
- else {
- /* proportional editing falloff */
- mul_v3_fl(tvec, td->factor);
- }
-
- protectedTransBits(td->protectflag, tvec);
-
- if (td->loc)
- add_v3_v3v3(td->loc, td->iloc, tvec);
-
- constraintTransLim(t, td);
- }
- }
+ const bool apply_snap_align_rotation = usingSnappingNormal(
+ t); // && (t->tsnap.status & POINT_INIT);
+ float tvec[3];
+
+ /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
+ * so, maybe inside this function is not the best place to apply this rotation.
+ * but you need "handle snapping rotation before doing the translation" (really?) */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ float pivot[3];
+ if (apply_snap_align_rotation) {
+ copy_v3_v3(pivot, t->tsnap.snapTarget);
+ /* The pivot has to be in local-space (see T49494) */
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->imat, pivot);
+ }
+ }
+
+ TransData *td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ float rotate_offset[3] = {0};
+ bool use_rotate_offset = false;
+
+ /* handle snapping rotation before doing the translation */
+ if (apply_snap_align_rotation) {
+ float mat[3][3];
+
+ if (validSnappingNormal(t)) {
+ const float *original_normal;
+
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ if (t->flag & T_POSE)
+ original_normal = td->axismtx[1];
+ else
+ original_normal = td->axismtx[2];
+
+ rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal);
+ }
+ else {
+ unit_m3(mat);
+ }
+
+ ElementRotation_ex(t, tc, td, mat, pivot);
+
+ if (td->loc) {
+ use_rotate_offset = true;
+ sub_v3_v3v3(rotate_offset, td->loc, td->iloc);
+ }
+ }
+
+ if (t->con.applyVec) {
+ float pvec[3];
+ t->con.applyVec(t, tc, td, vec, tvec, pvec);
+ }
+ else {
+ copy_v3_v3(tvec, vec);
+ }
+
+ if (use_rotate_offset) {
+ add_v3_v3(tvec, rotate_offset);
+ }
+
+ mul_m3_v3(td->smtx, tvec);
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* grease pencil multiframe falloff */
+ bGPDstroke *gps = (bGPDstroke *)td->extra;
+ if (gps != NULL) {
+ mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff);
+ }
+ else {
+ mul_v3_fl(tvec, td->factor);
+ }
+ }
+ else {
+ /* proportional editing falloff */
+ mul_v3_fl(tvec, td->factor);
+ }
+
+ protectedTransBits(td->protectflag, tvec);
+
+ if (td->loc)
+ add_v3_v3v3(td->loc, td->iloc, tvec);
+
+ constraintTransLim(t, td);
+ }
+ }
}
static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
- float value_final[3];
+ char str[UI_MAX_DRAW_STR];
+ float value_final[3];
- if (t->flag & T_AUTOVALUES) {
- copy_v3_v3(t->values, t->auto_values);
- }
- else {
- if ((t->con.mode & CON_APPLY) == 0) {
- snapGridIncrement(t, t->values);
- }
+ if (t->flag & T_AUTOVALUES) {
+ copy_v3_v3(t->values, t->auto_values);
+ }
+ else {
+ if ((t->con.mode & CON_APPLY) == 0) {
+ snapGridIncrement(t, t->values);
+ }
- if (applyNumInput(&t->num, t->values)) {
- removeAspectRatio(t, t->values);
- }
+ if (applyNumInput(&t->num, t->values)) {
+ removeAspectRatio(t, t->values);
+ }
- applySnapping(t, t->values);
- }
+ applySnapping(t, t->values);
+ }
- if (t->con.mode & CON_APPLY) {
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec);
- headerTranslation(t, pvec, str);
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec);
+ headerTranslation(t, pvec, str);
- /* only so we have re-usable value with redo, see T46741. */
- mul_v3_m3v3(t->values, t->con.imtx, value_final);
- }
- else {
- headerTranslation(t, t->values, str);
- copy_v3_v3(value_final, t->values);
- }
+ /* only so we have re-usable value with redo, see T46741. */
+ mul_v3_m3v3(t->values, t->con.imtx, value_final);
+ }
+ else {
+ headerTranslation(t, t->values, str);
+ copy_v3_v3(value_final, t->values);
+ }
- /* don't use 't->values' now on */
+ /* don't use 't->values' now on */
- applyTranslationValue(t, value_final);
+ applyTranslationValue(t, value_final);
- /* evil hack - redo translation if clipping needed */
- if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) {
- applyTranslationValue(t, value_final);
+ /* evil hack - redo translation if clipping needed */
+ if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) {
+ applyTranslationValue(t, value_final);
- /* In proportional edit it can happen that */
- /* vertices in the radius of the brush end */
- /* outside the clipping area */
- /* XXX HACK - dg */
- if (t->flag & T_PROP_EDIT_ALL) {
- clipUVData(t);
- }
- }
+ /* In proportional edit it can happen that */
+ /* vertices in the radius of the brush end */
+ /* outside the clipping area */
+ /* XXX HACK - dg */
+ if (t->flag & T_PROP_EDIT_ALL) {
+ clipUVData(t);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Shrink-Fatten) */
@@ -5097,100 +5226,101 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
static void initShrinkFatten(TransInfo *t)
{
- // If not in mesh edit mode, fallback to Resize
- if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) {
- initResize(t);
- }
- else {
- t->mode = TFM_SHRINKFATTEN;
- t->transform = applyShrinkFatten;
+ // If not in mesh edit mode, fallback to Resize
+ if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) {
+ initResize(t);
+ }
+ else {
+ t->mode = TFM_SHRINKFATTEN;
+ t->transform = applyShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_LENGTH;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_LENGTH;
- t->flag |= T_NO_CONSTRAINT;
- }
+ t->flag |= T_NO_CONSTRAINT;
+ }
}
-
static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- float distance;
- int i;
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
-
- distance = -t->values[0];
-
- snapGridIncrement(t, &distance);
-
- applyNumInput(&t->num, &distance);
-
- t->values[0] = -distance;
-
- /* header print for NumInput */
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c);
- }
- else {
- /* default header print */
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance);
- }
-
- if (t->proptext[0]) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext);
- }
- ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs);
-
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
- }
- }
- BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" or Alt) Even Thickness %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
- /* done with header string */
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float tdistance; /* temp dist */
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- /* get the final offset */
- tdistance = distance * td->factor;
- if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
- tdistance *= td->ext->isize[0]; /* shell factor */
- }
-
- madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ float distance;
+ int i;
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+
+ distance = -t->values[0];
+
+ snapGridIncrement(t, &distance);
+
+ applyNumInput(&t->num, &distance);
+
+ t->values[0] = -distance;
+
+ /* header print for NumInput */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c);
+ }
+ else {
+ /* default header print */
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance);
+ }
+
+ if (t->proptext[0]) {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext);
+ }
+ ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs);
+
+ if (t->keymap) {
+ wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE);
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs);
+ }
+ }
+ BLI_snprintf(str + ofs,
+ sizeof(str) - ofs,
+ IFACE_(" or Alt) Even Thickness %s"),
+ WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+ /* done with header string */
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float tdistance; /* temp dist */
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* get the final offset */
+ tdistance = distance * td->factor;
+ if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) {
+ tdistance *= td->ext->isize[0]; /* shell factor */
+ }
+
+ madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance);
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Tilt) */
@@ -5199,77 +5329,76 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initTilt(TransInfo *t)
{
- t->mode = TFM_TILT;
- t->transform = applyTilt;
+ t->mode = TFM_TILT;
+ t->transform = applyTilt;
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
- copy_v3_fl(t->num.val_inc, t->snap[2]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
+ copy_v3_fl(t->num.val_inc, t->snap[2]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
-
static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
{
- int i;
- char str[UI_MAX_DRAW_STR];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- applyNumInput(&t->num, &final);
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
+ BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
- /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */
- t->values[0] = final;
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
- }
+ /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */
+ t->values[0] = final;
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival + final * td->factor;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival + final * td->factor;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Curve Shrink/Fatten) */
@@ -5278,79 +5407,80 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
static void initCurveShrinkFatten(TransInfo *t)
{
- t->mode = TFM_CURVE_SHRINKFATTEN;
- t->transform = applyCurveShrinkFatten;
+ t->mode = TFM_CURVE_SHRINKFATTEN;
+ t->transform = applyCurveShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) *td->val = 0.001f;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f)
+ *td->val = 0.001f;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Mask Shrink/Fatten) */
@@ -5359,104 +5489,106 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initMaskShrinkFatten(TransInfo *t)
{
- t->mode = TFM_MASK_SHRINKFATTEN;
- t->transform = applyMaskShrinkFatten;
+ t->mode = TFM_MASK_SHRINKFATTEN;
+ t->transform = applyMaskShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- float ratio;
- int i;
- bool initial_feather = false;
- char str[UI_MAX_DRAW_STR];
+ float ratio;
+ int i;
+ bool initial_feather = false;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio);
+ }
- /* detect if no points have feather yet */
- if (ratio > 1.0f) {
- initial_feather = true;
+ /* detect if no points have feather yet */
+ if (ratio > 1.0f) {
+ initial_feather = true;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->ival >= 0.001f)
- initial_feather = false;
- }
- }
- }
+ if (td->ival >= 0.001f)
+ initial_feather = false;
+ }
+ }
+ }
- /* apply shrink/fatten */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ /* apply shrink/fatten */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- if (initial_feather)
- *td->val = td->ival + (ratio - 1.0f) * 0.01f;
- else
- *td->val = td->ival * ratio;
+ if (td->val) {
+ if (initial_feather)
+ *td->val = td->ival + (ratio - 1.0f) * 0.01f;
+ else
+ *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) *td->val = 0.001f;
- }
- }
- }
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f)
+ *td->val = 0.001f;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (GPencil Shrink/Fatten) */
@@ -5465,73 +5597,75 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initGPShrinkFatten(TransInfo *t)
{
- t->mode = TFM_GPENCIL_SHRINKFATTEN;
- t->transform = applyGPShrinkFatten;
+ t->mode = TFM_GPENCIL_SHRINKFATTEN;
+ t->transform = applyGPShrinkFatten;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- if (*td->val <= 0.0f) *td->val = 0.001f;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ if (*td->val <= 0.0f)
+ *td->val = 0.001f;
+ }
+ }
+ }
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -5543,77 +5677,77 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
static void initGPOpacity(TransInfo *t)
{
- t->mode = TFM_GPENCIL_OPACITY;
- t->transform = applyGPOpacity;
+ t->mode = TFM_GPENCIL_OPACITY;
+ t->transform = applyGPOpacity;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_ZERO;
+ t->flag |= T_NO_ZERO;
#ifdef USE_NUM_NO_ZERO
- t->num.val_flag[0] |= NUM_NO_ZERO;
+ t->num.val_flag[0] |= NUM_NO_ZERO;
#endif
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
}
static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %3f"), ratio);
+ }
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival * ratio;
- /* apply PET */
- *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
- CLAMP(*td->val, 0.0f, 1.0f);
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival * ratio;
+ /* apply PET */
+ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival);
+ CLAMP(*td->val, 0.0f, 1.0f);
+ }
+ }
+ }
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Push/Pull) */
@@ -5622,93 +5756,93 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
static void initPushPull(TransInfo *t)
{
- t->mode = TFM_PUSHPULL;
- t->transform = applyPushPull;
+ t->mode = TFM_PUSHPULL;
+ t->transform = applyPushPull;
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_LENGTH;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_LENGTH;
}
-
static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3], axis_global[3];
- float distance;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float vec[3], axis_global[3];
+ float distance;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- distance = t->values[0];
+ distance = t->values[0];
- snapGridIncrement(t, &distance);
+ snapGridIncrement(t, &distance);
- applyNumInput(&t->num, &distance);
+ applyNumInput(&t->num, &distance);
- t->values[0] = distance;
+ t->values[0] = distance;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
- }
- else {
- /* default header print */
- BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
+ }
+ else {
+ /* default header print */
+ BLI_snprintf(
+ str, sizeof(str), IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
+ }
- if (t->con.applyRot && t->con.mode & CON_APPLY) {
- t->con.applyRot(t, NULL, NULL, axis_global, NULL);
- }
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ t->con.applyRot(t, NULL, NULL, axis_global, NULL);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- sub_v3_v3v3(vec, tc->center_local, td->center);
- if (t->con.applyRot && t->con.mode & CON_APPLY) {
- float axis[3];
- copy_v3_v3(axis, axis_global);
- t->con.applyRot(t, tc, td, axis, NULL);
+ sub_v3_v3v3(vec, tc->center_local, td->center);
+ if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ float axis[3];
+ copy_v3_v3(axis, axis_global);
+ t->con.applyRot(t, tc, td, axis, NULL);
- mul_m3_v3(td->smtx, axis);
- if (isLockConstraint(t)) {
- float dvec[3];
- project_v3_v3v3(dvec, vec, axis);
- sub_v3_v3(vec, dvec);
- }
- else {
- project_v3_v3v3(vec, vec, axis);
- }
- }
- normalize_v3_length(vec, distance * td->factor);
+ mul_m3_v3(td->smtx, axis);
+ if (isLockConstraint(t)) {
+ float dvec[3];
+ project_v3_v3v3(dvec, vec, axis);
+ sub_v3_v3(vec, dvec);
+ }
+ else {
+ project_v3_v3v3(vec, vec, axis);
+ }
+ }
+ normalize_v3_length(vec, distance * td->factor);
- add_v3_v3v3(td->loc, td->iloc, vec);
- }
- }
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bevel Weight) */
@@ -5717,80 +5851,82 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
static void initBevelWeight(TransInfo *t)
{
- t->mode = TFM_BWEIGHT;
- t->transform = applyBevelWeight;
+ t->mode = TFM_BWEIGHT;
+ t->transform = applyBevelWeight;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
{
- float weight;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float weight;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- weight = t->values[0];
+ weight = t->values[0];
- CLAMP_MAX(weight, 1.0f);
+ CLAMP_MAX(weight, 1.0f);
- snapGridIncrement(t, &weight);
+ snapGridIncrement(t, &weight);
- applyNumInput(&t->num, &weight);
+ applyNumInput(&t->num, &weight);
- t->values[0] = weight;
+ t->values[0] = weight;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- if (weight >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (weight >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext);
- }
+ if (weight >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (weight >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->val) {
- *td->val = td->ival + weight * td->factor;
- if (*td->val < 0.0f) *td->val = 0.0f;
- if (*td->val > 1.0f) *td->val = 1.0f;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival + weight * td->factor;
+ if (*td->val < 0.0f)
+ *td->val = 0.0f;
+ if (*td->val > 1.0f)
+ *td->val = 1.0f;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Crease) */
@@ -5799,83 +5935,85 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
static void initCrease(TransInfo *t)
{
- t->mode = TFM_CREASE;
- t->transform = applyCrease;
+ t->mode = TFM_CREASE;
+ t->transform = applyCrease;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
{
- float crease;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float crease;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- crease = t->values[0];
+ crease = t->values[0];
- CLAMP_MAX(crease, 1.0f);
+ CLAMP_MAX(crease, 1.0f);
- snapGridIncrement(t, &crease);
+ snapGridIncrement(t, &crease);
- applyNumInput(&t->num, &crease);
+ applyNumInput(&t->num, &crease);
- t->values[0] = crease;
+ t->values[0] = crease;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- if (crease >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (crease >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext);
- }
+ if (crease >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (crease >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- *td->val = td->ival + crease * td->factor;
- if (*td->val < 0.0f) *td->val = 0.0f;
- if (*td->val > 1.0f) *td->val = 1.0f;
- }
- }
- }
+ if (td->val) {
+ *td->val = td->ival + crease * td->factor;
+ if (*td->val < 0.0f)
+ *td->val = 0.0f;
+ if (*td->val > 1.0f)
+ *td->val = 1.0f;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (EditBone (B-bone) width scaling) */
@@ -5884,121 +6022,134 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneSize(TransInfo *t)
{
- t->mode = TFM_BONESIZE;
- t->transform = applyBoneSize;
+ t->mode = TFM_BONESIZE;
+ t->transform = applyBoneSize;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
- t->idx_max = 2;
- t->num.idx_max = 2;
- t->num.val_flag[0] |= NUM_NULL_ONE;
- t->num.val_flag[1] |= NUM_NULL_ONE;
- t->num.val_flag[2] |= NUM_NULL_ONE;
- t->num.flag |= NUM_AFFECT_ALL;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 2;
+ t->num.idx_max = 2;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->num.val_flag[1] |= NUM_NULL_ONE;
+ t->num.val_flag[2] |= NUM_NULL_ONE;
+ t->num.flag |= NUM_AFFECT_ALL;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
- t->num.unit_type[2] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
+ t->num.unit_type[2] = B_UNIT_NONE;
}
static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR])
{
- char tvec[NUM_STR_REP_LEN * 3];
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
- BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
- }
-
- /* hmm... perhaps the y-axis values don't need to be shown? */
- if (t->con.mode & CON_APPLY) {
- if (t->num.idx_max == 0)
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
- else
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s : %s : %s%s %s"),
- &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
- }
- else {
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"),
- &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
- }
+ char tvec[NUM_STR_REP_LEN * 3];
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
+ }
+
+ /* hmm... perhaps the y-axis values don't need to be shown? */
+ if (t->con.mode & CON_APPLY) {
+ if (t->num.idx_max == 0)
+ BLI_snprintf(
+ str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
+ else
+ BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ IFACE_("ScaleB: %s : %s : %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
+ else {
+ BLI_snprintf(str,
+ UI_MAX_DRAW_STR,
+ IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"),
+ &tvec[0],
+ &tvec[NUM_STR_REP_LEN],
+ &tvec[NUM_STR_REP_LEN * 2],
+ t->con.text,
+ t->proptext);
+ }
}
static void ElementBoneSize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3])
{
- float tmat[3][3], smat[3][3], oldy;
- float sizemat[3][3];
+ float tmat[3][3], smat[3][3], oldy;
+ float sizemat[3][3];
- mul_m3_m3m3(smat, mat, td->mtx);
- mul_m3_m3m3(tmat, td->smtx, smat);
+ mul_m3_m3m3(smat, mat, td->mtx);
+ mul_m3_m3m3(tmat, td->smtx, smat);
- if (t->con.applySize) {
- t->con.applySize(t, tc, td, tmat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, tc, td, tmat);
+ }
- /* we've tucked the scale in loc */
- oldy = td->iloc[1];
- size_to_mat3(sizemat, td->iloc);
- mul_m3_m3m3(tmat, tmat, sizemat);
- mat3_to_size(td->loc, tmat);
- td->loc[1] = oldy;
+ /* we've tucked the scale in loc */
+ oldy = td->iloc[1];
+ size_to_mat3(sizemat, td->iloc);
+ mul_m3_m3m3(tmat, tmat, sizemat);
+ mat3_to_size(td->loc, tmat);
+ td->loc[1] = oldy;
}
static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
{
- float size[3], mat[3][3];
- float ratio = t->values[0];
- int i;
- char str[UI_MAX_DRAW_STR];
+ float size[3], mat[3][3];
+ float ratio = t->values[0];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- copy_v3_fl(size, ratio);
+ copy_v3_fl(size, ratio);
- snapGridIncrement(t, size);
+ snapGridIncrement(t, size);
- if (applyNumInput(&t->num, size)) {
- constraintNumInput(t, size);
- }
+ if (applyNumInput(&t->num, size)) {
+ constraintNumInput(t, size);
+ }
- copy_v3_v3(t->values, size);
+ copy_v3_v3(t->values, size);
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
- copy_m3_m3(t->mat, mat); // used in gizmo
+ copy_m3_m3(t->mat, mat); // used in gizmo
- headerBoneSize(t, size, str);
+ headerBoneSize(t, size, str);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- ElementBoneSize(t, tc, td, mat);
- }
- }
+ ElementBoneSize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bone Envelope) */
@@ -6007,71 +6158,72 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneEnvelope(TransInfo *t)
{
- t->mode = TFM_BONE_ENVELOPE;
- t->transform = applyBoneEnvelope;
+ t->mode = TFM_BONE_ENVELOPE;
+ t->transform = applyBoneEnvelope;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
{
- float ratio;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float ratio;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- ratio = t->values[0];
+ ratio = t->values[0];
- snapGridIncrement(t, &ratio);
+ snapGridIncrement(t, &ratio);
- applyNumInput(&t->num, &ratio);
+ applyNumInput(&t->num, &ratio);
- t->values[0] = ratio;
+ t->values[0] = ratio;
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %s"), c);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio);
- }
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %s"), c);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio);
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->val) {
- /* if the old/original value was 0.0f, then just use ratio */
- if (td->ival)
- *td->val = td->ival * ratio;
- else
- *td->val = ratio;
- }
- }
- }
+ if (td->val) {
+ /* if the old/original value was 0.0f, then just use ratio */
+ if (td->ival)
+ *td->val = td->ival * ratio;
+ else
+ *td->val = ratio;
+ }
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
@@ -6081,159 +6233,157 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
/** \name Orig-Data Store Utility Functions
* \{ */
-static void slide_origdata_init_flag(
- TransInfo *t, TransDataContainer *tc, SlideOrigData *sod)
-{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- const bool has_layer_math = CustomData_has_math(&bm->ldata);
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
-
- if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
- /* don't do this at all for non-basis shape keys, too easy to
- * accidentally break uv maps or vertex colors then */
- (bm->shapenr <= 1) &&
- (has_layer_math || (cd_loop_mdisp_offset != -1)))
- {
- sod->use_origfaces = true;
- sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
- }
- else {
- sod->use_origfaces = false;
- sod->cd_loop_mdisp_offset = -1;
- }
-}
-
-static void slide_origdata_init_data(
- TransDataContainer *tc, SlideOrigData *sod)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
-
- sod->origfaces = BLI_ghash_ptr_new(__func__);
- sod->bm_origfaces = BM_mesh_create(
- &bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){.use_toolflags = false,}));
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
- }
-}
-
-static void slide_origdata_create_data_vert(
- BMesh *bm, SlideOrigData *sod,
- TransDataGenericSlideVert *sv)
-{
- BMIter liter;
- int j, l_num;
- float *loop_weights;
-
- /* copy face data */
- // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
- BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
- l_num = liter.count;
- loop_weights = BLI_array_alloca(loop_weights, l_num);
- for (j = 0; j < l_num; j++) {
- BMLoop *l = BM_iter_step(&liter);
- 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);
- *val_p = f_copy;
- }
-
- 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 */
- if (sod->layer_math_map_num && (l_num != 0)) {
- sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
- for (j = 0; j < sod->layer_math_map_num; j++) {
- const int layer_nr = sod->layer_math_map[j];
- sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(bm, sv->v, layer_nr, loop_weights, sod->arena);
- }
- }
- else {
- sv->cd_loop_groups = NULL;
- }
-
- BLI_ghash_insert(sod->origverts, sv->v, sv);
-}
-
-static void slide_origdata_create_data(
- TransDataContainer *tc, SlideOrigData *sod,
- TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- unsigned int i;
- TransDataGenericSlideVert *sv;
-
- int layer_index_dst;
- int j;
-
- layer_index_dst = 0;
-
- if (CustomData_has_math(&bm->ldata)) {
- /* over alloc, only 'math' layers are indexed */
- sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
- for (j = 0; j < bm->ldata.totlayer; j++) {
- if (CustomData_layer_has_math(&bm->ldata, j)) {
- sod->layer_math_map[layer_index_dst++] = j;
- }
- }
- BLI_assert(layer_index_dst != 0);
- }
-
- sod->layer_math_map_num = layer_index_dst;
-
- sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
-
- sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
-
- for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
- slide_origdata_create_data_vert(bm, sod, sv);
- }
-
- if (tc->mirror.axis_flag) {
- TransData *td = tc->data;
- TransDataGenericSlideVert *sv_mirror;
-
- sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__);
- sod->totsv_mirror = tc->data_len;
-
- sv_mirror = sod->sv_mirror;
-
- for (i = 0; i < tc->data_len; i++, td++) {
- BMVert *eve = td->extra;
- /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */
- if (eve && !BLI_ghash_haskey(sod->origverts, eve)) {
- sv_mirror->v = eve;
- copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
-
- slide_origdata_create_data_vert(bm, sod, sv_mirror);
- sv_mirror++;
- }
- else {
- sod->totsv_mirror--;
- }
- }
-
- if (sod->totsv_mirror == 0) {
- MEM_freeN(sod->sv_mirror);
- sod->sv_mirror = NULL;
- }
- }
- }
+static void slide_origdata_init_flag(TransInfo *t, TransDataContainer *tc, SlideOrigData *sod)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ const bool has_layer_math = CustomData_has_math(&bm->ldata);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+
+ if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
+ /* don't do this at all for non-basis shape keys, too easy to
+ * accidentally break uv maps or vertex colors then */
+ (bm->shapenr <= 1) && (has_layer_math || (cd_loop_mdisp_offset != -1))) {
+ sod->use_origfaces = true;
+ sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
+ }
+ else {
+ sod->use_origfaces = false;
+ sod->cd_loop_mdisp_offset = -1;
+ }
+}
+
+static void slide_origdata_init_data(TransDataContainer *tc, SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+
+ sod->origfaces = BLI_ghash_ptr_new(__func__);
+ sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL);
+ }
+}
+
+static void slide_origdata_create_data_vert(BMesh *bm,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+
+ /* copy face data */
+ // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+ BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v);
+ l_num = liter.count;
+ loop_weights = BLI_array_alloca(loop_weights, l_num);
+ for (j = 0; j < l_num; j++) {
+ BMLoop *l = BM_iter_step(&liter);
+ 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);
+ *val_p = f_copy;
+ }
+
+ 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 */
+ if (sod->layer_math_map_num && (l_num != 0)) {
+ sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *));
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ const int layer_nr = sod->layer_math_map[j];
+ sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(
+ bm, sv->v, layer_nr, loop_weights, sod->arena);
+ }
+ }
+ else {
+ sv->cd_loop_groups = NULL;
+ }
+
+ BLI_ghash_insert(sod->origverts, sv->v, sv);
+}
+
+static void slide_origdata_create_data(TransDataContainer *tc,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv_array,
+ unsigned int v_stride,
+ unsigned int v_num)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+ TransDataGenericSlideVert *sv;
+
+ int layer_index_dst;
+ int j;
+
+ layer_index_dst = 0;
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* over alloc, only 'math' layers are indexed */
+ sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
+ for (j = 0; j < bm->ldata.totlayer; j++) {
+ if (CustomData_layer_has_math(&bm->ldata, j)) {
+ sod->layer_math_map[layer_index_dst++] = j;
+ }
+ }
+ BLI_assert(layer_index_dst != 0);
+ }
+
+ sod->layer_math_map_num = layer_index_dst;
+
+ sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num);
+
+ for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+ slide_origdata_create_data_vert(bm, sod, sv);
+ }
+
+ if (tc->mirror.axis_flag) {
+ TransData *td = tc->data;
+ TransDataGenericSlideVert *sv_mirror;
+
+ sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__);
+ sod->totsv_mirror = tc->data_len;
+
+ sv_mirror = sod->sv_mirror;
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ BMVert *eve = td->extra;
+ /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */
+ if (eve && !BLI_ghash_haskey(sod->origverts, eve)) {
+ sv_mirror->v = eve;
+ copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
+
+ slide_origdata_create_data_vert(bm, sod, sv_mirror);
+ sv_mirror++;
+ }
+ else {
+ sod->totsv_mirror--;
+ }
+ }
+
+ if (sod->totsv_mirror == 0) {
+ MEM_freeN(sod->sv_mirror);
+ sod->sv_mirror = NULL;
+ }
+ }
+ }
}
/**
@@ -6241,192 +6391,199 @@ static void slide_origdata_create_data(
*/
static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v)
{
- TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
- return sv ? sv->co_orig_3d : v->co;
-}
-
-static void slide_origdata_interp_data_vert(
- SlideOrigData *sod, BMesh *bm, bool is_final,
- TransDataGenericSlideVert *sv)
-{
- BMIter liter;
- int j, l_num;
- float *loop_weights;
- const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
- const bool do_loop_weight = sod->layer_math_map_num && is_moved;
- const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1);
- 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 || do_loop_mdisps) {
- project_plane_normalized_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);
- l_num = liter.count;
- loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
- for (j = 0; j < l_num; j++) {
- BMFace *f_copy; /* the copy of 'f' */
- BMLoop *l = BM_iter_step(&liter);
-
- f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
-
- /* only loop data, no vertex data since that contains shape keys,
- * and we do not want to mess up other shape keys */
- BM_loop_interp_from_face(bm, l, f_copy, false, false);
-
- /* make sure face-attributes are correct (e.g. MTexPoly) */
- BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
-
- /* weight the loop */
- if (do_loop_weight) {
- 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_normalized_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_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
- }
- project_plane_normalized_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_normalized_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;
- }
- }
- }
-
- if (sod->layer_math_map_num) {
- if (do_loop_weight) {
- for (j = 0; j < sod->layer_math_map_num; j++) {
- BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
- }
- }
- else {
- for (j = 0; j < sod->layer_math_map_num; j++) {
- BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
- }
- }
- }
-
- /* Special handling for multires
- *
- * Interpolate from every other loop (not ideal)
- * However values will only be taken from loops which overlap other mdisps.
- * */
- if (do_loop_mdisps) {
- float (*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
- BMLoop *l;
-
- BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) {
- BM_face_calc_center_median(l->f, faces_center[j]);
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) {
- BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
- float f_copy_center[3];
- BMIter liter_other;
- BMLoop *l_other;
- int j_other;
-
- BM_face_calc_center_median(f_copy, f_copy_center);
-
- BM_ITER_ELEM_INDEX (l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other) {
- BM_face_interp_multires_ex(
- bm, l_other->f, f_copy,
- faces_center[j_other], f_copy_center, sod->cd_loop_mdisp_offset);
- }
- }
- }
-}
-
-static void slide_origdata_interp_data(
- Object *obedit, SlideOrigData *sod,
- TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num,
- bool is_final)
-{
- if (sod->use_origfaces) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- unsigned int i;
- const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1);
-
- for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
-
- if (sv->cd_loop_groups || has_mdisps) {
- slide_origdata_interp_data_vert(sod, bm, is_final, sv);
- }
- }
-
- if (sod->sv_mirror) {
- sv = sod->sv_mirror;
- for (i = 0; i < v_num; i++, sv++) {
- if (sv->cd_loop_groups || has_mdisps) {
- slide_origdata_interp_data_vert(sod, bm, is_final, sv);
- }
- }
- }
- }
-}
-
-static void slide_origdata_free_date(
- SlideOrigData *sod)
-{
- if (sod->use_origfaces) {
- if (sod->bm_origfaces) {
- BM_mesh_free(sod->bm_origfaces);
- sod->bm_origfaces = NULL;
- }
-
- if (sod->origfaces) {
- BLI_ghash_free(sod->origfaces, NULL, NULL);
- sod->origfaces = NULL;
- }
-
- if (sod->origverts) {
- BLI_ghash_free(sod->origverts, NULL, NULL);
- sod->origverts = NULL;
- }
-
- if (sod->arena) {
- BLI_memarena_free(sod->arena);
- sod->arena = NULL;
- }
-
- MEM_SAFE_FREE(sod->layer_math_map);
-
- MEM_SAFE_FREE(sod->sv_mirror);
- }
+ TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v);
+ return sv ? sv->co_orig_3d : v->co;
+}
+
+static void slide_origdata_interp_data_vert(SlideOrigData *sod,
+ BMesh *bm,
+ bool is_final,
+ TransDataGenericSlideVert *sv)
+{
+ BMIter liter;
+ int j, l_num;
+ float *loop_weights;
+ const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON);
+ const bool do_loop_weight = sod->layer_math_map_num && is_moved;
+ const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1);
+ 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 || do_loop_mdisps) {
+ project_plane_normalized_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);
+ l_num = liter.count;
+ loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL;
+ for (j = 0; j < l_num; j++) {
+ BMFace *f_copy; /* the copy of 'f' */
+ BMLoop *l = BM_iter_step(&liter);
+
+ f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+
+ /* only loop data, no vertex data since that contains shape keys,
+ * and we do not want to mess up other shape keys */
+ BM_loop_interp_from_face(bm, l, f_copy, false, false);
+
+ /* make sure face-attributes are correct (e.g. MTexPoly) */
+ BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
+
+ /* weight the loop */
+ if (do_loop_weight) {
+ 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_normalized_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_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ }
+ project_plane_normalized_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_normalized_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;
+ }
+ }
+ }
+
+ if (sod->layer_math_map_num) {
+ if (do_loop_weight) {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge_weights(
+ bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights);
+ }
+ }
+ else {
+ for (j = 0; j < sod->layer_math_map_num; j++) {
+ BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]);
+ }
+ }
+ }
+
+ /* Special handling for multires
+ *
+ * Interpolate from every other loop (not ideal)
+ * However values will only be taken from loops which overlap other mdisps.
+ * */
+ if (do_loop_mdisps) {
+ float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
+ BMLoop *l;
+
+ BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j)
+ {
+ BM_face_calc_center_median(l->f, faces_center[j]);
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j)
+ {
+ BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f);
+ float f_copy_center[3];
+ BMIter liter_other;
+ BMLoop *l_other;
+ int j_other;
+
+ BM_face_calc_center_median(f_copy, f_copy_center);
+
+ BM_ITER_ELEM_INDEX(l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other)
+ {
+ BM_face_interp_multires_ex(bm,
+ l_other->f,
+ f_copy,
+ faces_center[j_other],
+ f_copy_center,
+ sod->cd_loop_mdisp_offset);
+ }
+ }
+ }
+}
+
+static void slide_origdata_interp_data(Object *obedit,
+ SlideOrigData *sod,
+ TransDataGenericSlideVert *sv,
+ unsigned int v_stride,
+ unsigned int v_num,
+ bool is_final)
+{
+ if (sod->use_origfaces) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ unsigned int i;
+ const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1);
+
+ for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
+
+ if (sv->cd_loop_groups || has_mdisps) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+
+ if (sod->sv_mirror) {
+ sv = sod->sv_mirror;
+ for (i = 0; i < v_num; i++, sv++) {
+ if (sv->cd_loop_groups || has_mdisps) {
+ slide_origdata_interp_data_vert(sod, bm, is_final, sv);
+ }
+ }
+ }
+ }
+}
+
+static void slide_origdata_free_date(SlideOrigData *sod)
+{
+ if (sod->use_origfaces) {
+ if (sod->bm_origfaces) {
+ BM_mesh_free(sod->bm_origfaces);
+ sod->bm_origfaces = NULL;
+ }
+
+ if (sod->origfaces) {
+ BLI_ghash_free(sod->origfaces, NULL, NULL);
+ sod->origfaces = NULL;
+ }
+
+ if (sod->origverts) {
+ BLI_ghash_free(sod->origverts, NULL, NULL);
+ sod->origverts = NULL;
+ }
+
+ if (sod->arena) {
+ BLI_memarena_free(sod->arena);
+ sod->arena = NULL;
+ }
+
+ MEM_SAFE_FREE(sod->layer_math_map);
+
+ MEM_SAFE_FREE(sod->sv_mirror);
+ }
}
/** \} */
@@ -6439,100 +6596,95 @@ static void slide_origdata_free_date(
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
+ 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 immediately so we don't refresh
- * with the value from the previous points */
- applyMouseInput(t, &t->mouse, t->mval, t->values);
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediately 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;
- BMEdge *e_iter;
+ BMIter iter;
+ BMEdge *e_iter;
- BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) {
- return e_iter;
- }
- }
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) {
+ return e_iter;
+ }
+ }
- return NULL;
+ return NULL;
}
/* 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], float t)
-{
- float t_mid, t_delta;
-
- /* could be pre-calculated */
- t_mid = line_point_factor_v3(v2, v1, v3);
-
- t_delta = 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 {
- 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 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;
+
+ /* could be pre-calculated */
+ t_mid = line_point_factor_v3(v2, v1, v3);
+
+ t_delta = 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 {
+ 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);
+ }
+ }
}
/**
* Find the closest point on the ngon on the opposite side.
* used to set the edge slide distance for ngons.
*/
-static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
- const float plane_no[3],
- float r_co[3])
-{
- /* skip adjacent edges */
- BMLoop *l_first = l_tmp->next;
- BMLoop *l_last = l_tmp->prev;
- BMLoop *l_iter;
- float dist = FLT_MAX;
- bool found = false;
-
- l_iter = l_first;
- do {
- float tvec[3];
- if (isect_line_plane_v3(tvec,
- l_iter->v->co, l_iter->next->v->co,
- l_tmp->v->co, plane_no))
- {
- const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
- /* allow some overlap to avoid missing the intersection because of float precision */
- if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) {
- /* likelihood of multiple intersections per ngon is quite low,
- * it would have to loop back on its self, but better support it
- * so check for the closest opposite edge */
- const float tdist = len_v3v3(l_tmp->v->co, tvec);
- if (tdist < dist) {
- copy_v3_v3(r_co, tvec);
- dist = tdist;
- found = true;
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_last);
-
- return found;
+static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, const float plane_no[3], float r_co[3])
+{
+ /* skip adjacent edges */
+ BMLoop *l_first = l_tmp->next;
+ BMLoop *l_last = l_tmp->prev;
+ BMLoop *l_iter;
+ float dist = FLT_MAX;
+ bool found = false;
+
+ l_iter = l_first;
+ do {
+ float tvec[3];
+ if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, l_tmp->v->co, plane_no)) {
+ const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
+ /* allow some overlap to avoid missing the intersection because of float precision */
+ if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) {
+ /* likelihood of multiple intersections per ngon is quite low,
+ * it would have to loop back on its self, but better support it
+ * so check for the closest opposite edge */
+ const float tdist = len_v3v3(l_tmp->v->co, tvec);
+ if (tdist < dist) {
+ copy_v3_v3(r_co, tvec);
+ dist = tdist;
+ found = true;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_last);
+
+ return found;
}
/**
@@ -6542,667 +6694,673 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
* \param r_slide_vec: the direction to slide,
* the length of the vector defines the slide distance.
*/
-static BMLoop *get_next_loop(BMVert *v, BMLoop *l,
- BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3])
-{
- BMLoop *l_first;
- float vec_accum[3] = {0.0f, 0.0f, 0.0f};
- float vec_accum_len = 0.0f;
- int i = 0;
-
- BLI_assert(BM_edge_share_vert(e_prev, e_next) == v);
- BLI_assert(BM_vert_in_edge(l->e, v));
-
- l_first = l;
- do {
- l = BM_loop_other_edge_loop(l, v);
-
- if (l->e == e_next) {
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
- else {
- /* When there is no edge to slide along,
- * we must slide along the vector defined by the face we're attach to */
- BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v);
-
- BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next));
-
- if (l_tmp->f->len == 4) {
- /* we could use code below, but in this case
- * sliding diagonally across the quad works well */
- sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co);
- }
- else {
- float tdir[3];
- BM_loop_calc_face_direction(l_tmp, tdir);
- cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir);
+static BMLoop *get_next_loop(
+ BMVert *v, BMLoop *l, BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3])
+{
+ BMLoop *l_first;
+ float vec_accum[3] = {0.0f, 0.0f, 0.0f};
+ float vec_accum_len = 0.0f;
+ int i = 0;
+
+ BLI_assert(BM_edge_share_vert(e_prev, e_next) == v);
+ BLI_assert(BM_vert_in_edge(l->e, v));
+
+ l_first = l;
+ do {
+ l = BM_loop_other_edge_loop(l, v);
+
+ if (l->e == e_next) {
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
+ else {
+ /* When there is no edge to slide along,
+ * we must slide along the vector defined by the face we're attach to */
+ BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v);
+
+ BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next));
+
+ if (l_tmp->f->len == 4) {
+ /* we could use code below, but in this case
+ * sliding diagonally across the quad works well */
+ sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co);
+ }
+ else {
+ float tdir[3];
+ BM_loop_calc_face_direction(l_tmp, tdir);
+ cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir);
#if 0
- /* rough guess, we can do better! */
- normalize_v3_length(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f);
+ /* rough guess, we can do better! */
+ normalize_v3_length(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f);
#else
- /* be clever, check the opposite ngon edge to slide into.
- * this gives best results */
- {
- float tvec[3];
- float dist;
-
- if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) {
- dist = len_v3v3(l_tmp->v->co, tvec);
- }
- else {
- dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f;
- }
-
- normalize_v3_length(vec_accum, dist);
- }
+ /* be clever, check the opposite ngon edge to slide into.
+ * this gives best results */
+ {
+ float tvec[3];
+ float dist;
+
+ if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) {
+ dist = len_v3v3(l_tmp->v->co, tvec);
+ }
+ else {
+ dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f;
+ }
+
+ normalize_v3_length(vec_accum, dist);
+ }
#endif
- }
- }
+ }
+ }
- copy_v3_v3(r_slide_vec, vec_accum);
- return l;
- }
- else {
- /* accumulate the normalized edge vector,
- * normalize so some edges don't skew the result */
- float tvec[3];
- sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co);
- vec_accum_len += normalize_v3(tvec);
- add_v3_v3(vec_accum, tvec);
- i += 1;
- }
+ copy_v3_v3(r_slide_vec, vec_accum);
+ return l;
+ }
+ else {
+ /* accumulate the normalized edge vector,
+ * normalize so some edges don't skew the result */
+ float tvec[3];
+ sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co);
+ vec_accum_len += normalize_v3(tvec);
+ add_v3_v3(vec_accum, tvec);
+ i += 1;
+ }
- if (BM_loop_other_edge_loop(l, v)->e == e_next) {
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
+ if (BM_loop_other_edge_loop(l, v)->e == e_next) {
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
- copy_v3_v3(r_slide_vec, vec_accum);
- return BM_loop_other_edge_loop(l, v);
- }
+ copy_v3_v3(r_slide_vec, vec_accum);
+ return BM_loop_other_edge_loop(l, v);
+ }
- } while ((l != l->radial_next) &&
- ((l = l->radial_next) != l_first));
+ } while ((l != l->radial_next) && ((l = l->radial_next) != l_first));
- if (i) {
- normalize_v3_length(vec_accum, vec_accum_len / (float)i);
- }
+ if (i) {
+ normalize_v3_length(vec_accum, vec_accum_len / (float)i);
+ }
- copy_v3_v3(r_slide_vec, vec_accum);
+ copy_v3_v3(r_slide_vec, vec_accum);
- return NULL;
+ return NULL;
}
/**
* Calculate screenspace `mval_start` / `mval_end`, optionally slide direction.
*/
-static void calcEdgeSlide_mval_range(
- TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const int *sv_table, const int loop_nr,
- const float mval[2], const bool use_occlude_geometry, const bool use_calc_direction)
-{
- TransDataEdgeSlideVert *sv_array = sld->sv;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- ARegion *ar = t->ar;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
- float projectMat[4][4];
- BMBVHTree *bmbvh;
-
- /* 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, tc->obedit, projectMat);
- }
-
- if (use_occlude_geometry) {
- bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
- }
- else {
- bmbvh = 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_occlude_geometry &&
- !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->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 (bmbvh) {
- BKE_bmbvh_free(bmbvh);
- }
-}
-
-static void calcEdgeSlide_even(
- TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const float mval[2])
-{
- TransDataEdgeSlideVert *sv = sld->sv;
-
- if (sld->totsv > 0) {
- ARegion *ar = t->ar;
- RegionView3D *rv3d = NULL;
- float projectMat[4][4];
-
- int i = 0;
-
- float v_proj[2];
- float dist_sq = 0;
- float dist_min_sq = FLT_MAX;
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* background mode support */
- 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, tc->obedit, projectMat);
- }
-
- for (i = 0; i < sld->totsv; i++, sv++) {
- /* Set length */
- 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);
- if (dist_sq < dist_min_sq) {
- dist_min_sq = dist_sq;
- sld->curr_sv_index = i;
- }
- }
- }
- else {
- sld->curr_sv_index = 0;
- }
+static void calcEdgeSlide_mval_range(TransInfo *t,
+ TransDataContainer *tc,
+ EdgeSlideData *sld,
+ const int *sv_table,
+ const int loop_nr,
+ const float mval[2],
+ const bool use_occlude_geometry,
+ const bool use_calc_direction)
+{
+ TransDataEdgeSlideVert *sv_array = sld->sv;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ ARegion *ar = t->ar;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+ BMBVHTree *bmbvh;
+
+ /* 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, tc->obedit, projectMat);
+ }
+
+ if (use_occlude_geometry) {
+ bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false);
+ }
+ else {
+ bmbvh = 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_occlude_geometry &&
+ !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->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 (bmbvh) {
+ BKE_bmbvh_free(bmbvh);
+ }
+}
+
+static void calcEdgeSlide_even(TransInfo *t,
+ TransDataContainer *tc,
+ EdgeSlideData *sld,
+ const float mval[2])
+{
+ TransDataEdgeSlideVert *sv = sld->sv;
+
+ if (sld->totsv > 0) {
+ ARegion *ar = t->ar;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+
+ int i = 0;
+
+ float v_proj[2];
+ float dist_sq = 0;
+ float dist_min_sq = FLT_MAX;
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ 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, tc->obedit, projectMat);
+ }
+
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ /* Set length */
+ 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);
+ if (dist_sq < dist_min_sq) {
+ dist_min_sq = dist_sq;
+ sld->curr_sv_index = i;
+ }
+ }
+ }
+ else {
+ sld->curr_sv_index = 0;
+ }
}
static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc)
{
- BMEditMesh *em = BKE_editmesh_from_object(tc->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 numsel, i, loop_nr;
- bool use_occlude_geometry = false;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
-
- slide_origdata_init_flag(t, tc, &sld->orig_data);
-
- sld->curr_sv_index = 0;
-
- /*ensure valid selection*/
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BMIter iter2;
- numsel = 0;
- BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- /* BMESH_TODO: this is probably very evil,
- * set v->e to a selected edge*/
- v->e = e;
-
- numsel++;
- }
- }
-
- if (numsel == 0 || numsel > 2) {
- MEM_freeN(sld);
- return false; /* invalid edge selection */
- }
- }
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- /* note, any edge with loops can work, but we won't get predictable results, so bail out */
- if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) {
- /* can edges with at least once face user */
- MEM_freeN(sld);
- return false;
- }
- }
- }
-
- sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
-
-#define INDEX_UNSET -1
+ BMEditMesh *em = BKE_editmesh_from_object(tc->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 numsel, i, loop_nr;
+ bool use_occlude_geometry = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+
+ slide_origdata_init_flag(t, tc, &sld->orig_data);
+
+ sld->curr_sv_index = 0;
+
+ /*ensure valid selection*/
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BMIter iter2;
+ numsel = 0;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ /* BMESH_TODO: this is probably very evil,
+ * set v->e to a selected edge*/
+ v->e = e;
+
+ numsel++;
+ }
+ }
+
+ if (numsel == 0 || numsel > 2) {
+ MEM_freeN(sld);
+ return false; /* invalid edge selection */
+ }
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ /* note, any edge with loops can work, but we won't get predictable results, so bail out */
+ if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) {
+ /* can edges with at least once face user */
+ MEM_freeN(sld);
+ return false;
+ }
+ }
+ }
+
+ sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__);
+
+#define INDEX_UNSET -1
#define INDEX_INVALID -2
- {
- int j = 0;
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- sv_table[i] = INDEX_UNSET;
- j += 1;
- }
- else {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- sv_table[i] = INDEX_INVALID;
- }
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- if (!j) {
- MEM_freeN(sld);
- MEM_freeN(sv_table);
- return false;
- }
- sv_tot = j;
- }
-
- sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array");
- loop_nr = 0;
-
- STACK_DECLARE(sv_array);
- STACK_INIT(sv_array, sv_tot);
-
- while (1) {
- float vec_a[3], vec_b[3];
- BMLoop *l_a, *l_b;
- BMLoop *l_a_prev, *l_b_prev;
- BMVert *v_first;
- /* If this succeeds call get_next_loop()
- * which calculates the direction to slide based on clever checks.
- *
- * otherwise we simply use 'e_dir' as an edge-rail.
- * (which is better when the attached edge is a boundary, see: T40422)
- */
+ {
+ int j = 0;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ sv_table[i] = INDEX_UNSET;
+ j += 1;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ sv_table[i] = INDEX_INVALID;
+ }
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ if (!j) {
+ MEM_freeN(sld);
+ MEM_freeN(sv_table);
+ return false;
+ }
+ sv_tot = j;
+ }
+
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array");
+ loop_nr = 0;
+
+ STACK_DECLARE(sv_array);
+ STACK_INIT(sv_array, sv_tot);
+
+ while (1) {
+ float vec_a[3], vec_b[3];
+ BMLoop *l_a, *l_b;
+ BMLoop *l_a_prev, *l_b_prev;
+ BMVert *v_first;
+ /* If this succeeds call get_next_loop()
+ * which calculates the direction to slide based on clever checks.
+ *
+ * otherwise we simply use 'e_dir' as an edge-rail.
+ * (which is better when the attached edge is a boundary, see: T40422)
+ */
#define EDGESLIDE_VERT_IS_INNER(v, e_dir) \
- ((BM_edge_is_boundary(e_dir) == false) && \
- (BM_vert_edge_count_nonwire(v) == 2))
-
- v = NULL;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG))
- break;
-
- }
-
- if (!v)
- break;
-
- if (!v->e)
- continue;
-
- v_first = v;
-
- /*walk along the edge loop*/
- e = v->e;
-
- /*first, rewind*/
- do {
- e = get_other_edge(v, e);
- if (!e) {
- e = v->e;
- break;
- }
-
- if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG))
- break;
-
- v = BM_edge_other_vert(e, v);
- } while (e != v_first->e);
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- l_a = e->l;
- l_b = e->l->radial_next;
-
- /* regarding e_next, use get_next_loop()'s improved interpolation where possible */
- {
- BMEdge *e_next = get_other_edge(v, e);
- if (e_next) {
- get_next_loop(v, l_a, e, e_next, vec_a);
- }
- else {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_a, e, l_tmp->e, vec_a);
- }
- else {
- sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
- }
- }
- }
-
- /* !BM_edge_is_boundary(e); */
- if (l_b != l_a) {
- BMEdge *e_next = get_other_edge(v, e);
- if (e_next) {
- get_next_loop(v, l_b, e, e_next, vec_b);
- }
- else {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
- if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
- get_next_loop(v, l_b, e, l_tmp->e, vec_b);
- }
- else {
- sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
- }
- }
- }
- else {
- l_b = NULL;
- }
-
- l_a_prev = NULL;
- l_b_prev = NULL;
-
-#define SV_FROM_VERT(v) ( \
- (sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \
- ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), STACK_PUSH_RET_PTR(sv_array)) : \
- (&sv_array[sv_table[BM_elem_index_get(v)]]))
-
- /*iterate over the loop*/
- v_first = v;
- do {
- bool l_a_ok_prev;
- bool l_b_ok_prev;
- TransDataEdgeSlideVert *sv;
- BMVert *v_prev;
- BMEdge *e_prev;
-
- /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
- BLI_assert(v != NULL);
- BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
- sv = SV_FROM_VERT(v);
- sv->v = v;
- copy_v3_v3(sv->v_co_orig, v->co);
- sv->loop_nr = loop_nr;
-
- if (l_a || l_a_prev) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
- 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_side[1] = BM_edge_other_vert(l_tmp->e, v);
- copy_v3_v3(sv->dir_side[1], vec_b);
- }
-
- v_prev = v;
- v = BM_edge_other_vert(e, v);
-
- e_prev = e;
- e = get_other_edge(v, e);
-
- if (!e) {
- BLI_assert(v != NULL);
-
- BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
- sv = SV_FROM_VERT(v);
-
- sv->v = v;
- copy_v3_v3(sv->v_co_orig, v->co);
- sv->loop_nr = loop_nr;
-
- if (l_a) {
- BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, 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_side[0]);
- }
- else {
- 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_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_side[1]);
- }
- else {
- sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
- }
- }
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
-
- break;
- }
- l_a_ok_prev = (l_a != NULL);
- l_b_ok_prev = (l_b != NULL);
-
- l_a_prev = l_a;
- l_b_prev = l_b;
-
- if (l_a) {
- l_a = get_next_loop(v, l_a, e_prev, e, vec_a);
- }
- else {
- zero_v3(vec_a);
- }
-
- if (l_b) {
- l_b = get_next_loop(v, l_b, e_prev, e, vec_b);
- }
- else {
- zero_v3(vec_b);
- }
-
-
- if (l_a && l_b) {
- /* pass */
- }
- else {
- if (l_a || l_b) {
- /* find the opposite loop if it was missing previously */
- if (l_a == NULL && l_b && (l_b->radial_next != l_b)) l_a = l_b->radial_next;
- else if (l_b == NULL && l_a && (l_a->radial_next != l_a)) l_b = l_a->radial_next;
- }
- else if (e->l != NULL) {
- /* if there are non-contiguous faces, we can still recover
- * the loops of the new edges faces */
-
- /* note!, the behavior in this case means edges may move in opposite directions,
- * this could be made to work more usefully. */
-
- if (l_a_ok_prev) {
- l_a = e->l;
- l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL;
- }
- else if (l_b_ok_prev) {
- l_b = e->l;
- l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL;
- }
- }
-
- if (!l_a_ok_prev && l_a) {
- get_next_loop(v, l_a, e, e_prev, vec_a);
- }
- if (!l_b_ok_prev && l_b) {
- get_next_loop(v, l_b, e, e_prev, vec_b);
- }
- }
-
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
- } while ((e != v_first->e) && (l_a || l_b));
+ ((BM_edge_is_boundary(e_dir) == false) && (BM_vert_edge_count_nonwire(v) == 2))
+
+ v = NULL;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG))
+ break;
+ }
+
+ if (!v)
+ break;
+
+ if (!v->e)
+ continue;
+
+ v_first = v;
+
+ /*walk along the edge loop*/
+ e = v->e;
+
+ /*first, rewind*/
+ do {
+ e = get_other_edge(v, e);
+ if (!e) {
+ e = v->e;
+ break;
+ }
+
+ if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG))
+ break;
+
+ v = BM_edge_other_vert(e, v);
+ } while (e != v_first->e);
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ l_a = e->l;
+ l_b = e->l->radial_next;
+
+ /* regarding e_next, use get_next_loop()'s improved interpolation where possible */
+ {
+ BMEdge *e_next = get_other_edge(v, e);
+ if (e_next) {
+ get_next_loop(v, l_a, e, e_next, vec_a);
+ }
+ else {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_a, e, l_tmp->e, vec_a);
+ }
+ else {
+ sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ }
+ }
+ }
+
+ /* !BM_edge_is_boundary(e); */
+ if (l_b != l_a) {
+ BMEdge *e_next = get_other_edge(v, e);
+ if (e_next) {
+ get_next_loop(v, l_b, e, e_next, vec_b);
+ }
+ else {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v);
+ if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) {
+ get_next_loop(v, l_b, e, l_tmp->e, vec_b);
+ }
+ else {
+ sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co);
+ }
+ }
+ }
+ else {
+ l_b = NULL;
+ }
+
+ l_a_prev = NULL;
+ l_b_prev = NULL;
+
+#define SV_FROM_VERT(v) \
+ ((sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \
+ ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), \
+ STACK_PUSH_RET_PTR(sv_array)) : \
+ (&sv_array[sv_table[BM_elem_index_get(v)]]))
+
+ /*iterate over the loop*/
+ v_first = v;
+ do {
+ bool l_a_ok_prev;
+ bool l_b_ok_prev;
+ TransDataEdgeSlideVert *sv;
+ BMVert *v_prev;
+ BMEdge *e_prev;
+
+ /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
+ BLI_assert(v != NULL);
+ BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
+ sv = SV_FROM_VERT(v);
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->loop_nr = loop_nr;
+
+ if (l_a || l_a_prev) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v);
+ 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_side[1] = BM_edge_other_vert(l_tmp->e, v);
+ copy_v3_v3(sv->dir_side[1], vec_b);
+ }
+
+ v_prev = v;
+ v = BM_edge_other_vert(e, v);
+
+ e_prev = e;
+ e = get_other_edge(v, e);
+
+ if (!e) {
+ BLI_assert(v != NULL);
+
+ BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID);
+ sv = SV_FROM_VERT(v);
+
+ sv->v = v;
+ copy_v3_v3(sv->v_co_orig, v->co);
+ sv->loop_nr = loop_nr;
+
+ if (l_a) {
+ BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, 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_side[0]);
+ }
+ else {
+ 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_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_side[1]);
+ }
+ else {
+ sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co);
+ }
+ }
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
+
+ break;
+ }
+ l_a_ok_prev = (l_a != NULL);
+ l_b_ok_prev = (l_b != NULL);
+
+ l_a_prev = l_a;
+ l_b_prev = l_b;
+
+ if (l_a) {
+ l_a = get_next_loop(v, l_a, e_prev, e, vec_a);
+ }
+ else {
+ zero_v3(vec_a);
+ }
+
+ if (l_b) {
+ l_b = get_next_loop(v, l_b, e_prev, e, vec_b);
+ }
+ else {
+ zero_v3(vec_b);
+ }
+
+ if (l_a && l_b) {
+ /* pass */
+ }
+ else {
+ if (l_a || l_b) {
+ /* find the opposite loop if it was missing previously */
+ if (l_a == NULL && l_b && (l_b->radial_next != l_b))
+ l_a = l_b->radial_next;
+ else if (l_b == NULL && l_a && (l_a->radial_next != l_a))
+ l_b = l_a->radial_next;
+ }
+ else if (e->l != NULL) {
+ /* if there are non-contiguous faces, we can still recover
+ * the loops of the new edges faces */
+
+ /* note!, the behavior in this case means edges may move in opposite directions,
+ * this could be made to work more usefully. */
+
+ if (l_a_ok_prev) {
+ l_a = e->l;
+ l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL;
+ }
+ else if (l_b_ok_prev) {
+ l_b = e->l;
+ l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL;
+ }
+ }
+
+ if (!l_a_ok_prev && l_a) {
+ get_next_loop(v, l_a, e, e_prev, vec_a);
+ }
+ if (!l_b_ok_prev && l_b) {
+ get_next_loop(v, l_b, e, e_prev, vec_b);
+ }
+ }
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ BM_elem_flag_disable(v_prev, BM_ELEM_TAG);
+ } while ((e != v_first->e) && (l_a || l_b));
#undef SV_FROM_VERT
#undef INDEX_UNSET
#undef INDEX_INVALID
- loop_nr++;
+ loop_nr++;
#undef EDGESLIDE_VERT_IS_INNER
- }
+ }
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+ /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
- BLI_assert(STACK_SIZE(sv_array) == sv_tot);
+ BLI_assert(STACK_SIZE(sv_array) == sv_tot);
- sld->sv = sv_array;
- sld->totsv = sv_tot;
+ 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_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && !XRAY_ENABLED(v3d));
- }
+ /* 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_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
+ !XRAY_ENABLED(v3d));
+ }
- calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
+ calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true);
- /* create copies of faces for customdata projection */
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
- sld->em = em;
+ sld->em = em;
- tc->custom.mode.data = sld;
+ tc->custom.mode.data = sld;
- MEM_freeN(sv_table);
+ MEM_freeN(sv_table);
- return true;
+ return true;
}
/**
@@ -7211,600 +7369,623 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t
*/
static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc)
{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMEdge *e;
- 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 loop_nr;
- bool use_occlude_geometry = false;
- View3D *v3d = NULL;
- RegionView3D *rv3d = NULL;
-
- 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, tc, &sld->orig_data);
-
- sld->curr_sv_index = 0;
- /* ensure valid selection */
- {
- int i = 0, j = 0;
- BMVert *v;
-
- 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;
- }
- }
- }
-
- if (len_sq_max != -1.0f) {
- j++;
- }
- }
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- if (!j) {
- MEM_freeN(sld);
- 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__);
-
- {
- int i = 0, j = 0;
- BMVert *v;
-
- 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;
-
- for (int 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;
- int j;
-
- 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 {
- 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;
- }
- }
-
- 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);
- }
- }
- }
- }
- }
-
- /* 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_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && !XRAY_ENABLED(v3d));
- }
-
- calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false);
-
- /* create copies of faces for customdata projection */
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
-
- if (rv3d) {
- calcEdgeSlide_even(t, tc, sld, mval);
- }
-
- sld->em = em;
-
- tc->custom.mode.data = sld;
-
- MEM_freeN(sv_table);
-
- return true;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMEdge *e;
+ 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 loop_nr;
+ bool use_occlude_geometry = false;
+ View3D *v3d = NULL;
+ RegionView3D *rv3d = NULL;
+
+ 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, tc, &sld->orig_data);
+
+ sld->curr_sv_index = 0;
+ /* ensure valid selection */
+ {
+ int i = 0, j = 0;
+ BMVert *v;
+
+ 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;
+ }
+ }
+ }
+
+ if (len_sq_max != -1.0f) {
+ j++;
+ }
+ }
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ if (!j) {
+ MEM_freeN(sld);
+ 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__);
+
+ {
+ int i = 0, j = 0;
+ BMVert *v;
+
+ 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;
+
+ for (int 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;
+ int j;
+
+ 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 {
+ 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;
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+ }
+
+ /* 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_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE &&
+ !XRAY_ENABLED(v3d));
+ }
+
+ calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false);
+
+ /* create copies of faces for customdata projection */
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
+ if (rv3d) {
+ calcEdgeSlide_even(t, tc, sld, mval);
+ }
+
+ sld->em = em;
+
+ tc->custom.mode.data = sld;
+
+ MEM_freeN(sv_table);
+
+ return true;
}
void projectEdgeSlideData(TransInfo *t, bool is_final)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
- SlideOrigData *sod = &sld->orig_data;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ SlideOrigData *sod = &sld->orig_data;
- if (sod->use_origfaces == false) {
- return;
- }
+ if (sod->use_origfaces == false) {
+ return;
+ }
- slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
- }
+ slide_origdata_interp_data(tc->obedit,
+ sod,
+ (TransDataGenericSlideVert *)sld->sv,
+ sizeof(*sld->sv),
+ sld->totsv,
+ is_final);
+ }
}
void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
- slide_origdata_free_date(&sld->orig_data);
+ slide_origdata_free_date(&sld->orig_data);
}
-void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+void freeEdgeSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- EdgeSlideData *sld = custom_data->data;
+ EdgeSlideData *sld = custom_data->data;
- if (!sld)
- return;
+ if (!sld)
+ return;
- freeEdgeSlideTempFaces(sld);
+ freeEdgeSlideTempFaces(sld);
- bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- MEM_freeN(sld->sv);
- MEM_freeN(sld);
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
- custom_data->data = NULL;
+ custom_data->data = NULL;
}
-static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
+static void initEdgeSlide_ex(
+ TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
{
- EdgeSlideData *sld;
- bool ok = false;
+ EdgeSlideData *sld;
+ bool ok = false;
- t->mode = TFM_EDGE_SLIDE;
- t->transform = applyEdgeSlide;
- t->handleEvent = handleEventEdgeSlide;
+ t->mode = TFM_EDGE_SLIDE;
+ t->transform = applyEdgeSlide;
+ t->handleEvent = handleEventEdgeSlide;
- {
- EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
- slp->use_even = use_even;
- slp->flipped = flipped;
- /* happens to be best for single-sided */
- if (use_double_side == false) {
- slp->flipped = !flipped;
- }
- slp->perc = 0.0f;
+ {
+ EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
+ slp->use_even = use_even;
+ slp->flipped = flipped;
+ /* happens to be best for single-sided */
+ if (use_double_side == false) {
+ slp->flipped = !flipped;
+ }
+ slp->perc = 0.0f;
- if (!use_clamp) {
- t->flag |= T_ALT_TRANSFORM;
- }
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
+ t->custom.mode.data = slp;
+ t->custom.mode.use_free = true;
+ }
- if (use_double_side) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createEdgeSlideVerts_double_side(t, tc);
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createEdgeSlideVerts_single_side(t, tc);
- }
- }
+ if (use_double_side) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ ok |= createEdgeSlideVerts_double_side(t, tc);
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ ok |= createEdgeSlideVerts_single_side(t, tc);
+ }
+ }
- if (!ok) {
- t->state = TRANS_CANCEL;
- return;
- }
+ if (!ok) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sld = tc->custom.mode.data;
- if (!sld) {
- continue;
- }
- tc->custom.mode.free_cb = freeEdgeSlideVerts;
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sld = tc->custom.mode.data;
+ if (!sld) {
+ continue;
+ }
+ tc->custom.mode.free_cb = freeEdgeSlideVerts;
+ }
- /* set custom point first if you want value to be initialized by init */
- calcEdgeSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
+ /* set custom point first if you want value to be initialized by init */
+ calcEdgeSlideCustomPoints(t);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void initEdgeSlide(TransInfo *t)
{
- initEdgeSlide_ex(t, true, false, false, true);
+ initEdgeSlide_ex(t, true, false, false, true);
}
static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
{
- if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
-
- if (slp) {
- switch (event->type) {
- case EKEY:
- if (event->val == KM_PRESS) {
- slp->use_even = !slp->use_even;
- calcEdgeSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case FKEY:
- if (event->val == KM_PRESS) {
- slp->flipped = !slp->flipped;
- 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:
+ if (t->mode == TFM_EDGE_SLIDE) {
+ EdgeSlideParams *slp = t->custom.mode.data;
+
+ if (slp) {
+ switch (event->type) {
+ case EKEY:
+ if (event->val == KM_PRESS) {
+ slp->use_even = !slp->use_even;
+ calcEdgeSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case FKEY:
+ if (event->val == KM_PRESS) {
+ slp->flipped = !slp->flipped;
+ 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:
#if 0
- switch (event->val) {
- case TFM_MODAL_EDGESLIDE_DOWN:
- sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
- return TREDRAW_HARD;
- case TFM_MODAL_EDGESLIDE_UP:
- sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
- return TREDRAW_HARD;
- }
+ switch (event->val) {
+ case TFM_MODAL_EDGESLIDE_DOWN:
+ sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv;
+ return TREDRAW_HARD;
+ case TFM_MODAL_EDGESLIDE_UP:
+ sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv;
+ return TREDRAW_HARD;
+ }
#endif
- break;
- case MOUSEMOVE:
- calcEdgeSlideCustomPoints(t);
- break;
- default:
- break;
- }
- }
- }
- return TREDRAW_NOTHING;
+ break;
+ case MOUSEMOVE:
+ calcEdgeSlideCustomPoints(t);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return TREDRAW_NOTHING;
}
static void drawEdgeSlide(TransInfo *t)
{
- if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
- const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
-
- /* Even mode */
- if ((slp->use_even == true) || (is_clamp == false)) {
- const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
-
- GPU_depth_test(false);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- if (slp->use_even == true) {
- float co_a[3], co_b[3], co_mark[3];
- TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float fac = (slp->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]);
-
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBeginAtMost(GPU_PRIM_LINES, 4);
- if (curr_sv->v_side[0]) {
- immVertex3fv(pos, curr_sv->v_side[0]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
- }
- if (curr_sv->v_side[1]) {
- immVertex3fv(pos, curr_sv->v_side[1]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
- }
- immEnd();
-
- immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- GPU_point_size(ctrl_size);
- immBegin(GPU_PRIM_POINTS, 1);
- if (slp->flipped) {
- if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
- }
- else {
- if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co);
- }
- immEnd();
-
- immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- GPU_point_size(guide_size);
- immBegin(GPU_PRIM_POINTS, 1);
- interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- immVertex3fv(pos, co_mark);
- immEnd();
- }
- else {
- if (is_clamp == false) {
- const int side_index = sld->curr_side_unclamp;
- TransDataEdgeSlideVert *sv;
- int i;
- const int alpha_shade = -160;
-
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBegin(GPU_PRIM_LINES, sld->totsv * 2);
-
- /* TODO(campbell): Loop over all verts */
- 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]);
- }
-
- 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);
-
- immVertex3fv(pos, a);
- immVertex3fv(pos, b);
- }
- immEnd();
- }
- else {
- BLI_assert(0);
- }
- }
-
- immUnbindProgram();
-
- GPU_matrix_pop();
-
- GPU_blend(false);
-
- GPU_depth_test(true);
- }
- }
+ if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ const EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
+ /* Even mode */
+ if ((slp->use_even == true) || (is_clamp == false)) {
+ const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
+
+ GPU_depth_test(false);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (slp->use_even == true) {
+ float co_a[3], co_b[3], co_mark[3];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (slp->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]);
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(GPU_PRIM_LINES, 4);
+ if (curr_sv->v_side[0]) {
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ if (curr_sv->v_side[1]) {
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ immEnd();
+
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ GPU_point_size(ctrl_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ if (slp->flipped) {
+ if (curr_sv->v_side[1])
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ }
+ else {
+ if (curr_sv->v_side[0])
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ }
+ immEnd();
+
+ immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ GPU_point_size(guide_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ immVertex3fv(pos, co_mark);
+ immEnd();
+ }
+ else {
+ if (is_clamp == false) {
+ const int side_index = sld->curr_side_unclamp;
+ TransDataEdgeSlideVert *sv;
+ int i;
+ const int alpha_shade = -160;
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+
+ /* TODO(campbell): Loop over all verts */
+ 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]);
+ }
+
+ 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);
+
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
+ }
+ immEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ immUnbindProgram();
+
+ GPU_matrix_pop();
+
+ GPU_blend(false);
+
+ GPU_depth_test(true);
+ }
+ }
}
static void doEdgeSlide(TransInfo *t, float perc)
{
- EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
-
- slp->perc = perc;
-
- if (slp->use_even == false) {
- 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);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
- TransDataEdgeSlideVert *sv = sld->sv;
- for (int i = 0; i < sld->totsv; i++, sv++) {
- madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
- }
- sld->curr_side_unclamp = side_index;
- }
- }
- else {
- const float perc_init = fabsf(perc) * ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
- const int side_index = sld_active->curr_side_unclamp;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
- TransDataEdgeSlideVert *sv = sld->sv;
- for (int 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);
- }
- }
- }
- }
- else {
- /**
- * Implementation note, even mode ignores the starting positions and uses only the
- * 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_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_active->sv[sld_active->curr_sv_index];
- const float curr_length_perc = curr_sv->edge_len * (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f);
-
- float co_a[3];
- float co_b[3];
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
- TransDataEdgeSlideVert *sv = sld->sv;
- for (int i = 0; i < sld->totsv; i++, sv++) {
- 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_side[0]);
- add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
-
- if (slp->flipped) {
- interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
- }
- else {
- interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
- }
- }
- }
- }
- }
+ EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+
+ slp->perc = perc;
+
+ if (slp->use_even == false) {
+ 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);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ TransDataEdgeSlideVert *sv = sld->sv;
+ for (int i = 0; i < sld->totsv; i++, sv++) {
+ madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
+ }
+ sld->curr_side_unclamp = side_index;
+ }
+ }
+ else {
+ const float perc_init = fabsf(perc) *
+ ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1);
+ const int side_index = sld_active->curr_side_unclamp;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ TransDataEdgeSlideVert *sv = sld->sv;
+ for (int 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);
+ }
+ }
+ }
+ }
+ else {
+ /**
+ * Implementation note, even mode ignores the starting positions and uses only the
+ * 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_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_active->sv[sld_active->curr_sv_index];
+ const float curr_length_perc = curr_sv->edge_len *
+ (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f);
+
+ float co_a[3];
+ float co_b[3];
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ TransDataEdgeSlideVert *sv = sld->sv;
+ for (int i = 0; i < sld->totsv; i++, sv++) {
+ 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_side[0]);
+ add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
+
+ if (slp->flipped) {
+ interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
+ }
+ else {
+ interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
+ }
+ }
+ }
+ }
+ }
}
static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float final;
- EdgeSlideParams *slp = t->custom.mode.data;
- bool flipped = slp->flipped;
- bool use_even = slp->use_even;
- 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 */
- 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: "), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
- /* done with header string */
-
- /* do stuff here */
- doEdgeSlide(t, final);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ float final;
+ EdgeSlideParams *slp = t->custom.mode.data;
+ bool flipped = slp->flipped;
+ bool use_even = slp->use_even;
+ 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 */
+ 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: "), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
+
+ /* do stuff here */
+ doEdgeSlide(t, final);
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Vert Slide) */
@@ -7813,35 +7994,35 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
static void calcVertSlideCustomPoints(struct TransInfo *t)
{
- VertSlideParams *slp = t->custom.mode.data;
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
+ VertSlideParams *slp = t->custom.mode.data;
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
- const float *co_orig_3d = sv->co_orig_3d;
- const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr];
+ 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];
+ float co_curr_2d[2], co_orig_2d[2];
- int mval_ofs[2], mval_start[2], mval_end[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);
+ 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->mouse.imval[0] - co_orig_2d[0], t->mouse.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]);
+ ARRAY_SET_ITEMS(mval_ofs, t->mouse.imval[0] - co_orig_2d[0], t->mouse.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 (slp->flipped && slp->use_even) {
- setCustomPoints(t, &t->mouse, mval_start, mval_end);
- }
- else {
- setCustomPoints(t, &t->mouse, mval_end, mval_start);
- }
+ if (slp->flipped && slp->use_even) {
+ setCustomPoints(t, &t->mouse, mval_start, mval_end);
+ }
+ else {
+ setCustomPoints(t, &t->mouse, mval_end, mval_start);
+ }
- /* setCustomPoints isn't normally changing as the mouse moves,
- * in this case apply mouse input immediately so we don't refresh
- * with the value from the previous points */
- applyMouseInput(t, &t->mouse, t->mval, t->values);
+ /* setCustomPoints isn't normally changing as the mouse moves,
+ * in this case apply mouse input immediately so we don't refresh
+ * with the value from the previous points */
+ applyMouseInput(t, &t->mouse, t->mval, t->values);
}
/**
@@ -7849,27 +8030,27 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
*/
static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
{
- /* Active object may have no selected vertices. */
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- float mval_fl[2] = {UNPACK2(mval)};
- TransDataVertSlideVert *sv;
+ /* Active object may have no selected vertices. */
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ float mval_fl[2] = {UNPACK2(mval)};
+ TransDataVertSlideVert *sv;
- /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */
- float dist_sq = 0.0f;
- float dist_min_sq = FLT_MAX;
- int i;
+ /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */
+ float dist_sq = 0.0f;
+ float dist_min_sq = FLT_MAX;
+ int i;
- for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- float co_2d[2];
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ float co_2d[2];
- ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat);
+ 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;
- }
- }
+ 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;
+ }
+ }
}
/**
@@ -7877,530 +8058,547 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
*/
static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2])
{
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- float imval_fl[2] = {UNPACK2(t->mouse.imval)};
- float mval_fl[2] = {UNPACK2(mval)};
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ float imval_fl[2] = {UNPACK2(t->mouse.imval)};
+ float mval_fl[2] = {UNPACK2(mval)};
- float dir[3];
- TransDataVertSlideVert *sv;
- int i;
+ float dir[3];
+ TransDataVertSlideVert *sv;
+ int i;
- /* note: we could save a matrix-multiply for each vertex
- * by finding the closest edge in local-space.
- * However this skews the outcome with non-uniform-scale. */
+ /* note: we could save a matrix-multiply for each vertex
+ * by finding the closest edge in local-space.
+ * However this skews the outcome with non-uniform-scale. */
- /* 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);
- normalize_v3(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);
+ normalize_v3(dir);
- for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
- if (sv->co_link_tot > 1) {
- float dir_dot_best = -FLT_MAX;
- int co_link_curr_best = -1;
- int j;
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ if (sv->co_link_tot > 1) {
+ float dir_dot_best = -FLT_MAX;
+ int co_link_curr_best = -1;
+ int j;
- for (j = 0; j < sv->co_link_tot; j++) {
- float tdir[3];
- float dir_dot;
+ for (j = 0; j < sv->co_link_tot; j++) {
+ float tdir[3];
+ float dir_dot;
- sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
- mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir);
- project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]);
+ sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]);
+ mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir);
+ 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;
- }
- }
+ 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;
+ }
+ }
- if (co_link_curr_best != -1) {
- sv->co_link_curr = co_link_curr_best;
- }
- }
- }
+ if (co_link_curr_best != -1) {
+ sv->co_link_curr = co_link_curr_best;
+ }
+ }
+ }
}
static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc)
{
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- BMIter iter;
- BMIter eiter;
- BMEdge *e;
- BMVert *v;
- TransDataVertSlideVert *sv_array;
- VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
- int j;
-
- slide_origdata_init_flag(t, tc, &sld->orig_data);
-
- sld->curr_sv_index = 0;
-
- j = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- bool ok = false;
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) {
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- ok = true;
- break;
- }
- }
- }
-
- if (ok) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- j += 1;
- }
- else {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- }
-
- if (!j) {
- MEM_freeN(sld);
- return false;
- }
-
- sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array");
-
- j = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- int k;
- sv_array[j].v = v;
- copy_v3_v3(sv_array[j].co_orig_3d, v->co);
-
- k = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- k++;
- }
- }
-
- sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__);
- sv_array[j].co_link_tot = k;
-
- k = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- 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);
- k++;
- }
- }
- j++;
- }
- }
-
- sld->sv = sv_array;
- sld->totsv = j;
-
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- slide_origdata_init_data(tc, &sld->orig_data);
- slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
-
- sld->em = em;
-
- tc->custom.mode.data = sld;
-
- /* 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, tc->obedit, sld->proj_mat);
- }
- }
-
- /* XXX, calc vert slide across all objects */
- if (tc == t->data_container) {
- calcVertSlideMouseActiveVert(t, t->mval);
- calcVertSlideMouseActiveEdges(t, t->mval);
- }
-
- return true;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v;
+ TransDataVertSlideVert *sv_array;
+ VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ int j;
+
+ slide_origdata_init_flag(t, tc, &sld->orig_data);
+
+ sld->curr_sv_index = 0;
+
+ j = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ bool ok = false;
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) {
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+
+ if (ok) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ j += 1;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+
+ if (!j) {
+ MEM_freeN(sld);
+ return false;
+ }
+
+ sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array");
+
+ j = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ int k;
+ sv_array[j].v = v;
+ copy_v3_v3(sv_array[j].co_orig_3d, v->co);
+
+ k = 0;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ k++;
+ }
+ }
+
+ sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k,
+ __func__);
+ sv_array[j].co_link_tot = k;
+
+ k = 0;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ 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);
+ k++;
+ }
+ }
+ j++;
+ }
+ }
+
+ sld->sv = sv_array;
+ sld->totsv = j;
+
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ slide_origdata_init_data(tc, &sld->orig_data);
+ slide_origdata_create_data(
+ tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
+
+ sld->em = em;
+
+ tc->custom.mode.data = sld;
+
+ /* 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, tc->obedit, sld->proj_mat);
+ }
+ }
+
+ /* XXX, calc vert slide across all objects */
+ if (tc == t->data_container) {
+ calcVertSlideMouseActiveVert(t, t->mval);
+ calcVertSlideMouseActiveEdges(t, t->mval);
+ }
+
+ return true;
}
void projectVertSlideData(TransInfo *t, bool is_final)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- VertSlideData *sld = tc->custom.mode.data;
- SlideOrigData *sod = &sld->orig_data;
- if (sod->use_origfaces == true) {
- slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final);
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ VertSlideData *sld = tc->custom.mode.data;
+ SlideOrigData *sod = &sld->orig_data;
+ if (sod->use_origfaces == true) {
+ slide_origdata_interp_data(tc->obedit,
+ sod,
+ (TransDataGenericSlideVert *)sld->sv,
+ sizeof(*sld->sv),
+ sld->totsv,
+ is_final);
+ }
+ }
}
void freeVertSlideTempFaces(VertSlideData *sld)
{
- slide_origdata_free_date(&sld->orig_data);
+ slide_origdata_free_date(&sld->orig_data);
}
-void freeVertSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+void freeVertSlideVerts(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- VertSlideData *sld = custom_data->data;
+ VertSlideData *sld = custom_data->data;
- if (!sld)
- return;
+ if (!sld)
+ return;
- freeVertSlideTempFaces(sld);
+ freeVertSlideTempFaces(sld);
- bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+ bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
- if (sld->totsv > 0) {
- TransDataVertSlideVert *sv = sld->sv;
- int i = 0;
- for (i = 0; i < sld->totsv; i++, sv++) {
- MEM_freeN(sv->co_link_orig_3d);
- }
- }
+ if (sld->totsv > 0) {
+ TransDataVertSlideVert *sv = sld->sv;
+ int i = 0;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ MEM_freeN(sv->co_link_orig_3d);
+ }
+ }
- MEM_freeN(sld->sv);
- MEM_freeN(sld);
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
- custom_data->data = NULL;
+ custom_data->data = NULL;
}
static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
{
- t->mode = TFM_VERT_SLIDE;
- t->transform = applyVertSlide;
- t->handleEvent = handleEventVertSlide;
+ t->mode = TFM_VERT_SLIDE;
+ t->transform = applyVertSlide;
+ t->handleEvent = handleEventVertSlide;
- {
- VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
- slp->use_even = use_even;
- slp->flipped = flipped;
- slp->perc = 0.0f;
+ {
+ VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
+ slp->use_even = use_even;
+ slp->flipped = flipped;
+ slp->perc = 0.0f;
- if (!use_clamp) {
- t->flag |= T_ALT_TRANSFORM;
- }
+ if (!use_clamp) {
+ t->flag |= T_ALT_TRANSFORM;
+ }
- t->custom.mode.data = slp;
- t->custom.mode.use_free = true;
- }
+ t->custom.mode.data = slp;
+ t->custom.mode.use_free = true;
+ }
- bool ok = false;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ok |= createVertSlideVerts(t, tc);
- VertSlideData *sld = tc->custom.mode.data;
- if (sld) {
- tc->custom.mode.free_cb = freeVertSlideVerts;
- }
- }
+ bool ok = false;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ ok |= createVertSlideVerts(t, tc);
+ VertSlideData *sld = tc->custom.mode.data;
+ if (sld) {
+ tc->custom.mode.free_cb = freeVertSlideVerts;
+ }
+ }
- if (ok == false) {
- t->state = TRANS_CANCEL;
- return;
- }
+ if (ok == false) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
- /* set custom point first if you want value to be initialized by init */
- calcVertSlideCustomPoints(t);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+ /* set custom point first if you want value to be initialized by init */
+ calcVertSlideCustomPoints(t);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 0.1f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 0.1f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void initVertSlide(TransInfo *t)
{
- initVertSlide_ex(t, false, false, true);
+ initVertSlide_ex(t, false, false, true);
}
static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
{
- if (t->mode == TFM_VERT_SLIDE) {
- VertSlideParams *slp = t->custom.mode.data;
-
- if (slp) {
- switch (event->type) {
- case EKEY:
- if (event->val == KM_PRESS) {
- slp->use_even = !slp->use_even;
- if (slp->flipped) {
- calcVertSlideCustomPoints(t);
- }
- return TREDRAW_HARD;
- }
- break;
- case FKEY:
- if (event->val == KM_PRESS) {
- slp->flipped = !slp->flipped;
- calcVertSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
- case CKEY:
- /* use like a modifier key */
- if (event->val == KM_PRESS) {
- t->flag ^= T_ALT_TRANSFORM;
- calcVertSlideCustomPoints(t);
- return TREDRAW_HARD;
- }
- break;
+ if (t->mode == TFM_VERT_SLIDE) {
+ VertSlideParams *slp = t->custom.mode.data;
+
+ if (slp) {
+ switch (event->type) {
+ case EKEY:
+ if (event->val == KM_PRESS) {
+ slp->use_even = !slp->use_even;
+ if (slp->flipped) {
+ calcVertSlideCustomPoints(t);
+ }
+ return TREDRAW_HARD;
+ }
+ break;
+ case FKEY:
+ if (event->val == KM_PRESS) {
+ slp->flipped = !slp->flipped;
+ calcVertSlideCustomPoints(t);
+ return TREDRAW_HARD;
+ }
+ break;
+ case CKEY:
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcVertSlideCustomPoints(t);
+ 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;
+ 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:
- {
- /* don't recalculate the best edge */
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- if (is_clamp) {
- calcVertSlideMouseActiveEdges(t, event->mval);
- }
- calcVertSlideCustomPoints(t);
- break;
- }
- default:
- break;
- }
- }
- }
- return TREDRAW_NOTHING;
+ case MOUSEMOVE: {
+ /* don't recalculate the best edge */
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ calcVertSlideMouseActiveEdges(t, event->mval);
+ }
+ calcVertSlideCustomPoints(t);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return TREDRAW_NOTHING;
}
static void drawVertSlide(TransInfo *t)
{
- if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
- const VertSlideParams *slp = t->custom.mode.data;
- VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
-
- /* Non-Prop mode */
- {
- 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;
- int i;
-
- GPU_depth_test(false);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ const VertSlideParams *slp = t->custom.mode.data;
+ VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+
+ /* Non-Prop mode */
+ {
+ 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;
+ int i;
+
+ GPU_depth_test(false);
- GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- GPU_line_width(line_size);
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_line_width(line_size);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBegin(GPU_PRIM_LINES, sld->totsv * 2);
- if (is_clamp) {
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- immVertex3fv(shdr_pos, sv->co_orig_3d);
- immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]);
- }
- }
- else {
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- float a[3], b[3];
- sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
- mul_v3_fl(a, 100.0f);
- negate_v3_v3(b, a);
- add_v3_v3(a, sv->co_orig_3d);
- add_v3_v3(b, sv->co_orig_3d);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immVertex3fv(shdr_pos, a);
- immVertex3fv(shdr_pos, b);
- }
- }
- immEnd();
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+ if (is_clamp) {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ immVertex3fv(shdr_pos, sv->co_orig_3d);
+ immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]);
+ }
+ }
+ else {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+ sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->co_orig_3d);
+ add_v3_v3(b, sv->co_orig_3d);
- GPU_point_size(ctrl_size);
+ immVertex3fv(shdr_pos, a);
+ immVertex3fv(shdr_pos, b);
+ }
+ }
+ immEnd();
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ?
- curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
- curr_sv->co_orig_3d);
- immEnd();
+ GPU_point_size(ctrl_size);
- immUnbindProgram();
+ immBegin(GPU_PRIM_POINTS, 1);
+ immVertex3fv(shdr_pos,
+ (slp->flipped && slp->use_even) ?
+ curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
+ curr_sv->co_orig_3d);
+ immEnd();
- /* direction from active vertex! */
- if ((t->mval[0] != t->mouse.imval[0]) ||
- (t->mval[1] != t->mouse.imval[1]))
- {
- float zfac;
- float mval_ofs[2];
- float co_orig_3d[3];
- float co_dest_3d[3];
+ immUnbindProgram();
- mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
- mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
+ /* direction from active vertex! */
+ if ((t->mval[0] != t->mouse.imval[0]) || (t->mval[1] != t->mouse.imval[1])) {
+ float zfac;
+ float mval_ofs[2];
+ float co_orig_3d[3];
+ float co_dest_3d[3];
- mul_v3_m4v3(co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d);
- zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL);
+ mval_ofs[0] = t->mval[0] - t->mouse.imval[0];
+ mval_ofs[1] = t->mval[1] - t->mouse.imval[1];
- ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
+ mul_v3_m4v3(
+ co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d);
+ zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL);
- invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d);
+ ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac);
- add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
+ invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat,
+ TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d);
- GPU_line_width(1.0f);
+ add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_line_width(1.0f);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
- immVertex3fv(shdr_pos, co_dest_3d);
- immEnd();
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
+ immVertex3fv(shdr_pos, co_dest_3d);
+ immEnd();
- immUnbindProgram();
- }
+ immUnbindProgram();
+ }
- GPU_matrix_pop();
+ GPU_matrix_pop();
- GPU_depth_test(true);
- }
- }
+ GPU_depth_test(true);
+ }
+ }
}
static void doVertSlide(TransInfo *t, float perc)
{
- VertSlideParams *slp = t->custom.mode.data;
-
- slp->perc = perc;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- VertSlideData *sld = tc->custom.mode.data;
- TransDataVertSlideVert *svlist = sld->sv, *sv;
- int i;
-
- sv = svlist;
-
- if (slp->use_even == false) {
- for (i = 0; i < sld->totsv; i++, sv++) {
- interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
- }
- }
- else {
- TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index];
- const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]);
- const float tperc = perc * edge_len_curr;
-
- for (i = 0; i < sld->totsv; i++, sv++) {
- float edge_len;
- float dir[3];
-
- sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
- edge_len = normalize_v3(dir);
-
- if (edge_len > FLT_EPSILON) {
- if (slp->flipped) {
- madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
- }
- else {
- madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc);
- }
- }
- else {
- copy_v3_v3(sv->v->co, sv->co_orig_3d);
- }
- }
- }
- }
+ VertSlideParams *slp = t->custom.mode.data;
+
+ slp->perc = perc;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ VertSlideData *sld = tc->custom.mode.data;
+ TransDataVertSlideVert *svlist = sld->sv, *sv;
+ int i;
+
+ sv = svlist;
+
+ if (slp->use_even == false) {
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
+ }
+ }
+ else {
+ TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index];
+ const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d,
+ sv_curr->co_link_orig_3d[sv_curr->co_link_curr]);
+ const float tperc = perc * edge_len_curr;
+
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float edge_len;
+ float dir[3];
+
+ sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ edge_len = normalize_v3(dir);
+
+ if (edge_len > FLT_EPSILON) {
+ if (slp->flipped) {
+ madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
+ }
+ else {
+ madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc);
+ }
+ }
+ else {
+ copy_v3_v3(sv->v->co, sv->co_orig_3d);
+ }
+ }
+ }
+ }
}
static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
- size_t ofs = 0;
- float final;
- VertSlideParams *slp = t->custom.mode.data;
- const bool flipped = slp->flipped;
- const bool use_even = slp->use_even;
- 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 */
- if (is_constrained) {
- CLAMP(final, 0.0f, 1.0f);
- }
-
- applyNumInput(&t->num, &final);
-
- t->values[0] = final;
-
- /* header string */
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), sizeof(str) - ofs);
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
- ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
- }
- else {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
- if (use_even) {
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
- }
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
- /* done with header string */
-
- /* do stuff here */
- doVertSlide(t, final);
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ float final;
+ VertSlideParams *slp = t->custom.mode.data;
+ const bool flipped = slp->flipped;
+ const bool use_even = slp->use_even;
+ 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 */
+ if (is_constrained) {
+ CLAMP(final, 0.0f, 1.0f);
+ }
+
+ applyNumInput(&t->num, &final);
+
+ t->values[0] = final;
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), sizeof(str) - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ outputNumInput(&(t->num), c, &t->scene->unit);
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final);
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
+ }
+ ofs += BLI_snprintf(
+ str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
+ /* done with header string */
+
+ /* do stuff here */
+ doVertSlide(t, final);
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (EditBone Roll) */
@@ -8409,72 +8607,72 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
static void initBoneRoll(TransInfo *t)
{
- t->mode = TFM_BONE_ROLL;
- t->transform = applyBoneRoll;
+ t->mode = TFM_BONE_ROLL;
+ t->transform = applyBoneRoll;
- initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = DEG2RAD(5.0);
- t->snap[2] = DEG2RAD(1.0);
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = DEG2RAD(5.0);
+ t->snap[2] = DEG2RAD(1.0);
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
- t->num.unit_type[0] = B_UNIT_ROTATION;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
+ t->num.unit_type[0] = B_UNIT_ROTATION;
- t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
{
- int i;
- char str[UI_MAX_DRAW_STR];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float final;
+ float final;
- final = t->values[0];
+ final = t->values[0];
- snapGridIncrement(t, &final);
+ snapGridIncrement(t, &final);
- applyNumInput(&t->num, &final);
+ applyNumInput(&t->num, &final);
- t->values[0] = final;
+ t->values[0] = final;
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
- outputNumInput(&(t->num), c, &t->scene->unit);
+ outputNumInput(&(t->num), c, &t->scene->unit);
- BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]);
- }
- else {
- BLI_snprintf(str, sizeof(str), IFACE_("Roll: %.2f"), RAD2DEGF(final));
- }
+ BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]);
+ }
+ else {
+ BLI_snprintf(str, sizeof(str), IFACE_("Roll: %.2f"), RAD2DEGF(final));
+ }
- /* set roll values */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ /* set roll values */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- *(td->val) = td->ival - final;
- }
- }
+ *(td->val) = td->ival - final;
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Bake-Time) */
@@ -8483,89 +8681,91 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
static void initBakeTime(TransInfo *t)
{
- t->transform = applyBakeTime;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ t->transform = applyBakeTime;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
- t->idx_max = 0;
- t->num.idx_max = 0;
- t->snap[0] = 0.0f;
- t->snap[1] = 1.0f;
- t->snap[2] = t->snap[1] * 0.1f;
+ t->idx_max = 0;
+ t->num.idx_max = 0;
+ t->snap[0] = 0.0f;
+ t->snap[1] = 1.0f;
+ t->snap[2] = t->snap[1] * 0.1f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */
}
static void applyBakeTime(TransInfo *t, const int mval[2])
{
- float time;
- int i;
- char str[UI_MAX_DRAW_STR];
+ float time;
+ int i;
+ char str[UI_MAX_DRAW_STR];
- float fac = 0.1f;
+ float fac = 0.1f;
- /* XXX, disable precision for now,
- * this isn't even accessible by the user */
+ /* XXX, disable precision for now,
+ * this isn't even accessible by the user */
#if 0
- if (t->mouse.precision) {
- /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
- time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
- time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time);
- }
- else
+ if (t->mouse.precision) {
+ /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
+ time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac;
+ time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time);
+ }
+ else
#endif
- {
- time = (float)(t->center2d[0] - mval[0]) * fac;
- }
-
- snapGridIncrement(t, &time);
-
- applyNumInput(&t->num, &time);
-
- /* header print for NumInput */
- if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
-
- outputNumInput(&(t->num), c, &t->scene->unit);
-
- if (time >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Time: +%s %s"), c, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext);
- }
- else {
- /* default header print */
- if (time >= 0.0f)
- BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext);
- else
- BLI_snprintf(str, sizeof(str), IFACE_("Time: %.3f %s"), time, t->proptext);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if (td->val) {
- *td->val = td->ival + time * td->factor;
- if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size;
- if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat;
- }
- }
- }
-
- recalcData(t);
-
- ED_area_status_text(t->sa, str);
+ {
+ time = (float)(t->center2d[0] - mval[0]) * fac;
+ }
+
+ snapGridIncrement(t, &time);
+
+ applyNumInput(&t->num, &time);
+
+ /* header print for NumInput */
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+
+ outputNumInput(&(t->num), c, &t->scene->unit);
+
+ if (time >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: +%s %s"), c, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext);
+ }
+ else {
+ /* default header print */
+ if (time >= 0.0f)
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext);
+ else
+ BLI_snprintf(str, sizeof(str), IFACE_("Time: %.3f %s"), time, t->proptext);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if (td->val) {
+ *td->val = td->ival + time * td->factor;
+ if (td->ext->size && *td->val < *td->ext->size)
+ *td->val = *td->ext->size;
+ if (td->ext->quat && *td->val > *td->ext->quat)
+ *td->val = *td->ext->quat;
+ }
+ }
+ }
+
+ recalcData(t);
+
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Mirror) */
@@ -8574,85 +8774,86 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
static void initMirror(TransInfo *t)
{
- t->transform = applyMirror;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ t->transform = applyMirror;
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
- t->flag |= T_NULL_ONE;
- if ((t->flag & T_EDIT) == 0) {
- t->flag |= T_NO_ZERO;
- }
+ t->flag |= T_NULL_ONE;
+ if ((t->flag & T_EDIT) == 0) {
+ t->flag |= T_NO_ZERO;
+ }
}
static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
{
- float size[3], mat[3][3];
- int i;
- char str[UI_MAX_DRAW_STR];
+ float size[3], mat[3][3];
+ int i;
+ char str[UI_MAX_DRAW_STR];
- /*
- * OPTIMIZATION:
- * This still recalcs transformation on mouse move
- * while it should only recalc on constraint change
- * */
+ /*
+ * OPTIMIZATION:
+ * This still recalcs transformation on mouse move
+ * while it should only recalc on constraint change
+ * */
- /* if an axis has been selected */
- if (t->con.mode & CON_APPLY) {
- size[0] = size[1] = size[2] = -1;
+ /* if an axis has been selected */
+ if (t->con.mode & CON_APPLY) {
+ size[0] = size[1] = size[2] = -1;
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
- }
+ if (t->con.applySize) {
+ t->con.applySize(t, NULL, NULL, mat);
+ }
- BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text);
+ BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- ElementResize(t, tc, td, mat);
- }
- }
+ ElementResize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
- }
- else {
- size[0] = size[1] = size[2] = 1;
+ ED_area_status_text(t->sa, str);
+ }
+ else {
+ size[0] = size[1] = size[2] = 1;
- size_to_mat3(mat, size);
+ size_to_mat3(mat, size);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- ElementResize(t, tc, td, mat);
- }
- }
+ ElementResize(t, tc, td, mat);
+ }
+ }
- recalcData(t);
+ recalcData(t);
- if (t->flag & T_2D_EDIT)
- ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)"));
- else
- ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
- }
+ if (t->flag & T_2D_EDIT)
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)"));
+ else
+ ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Align) */
@@ -8661,59 +8862,58 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
static void initAlign(TransInfo *t)
{
- t->flag |= T_NO_CONSTRAINT;
+ t->flag |= T_NO_CONSTRAINT;
- t->transform = applyAlign;
+ t->transform = applyAlign;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
}
static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
{
- float center[3];
- int i;
+ float center[3];
+ int i;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ /* saving original center */
+ copy_v3_v3(center, tc->center_local);
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float mat[3][3], invmat[3][3];
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- /* saving original center */
- copy_v3_v3(center, tc->center_local);
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float mat[3][3], invmat[3][3];
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_NOACTION)
- break;
+ if (td->flag & TD_SKIP)
+ continue;
- if (td->flag & TD_SKIP)
- continue;
+ /* around local centers */
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ copy_v3_v3(tc->center_local, td->center);
+ }
+ else {
+ if (t->settings->selectmode & SCE_SELECT_FACE) {
+ copy_v3_v3(tc->center_local, td->center);
+ }
+ }
- /* around local centers */
- if (t->flag & (T_OBJECT | T_POSE)) {
- copy_v3_v3(tc->center_local, td->center);
- }
- else {
- if (t->settings->selectmode & SCE_SELECT_FACE) {
- copy_v3_v3(tc->center_local, td->center);
- }
- }
+ invert_m3_m3(invmat, td->axismtx);
- invert_m3_m3(invmat, td->axismtx);
+ mul_m3_m3m3(mat, t->spacemtx, invmat);
- mul_m3_m3m3(mat, t->spacemtx, invmat);
+ ElementRotation(t, tc, td, mat, t->around);
+ }
+ /* restoring original center */
+ copy_v3_v3(tc->center_local, center);
+ }
- ElementRotation(t, tc, td, mat, t->around);
- }
- /* restoring original center */
- copy_v3_v3(tc->center_local, center);
- }
+ recalcData(t);
- recalcData(t);
-
- ED_area_status_text(t->sa, IFACE_("Align"));
+ ED_area_status_text(t->sa, IFACE_("Align"));
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Sequencer Slide) */
@@ -8722,98 +8922,101 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
static void initSeqSlide(TransInfo *t)
{
- t->transform = applySeqSlide;
+ t->transform = applySeqSlide;
- initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
+ initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
- t->idx_max = 1;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
+ t->idx_max = 1;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
- t->snap[0] = 0.0f;
- t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base);
- t->snap[2] = 10.0f;
+ t->snap[0] = 0.0f;
+ 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]);
- t->num.unit_sys = t->scene->unit.system;
- /* Would be nice to have a time handling in units as well
- * (supporting frames in addition to "natural" time...). */
- t->num.unit_type[0] = B_UNIT_NONE;
- t->num.unit_type[1] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* Would be nice to have a time handling in units as well
+ * (supporting frames in addition to "natural" time...). */
+ t->num.unit_type[0] = B_UNIT_NONE;
+ t->num.unit_type[1] = B_UNIT_NONE;
}
static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR])
{
- char tvec[NUM_STR_REP_LEN * 3];
- size_t ofs = 0;
+ char tvec[NUM_STR_REP_LEN * 3];
+ size_t ofs = 0;
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
- }
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
+ }
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
- if (t->keymap) {
- wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
- if (kmi) {
- ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
- }
- }
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" or Alt) Expand to fit %s"),
- WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
+ if (t->keymap) {
+ wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE);
+ if (kmi) {
+ ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs);
+ }
+ }
+ ofs += BLI_snprintf(str + ofs,
+ UI_MAX_DRAW_STR - ofs,
+ IFACE_(" or Alt) Expand to fit %s"),
+ WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
}
static void applySeqSlideValue(TransInfo *t, const float val[2])
{
- int i;
+ int i;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if (td->flag & TD_SKIP)
- continue;
+ if (td->flag & TD_SKIP)
+ continue;
- madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
- }
- }
+ madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor);
+ }
+ }
}
static void applySeqSlide(TransInfo *t, const int mval[2])
{
- char str[UI_MAX_DRAW_STR];
+ char str[UI_MAX_DRAW_STR];
- snapSequenceBounds(t, mval);
+ snapSequenceBounds(t, mval);
- if (t->con.mode & CON_APPLY) {
- float pvec[3] = {0.0f, 0.0f, 0.0f};
- float tvec[3];
- t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec);
- copy_v3_v3(t->values, tvec);
- }
- else {
- // snapGridIncrement(t, t->values);
- applyNumInput(&t->num, t->values);
- }
+ if (t->con.mode & CON_APPLY) {
+ float pvec[3] = {0.0f, 0.0f, 0.0f};
+ float tvec[3];
+ t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec);
+ copy_v3_v3(t->values, tvec);
+ }
+ else {
+ // snapGridIncrement(t, t->values);
+ applyNumInput(&t->num, t->values);
+ }
- t->values[0] = floorf(t->values[0] + 0.5f);
- t->values[1] = floorf(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);
+ headerSeqSlide(t, t->values, str);
+ applySeqSlideValue(t, t->values);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Animation Editors - Transform Utils
*
@@ -8829,109 +9032,109 @@ static void applySeqSlide(TransInfo *t, const int mval[2])
// XXX these modifier checks should be keymappable
static short getAnimEdit_SnapMode(TransInfo *t)
{
- short autosnap = SACTSNAP_OFF;
+ short autosnap = SACTSNAP_OFF;
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- if (saction)
- autosnap = saction->autosnap;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ if (saction)
+ autosnap = saction->autosnap;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- if (sipo)
- autosnap = sipo->autosnap;
- }
- else if (t->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
+ if (sipo)
+ autosnap = sipo->autosnap;
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
- if (snla)
- autosnap = snla->autosnap;
- }
- else {
- autosnap = SACTSNAP_OFF;
- }
+ if (snla)
+ autosnap = snla->autosnap;
+ }
+ else {
+ autosnap = SACTSNAP_OFF;
+ }
- /* toggle autosnap on/off
- * - when toggling on, prefer nearest frame over 1.0 frame increments
- */
- if (t->modifiers & MOD_SNAP_INVERT) {
- if (autosnap)
- autosnap = SACTSNAP_OFF;
- else
- autosnap = SACTSNAP_FRAME;
- }
+ /* toggle autosnap on/off
+ * - when toggling on, prefer nearest frame over 1.0 frame increments
+ */
+ if (t->modifiers & MOD_SNAP_INVERT) {
+ if (autosnap)
+ autosnap = SACTSNAP_OFF;
+ else
+ autosnap = SACTSNAP_FRAME;
+ }
- return autosnap;
+ return autosnap;
}
/* This function is used by Animation Editor specific transform functions to do
* the Snap Keyframe to Nearest Frame/Marker
*/
-static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
-{
- /* snap key to nearest frame or second? */
- if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) {
- const Scene *scene = t->scene;
- const double secf = FPS;
- double val;
-
- /* convert frame to nla-action time (if needed) */
- if (adt)
- val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
- else
- val = *(td->val);
-
- /* do the snapping to nearest frame/second */
- if (autosnap == SACTSNAP_FRAME) {
- val = floorf(val + 0.5);
- }
- else if (autosnap == SACTSNAP_SECOND) {
- val = (float)(floor((val / secf) + 0.5) * secf);
- }
-
- /* convert frame out of nla-action time */
- if (adt)
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- else
- *(td->val) = val;
- }
- /* snap key to nearest marker? */
- else if (autosnap == SACTSNAP_MARKER) {
- float val;
-
- /* convert frame to nla-action time (if needed) */
- if (adt)
- val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
- else
- val = *(td->val);
-
- /* snap to nearest marker */
- // TODO: need some more careful checks for where data comes from
- val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val);
-
- /* convert frame out of nla-action time */
- if (adt)
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- else
- *(td->val) = val;
- }
-
- /* if the handles are to be moved too (as side-effect of keyframes moving, to keep the general effect)
- * offset them by the same amount so that the general angles are maintained (i.e. won't change while
- * handles are free-to-roam and keyframes are snap-locked)
- */
- if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
- td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival;
- }
- if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
- td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival;
- }
+static void doAnimEdit_SnapFrame(
+ TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
+{
+ /* snap key to nearest frame or second? */
+ if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) {
+ const Scene *scene = t->scene;
+ const double secf = FPS;
+ double val;
+
+ /* convert frame to nla-action time (if needed) */
+ if (adt)
+ val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
+ else
+ val = *(td->val);
+
+ /* do the snapping to nearest frame/second */
+ if (autosnap == SACTSNAP_FRAME) {
+ val = floorf(val + 0.5);
+ }
+ else if (autosnap == SACTSNAP_SECOND) {
+ val = (float)(floor((val / secf) + 0.5) * secf);
+ }
+
+ /* convert frame out of nla-action time */
+ if (adt)
+ *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
+ else
+ *(td->val) = val;
+ }
+ /* snap key to nearest marker? */
+ else if (autosnap == SACTSNAP_MARKER) {
+ float val;
+
+ /* convert frame to nla-action time (if needed) */
+ if (adt)
+ val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP);
+ else
+ val = *(td->val);
+
+ /* snap to nearest marker */
+ // TODO: need some more careful checks for where data comes from
+ val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val);
+
+ /* convert frame out of nla-action time */
+ if (adt)
+ *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
+ else
+ *(td->val) = val;
+ }
+
+ /* if the handles are to be moved too (as side-effect of keyframes moving, to keep the general effect)
+ * offset them by the same amount so that the general angles are maintained (i.e. won't change while
+ * handles are free-to-roam and keyframes are snap-locked)
+ */
+ if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
+ td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival;
+ }
+ if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival;
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Animation Translation) */
@@ -8940,164 +9143,165 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
static void initTimeTranslate(TransInfo *t)
{
- /* this tool is only really available in the Action Editor... */
- if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) {
- t->state = TRANS_CANCEL;
- }
+ /* this tool is only really available in the Action Editor... */
+ if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) {
+ t->state = TRANS_CANCEL;
+ }
- t->mode = TFM_TIME_TRANSLATE;
- t->transform = applyTimeTranslate;
+ t->mode = TFM_TIME_TRANSLATE;
+ t->transform = applyTimeTranslate;
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- /* No time unit supporting frames currently... */
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* No time unit supporting frames currently... */
+ t->num.unit_type[0] = B_UNIT_NONE;
}
static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR])
{
- 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)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- const Scene *scene = t->scene;
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
- float val = t->values[0];
-
- /* apply snapping + frame->seconds conversions */
- if (autosnap == SACTSNAP_STEP) {
- /* frame step */
- val = floorf(val + 0.5f);
- }
- else if (autosnap == SACTSNAP_TSTEP) {
- /* second step */
- val = floorf((double)val / secf + 0.5);
- }
- else if (autosnap == SACTSNAP_SECOND) {
- /* nearest second */
- val = (float)((double)val / secf);
- }
-
- if (autosnap == SACTSNAP_FRAME)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val);
- else if (autosnap == SACTSNAP_SECOND)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val);
- else if (autosnap == SACTSNAP_TSTEP)
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val);
- else
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
- }
-
- ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]);
-
- if (t->flag & T_PROP_EDIT_ALL) {
- ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
- }
+ 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)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ const Scene *scene = t->scene;
+ const short autosnap = getAnimEdit_SnapMode(t);
+ const double secf = FPS;
+ float val = t->values[0];
+
+ /* apply snapping + frame->seconds conversions */
+ if (autosnap == SACTSNAP_STEP) {
+ /* frame step */
+ val = floorf(val + 0.5f);
+ }
+ else if (autosnap == SACTSNAP_TSTEP) {
+ /* second step */
+ val = floorf((double)val / secf + 0.5);
+ }
+ else if (autosnap == SACTSNAP_SECOND) {
+ /* nearest second */
+ val = (float)((double)val / secf);
+ }
+
+ if (autosnap == SACTSNAP_FRAME)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val);
+ else if (autosnap == SACTSNAP_SECOND)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val);
+ else if (autosnap == SACTSNAP_TSTEP)
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val);
+ else
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
+ }
+
+ ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]);
+
+ if (t->flag & T_PROP_EDIT_ALL) {
+ ofs += BLI_snprintf(
+ str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
+ }
}
static void applyTimeTranslateValue(TransInfo *t)
{
- Scene *scene = t->scene;
- int i;
-
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
-
- float deltax, val /* , valprev */;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- TransData2D *td2d = tc->data_2d;
- /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
- for (i = 0; i < tc->data_len; i++, td++, td2d++) {
- /* it is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from
- * (this is only valid when not in NLA)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
-
- /* valprev = *td->val; */ /* UNUSED */
-
- /* check if any need to apply nla-mapping */
- if (adt && (t->spacetype != SPACE_SEQ)) {
- deltax = t->values[0];
-
- if (autosnap == SACTSNAP_TSTEP) {
- deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- deltax = floorf(deltax + 0.5f);
- }
-
- val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
- val += deltax * td->factor;
- *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
- }
- else {
- deltax = val = t->values[0];
-
- if (autosnap == SACTSNAP_TSTEP) {
- val = (float)(floor(((double)deltax / secf) + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- val = floorf(val + 0.5f);
- }
-
- *(td->val) = td->ival + val;
- }
-
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
+ Scene *scene = t->scene;
+ int i;
+
+ const short autosnap = getAnimEdit_SnapMode(t);
+ const double secf = FPS;
+
+ float deltax, val /* , valprev */;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ TransData2D *td2d = tc->data_2d;
+ /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
+ for (i = 0; i < tc->data_len; i++, td++, td2d++) {
+ /* it is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from
+ * (this is only valid when not in NLA)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+
+ /* valprev = *td->val; */ /* UNUSED */
+
+ /* check if any need to apply nla-mapping */
+ if (adt && (t->spacetype != SPACE_SEQ)) {
+ deltax = t->values[0];
+
+ if (autosnap == SACTSNAP_TSTEP) {
+ deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf);
+ }
+ else if (autosnap == SACTSNAP_STEP) {
+ deltax = floorf(deltax + 0.5f);
+ }
+
+ val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP);
+ val += deltax * td->factor;
+ *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP);
+ }
+ else {
+ deltax = val = t->values[0];
+
+ if (autosnap == SACTSNAP_TSTEP) {
+ val = (float)(floor(((double)deltax / secf) + 0.5) * secf);
+ }
+ else if (autosnap == SACTSNAP_STEP) {
+ val = floorf(val + 0.5f);
+ }
+
+ *(td->val) = td->ival + val;
+ }
+
+ /* apply nearest snapping */
+ doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
+ }
+ }
}
static void applyTimeTranslate(TransInfo *t, const int mval[2])
{
- View2D *v2d = (View2D *)t->view;
- char str[UI_MAX_DRAW_STR];
+ View2D *v2d = (View2D *)t->view;
+ char str[UI_MAX_DRAW_STR];
- /* calculate translation amount from mouse movement - in 'time-grid space' */
- 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->mouse.imval[0], t->mouse.imval[0], &sval[0], &sval[1]);
+ /* calculate translation amount from mouse movement - in 'time-grid space' */
+ 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->mouse.imval[0], t->mouse.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];
- applyNumInput(&t->num, &t->vec[0]);
- t->values[0] = t->vec[0];
- headerTimeTranslate(t, str);
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeTranslate(t, str);
- applyTimeTranslateValue(t);
+ applyTimeTranslateValue(t);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Animation Time Slide) */
@@ -9106,188 +9310,190 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2])
static void initTimeSlide(TransInfo *t)
{
- /* this tool is only really available in the Action Editor... */
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-
- /* set flag for drawing stuff */
- saction->flag |= SACTION_MOVING;
- }
- else {
- t->state = TRANS_CANCEL;
- }
-
-
- t->mode = TFM_TIME_SLIDE;
- t->transform = applyTimeSlide;
-
- initMouseInputMode(t, &t->mouse, INPUT_NONE);
-
- {
- Scene *scene = t->scene;
- float *range;
- t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max");
- t->custom.mode.use_free = true;
-
- float min = 999999999.0f, max = -999999999.0f;
- int i;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
- float val = *(td->val);
-
- /* strip/action time to global (mapped) time */
- if (adt)
- val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP);
-
- if (min > val) min = val;
- if (max < val) max = val;
- }
- }
-
- if (min == max) {
- /* just use the current frame ranges */
- min = (float)PSFRA;
- max = (float)PEFRA;
- }
-
- range[0] = min;
- range[1] = max;
- }
-
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
-
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
-
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- /* No time unit supporting frames currently... */
- t->num.unit_type[0] = B_UNIT_NONE;
+ /* this tool is only really available in the Action Editor... */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+
+ /* set flag for drawing stuff */
+ saction->flag |= SACTION_MOVING;
+ }
+ else {
+ t->state = TRANS_CANCEL;
+ }
+
+ t->mode = TFM_TIME_SLIDE;
+ t->transform = applyTimeSlide;
+
+ initMouseInputMode(t, &t->mouse, INPUT_NONE);
+
+ {
+ Scene *scene = t->scene;
+ float *range;
+ t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max");
+ t->custom.mode.use_free = true;
+
+ float min = 999999999.0f, max = -999999999.0f;
+ int i;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float val = *(td->val);
+
+ /* strip/action time to global (mapped) time */
+ if (adt)
+ val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP);
+
+ if (min > val)
+ min = val;
+ if (max < val)
+ max = val;
+ }
+ }
+
+ if (min == max) {
+ /* just use the current frame ranges */
+ min = (float)PSFRA;
+ max = (float)PEFRA;
+ }
+
+ range[0] = min;
+ range[1] = max;
+ }
+
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
+
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
+
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ /* No time unit supporting frames currently... */
+ t->num.unit_type[0] = B_UNIT_NONE;
}
static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR])
{
- char tvec[NUM_STR_REP_LEN * 3];
+ char tvec[NUM_STR_REP_LEN * 3];
- if (hasNumInput(&t->num)) {
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- }
- else {
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
- float cval = t->values[0];
- float val;
+ if (hasNumInput(&t->num)) {
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ }
+ else {
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+ float cval = t->values[0];
+ float val;
- val = 2.0f * (cval - sval) / (maxx - minx);
- CLAMP(val, -1.0f, 1.0f);
+ val = 2.0f * (cval - sval) / (maxx - minx);
+ CLAMP(val, -1.0f, 1.0f);
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
- }
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
+ }
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]);
+ BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]);
}
static void applyTimeSlideValue(TransInfo *t, float sval)
{
- int i;
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
-
- /* set value for drawing black line */
- if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- float cvalf = t->values[0];
-
- saction->timeslide = cvalf;
- }
-
- /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- /* it is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from
- * (this is only valid when not in NLA)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
- float cval = t->values[0];
-
- /* only apply to data if in range */
- if ((sval > minx) && (sval < maxx)) {
- float cvalc = CLAMPIS(cval, minx, maxx);
- float ival = td->ival;
- float timefac;
-
- /* NLA mapping magic here works as follows:
- * - "ival" goes from strip time to global time
- * - calculation is performed into td->val in global time
- * (since sval and min/max are all in global time)
- * - "td->val" then gets put back into strip time
- */
- if (adt) {
- /* strip to global */
- ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP);
- }
-
- /* left half? */
- if (ival < sval) {
- timefac = (sval - ival) / (sval - minx);
- *(td->val) = cvalc - timefac * (cvalc - minx);
- }
- else {
- timefac = (ival - sval) / (maxx - sval);
- *(td->val) = cvalc + timefac * (maxx - cvalc);
- }
-
- if (adt) {
- /* global to strip */
- *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP);
- }
- }
- }
- }
+ int i;
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+
+ /* set value for drawing black line */
+ if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ float cvalf = t->values[0];
+
+ saction->timeslide = cvalf;
+ }
+
+ /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ /* it is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from
+ * (this is only valid when not in NLA)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float cval = t->values[0];
+
+ /* only apply to data if in range */
+ if ((sval > minx) && (sval < maxx)) {
+ float cvalc = CLAMPIS(cval, minx, maxx);
+ float ival = td->ival;
+ float timefac;
+
+ /* NLA mapping magic here works as follows:
+ * - "ival" goes from strip time to global time
+ * - calculation is performed into td->val in global time
+ * (since sval and min/max are all in global time)
+ * - "td->val" then gets put back into strip time
+ */
+ if (adt) {
+ /* strip to global */
+ ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP);
+ }
+
+ /* left half? */
+ if (ival < sval) {
+ timefac = (sval - ival) / (sval - minx);
+ *(td->val) = cvalc - timefac * (cvalc - minx);
+ }
+ else {
+ timefac = (ival - sval) / (maxx - sval);
+ *(td->val) = cvalc + timefac * (maxx - cvalc);
+ }
+
+ if (adt) {
+ /* global to strip */
+ *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP);
+ }
+ }
+ }
+ }
}
static void applyTimeSlide(TransInfo *t, const int mval[2])
{
- View2D *v2d = (View2D *)t->view;
- float cval[2], sval[2];
- const float *range = t->custom.mode.data;
- float minx = range[0];
- float maxx = range[1];
- char str[UI_MAX_DRAW_STR];
+ View2D *v2d = (View2D *)t->view;
+ float cval[2], sval[2];
+ const float *range = t->custom.mode.data;
+ float minx = range[0];
+ float maxx = range[1];
+ char str[UI_MAX_DRAW_STR];
- /* calculate mouse co-ordinates */
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]);
+ /* calculate mouse co-ordinates */
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]);
- /* 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]; */ /* UNUSED (reset again later). */
+ /* 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]; */ /* UNUSED (reset again later). */
- /* handle numeric-input stuff */
- t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
- applyNumInput(&t->num, &t->vec[0]);
- t->values[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
+ /* handle numeric-input stuff */
+ t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx);
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0];
- headerTimeSlide(t, sval[0], str);
- applyTimeSlideValue(t, sval[0]);
+ headerTimeSlide(t, sval[0], str);
+ applyTimeSlideValue(t, sval[0]);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Transform (Animation Time Scale) */
@@ -9296,134 +9502,133 @@ static void applyTimeSlide(TransInfo *t, const int mval[2])
static void initTimeScale(TransInfo *t)
{
- float center[2];
+ float center[2];
- /* this tool is only really available in the Action Editor
- * AND NLA Editor (for strip scaling)
- */
- if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) {
- t->state = TRANS_CANCEL;
- }
+ /* this tool is only really available in the Action Editor
+ * AND NLA Editor (for strip scaling)
+ */
+ if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) {
+ t->state = TRANS_CANCEL;
+ }
- t->mode = TFM_TIME_SCALE;
- t->transform = applyTimeScale;
+ t->mode = TFM_TIME_SCALE;
+ t->transform = applyTimeScale;
- /* recalculate center2d to use CFRA and mouse Y, since that's
- * what is used in time scale */
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- t->center_global[0] = t->scene->r.cfra;
- projectFloatView(t, t->center_global, center);
- center[1] = t->mouse.imval[1];
- }
+ /* recalculate center2d to use CFRA and mouse Y, since that's
+ * what is used in time scale */
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ t->center_global[0] = t->scene->r.cfra;
+ projectFloatView(t, t->center_global, center);
+ center[1] = t->mouse.imval[1];
+ }
- /* force a reinit with the center2d used here */
- initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
+ /* force a reinit with the center2d used here */
+ initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
- t->flag |= T_NULL_ONE;
- t->num.val_flag[0] |= NUM_NULL_ONE;
+ t->flag |= T_NULL_ONE;
+ t->num.val_flag[0] |= NUM_NULL_ONE;
- /* num-input has max of (n-1) */
- t->idx_max = 0;
- t->num.flag = 0;
- t->num.idx_max = t->idx_max;
+ /* num-input has max of (n-1) */
+ t->idx_max = 0;
+ t->num.flag = 0;
+ t->num.idx_max = t->idx_max;
- /* initialize snap like for everything else */
- t->snap[0] = 0.0f;
- t->snap[1] = t->snap[2] = 1.0f;
+ /* initialize snap like for everything else */
+ t->snap[0] = 0.0f;
+ t->snap[1] = t->snap[2] = 1.0f;
- copy_v3_fl(t->num.val_inc, t->snap[1]);
- t->num.unit_sys = t->scene->unit.system;
- t->num.unit_type[0] = B_UNIT_NONE;
+ copy_v3_fl(t->num.val_inc, t->snap[1]);
+ t->num.unit_sys = t->scene->unit.system;
+ t->num.unit_type[0] = B_UNIT_NONE;
}
static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR])
{
- char tvec[NUM_STR_REP_LEN * 3];
+ char tvec[NUM_STR_REP_LEN * 3];
- if (hasNumInput(&t->num))
- outputNumInput(&(t->num), tvec, &t->scene->unit);
- else
- BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);
+ if (hasNumInput(&t->num))
+ outputNumInput(&(t->num), tvec, &t->scene->unit);
+ else
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);
- BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]);
+ BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]);
}
static void applyTimeScaleValue(TransInfo *t)
{
- Scene *scene = t->scene;
- int i;
+ Scene *scene = t->scene;
+ int i;
- const short autosnap = getAnimEdit_SnapMode(t);
- const double secf = FPS;
+ const short autosnap = getAnimEdit_SnapMode(t);
+ const double secf = FPS;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- TransData2D *td2d = tc->data_2d;
- for (i = 0; i < tc->data_len; i++, td++, td2d++) {
- /* it is assumed that td->extra is a pointer to the AnimData,
- * whose active action is where this keyframe comes from
- * (this is only valid when not in NLA)
- */
- AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
- float startx = CFRA;
- float fac = t->values[0];
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ TransData2D *td2d = tc->data_2d;
+ for (i = 0; i < tc->data_len; i++, td++, td2d++) {
+ /* it is assumed that td->extra is a pointer to the AnimData,
+ * whose active action is where this keyframe comes from
+ * (this is only valid when not in NLA)
+ */
+ AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL;
+ float startx = CFRA;
+ float fac = t->values[0];
- if (autosnap == SACTSNAP_TSTEP) {
- fac = (float)(floor((double)fac / secf + 0.5) * secf);
- }
- else if (autosnap == SACTSNAP_STEP) {
- fac = floorf(fac + 0.5f);
- }
+ if (autosnap == SACTSNAP_TSTEP) {
+ fac = (float)(floor((double)fac / secf + 0.5) * secf);
+ }
+ else if (autosnap == SACTSNAP_STEP) {
+ fac = floorf(fac + 0.5f);
+ }
- /* take proportional editing into account */
- fac = ((fac - 1.0f) * td->factor) + 1;
+ /* take proportional editing into account */
+ fac = ((fac - 1.0f) * td->factor) + 1;
- /* check if any need to apply nla-mapping */
- if (adt)
- startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP);
+ /* check if any need to apply nla-mapping */
+ if (adt)
+ startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP);
- /* now, calculate the new value */
- *(td->val) = ((td->ival - startx) * fac) + startx;
+ /* now, calculate the new value */
+ *(td->val) = ((td->ival - startx) * fac) + startx;
- /* apply nearest snapping */
- doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
- }
- }
+ /* apply nearest snapping */
+ doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
+ }
+ }
}
static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[UI_MAX_DRAW_STR];
+ char str[UI_MAX_DRAW_STR];
- /* handle numeric-input stuff */
- t->vec[0] = t->values[0];
- applyNumInput(&t->num, &t->vec[0]);
- t->values[0] = t->vec[0];
- headerTimeScale(t, str);
+ /* handle numeric-input stuff */
+ t->vec[0] = t->values[0];
+ applyNumInput(&t->num, &t->vec[0]);
+ t->values[0] = t->vec[0];
+ headerTimeScale(t, str);
- applyTimeScaleValue(t);
+ applyTimeScaleValue(t);
- recalcData(t);
+ recalcData(t);
- ED_area_status_text(t->sa, str);
+ ED_area_status_text(t->sa, str);
}
/** \} */
-
/* TODO, move to: transform_query.c */
bool checkUseAxisMatrix(TransInfo *t)
{
- /* currently only checks for editmode */
- if (t->flag & T_EDIT) {
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)))
- {
- /* not all editmode supports axis-matrix */
- return true;
- }
- }
-
- return false;
+ /* currently only checks for editmode */
+ if (t->flag & T_EDIT) {
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
+ /* not all editmode supports axis-matrix */
+ return true;
+ }
+ }
+
+ return false;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 835346d9eee..6451d82e45c 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -21,7 +21,6 @@
* \ingroup edtransform
*/
-
#ifndef __TRANSFORM_H__
#define __TRANSFORM_H__
@@ -66,158 +65,170 @@ struct wmTimer;
/* transinfo->redraw */
typedef enum {
- TREDRAW_NOTHING = 0,
- TREDRAW_HARD = 1,
- TREDRAW_SOFT = 2,
+ TREDRAW_NOTHING = 0,
+ TREDRAW_HARD = 1,
+ TREDRAW_SOFT = 2,
} eRedrawFlag;
typedef struct TransSnapPoint {
- struct TransSnapPoint *next, *prev;
- float co[3];
+ struct TransSnapPoint *next, *prev;
+ float co[3];
} TransSnapPoint;
typedef struct TransSnap {
- short mode;
- short target;
- short modePoint;
- short modeSelect;
- bool align;
- bool project;
- bool snap_self;
- bool peel;
- bool snap_spatial_grid;
- short status;
- /** snapping from this point (in global-space). */
- float snapPoint[3];
- /** to this point (in global-space). */
- float snapTarget[3];
- float snapNormal[3];
- char snapNodeBorder;
- ListBase points;
- TransSnapPoint *selectedPoint;
- double last;
- void (*applySnap)(struct TransInfo *, float *);
- void (*calcSnap)(struct TransInfo *, float *);
- void (*targetSnap)(struct TransInfo *);
- /**
- * Get the transform distance between two points (used by Closest snap)
- *
- * \note Return value can be anything,
- * where the smallest absolute value defines whats closest.
- */
- float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
-
- /**
- * Re-usable snap context data.
- */
- struct SnapObjectContext *object_context;
+ short mode;
+ short target;
+ short modePoint;
+ short modeSelect;
+ bool align;
+ bool project;
+ bool snap_self;
+ bool peel;
+ bool snap_spatial_grid;
+ short status;
+ /** snapping from this point (in global-space). */
+ float snapPoint[3];
+ /** to this point (in global-space). */
+ float snapTarget[3];
+ float snapNormal[3];
+ char snapNodeBorder;
+ ListBase points;
+ TransSnapPoint *selectedPoint;
+ double last;
+ void (*applySnap)(struct TransInfo *, float *);
+ void (*calcSnap)(struct TransInfo *, float *);
+ void (*targetSnap)(struct TransInfo *);
+ /**
+ * Get the transform distance between two points (used by Closest snap)
+ *
+ * \note Return value can be anything,
+ * where the smallest absolute value defines whats closest.
+ */
+ float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
+
+ /**
+ * Re-usable snap context data.
+ */
+ struct SnapObjectContext *object_context;
} TransSnap;
typedef struct TransCon {
- short orientation;
- /** Description of the constraint for header_print. */
- char text[50];
- /** Matrix of the constraint space. */
- float mtx[3][3];
- /** Inverse matrix of the constraint space. */
- float imtx[3][3];
- /** Projection constraint matrix (same as #imtx with some axis == 0). */
- float pmtx[3][3];
- /** Initial mouse value for visual calculation
- * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
- int imval[2];
- /** Mode flags of the constraint. */
- int mode;
- void (*drawExtra)(struct TransInfo *t);
-
- /* Note: if 'tc' is NULL, 'td' must also be NULL.
- * For constraints that needs to draw differently from the other
- * uses this instead of the generic draw function. */
-
- /** Apply function pointer for linear vectorial transformation
- * The last three parameters are pointers to the in/out/printable vectors. */
- void (*applyVec)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, const float in[3], float out[3], float pvec[3]);
- /** Apply function pointer for size transformation. */
- void (*applySize)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, float smat[3][3]);
- /** Apply function pointer for rotation transformation */
- void (*applyRot)(struct TransInfo *t, struct TransDataContainer *tc, struct TransData *td, float vec[3], float *angle);
+ short orientation;
+ /** Description of the constraint for header_print. */
+ char text[50];
+ /** Matrix of the constraint space. */
+ float mtx[3][3];
+ /** Inverse matrix of the constraint space. */
+ float imtx[3][3];
+ /** Projection constraint matrix (same as #imtx with some axis == 0). */
+ float pmtx[3][3];
+ /** Initial mouse value for visual calculation
+ * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
+ int imval[2];
+ /** Mode flags of the constraint. */
+ int mode;
+ void (*drawExtra)(struct TransInfo *t);
+
+ /* Note: if 'tc' is NULL, 'td' must also be NULL.
+ * For constraints that needs to draw differently from the other
+ * uses this instead of the generic draw function. */
+
+ /** Apply function pointer for linear vectorial transformation
+ * The last three parameters are pointers to the in/out/printable vectors. */
+ void (*applyVec)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3]);
+ /** Apply function pointer for size transformation. */
+ void (*applySize)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ float smat[3][3]);
+ /** Apply function pointer for rotation transformation */
+ void (*applyRot)(struct TransInfo *t,
+ struct TransDataContainer *tc,
+ struct TransData *td,
+ float vec[3],
+ float *angle);
} TransCon;
typedef struct TransDataExtension {
- /** Initial object drot. */
- float drot[3];
- // /* Initial object drotAngle, TODO: not yet implemented */
- // float drotAngle;
- // /* Initial object drotAxis, TODO: not yet implemented */
- // float drotAxis[3];
- /** Initial object delta quat. */
- float dquat[4];
- /** Initial object delta scale. */
- float dscale[3];
- /** Rotation of the data to transform. */
- float *rot;
- /** Initial rotation. */
- float irot[3];
- /** Rotation quaternion of the data to transform. */
- float *quat;
- /** Initial rotation quaternion. */
- float iquat[4];
- /** Rotation angle of the data to transform. */
- float *rotAngle;
- /** Initial rotation angle. */
- float irotAngle;
- /** Rotation axis of the data to transform. */
- float *rotAxis;
- /** Initial rotation axis. */
- float irotAxis[4];
- /** Size of the data to transform. */
- float *size;
- /** Initial size. */
- float isize[3];
- /** Object matrix. */
- float obmat[4][4];
- /** Use instead of #TransData.smtx,
- * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
- float l_smtx[3][3];
- /** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
- * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
- * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
- float r_mtx[3][3];
- /** Inverse of previous one. */
- float r_smtx[3][3];
- /** Rotation mode, as defined in #eRotationModes (DNA_action_types.h). */
- int rotOrder;
- /** Original object transformation used for rigid bodies. */
- float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle;
+ /** Initial object drot. */
+ float drot[3];
+ // /* Initial object drotAngle, TODO: not yet implemented */
+ // float drotAngle;
+ // /* Initial object drotAxis, TODO: not yet implemented */
+ // float drotAxis[3];
+ /** Initial object delta quat. */
+ float dquat[4];
+ /** Initial object delta scale. */
+ float dscale[3];
+ /** Rotation of the data to transform. */
+ float *rot;
+ /** Initial rotation. */
+ float irot[3];
+ /** Rotation quaternion of the data to transform. */
+ float *quat;
+ /** Initial rotation quaternion. */
+ float iquat[4];
+ /** Rotation angle of the data to transform. */
+ float *rotAngle;
+ /** Initial rotation angle. */
+ float irotAngle;
+ /** Rotation axis of the data to transform. */
+ float *rotAxis;
+ /** Initial rotation axis. */
+ float irotAxis[4];
+ /** Size of the data to transform. */
+ float *size;
+ /** Initial size. */
+ float isize[3];
+ /** Object matrix. */
+ float obmat[4][4];
+ /** Use instead of #TransData.smtx,
+ * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
+ float l_smtx[3][3];
+ /** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
+ * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
+ * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
+ float r_mtx[3][3];
+ /** Inverse of previous one. */
+ float r_smtx[3][3];
+ /** Rotation mode, as defined in #eRotationModes (DNA_action_types.h). */
+ int rotOrder;
+ /** Original object transformation used for rigid bodies. */
+ float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle;
} TransDataExtension;
typedef struct TransData2D {
- /** Location of data used to transform (x,y,0). */
- float loc[3];
- /** Pointer to real 2d location of data. */
- float *loc2d;
-
- /** Pointer to handle locations, if handles aren't being moved independently. */
- float *h1, *h2;
- float ih1[2], ih2[2];
+ /** Location of data used to transform (x,y,0). */
+ float loc[3];
+ /** Pointer to real 2d location of data. */
+ float *loc2d;
+
+ /** Pointer to handle locations, if handles aren't being moved independently. */
+ float *h1, *h2;
+ float ih1[2], ih2[2];
} TransData2D;
/** Used to store 2 handles for each #TransData in case the other handle wasn't selected. */
typedef struct TransDataCurveHandleFlags {
- char ih1, ih2;
- char *h1, *h2;
+ char ih1, ih2;
+ char *h1, *h2;
} TransDataCurveHandleFlags;
/** Used for sequencer transform. */
typedef struct TransDataSeq {
- struct Sequence *seq;
- /** A copy of #Sequence.flag that may be modified for nested strips. */
- int flag;
- /** Use this so we can have transform data at the strips start,
- * but apply correctly to the start frame. */
- int start_offset;
- /** one of #SELECT, #SEQ_LEFTSEL and #SEQ_RIGHTSEL. */
- short sel_flag;
+ struct Sequence *seq;
+ /** A copy of #Sequence.flag that may be modified for nested strips. */
+ int flag;
+ /** Use this so we can have transform data at the strips start,
+ * but apply correctly to the start frame. */
+ int start_offset;
+ /** one of #SELECT, #SEQ_LEFTSEL and #SEQ_RIGHTSEL. */
+ short sel_flag;
} TransDataSeq;
@@ -225,35 +236,35 @@ typedef struct TransDataSeq {
* Sequencer transform customdata (stored in #TransCustomDataContainer).
*/
typedef struct TransSeq {
- TransDataSeq *tdseq;
- int min;
- int max;
- bool snap_left;
+ TransDataSeq *tdseq;
+ int min;
+ int max;
+ bool snap_left;
} TransSeq;
/** Used for NLA transform (stored in #TransData.extra pointer). */
typedef struct TransDataNla {
- /** ID-block NLA-data is attached to. */
- ID *id;
-
- /** Original NLA-Track that the strip belongs to. */
- struct NlaTrack *oldTrack;
- /** Current NLA-Track that the strip belongs to. */
- struct NlaTrack *nlt;
-
- /** NLA-strip this data represents. */
- struct NlaStrip *strip;
-
- /* dummy values for transform to write in - must have 3 elements... */
- /** start handle. */
- float h1[3];
- /** end handle. */
- float h2[3];
-
- /** index of track that strip is currently in. */
- int trackIndex;
- /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
- int handle;
+ /** ID-block NLA-data is attached to. */
+ ID *id;
+
+ /** Original NLA-Track that the strip belongs to. */
+ struct NlaTrack *oldTrack;
+ /** Current NLA-Track that the strip belongs to. */
+ struct NlaTrack *nlt;
+
+ /** NLA-strip this data represents. */
+ struct NlaStrip *strip;
+
+ /* dummy values for transform to write in - must have 3 elements... */
+ /** start handle. */
+ float h1[3];
+ /** end handle. */
+ float h2[3];
+
+ /** index of track that strip is currently in. */
+ int trackIndex;
+ /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
+ int handle;
} TransDataNla;
struct GHash;
@@ -261,197 +272,197 @@ struct LinkNode;
/* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */
typedef struct TransDataGenericSlideVert {
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float co_orig_3d[3];
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
} TransDataGenericSlideVert;
typedef struct TransDataEdgeSlideVert {
- /** #TransDataGenericSlideVert (header) */
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float v_co_orig[3];
- /* end generic */
+ /** #TransDataGenericSlideVert (header) */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float v_co_orig[3];
+ /* end generic */
- float edge_len;
+ float edge_len;
- struct BMVert *v_side[2];
+ struct BMVert *v_side[2];
- /* add origvert.co to get the original locations */
- float dir_side[2][3];
+ /* add origvert.co to get the original locations */
+ float dir_side[2][3];
- int loop_nr;
+ int loop_nr;
} TransDataEdgeSlideVert;
-
/* store original data so we can correct UV's and similar when sliding */
typedef struct SlideOrigData {
- /** Set when #origfaces is initialized. */
- bool use_origfaces;
- int cd_loop_mdisp_offset;
-
- /** map {BMVert: TransDataGenericSlideVert} */
- struct GHash *origverts;
- struct GHash *origfaces;
- struct BMesh *bm_origfaces;
-
- struct MemArena *arena;
- /** Number of math BMLoop layers. */
- int layer_math_map_num;
- /** Array size of 'layer_math_map_num'
- * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
- int *layer_math_map;
-
- /** Array of slide vert data especially for mirror verts. */
- TransDataGenericSlideVert *sv_mirror;
- int totsv_mirror;
+ /** Set when #origfaces is initialized. */
+ bool use_origfaces;
+ int cd_loop_mdisp_offset;
+
+ /** map {BMVert: TransDataGenericSlideVert} */
+ struct GHash *origverts;
+ struct GHash *origfaces;
+ struct BMesh *bm_origfaces;
+
+ struct MemArena *arena;
+ /** Number of math BMLoop layers. */
+ int layer_math_map_num;
+ /** Array size of 'layer_math_map_num'
+ * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
+ int *layer_math_map;
+
+ /** Array of slide vert data especially for mirror verts. */
+ TransDataGenericSlideVert *sv_mirror;
+ int totsv_mirror;
} SlideOrigData;
typedef struct EdgeSlideData {
- TransDataEdgeSlideVert *sv;
- int totsv;
+ TransDataEdgeSlideVert *sv;
+ int totsv;
- int mval_start[2], mval_end[2];
- struct BMEditMesh *em;
+ int mval_start[2], mval_end[2];
+ struct BMEditMesh *em;
- SlideOrigData orig_data;
+ SlideOrigData orig_data;
+ int curr_sv_index;
- int curr_sv_index;
-
- /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
- int curr_side_unclamp;
+ /** when un-clamped - use this index: #TransDataEdgeSlideVert.dir_side */
+ int curr_side_unclamp;
} EdgeSlideData;
typedef struct EdgeSlideParams {
- float perc;
+ float perc;
- bool use_even;
- bool flipped;
+ bool use_even;
+ bool flipped;
} EdgeSlideParams;
typedef struct TransDataVertSlideVert {
- /** #TransDataGenericSlideVert (header) */
- struct BMVert *v;
- struct LinkNode **cd_loop_groups;
- float co_orig_3d[3];
- /* end generic */
-
- float (*co_link_orig_3d)[3];
- int co_link_tot;
- int co_link_curr;
+ /** #TransDataGenericSlideVert (header) */
+ struct BMVert *v;
+ struct LinkNode **cd_loop_groups;
+ float co_orig_3d[3];
+ /* end generic */
+
+ float (*co_link_orig_3d)[3];
+ int co_link_tot;
+ int co_link_curr;
} TransDataVertSlideVert;
typedef struct VertSlideData {
- TransDataVertSlideVert *sv;
- int totsv;
+ TransDataVertSlideVert *sv;
+ int totsv;
- struct BMEditMesh *em;
+ struct BMEditMesh *em;
- SlideOrigData orig_data;
+ SlideOrigData orig_data;
- int curr_sv_index;
+ int curr_sv_index;
- /* result of ED_view3d_ob_project_mat_get */
- float proj_mat[4][4];
+ /* result of ED_view3d_ob_project_mat_get */
+ float proj_mat[4][4];
} VertSlideData;
typedef struct VertSlideParams {
- float perc;
+ float perc;
- bool use_even;
- bool flipped;
+ bool use_even;
+ bool flipped;
} VertSlideParams;
typedef struct BoneInitData {
- struct EditBone *bone;
- float tail[3];
- float rad_tail;
- float roll;
- float head[3];
- float dist;
- float xwidth;
- float zwidth;
+ struct EditBone *bone;
+ float tail[3];
+ float rad_tail;
+ float roll;
+ float head[3];
+ float dist;
+ float xwidth;
+ float zwidth;
} BoneInitData;
typedef struct TransData {
- /** Distance needed to affect element (for Proportionnal Editing). */
- float dist;
- /** Distance to the nearest element (for Proportionnal Editing). */
- float rdist;
- /** Factor of the transformation (for Proportionnal Editing). */
- float factor;
- /** Location of the data to transform. */
- float *loc;
- /** Initial location. */
- float iloc[3];
- /** Value pointer for special transforms. */
- float *val;
- /** Old value. */
- float ival;
- /** Individual data center. */
- float center[3];
- /** Transformation matrix from data space to global space. */
- float mtx[3][3];
- /** Transformation matrix from global space to data space. */
- float smtx[3][3];
- /** Axis orientation matrix of the data. */
- float axismtx[3][3];
- struct Object *ob;
- /** For objects/bones, the first constraint in its constraint stack. */
- struct bConstraint *con;
- /** For objects, poses. 1 single malloc per TransInfo! */
- TransDataExtension *ext;
- /** for curves, stores handle flags for modification/cancel. */
- TransDataCurveHandleFlags *hdata;
- /**
- * Extra data (mirrored element pointer, in editmode mesh to BMVert)
- * (editbone for roll fixing) (...).
- */
- void *extra;
- /** Various flags. */
- int flag;
- /** If set, copy of Object or PoseChannel protection. */
- short protectflag;
+ /** Distance needed to affect element (for Proportionnal Editing). */
+ float dist;
+ /** Distance to the nearest element (for Proportionnal Editing). */
+ float rdist;
+ /** Factor of the transformation (for Proportionnal Editing). */
+ float factor;
+ /** Location of the data to transform. */
+ float *loc;
+ /** Initial location. */
+ float iloc[3];
+ /** Value pointer for special transforms. */
+ float *val;
+ /** Old value. */
+ float ival;
+ /** Individual data center. */
+ float center[3];
+ /** Transformation matrix from data space to global space. */
+ float mtx[3][3];
+ /** Transformation matrix from global space to data space. */
+ float smtx[3][3];
+ /** Axis orientation matrix of the data. */
+ float axismtx[3][3];
+ struct Object *ob;
+ /** For objects/bones, the first constraint in its constraint stack. */
+ struct bConstraint *con;
+ /** For objects, poses. 1 single malloc per TransInfo! */
+ TransDataExtension *ext;
+ /** for curves, stores handle flags for modification/cancel. */
+ TransDataCurveHandleFlags *hdata;
+ /**
+ * Extra data (mirrored element pointer, in editmode mesh to BMVert)
+ * (editbone for roll fixing) (...).
+ */
+ void *extra;
+ /** Various flags. */
+ int flag;
+ /** If set, copy of Object or PoseChannel protection. */
+ short protectflag;
} TransData;
typedef struct MouseInput {
- void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
- void (*post)(struct TransInfo *t, float values[3]);
-
- /** Initial mouse position. */
- int imval[2];
- bool precision;
- float precision_factor;
- float center[2];
- float factor;
- /** Additional data, if needed by the particular function. */
- void *data;
-
- /**
- * Use virtual cursor, which takes precision into account
- * keeping track of the cursors 'virtual' location,
- * to avoid jumping values when its toggled.
- *
- * This works well for scaling drag motion,
- * but not for rotating around a point (rotaton needs its own custom accumulator)
- */
- bool use_virtual_mval;
- struct {
- double prev[2];
- double accum[2];
- } virtual_mval;
+ void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
+ void (*post)(struct TransInfo *t, float values[3]);
+
+ /** Initial mouse position. */
+ int imval[2];
+ bool precision;
+ float precision_factor;
+ float center[2];
+ float factor;
+ /** Additional data, if needed by the particular function. */
+ void *data;
+
+ /**
+ * Use virtual cursor, which takes precision into account
+ * keeping track of the cursors 'virtual' location,
+ * to avoid jumping values when its toggled.
+ *
+ * This works well for scaling drag motion,
+ * but not for rotating around a point (rotaton needs its own custom accumulator)
+ */
+ bool use_virtual_mval;
+ struct {
+ double prev[2];
+ double accum[2];
+ } virtual_mval;
} MouseInput;
typedef struct TransCustomData {
- void *data;
- void (*free_cb)(struct TransInfo *, struct TransDataContainer *tc, struct TransCustomData *custom_data);
- unsigned int use_free : 1;
+ void *data;
+ void (*free_cb)(struct TransInfo *,
+ struct TransDataContainer *tc,
+ struct TransCustomData *custom_data);
+ unsigned int use_free : 1;
} TransCustomData;
typedef struct TransCenterData {
- float global[3];
- unsigned int is_set : 1;
+ float global[3];
+ unsigned int is_set : 1;
} TransCenterData;
/**
@@ -462,304 +473,303 @@ typedef struct TransCenterData {
* (typically in transform_conversion.c).
*/
typedef struct TransCustomDataContainer {
- /** Owned by the mode (grab, scale, bend... ).*/
- union {
- TransCustomData mode, first_elem;
- };
- TransCustomData type;
+ /** Owned by the mode (grab, scale, bend... ).*/
+ union {
+ TransCustomData mode, first_elem;
+ };
+ TransCustomData type;
} TransCustomDataContainer;
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(TransCustomDataContainer) / sizeof(TransCustomData))
typedef struct TransDataContainer {
- /**
- * Use for cases we care about the active, eg: active vert of active mesh.
- * if set this will _always_ be the first item in the array.
- */
- bool is_active;
-
- /** Transformed data (array). */
- TransData *data;
- /** Total number of transformed data. */
- int data_len;
-
- /** Transformed data extension (array). */
- TransDataExtension *data_ext;
- /** Transformed data for 2d (array). */
- TransData2D *data_2d;
-
- struct Object *obedit;
-
- /**
- * Use when #T_LOCAL_MATRIX is set.
- * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
- */
- bool use_local_mat;
- float mat[4][4];
- float imat[4][4];
- /** 3x3 copies of matrices above. */
- float mat3[3][3];
- float imat3[3][3];
-
- /** Normalized 'mat3' */
- float mat3_unit[3][3];
-
- /** if 't->flag & T_POSE', this denotes pose object */
- struct Object *poseobj;
-
- /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
- float center_local[3];
-
- /**
- * Mirror option
- */
- struct {
- /* Currently for mesh X mirror only. */
- int axis_flag;
- /** Set to -1.0f or 1.0 when use_mirror is set. */
- float sign;
- } mirror;
-
- TransCustomDataContainer custom;
+ /**
+ * Use for cases we care about the active, eg: active vert of active mesh.
+ * if set this will _always_ be the first item in the array.
+ */
+ bool is_active;
+
+ /** Transformed data (array). */
+ TransData *data;
+ /** Total number of transformed data. */
+ int data_len;
+
+ /** Transformed data extension (array). */
+ TransDataExtension *data_ext;
+ /** Transformed data for 2d (array). */
+ TransData2D *data_2d;
+
+ struct Object *obedit;
+
+ /**
+ * Use when #T_LOCAL_MATRIX is set.
+ * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
+ */
+ bool use_local_mat;
+ float mat[4][4];
+ float imat[4][4];
+ /** 3x3 copies of matrices above. */
+ float mat3[3][3];
+ float imat3[3][3];
+
+ /** Normalized 'mat3' */
+ float mat3_unit[3][3];
+
+ /** if 't->flag & T_POSE', this denotes pose object */
+ struct Object *poseobj;
+
+ /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
+ float center_local[3];
+
+ /**
+ * Mirror option
+ */
+ struct {
+ /* Currently for mesh X mirror only. */
+ int axis_flag;
+ /** Set to -1.0f or 1.0 when use_mirror is set. */
+ float sign;
+ } mirror;
+
+ TransCustomDataContainer custom;
} TransDataContainer;
typedef struct TransInfo {
- TransDataContainer *data_container;
- int data_container_len;
- /** Combine length of all #TransDataContainer.data_len
- * Use to check if nothing is selected or if we have a single selection. */
- int data_len_all;
-
- /** Current mode. */
- int mode;
- /** Generic flags for special behaviors. */
- int flag;
- /** Special modifiers, by function, not key. */
- int modifiers;
- /** Current state (running, canceled. */
- short state;
- /** Current context/options for transform. */
- int options;
- /** Init value for some transformations (and rotation angle). */
- float val;
- void (*transform)(struct TransInfo *, const int[2]);
- /** Transform function pointer. */
- eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
- /* event handler function pointer RETURN 1 if redraw is needed */
- /** transformed constraint. */
- TransCon con;
- TransSnap tsnap;
- /** numerical input. */
- NumInput num;
- /** mouse input. */
- MouseInput mouse;
- /** redraw flag. */
- eRedrawFlag redraw;
- /** proportional circle radius. */
- float prop_size;
- /** proportional falloff text. */
- char proptext[20];
- /**
- * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
- * use for conversion and snapping.
- */
- float aspect[3];
- /** center of transformation (in global-space) */
- float center_global[3];
- /** center in screen coordinates. */
- float center2d[2];
- /* Lazy initialize center data for when we need other center values.
- * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
- TransCenterData center_cache[5];
- /** maximum index on the input vector. */
- short idx_max;
- /** Snapping Gears. */
- float snap[3];
- /** Spatial snapping gears(even when rotating, scaling... etc). */
- float snap_spatial[3];
- /** Mouse side of the cfra, 'L', 'R' or 'B' */
- char frame_side;
-
- /** copy from G.vd, prevents feedback. */
- float viewmat[4][4];
- /** and to make sure we don't have to. */
- float viewinv[4][4];
- /** access G.vd from other space types. */
- float persmat[4][4];
- float persinv[4][4];
- short persp;
- short around;
- /** spacetype where transforming is. */
- char spacetype;
- /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
- char helpline;
- /** Avoid looking inside TransDataContainer obedit. */
- short obedit_type;
-
- /** translation, to show for widget. */
- float vec[3];
- /** rot/rescale, to show for widget. */
- float mat[3][3];
-
- /** orientation matrix of the current space. */
- float spacemtx[3][3];
- /** name of the current space, MAX_NAME. */
- char spacename[64];
-
- /*************** NEW STUFF *********************/
- /** event type used to launch transform. */
- short launch_event;
-
- struct {
- /** Orientation type when when we're not constrained.
- * nearly always global except for rotate which defaults to screen-space orientation. */
- short unset;
- /** Orientation to use when a key is pressed. */
- short user;
- /* Used when user is global. */
- short user_alt;
- short index;
- short *types[2];
- /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */
- TransformOrientation *custom;
- } orientation;
- /** backup from view3d, to restore on end. */
- short gizmo_flag;
-
- short prop_mode;
-
- float values[4];
- /** Offset applied ontop of modal input. */
- float values_modal_offset[4];
- float auto_values[4];
-
- /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
-
- /** Primary axis, rotate only uses this. */
- int orient_axis;
- /** Secondary axis, shear uses this. */
- int orient_axis_ortho;
-
- /** Often this matrix has similar usage to #TransInfo.spacemtx however this
- * is used to define extra axes to operate on, not necessarily a space.
- *
- * For example, by default rotation operates on the view (`orient_matrix[2]`),
- * even when the current space isn't set to the view. */
- float orient_matrix[3][3];
- /** Don't overwrite when set by operator redo defines the orientation axis. */
- bool orient_matrix_is_set;
-
- /** remove elements if operator is canceled. */
- bool remove_on_cancel;
-
- void *view;
- /** Only valid (non null) during an operator called function. */
- struct bContext *context;
- struct ScrArea *sa;
- struct ARegion *ar;
- struct Depsgraph *depsgraph;
- struct Scene *scene;
- struct ViewLayer *view_layer;
- struct ToolSettings *settings;
- struct wmTimer *animtimer;
- /** so we can do lookups for header text. */
- struct wmKeyMap *keymap;
- /** assign from the operator, or can be NULL. */
- struct ReportList *reports;
- /** current mouse position. */
- int mval[2];
- /** use for 3d view. */
- float zfac;
- void *draw_handle_apply;
- void *draw_handle_view;
- void *draw_handle_pixel;
- void *draw_handle_cursor;
-
- /** Currently only used for random curve of proportional editing. */
- struct RNG *rng;
-
- /** Typically for mode settings. */
- TransCustomDataContainer custom;
+ TransDataContainer *data_container;
+ int data_container_len;
+ /** Combine length of all #TransDataContainer.data_len
+ * Use to check if nothing is selected or if we have a single selection. */
+ int data_len_all;
+
+ /** Current mode. */
+ int mode;
+ /** Generic flags for special behaviors. */
+ int flag;
+ /** Special modifiers, by function, not key. */
+ int modifiers;
+ /** Current state (running, canceled. */
+ short state;
+ /** Current context/options for transform. */
+ int options;
+ /** Init value for some transformations (and rotation angle). */
+ float val;
+ void (*transform)(struct TransInfo *, const int[2]);
+ /** Transform function pointer. */
+ eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
+ /* event handler function pointer RETURN 1 if redraw is needed */
+ /** transformed constraint. */
+ TransCon con;
+ TransSnap tsnap;
+ /** numerical input. */
+ NumInput num;
+ /** mouse input. */
+ MouseInput mouse;
+ /** redraw flag. */
+ eRedrawFlag redraw;
+ /** proportional circle radius. */
+ float prop_size;
+ /** proportional falloff text. */
+ char proptext[20];
+ /**
+ * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
+ * use for conversion and snapping.
+ */
+ float aspect[3];
+ /** center of transformation (in global-space) */
+ float center_global[3];
+ /** center in screen coordinates. */
+ float center2d[2];
+ /* Lazy initialize center data for when we need other center values.
+ * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
+ TransCenterData center_cache[5];
+ /** maximum index on the input vector. */
+ short idx_max;
+ /** Snapping Gears. */
+ float snap[3];
+ /** Spatial snapping gears(even when rotating, scaling... etc). */
+ float snap_spatial[3];
+ /** Mouse side of the cfra, 'L', 'R' or 'B' */
+ char frame_side;
+
+ /** copy from G.vd, prevents feedback. */
+ float viewmat[4][4];
+ /** and to make sure we don't have to. */
+ float viewinv[4][4];
+ /** access G.vd from other space types. */
+ float persmat[4][4];
+ float persinv[4][4];
+ short persp;
+ short around;
+ /** spacetype where transforming is. */
+ char spacetype;
+ /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
+ char helpline;
+ /** Avoid looking inside TransDataContainer obedit. */
+ short obedit_type;
+
+ /** translation, to show for widget. */
+ float vec[3];
+ /** rot/rescale, to show for widget. */
+ float mat[3][3];
+
+ /** orientation matrix of the current space. */
+ float spacemtx[3][3];
+ /** name of the current space, MAX_NAME. */
+ char spacename[64];
+
+ /*************** NEW STUFF *********************/
+ /** event type used to launch transform. */
+ short launch_event;
+
+ struct {
+ /** Orientation type when when we're not constrained.
+ * nearly always global except for rotate which defaults to screen-space orientation. */
+ short unset;
+ /** Orientation to use when a key is pressed. */
+ short user;
+ /* Used when user is global. */
+ short user_alt;
+ short index;
+ short *types[2];
+ /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */
+ TransformOrientation *custom;
+ } orientation;
+ /** backup from view3d, to restore on end. */
+ short gizmo_flag;
+
+ short prop_mode;
+
+ float values[4];
+ /** Offset applied ontop of modal input. */
+ float values_modal_offset[4];
+ float auto_values[4];
+
+ /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
+
+ /** Primary axis, rotate only uses this. */
+ int orient_axis;
+ /** Secondary axis, shear uses this. */
+ int orient_axis_ortho;
+
+ /** Often this matrix has similar usage to #TransInfo.spacemtx however this
+ * is used to define extra axes to operate on, not necessarily a space.
+ *
+ * For example, by default rotation operates on the view (`orient_matrix[2]`),
+ * even when the current space isn't set to the view. */
+ float orient_matrix[3][3];
+ /** Don't overwrite when set by operator redo defines the orientation axis. */
+ bool orient_matrix_is_set;
+
+ /** remove elements if operator is canceled. */
+ bool remove_on_cancel;
+
+ void *view;
+ /** Only valid (non null) during an operator called function. */
+ struct bContext *context;
+ struct ScrArea *sa;
+ struct ARegion *ar;
+ struct Depsgraph *depsgraph;
+ struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct ToolSettings *settings;
+ struct wmTimer *animtimer;
+ /** so we can do lookups for header text. */
+ struct wmKeyMap *keymap;
+ /** assign from the operator, or can be NULL. */
+ struct ReportList *reports;
+ /** current mouse position. */
+ int mval[2];
+ /** use for 3d view. */
+ float zfac;
+ void *draw_handle_apply;
+ void *draw_handle_view;
+ void *draw_handle_pixel;
+ void *draw_handle_cursor;
+
+ /** Currently only used for random curve of proportional editing. */
+ struct RNG *rng;
+
+ /** Typically for mode settings. */
+ TransCustomDataContainer custom;
} TransInfo;
-
/* ******************** Macros & Prototypes *********************** */
/* transinfo->state */
enum {
- TRANS_STARTING = 0,
- TRANS_RUNNING = 1,
- TRANS_CONFIRM = 2,
- TRANS_CANCEL = 3,
+ TRANS_STARTING = 0,
+ TRANS_RUNNING = 1,
+ TRANS_CONFIRM = 2,
+ TRANS_CANCEL = 3,
};
/* transinfo->flag */
enum {
- T_OBJECT = 1 << 0,
- /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
- T_EDIT = 1 << 1,
- T_POSE = 1 << 2,
- T_TEXTURE = 1 << 3,
- /** Transforming the camera while in camera view. */
- T_CAMERA = 1 << 4,
- /** Transforming the 3D cursor. */
- T_CURSOR = 1 << 5,
- /** Transform points, having no rotation/scale. */
- T_POINTS = 1 << 6,
- /**
- * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
- * that happen to apply to specific modes (edit & pose for eg). */
- T_LOCAL_MATRIX = 1 << 7,
-
- /** restrictions flags */
- T_NO_CONSTRAINT = 1 << 8,
- T_NULL_ONE = 1 << 9,
- T_NO_ZERO = 1 << 10,
- T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
-
- T_PROP_EDIT = 1 << 11,
- T_PROP_CONNECTED = 1 << 12,
- T_PROP_PROJECTED = 1 << 13,
- T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
-
- T_V3D_ALIGN = 1 << 14,
- /** For 2d views like uv or fcurve. */
- T_2D_EDIT = 1 << 15,
- T_CLIP_UV = 1 << 16,
-
- /** Auto-ik is on. */
- T_AUTOIK = 1 << 18,
-
- /** Don't use mirror even if the data-block option is set. */
- T_NO_MIRROR = 1 << 19,
-
- T_AUTOVALUES = 1 << 20,
-
- /** To specify if we save back settings at the end. */
- T_MODAL = 1 << 21,
-
- /** No retopo. */
- T_NO_PROJECT = 1 << 22,
-
- T_RELEASE_CONFIRM = 1 << 23,
-
- /** Alternative transformation. used to add offset to tracking markers. */
- T_ALT_TRANSFORM = 1 << 24,
-
- /** #TransInfo.center has been set, don't change it. */
- T_OVERRIDE_CENTER = 1 << 25,
-
- T_MODAL_CURSOR_SET = 1 << 26,
-
- T_CLNOR_REBUILD = 1 << 27,
+ T_OBJECT = 1 << 0,
+ /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
+ T_EDIT = 1 << 1,
+ T_POSE = 1 << 2,
+ T_TEXTURE = 1 << 3,
+ /** Transforming the camera while in camera view. */
+ T_CAMERA = 1 << 4,
+ /** Transforming the 3D cursor. */
+ T_CURSOR = 1 << 5,
+ /** Transform points, having no rotation/scale. */
+ T_POINTS = 1 << 6,
+ /**
+ * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
+ * that happen to apply to specific modes (edit & pose for eg). */
+ T_LOCAL_MATRIX = 1 << 7,
+
+ /** restrictions flags */
+ T_NO_CONSTRAINT = 1 << 8,
+ T_NULL_ONE = 1 << 9,
+ T_NO_ZERO = 1 << 10,
+ T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
+
+ T_PROP_EDIT = 1 << 11,
+ T_PROP_CONNECTED = 1 << 12,
+ T_PROP_PROJECTED = 1 << 13,
+ T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
+
+ T_V3D_ALIGN = 1 << 14,
+ /** For 2d views like uv or fcurve. */
+ T_2D_EDIT = 1 << 15,
+ T_CLIP_UV = 1 << 16,
+
+ /** Auto-ik is on. */
+ T_AUTOIK = 1 << 18,
+
+ /** Don't use mirror even if the data-block option is set. */
+ T_NO_MIRROR = 1 << 19,
+
+ T_AUTOVALUES = 1 << 20,
+
+ /** To specify if we save back settings at the end. */
+ T_MODAL = 1 << 21,
+
+ /** No retopo. */
+ T_NO_PROJECT = 1 << 22,
+
+ T_RELEASE_CONFIRM = 1 << 23,
+
+ /** Alternative transformation. used to add offset to tracking markers. */
+ T_ALT_TRANSFORM = 1 << 24,
+
+ /** #TransInfo.center has been set, don't change it. */
+ T_OVERRIDE_CENTER = 1 << 25,
+
+ T_MODAL_CURSOR_SET = 1 << 26,
+
+ T_CLNOR_REBUILD = 1 << 27,
};
/** #TransInfo.modifiers */
enum {
- MOD_CONSTRAINT_SELECT = 1 << 0,
- MOD_PRECISION = 1 << 1,
- MOD_SNAP = 1 << 2,
- MOD_SNAP_INVERT = 1 << 3,
- MOD_CONSTRAINT_PLANE = 1 << 4,
+ MOD_CONSTRAINT_SELECT = 1 << 0,
+ MOD_PRECISION = 1 << 1,
+ MOD_SNAP = 1 << 2,
+ MOD_SNAP_INVERT = 1 << 3,
+ MOD_CONSTRAINT_PLANE = 1 << 4,
};
/* use node center for transform instead of upper-left corner.
@@ -767,87 +777,90 @@ enum {
*/
// #define USE_NODE_CENTER
-
/* ******************************************************************************** */
/** #TransInfo.helpline */
enum {
- HLP_NONE = 0,
- HLP_SPRING = 1,
- HLP_ANGLE = 2,
- HLP_HARROW = 3,
- HLP_VARROW = 4,
- HLP_CARROW = 5,
- HLP_TRACKBALL = 6,
+ HLP_NONE = 0,
+ HLP_SPRING = 1,
+ HLP_ANGLE = 2,
+ HLP_HARROW = 3,
+ HLP_VARROW = 4,
+ HLP_CARROW = 5,
+ HLP_TRACKBALL = 6,
};
/** #TransCon.mode, #TransInfo.con.mode */
enum {
- /** When set constraints are in use. */
- CON_APPLY = 1 << 0,
- /** These are only used for modal execution. */
- CON_AXIS0 = 1 << 1,
- CON_AXIS1 = 1 << 2,
- CON_AXIS2 = 1 << 3,
- CON_SELECT = 1 << 4,
- /** Does not reorient vector to face viewport when on. */
- CON_NOFLIP = 1 << 5,
- CON_USER = 1 << 6,
+ /** When set constraints are in use. */
+ CON_APPLY = 1 << 0,
+ /** These are only used for modal execution. */
+ CON_AXIS0 = 1 << 1,
+ CON_AXIS1 = 1 << 2,
+ CON_AXIS2 = 1 << 3,
+ CON_SELECT = 1 << 4,
+ /** Does not reorient vector to face viewport when on. */
+ CON_NOFLIP = 1 << 5,
+ CON_USER = 1 << 6,
};
/** #TransData.flag */
enum {
- TD_SELECTED = 1 << 0,
- TD_NOACTION = 1 << 2,
- TD_USEQUAT = 1 << 3,
- TD_NOTCONNECTED = 1 << 4,
- /** Used for scaling of #MetaElem.rad */
- TD_SINGLESIZE = 1 << 5,
- /** Scale relative to individual element center */
- TD_INDIVIDUAL_SCALE = 1 << 8,
- TD_NOCENTER = 1 << 9,
- /** #TransData.ext abused for particle key timing. */
- TD_NO_EXT = 1 << 10,
- /** don't transform this data */
- TD_SKIP = 1 << 11,
- /** if this is a bez triple, we need to restore the handles,
- * if this is set #TransData.hdata needs freeing */
- TD_BEZTRIPLE = 1 << 12,
- /** when this is set, don't apply translation changes to this element */
- TD_NO_LOC = 1 << 13,
- /** for Graph Editor autosnap, indicates that point should not undergo autosnapping */
- TD_NOTIMESNAP = 1 << 14,
- /** for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
- TD_INTVALUES = 1 << 15,
- /** For editmode mirror, clamp to x = 0 */
- TD_MIRROR_EDGE = 1 << 16,
- /** For fcurve handles, move them along with their keyframes */
- TD_MOVEHANDLE1 = 1 << 17,
- TD_MOVEHANDLE2 = 1 << 18,
- /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
- * option enabled and rotating also transforms it. */
- TD_PBONE_LOCAL_MTX_P = 1 << 19,
- /** Same as above but for a child bone. */
- TD_PBONE_LOCAL_MTX_C = 1 << 20,
+ TD_SELECTED = 1 << 0,
+ TD_NOACTION = 1 << 2,
+ TD_USEQUAT = 1 << 3,
+ TD_NOTCONNECTED = 1 << 4,
+ /** Used for scaling of #MetaElem.rad */
+ TD_SINGLESIZE = 1 << 5,
+ /** Scale relative to individual element center */
+ TD_INDIVIDUAL_SCALE = 1 << 8,
+ TD_NOCENTER = 1 << 9,
+ /** #TransData.ext abused for particle key timing. */
+ TD_NO_EXT = 1 << 10,
+ /** don't transform this data */
+ TD_SKIP = 1 << 11,
+ /** if this is a bez triple, we need to restore the handles,
+ * if this is set #TransData.hdata needs freeing */
+ TD_BEZTRIPLE = 1 << 12,
+ /** when this is set, don't apply translation changes to this element */
+ TD_NO_LOC = 1 << 13,
+ /** for Graph Editor autosnap, indicates that point should not undergo autosnapping */
+ TD_NOTIMESNAP = 1 << 14,
+ /** for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
+ TD_INTVALUES = 1 << 15,
+ /** For editmode mirror, clamp to x = 0 */
+ TD_MIRROR_EDGE = 1 << 16,
+ /** For fcurve handles, move them along with their keyframes */
+ TD_MOVEHANDLE1 = 1 << 17,
+ TD_MOVEHANDLE2 = 1 << 18,
+ /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
+ * option enabled and rotating also transforms it. */
+ TD_PBONE_LOCAL_MTX_P = 1 << 19,
+ /** Same as above but for a child bone. */
+ TD_PBONE_LOCAL_MTX_C = 1 << 20,
};
/** #TransSnap.status */
enum {
- SNAP_FORCED = 1 << 0,
- TARGET_INIT = 1 << 1,
- POINT_INIT = 1 << 2,
- MULTI_POINTS = 1 << 3,
+ SNAP_FORCED = 1 << 0,
+ TARGET_INIT = 1 << 1,
+ POINT_INIT = 1 << 2,
+ MULTI_POINTS = 1 << 3,
};
/* Hard min/max for proportional size. */
#define T_PROP_SIZE_MIN 1e-6f
#define T_PROP_SIZE_MAX 1e12f
-bool initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode);
+bool initTransform(struct bContext *C,
+ struct TransInfo *t,
+ struct wmOperator *op,
+ const struct wmEvent *event,
+ int mode);
void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
-int transformEvent(TransInfo *t, const struct wmEvent *event);
+int transformEvent(TransInfo *t, const struct wmEvent *event);
void transformApply(struct bContext *C, TransInfo *t);
-int transformEnd(struct bContext *C, TransInfo *t);
+int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
@@ -864,7 +877,6 @@ void drawPropCircle(const struct bContext *C, TransInfo *t);
struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
-
/*********************** transform_conversions.c ********** */
void flushTransIntFrameActionData(TransInfo *t);
@@ -893,18 +905,24 @@ void drawDial3d(const TransInfo *t);
void createTransData(struct bContext *C, TransInfo *t);
void sort_trans_data_dist(TransInfo *t);
void special_aftertrans_update(struct bContext *C, TransInfo *t);
-int special_transform_moving(TransInfo *t);
+int special_transform_moving(TransInfo *t);
void transform_autoik_update(TransInfo *t, short mode);
bool transdata_check_local_islands(TransInfo *t, short around);
-int count_set_pose_transflags(struct Object *ob, const int mode, const short around, bool has_translate_rotate[2]);
+int count_set_pose_transflags(struct Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2]);
/* Auto-keyframe applied after transform, returns true if motion paths need to be updated. */
-void autokeyframe_object(
- struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, int tmode);
+void autokeyframe_object(struct bContext *C,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct Object *ob,
+ int tmode);
void autokeyframe_pose(
- struct bContext *C, struct Scene *scene, struct Object *ob, int tmode, short targetless_ik);
+ struct bContext *C, struct Scene *scene, struct Object *ob, int tmode, short targetless_ik);
/* Test if we need to update motion paths for a given object. */
bool motionpath_need_update_object(struct Scene *scene, struct Object *ob);
@@ -923,8 +941,8 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char tex
void constraintNumInput(TransInfo *t, float vec[3]);
bool isLockConstraint(TransInfo *t);
-int getConstraintSpaceDimension(TransInfo *t);
-int constraintModeToIndex(const TransInfo *t);
+int getConstraintSpaceDimension(TransInfo *t);
+int constraintModeToIndex(const TransInfo *t);
char constraintModeToChar(const TransInfo *t);
void startConstraint(TransInfo *t);
@@ -939,9 +957,9 @@ void setNearestAxis(TransInfo *t);
/*********************** Snapping ********************************/
typedef enum {
- NO_GEARS = 0,
- BIG_GEARS = 1,
- SMALL_GEARS = 2,
+ NO_GEARS = 0,
+ BIG_GEARS = 1,
+ SMALL_GEARS = 2,
} GearsType;
bool transformModeUseSnap(const TransInfo *t);
@@ -973,35 +991,47 @@ void removeSnapPoint(TransInfo *t);
/********************** Mouse Input ******************************/
typedef enum {
- INPUT_NONE,
- INPUT_VECTOR,
- INPUT_SPRING,
- INPUT_SPRING_FLIP,
- INPUT_SPRING_DELTA,
- INPUT_ANGLE,
- INPUT_ANGLE_SPRING,
- INPUT_TRACKBALL,
- INPUT_HORIZONTAL_RATIO,
- INPUT_HORIZONTAL_ABSOLUTE,
- INPUT_VERTICAL_RATIO,
- INPUT_VERTICAL_ABSOLUTE,
- INPUT_CUSTOM_RATIO,
- INPUT_CUSTOM_RATIO_FLIP,
+ INPUT_NONE,
+ INPUT_VECTOR,
+ INPUT_SPRING,
+ INPUT_SPRING_FLIP,
+ INPUT_SPRING_DELTA,
+ INPUT_ANGLE,
+ INPUT_ANGLE_SPRING,
+ INPUT_TRACKBALL,
+ INPUT_HORIZONTAL_RATIO,
+ INPUT_HORIZONTAL_ABSOLUTE,
+ INPUT_VERTICAL_RATIO,
+ INPUT_VERTICAL_ABSOLUTE,
+ INPUT_CUSTOM_RATIO,
+ INPUT_CUSTOM_RATIO_FLIP,
} MouseInputMode;
-void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
+void initMouseInput(
+ TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
-eRedrawFlag handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event);
-void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
+eRedrawFlag handleMouseInput(struct TransInfo *t,
+ struct MouseInput *mi,
+ const struct wmEvent *event);
+void applyMouseInput(struct TransInfo *t,
+ struct MouseInput *mi,
+ const int mval[2],
+ float output[3]);
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);
-void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
+void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
/*********************** Generics ********************************/
-void initTransDataContainers_FromObjectData(TransInfo *t, struct Object *obact, struct Object **objects, uint objects_len);
-void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
+void initTransDataContainers_FromObjectData(TransInfo *t,
+ struct Object *obact,
+ struct Object **objects,
+ uint objects_len);
+void initTransInfo(struct bContext *C,
+ TransInfo *t,
+ struct wmOperator *op,
+ const struct wmEvent *event);
void freeTransCustomDataForMode(TransInfo *t);
void postTrans(struct bContext *C, TransInfo *t);
void resetTransModal(TransInfo *t);
@@ -1010,7 +1040,7 @@ void resetTransRestrictions(TransInfo *t);
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options);
/* DRAWLINE options flags */
-#define DRAWLIGHT 1
+#define DRAWLIGHT 1
void applyTransObjects(TransInfo *t);
void restoreTransObjects(TransInfo *t);
@@ -1044,21 +1074,27 @@ void initTransformOrientation(struct bContext *C, TransInfo *t);
bool createSpaceNormal(float mat[3][3], const float normal[3]);
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]);
-struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3],
- const char *name, const bool overwrite);
-bool applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]);
+struct TransformOrientation *addMatrixSpace(struct bContext *C,
+ float mat[3][3],
+ const char *name,
+ const bool overwrite);
+bool applyTransformOrientation(const struct TransformOrientation *ts,
+ float r_mat[3][3],
+ char r_name[64]);
enum {
- ORIENTATION_NONE = 0,
- ORIENTATION_NORMAL = 1,
- ORIENTATION_VERT = 2,
- ORIENTATION_EDGE = 3,
- ORIENTATION_FACE = 4,
+ ORIENTATION_NONE = 0,
+ ORIENTATION_NORMAL = 1,
+ ORIENTATION_VERT = 2,
+ ORIENTATION_EDGE = 3,
+ ORIENTATION_FACE = 4,
};
-#define ORIENTATION_USE_PLANE(ty) \
- ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE)
+#define ORIENTATION_USE_PLANE(ty) ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE)
-int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around);
+int getTransformOrientation_ex(const struct bContext *C,
+ float normal[3],
+ float plane[3],
+ const short around);
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
@@ -1071,7 +1107,6 @@ void freeVertSlideTempFaces(VertSlideData *sld);
void freeVertSlideVerts(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
void projectVertSlideData(TransInfo *t, bool is_final);
-
/* TODO. transform_query.c */
bool checkUseAxisMatrix(TransInfo *t);
@@ -1082,16 +1117,19 @@ bool checkUseAxisMatrix(TransInfo *t);
#define TRANS_DATA_CONTAINER_FIRST_OK(t) (&(t)->data_container[0])
/* For cases we _know_ there is only one handle. */
-#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t) (BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
+#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t) \
+ (BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
#define FOREACH_TRANS_DATA_CONTAINER(t, th) \
- for (TransDataContainer *tc = t->data_container, *tc_end = t->data_container + t->data_container_len; \
- th != tc_end; \
- th++)
+ for (TransDataContainer *tc = t->data_container, \
+ *tc_end = t->data_container + t->data_container_len; \
+ th != tc_end; \
+ th++)
#define FOREACH_TRANS_DATA_CONTAINER_INDEX(t, th, i) \
- for (TransDataContainer *tc = ((i = 0), t->data_container), *tc_end = t->data_container + t->data_container_len; \
- th != tc_end; \
- th++, i++)
+ for (TransDataContainer *tc = ((i = 0), t->data_container), \
+ *tc_end = t->data_container + t->data_container_len; \
+ th != tc_end; \
+ th++, i++)
#endif
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 2e8a921c7d8..27d6e597931 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -59,213 +59,221 @@ static void drawObjectConstraint(TransInfo *t);
/* ************************** CONSTRAINTS ************************* */
static void constraintAutoValues(TransInfo *t, float vec[3])
{
- int mode = t->con.mode;
- if (mode & CON_APPLY) {
- float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
-
- if ((mode & CON_AXIS0) == 0) {
- vec[0] = nval;
- }
- if ((mode & CON_AXIS1) == 0) {
- vec[1] = nval;
- }
- if ((mode & CON_AXIS2) == 0) {
- vec[2] = nval;
- }
- }
+ int mode = t->con.mode;
+ if (mode & CON_APPLY) {
+ float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
+
+ if ((mode & CON_AXIS0) == 0) {
+ vec[0] = nval;
+ }
+ if ((mode & CON_AXIS1) == 0) {
+ vec[1] = nval;
+ }
+ if ((mode & CON_AXIS2) == 0) {
+ vec[2] = nval;
+ }
+ }
}
void constraintNumInput(TransInfo *t, float vec[3])
{
- int mode = t->con.mode;
- if (mode & CON_APPLY) {
- float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
-
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
- if (axis == (CON_AXIS0 | CON_AXIS1)) {
- /* vec[0] = vec[0]; */ /* same */
- /* vec[1] = vec[1]; */ /* same */
- vec[2] = nval;
- }
- else if (axis == (CON_AXIS1 | CON_AXIS2)) {
- vec[2] = vec[1];
- vec[1] = vec[0];
- vec[0] = nval;
- }
- else if (axis == (CON_AXIS0 | CON_AXIS2)) {
- /* vec[0] = vec[0]; */ /* same */
- vec[2] = vec[1];
- vec[1] = nval;
- }
- }
- else if (dims == 1) {
- if (mode & CON_AXIS0) {
- /* vec[0] = vec[0]; */ /* same */
- vec[1] = nval;
- vec[2] = nval;
- }
- else if (mode & CON_AXIS1) {
- vec[1] = vec[0];
- vec[0] = nval;
- vec[2] = nval;
- }
- else if (mode & CON_AXIS2) {
- vec[2] = vec[0];
- vec[0] = nval;
- vec[1] = nval;
- }
- }
- }
+ int mode = t->con.mode;
+ if (mode & CON_APPLY) {
+ float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;
+
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+ if (axis == (CON_AXIS0 | CON_AXIS1)) {
+ /* vec[0] = vec[0]; */ /* same */
+ /* vec[1] = vec[1]; */ /* same */
+ vec[2] = nval;
+ }
+ else if (axis == (CON_AXIS1 | CON_AXIS2)) {
+ vec[2] = vec[1];
+ vec[1] = vec[0];
+ vec[0] = nval;
+ }
+ else if (axis == (CON_AXIS0 | CON_AXIS2)) {
+ /* vec[0] = vec[0]; */ /* same */
+ vec[2] = vec[1];
+ vec[1] = nval;
+ }
+ }
+ else if (dims == 1) {
+ if (mode & CON_AXIS0) {
+ /* vec[0] = vec[0]; */ /* same */
+ vec[1] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS1) {
+ vec[1] = vec[0];
+ vec[0] = nval;
+ vec[2] = nval;
+ }
+ else if (mode & CON_AXIS2) {
+ vec[2] = vec[0];
+ vec[0] = nval;
+ vec[1] = nval;
+ }
+ }
+ }
}
static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
{
- int i = 0;
-
- mul_m3_v3(t->con.imtx, vec);
-
- snapGridIncrement(t, vec);
-
- if (t->flag & T_NULL_ONE) {
- if (!(t->con.mode & CON_AXIS0))
- vec[0] = 1.0f;
-
- if (!(t->con.mode & CON_AXIS1))
- vec[1] = 1.0f;
-
- if (!(t->con.mode & CON_AXIS2))
- vec[2] = 1.0f;
- }
-
- if (applyNumInput(&t->num, vec)) {
- constraintNumInput(t, vec);
- removeAspectRatio(t, vec);
- }
-
- /* autovalues is operator param, use that directly but not if snapping is forced */
- if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) {
- copy_v3_v3(vec, t->auto_values);
- constraintAutoValues(t, vec);
- /* inverse transformation at the end */
- }
-
- if (t->con.mode & CON_AXIS0) {
- pvec[i++] = vec[0];
- }
- if (t->con.mode & CON_AXIS1) {
- pvec[i++] = vec[1];
- }
- if (t->con.mode & CON_AXIS2) {
- pvec[i++] = vec[2];
- }
-
- mul_m3_v3(t->con.mtx, vec);
+ int i = 0;
+
+ mul_m3_v3(t->con.imtx, vec);
+
+ snapGridIncrement(t, vec);
+
+ if (t->flag & T_NULL_ONE) {
+ if (!(t->con.mode & CON_AXIS0))
+ vec[0] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS1))
+ vec[1] = 1.0f;
+
+ if (!(t->con.mode & CON_AXIS2))
+ vec[2] = 1.0f;
+ }
+
+ if (applyNumInput(&t->num, vec)) {
+ constraintNumInput(t, vec);
+ removeAspectRatio(t, vec);
+ }
+
+ /* autovalues is operator param, use that directly but not if snapping is forced */
+ if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) {
+ copy_v3_v3(vec, t->auto_values);
+ constraintAutoValues(t, vec);
+ /* inverse transformation at the end */
+ }
+
+ if (t->con.mode & CON_AXIS0) {
+ pvec[i++] = vec[0];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ pvec[i++] = vec[1];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ pvec[i++] = vec[2];
+ }
+
+ mul_m3_v3(t->con.mtx, vec);
}
static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3])
{
- if (t->spacetype == SPACE_VIEW3D) {
- // View3D *v3d = t->sa->spacedata.first;
- const float min_dist = 1.0f; /* v3d->clip_start; */
- float dir[3];
- float l;
-
- sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
- if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
- negate_v3(dir);
- }
- project_v3_v3v3(dir, dir, t->viewinv[2]);
-
- l = len_v3(dir);
-
- if (l < min_dist) {
- float diff[3];
- normalize_v3_v3_length(diff, t->viewinv[2], min_dist - l);
- sub_v3_v3(t_con_center, diff);
- }
- }
+ if (t->spacetype == SPACE_VIEW3D) {
+ // View3D *v3d = t->sa->spacedata.first;
+ const float min_dist = 1.0f; /* v3d->clip_start; */
+ float dir[3];
+ float l;
+
+ sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
+ if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
+ negate_v3(dir);
+ }
+ project_v3_v3v3(dir, dir, t->viewinv[2]);
+
+ l = len_v3(dir);
+
+ if (l < min_dist) {
+ float diff[3];
+ normalize_v3_v3_length(diff, t->viewinv[2], min_dist - l);
+ sub_v3_v3(t_con_center, diff);
+ }
+ }
}
/**
* Axis calculation taking the view into account, correcting view-aligned axis.
*/
-static void axisProjection(const TransInfo *t, const float axis[3], const float in[3], float out[3])
+static void axisProjection(const TransInfo *t,
+ const float axis[3],
+ const float in[3],
+ float out[3])
{
- float norm[3], vec[3], factor, angle;
- float t_con_center[3];
-
- if (is_zero_v3(in)) {
- return;
- }
-
- copy_v3_v3(t_con_center, t->center_global);
-
- /* checks for center being too close to the view center */
- viewAxisCorrectCenter(t, t_con_center);
-
- angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
- if (angle > (float)M_PI_2) {
- angle = (float)M_PI - angle;
- }
-
- /* For when view is parallel to constraint... will cause NaNs otherwise
- * So we take vertical motion in 3D space and apply it to the
- * constraint axis. Nice for camera grab + MMB */
- if (angle < DEG2RADF(5.0f)) {
- project_v3_v3v3(vec, in, t->viewinv[1]);
- factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
- /* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
- if (factor < 0.0f) factor *= -factor;
- else factor *= factor;
-
- /* -factor makes move down going backwards */
- normalize_v3_v3_length(out, axis, -factor);
- }
- else {
- float v[3], i1[3], i2[3];
- float v2[3], v4[3];
- float norm_center[3];
- float plane[3];
-
- getViewVector(t, t_con_center, norm_center);
- cross_v3_v3v3(plane, norm_center, axis);
-
- project_v3_v3v3(vec, in, plane);
- sub_v3_v3v3(vec, in, vec);
-
- add_v3_v3v3(v, vec, t_con_center);
- getViewVector(t, v, norm);
-
- /* give arbitrary large value if projection is impossible */
- factor = dot_v3v3(axis, norm);
- if (1.0f - fabsf(factor) < 0.0002f) {
- copy_v3_v3(out, axis);
- if (factor > 0) {
- mul_v3_fl(out, 1000000000.0f);
- }
- else {
- mul_v3_fl(out, -1000000000.0f);
- }
- }
- else {
- add_v3_v3v3(v2, t_con_center, axis);
- add_v3_v3v3(v4, v, norm);
-
- isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
-
- sub_v3_v3v3(v, i2, v);
-
- sub_v3_v3v3(out, i1, t_con_center);
-
- /* possible some values become nan when
- * viewpoint and object are both zero */
- if (!isfinite(out[0])) out[0] = 0.0f;
- if (!isfinite(out[1])) out[1] = 0.0f;
- if (!isfinite(out[2])) out[2] = 0.0f;
- }
- }
+ float norm[3], vec[3], factor, angle;
+ float t_con_center[3];
+
+ if (is_zero_v3(in)) {
+ return;
+ }
+
+ copy_v3_v3(t_con_center, t->center_global);
+
+ /* checks for center being too close to the view center */
+ viewAxisCorrectCenter(t, t_con_center);
+
+ angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
+ if (angle > (float)M_PI_2) {
+ angle = (float)M_PI - angle;
+ }
+
+ /* For when view is parallel to constraint... will cause NaNs otherwise
+ * So we take vertical motion in 3D space and apply it to the
+ * constraint axis. Nice for camera grab + MMB */
+ if (angle < DEG2RADF(5.0f)) {
+ project_v3_v3v3(vec, in, t->viewinv[1]);
+ factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
+ /* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
+ if (factor < 0.0f)
+ factor *= -factor;
+ else
+ factor *= factor;
+
+ /* -factor makes move down going backwards */
+ normalize_v3_v3_length(out, axis, -factor);
+ }
+ else {
+ float v[3], i1[3], i2[3];
+ float v2[3], v4[3];
+ float norm_center[3];
+ float plane[3];
+
+ getViewVector(t, t_con_center, norm_center);
+ cross_v3_v3v3(plane, norm_center, axis);
+
+ project_v3_v3v3(vec, in, plane);
+ sub_v3_v3v3(vec, in, vec);
+
+ add_v3_v3v3(v, vec, t_con_center);
+ getViewVector(t, v, norm);
+
+ /* give arbitrary large value if projection is impossible */
+ factor = dot_v3v3(axis, norm);
+ if (1.0f - fabsf(factor) < 0.0002f) {
+ copy_v3_v3(out, axis);
+ if (factor > 0) {
+ mul_v3_fl(out, 1000000000.0f);
+ }
+ else {
+ mul_v3_fl(out, -1000000000.0f);
+ }
+ }
+ else {
+ add_v3_v3v3(v2, t_con_center, axis);
+ add_v3_v3v3(v4, v, norm);
+
+ isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
+
+ sub_v3_v3v3(v, i2, v);
+
+ sub_v3_v3v3(out, i1, t_con_center);
+
+ /* possible some values become nan when
+ * viewpoint and object are both zero */
+ if (!isfinite(out[0]))
+ out[0] = 0.0f;
+ if (!isfinite(out[1]))
+ out[1] = 0.0f;
+ if (!isfinite(out[2]))
+ out[2] = 0.0f;
+ }
+ }
}
/**
@@ -274,49 +282,49 @@ static void axisProjection(const TransInfo *t, const float axis[3], const float
*/
static bool isPlaneProjectionViewAligned(const TransInfo *t)
{
- const float eps = 0.001f;
- const float *constraint_vector[2];
- int n = 0;
- for (int i = 0; i < 3; i++) {
- if (t->con.mode & (CON_AXIS0 << i)) {
- constraint_vector[n++] = t->con.mtx[i];
- if (n == 2) {
- break;
- }
- }
- }
- BLI_assert(n == 2);
-
- float view_to_plane[3], plane_normal[3];
-
- getViewVector(t, t->center_global, view_to_plane);
-
- cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]);
- normalize_v3(plane_normal);
-
- float factor = dot_v3v3(plane_normal, view_to_plane);
- return fabsf(factor) < eps;
+ const float eps = 0.001f;
+ const float *constraint_vector[2];
+ int n = 0;
+ for (int i = 0; i < 3; i++) {
+ if (t->con.mode & (CON_AXIS0 << i)) {
+ constraint_vector[n++] = t->con.mtx[i];
+ if (n == 2) {
+ break;
+ }
+ }
+ }
+ BLI_assert(n == 2);
+
+ float view_to_plane[3], plane_normal[3];
+
+ getViewVector(t, t->center_global, view_to_plane);
+
+ cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]);
+ normalize_v3(plane_normal);
+
+ float factor = dot_v3v3(plane_normal, view_to_plane);
+ return fabsf(factor) < eps;
}
static void planeProjection(const TransInfo *t, const float in[3], float out[3])
{
- float vec[3], factor, norm[3];
+ float vec[3], factor, norm[3];
- add_v3_v3v3(vec, in, t->center_global);
- getViewVector(t, vec, norm);
+ add_v3_v3v3(vec, in, t->center_global);
+ getViewVector(t, vec, norm);
- sub_v3_v3v3(vec, out, in);
+ sub_v3_v3v3(vec, out, in);
- factor = dot_v3v3(vec, norm);
- if (fabsf(factor) <= 0.001f) {
- return; /* prevent divide by zero */
- }
- factor = dot_v3v3(vec, vec) / factor;
+ factor = dot_v3v3(vec, norm);
+ if (fabsf(factor) <= 0.001f) {
+ return; /* prevent divide by zero */
+ }
+ factor = dot_v3v3(vec, vec) / factor;
- copy_v3_v3(vec, norm);
- mul_v3_fl(vec, factor);
+ copy_v3_v3(vec, norm);
+ mul_v3_fl(vec, factor);
- add_v3_v3v3(out, in, vec);
+ add_v3_v3v3(out, in, vec);
}
/*
@@ -327,40 +335,44 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3])
* (in perspective mode, the view vector is relative to the position on screen)
*/
-static void applyAxisConstraintVec(
- TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3], float pvec[3])
+static void applyAxisConstraintVec(TransInfo *t,
+ TransDataContainer *UNUSED(tc),
+ TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3])
{
- copy_v3_v3(out, in);
- if (!td && t->con.mode & CON_APPLY) {
- mul_m3_v3(t->con.pmtx, out);
-
- // With snap, a projection is alright, no need to correct for view alignment
- if (!validSnap(t)) {
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
- }
- }
- }
- else if (dims == 1) {
- float c[3];
-
- if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
- }
- else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
- }
- else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
- }
- axisProjection(t, c, in, out);
- }
- }
- postConstraintChecks(t, out, pvec);
- }
+ copy_v3_v3(out, in);
+ if (!td && t->con.mode & CON_APPLY) {
+ mul_m3_v3(t->con.pmtx, out);
+
+ // With snap, a projection is alright, no need to correct for view alignment
+ if (!validSnap(t)) {
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ if (!is_zero_v3(out)) {
+ if (!isPlaneProjectionViewAligned(t)) {
+ planeProjection(t, in, out);
+ }
+ }
+ }
+ else if (dims == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ copy_v3_v3(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ copy_v3_v3(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ copy_v3_v3(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ }
+ postConstraintChecks(t, out, pvec);
+ }
}
/*
@@ -374,115 +386,123 @@ static void applyAxisConstraintVec(
* Further down, that vector is mapped to each data's space.
*/
-static void applyObjectConstraintVec(
- TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3], float pvec[3])
+static void applyObjectConstraintVec(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ const float in[3],
+ float out[3],
+ float pvec[3])
{
- copy_v3_v3(out, in);
- if (t->con.mode & CON_APPLY) {
- if (!td) {
- mul_m3_v3(t->con.pmtx, out);
-
- const int dims = getConstraintSpaceDimension(t);
- if (dims == 2) {
- if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
- }
- }
- }
- else if (dims == 1) {
- float c[3];
-
- if (t->con.mode & CON_AXIS0) {
- copy_v3_v3(c, t->con.mtx[0]);
- }
- else if (t->con.mode & CON_AXIS1) {
- copy_v3_v3(c, t->con.mtx[1]);
- }
- else if (t->con.mode & CON_AXIS2) {
- copy_v3_v3(c, t->con.mtx[2]);
- }
- axisProjection(t, c, in, out);
- }
- postConstraintChecks(t, out, pvec);
- copy_v3_v3(out, pvec);
- }
- else {
- int i = 0;
-
- out[0] = out[1] = out[2] = 0.0f;
- if (t->con.mode & CON_AXIS0) {
- out[0] = in[i++];
- }
- if (t->con.mode & CON_AXIS1) {
- out[1] = in[i++];
- }
- if (t->con.mode & CON_AXIS2) {
- out[2] = in[i++];
- }
-
- mul_m3_v3(td->axismtx, out);
- if (t->flag & T_EDIT) {
- mul_m3_v3(tc->mat3_unit, out);
- }
- }
- }
+ copy_v3_v3(out, in);
+ if (t->con.mode & CON_APPLY) {
+ if (!td) {
+ mul_m3_v3(t->con.pmtx, out);
+
+ const int dims = getConstraintSpaceDimension(t);
+ if (dims == 2) {
+ if (!is_zero_v3(out)) {
+ if (!isPlaneProjectionViewAligned(t)) {
+ planeProjection(t, in, out);
+ }
+ }
+ }
+ else if (dims == 1) {
+ float c[3];
+
+ if (t->con.mode & CON_AXIS0) {
+ copy_v3_v3(c, t->con.mtx[0]);
+ }
+ else if (t->con.mode & CON_AXIS1) {
+ copy_v3_v3(c, t->con.mtx[1]);
+ }
+ else if (t->con.mode & CON_AXIS2) {
+ copy_v3_v3(c, t->con.mtx[2]);
+ }
+ axisProjection(t, c, in, out);
+ }
+ postConstraintChecks(t, out, pvec);
+ copy_v3_v3(out, pvec);
+ }
+ else {
+ int i = 0;
+
+ out[0] = out[1] = out[2] = 0.0f;
+ if (t->con.mode & CON_AXIS0) {
+ out[0] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS1) {
+ out[1] = in[i++];
+ }
+ if (t->con.mode & CON_AXIS2) {
+ out[2] = in[i++];
+ }
+
+ mul_m3_v3(td->axismtx, out);
+ if (t->flag & T_EDIT) {
+ mul_m3_v3(tc->mat3_unit, out);
+ }
+ }
+ }
}
/*
* Generic callback for constant spatial constraints applied to resize motion
*/
-static void applyAxisConstraintSize(
- TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float smat[3][3])
+static void applyAxisConstraintSize(TransInfo *t,
+ TransDataContainer *UNUSED(tc),
+ TransData *td,
+ float smat[3][3])
{
- if (!td && t->con.mode & CON_APPLY) {
- float tmat[3][3];
-
- if (!(t->con.mode & CON_AXIS0)) {
- smat[0][0] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS1)) {
- smat[1][1] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS2)) {
- smat[2][2] = 1.0f;
- }
-
- mul_m3_m3m3(tmat, smat, t->con.imtx);
- mul_m3_m3m3(smat, t->con.mtx, tmat);
- }
+ if (!td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ mul_m3_m3m3(tmat, smat, t->con.imtx);
+ mul_m3_m3m3(smat, t->con.mtx, tmat);
+ }
}
/*
* Callback for object based spatial constraints applied to resize motion
*/
-static void applyObjectConstraintSize(
- TransInfo *t, TransDataContainer *tc, TransData *td, float smat[3][3])
+static void applyObjectConstraintSize(TransInfo *t,
+ TransDataContainer *tc,
+ TransData *td,
+ float smat[3][3])
{
- if (td && t->con.mode & CON_APPLY) {
- float tmat[3][3];
- float imat[3][3];
-
- invert_m3_m3(imat, td->axismtx);
-
- if (!(t->con.mode & CON_AXIS0)) {
- smat[0][0] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS1)) {
- smat[1][1] = 1.0f;
- }
- if (!(t->con.mode & CON_AXIS2)) {
- smat[2][2] = 1.0f;
- }
-
- mul_m3_m3m3(tmat, smat, imat);
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(smat, tc->mat3_unit, smat);
- }
- mul_m3_m3m3(smat, td->axismtx, tmat);
- }
+ if (td && t->con.mode & CON_APPLY) {
+ float tmat[3][3];
+ float imat[3][3];
+
+ invert_m3_m3(imat, td->axismtx);
+
+ if (!(t->con.mode & CON_AXIS0)) {
+ smat[0][0] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS1)) {
+ smat[1][1] = 1.0f;
+ }
+ if (!(t->con.mode & CON_AXIS2)) {
+ smat[2][2] = 1.0f;
+ }
+
+ mul_m3_m3m3(tmat, smat, imat);
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(smat, tc->mat3_unit, smat);
+ }
+ mul_m3_m3m3(smat, td->axismtx, tmat);
+ }
}
/*
@@ -499,32 +519,33 @@ static void applyObjectConstraintSize(
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
*/
-static void applyAxisConstraintRot(TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle)
+static void applyAxisConstraintRot(
+ TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle)
{
- if (!td && t->con.mode & CON_APPLY) {
- int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
-
- switch (mode) {
- case CON_AXIS0:
- case (CON_AXIS1 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[0]);
- break;
- case CON_AXIS1:
- case (CON_AXIS0 | CON_AXIS2):
- copy_v3_v3(vec, t->con.mtx[1]);
- break;
- case CON_AXIS2:
- case (CON_AXIS0 | CON_AXIS1):
- copy_v3_v3(vec, t->con.mtx[2]);
- break;
- }
- /* don't flip axis if asked to or if num input */
- if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
- if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
- *angle = -(*angle);
- }
- }
- }
+ if (!td && t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+
+ switch (mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1 | CON_AXIS2):
+ copy_v3_v3(vec, t->con.mtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0 | CON_AXIS2):
+ copy_v3_v3(vec, t->con.mtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0 | CON_AXIS1):
+ copy_v3_v3(vec, t->con.mtx[2]);
+ break;
+ }
+ /* don't flip axis if asked to or if num input */
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
}
/*
@@ -542,110 +563,110 @@ static void applyAxisConstraintRot(TransInfo *t, TransDataContainer *UNUSED(tc),
*/
static void applyObjectConstraintRot(
- TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle)
+ TransInfo *t, TransDataContainer *tc, TransData *td, float vec[3], float *angle)
{
- if (t->con.mode & CON_APPLY) {
- int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
- float tmp_axismtx[3][3];
- float (*axismtx)[3];
-
- /* on setup call, use first object */
- if (td == NULL) {
- BLI_assert(tc == NULL);
- tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
- td = tc->data;
- }
-
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
- axismtx = tmp_axismtx;
- }
- else {
- axismtx = td->axismtx;
- }
-
- switch (mode) {
- case CON_AXIS0:
- case (CON_AXIS1 | CON_AXIS2):
- copy_v3_v3(vec, axismtx[0]);
- break;
- case CON_AXIS1:
- case (CON_AXIS0 | CON_AXIS2):
- copy_v3_v3(vec, axismtx[1]);
- break;
- case CON_AXIS2:
- case (CON_AXIS0 | CON_AXIS1):
- copy_v3_v3(vec, axismtx[2]);
- break;
- }
- if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
- if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
- *angle = -(*angle);
- }
- }
- }
+ if (t->con.mode & CON_APPLY) {
+ int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
+ float tmp_axismtx[3][3];
+ float(*axismtx)[3];
+
+ /* on setup call, use first object */
+ if (td == NULL) {
+ BLI_assert(tc == NULL);
+ tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ td = tc->data;
+ }
+
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
+ axismtx = tmp_axismtx;
+ }
+ else {
+ axismtx = td->axismtx;
+ }
+
+ switch (mode) {
+ case CON_AXIS0:
+ case (CON_AXIS1 | CON_AXIS2):
+ copy_v3_v3(vec, axismtx[0]);
+ break;
+ case CON_AXIS1:
+ case (CON_AXIS0 | CON_AXIS2):
+ copy_v3_v3(vec, axismtx[1]);
+ break;
+ case CON_AXIS2:
+ case (CON_AXIS0 | CON_AXIS1):
+ copy_v3_v3(vec, axismtx[2]);
+ break;
+ }
+ if (angle && (mode & CON_NOFLIP) == 0 && hasNumInput(&t->num) == 0) {
+ if (dot_v3v3(vec, t->viewinv[2]) > 0.0f) {
+ *angle = -(*angle);
+ }
+ }
+ }
}
/*--------------------- INTERNAL SETUP CALLS ------------------*/
void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
{
- BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- copy_m3_m3(t->con.mtx, space);
- t->con.mode = mode;
- getConstraintMatrix(t);
-
- startConstraint(t);
-
- t->con.drawExtra = NULL;
- t->con.applyVec = applyAxisConstraintVec;
- t->con.applySize = applyAxisConstraintSize;
- t->con.applyRot = applyAxisConstraintRot;
- t->redraw = TREDRAW_HARD;
+ BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
+ copy_m3_m3(t->con.mtx, space);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
+ t->redraw = TREDRAW_HARD;
}
/* applies individual td->axismtx constraints */
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
{
- TransDataContainer *tc = t->data_container;
- if (t->data_len_all == 1) {
- float axismtx[3][3];
- if (t->flag & T_EDIT) {
- mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx);
- }
- else {
- copy_m3_m3(axismtx, tc->data->axismtx);
- }
-
- setConstraint(t, axismtx, mode, text);
- }
- else {
- BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
- copy_m3_m3(t->con.mtx, tc->data->axismtx);
- t->con.mode = mode;
- getConstraintMatrix(t);
-
- startConstraint(t);
-
- t->con.drawExtra = drawObjectConstraint;
- t->con.applyVec = applyObjectConstraintVec;
- t->con.applySize = applyObjectConstraintSize;
- t->con.applyRot = applyObjectConstraintRot;
- t->redraw = TREDRAW_HARD;
- }
+ TransDataContainer *tc = t->data_container;
+ if (t->data_len_all == 1) {
+ float axismtx[3][3];
+ if (t->flag & T_EDIT) {
+ mul_m3_m3m3(axismtx, tc->mat3_unit, tc->data->axismtx);
+ }
+ else {
+ copy_m3_m3(axismtx, tc->data->axismtx);
+ }
+
+ setConstraint(t, axismtx, mode, text);
+ }
+ else {
+ BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
+ copy_m3_m3(t->con.mtx, tc->data->axismtx);
+ t->con.mode = mode;
+ getConstraintMatrix(t);
+
+ startConstraint(t);
+
+ t->con.drawExtra = drawObjectConstraint;
+ t->con.applyVec = applyObjectConstraintVec;
+ t->con.applySize = applyObjectConstraintSize;
+ t->con.applyRot = applyObjectConstraintRot;
+ t->redraw = TREDRAW_HARD;
+ }
}
void setLocalConstraint(TransInfo *t, int mode, const char text[])
{
- /* edit-mode now allows local transforms too */
- if (t->flag & T_EDIT) {
- /* Use the active (first) edit object. */
- TransDataContainer *tc = t->data_container;
- setConstraint(t, tc->mat3_unit, mode, text);
- }
- else {
- setAxisMatrixConstraint(t, mode, text);
- }
+ /* edit-mode now allows local transforms too */
+ if (t->flag & T_EDIT) {
+ /* Use the active (first) edit object. */
+ TransDataContainer *tc = t->data_container;
+ setConstraint(t, tc->mat3_unit, mode, text);
+ }
+ else {
+ setAxisMatrixConstraint(t, mode, text);
+ }
}
/*
@@ -656,486 +677,489 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
*/
void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[])
{
- char text[256];
-
- switch (orientation) {
- case V3D_ORIENT_GLOBAL:
- {
- float mtx[3][3];
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("global"));
- unit_m3(mtx);
- setConstraint(t, mtx, mode, text);
- break;
- }
- case V3D_ORIENT_LOCAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("local"));
- setLocalConstraint(t, mode, text);
- break;
- case V3D_ORIENT_NORMAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal"));
- if (checkUseAxisMatrix(t)) {
- setAxisMatrixConstraint(t, mode, text);
- }
- else {
- setConstraint(t, t->spacemtx, mode, text);
- }
- break;
- case V3D_ORIENT_VIEW:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("view"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CURSOR:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("cursor"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_GIMBAL:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CUSTOM_MATRIX:
- BLI_snprintf(text, sizeof(text), ftext, IFACE_("custom matrix"));
- setConstraint(t, t->spacemtx, mode, text);
- break;
- case V3D_ORIENT_CUSTOM:
- {
- char orientation_str[128];
- BLI_snprintf(orientation_str, sizeof(orientation_str), "%s \"%s\"",
- IFACE_("custom orientation"), t->orientation.custom->name);
- BLI_snprintf(text, sizeof(text), ftext, orientation_str);
- setConstraint(t, t->spacemtx, mode, text);
- break;
- }
- }
-
- t->con.orientation = orientation;
-
- t->con.mode |= CON_USER;
+ char text[256];
+
+ switch (orientation) {
+ case V3D_ORIENT_GLOBAL: {
+ float mtx[3][3];
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("global"));
+ unit_m3(mtx);
+ setConstraint(t, mtx, mode, text);
+ break;
+ }
+ case V3D_ORIENT_LOCAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("local"));
+ setLocalConstraint(t, mode, text);
+ break;
+ case V3D_ORIENT_NORMAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal"));
+ if (checkUseAxisMatrix(t)) {
+ setAxisMatrixConstraint(t, mode, text);
+ }
+ else {
+ setConstraint(t, t->spacemtx, mode, text);
+ }
+ break;
+ case V3D_ORIENT_VIEW:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("view"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CURSOR:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("cursor"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_GIMBAL:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CUSTOM_MATRIX:
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("custom matrix"));
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ case V3D_ORIENT_CUSTOM: {
+ char orientation_str[128];
+ BLI_snprintf(orientation_str,
+ sizeof(orientation_str),
+ "%s \"%s\"",
+ IFACE_("custom orientation"),
+ t->orientation.custom->name);
+ BLI_snprintf(text, sizeof(text), ftext, orientation_str);
+ setConstraint(t, t->spacemtx, mode, text);
+ break;
+ }
+ }
+
+ t->con.orientation = orientation;
+
+ t->con.mode |= CON_USER;
}
/*----------------- DRAWING CONSTRAINTS -------------------*/
void drawConstraint(TransInfo *t)
{
- TransCon *tc = &(t->con);
-
- if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
- return;
- if (!(tc->mode & CON_APPLY))
- return;
- if (t->flag & T_NO_CONSTRAINT)
- return;
-
- if (tc->drawExtra) {
- tc->drawExtra(t);
- }
- else {
- if (tc->mode & CON_SELECT) {
- float vec[3];
- 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, t->center_global);
-
- 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);
-
- depth_test_enabled = GPU_depth_test_enabled();
- if (depth_test_enabled)
- GPU_depth_test(false);
-
- const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- immUniform1f("dash_width", 2.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(shdr_pos, t->center_global);
- immVertex3fv(shdr_pos, vec);
- immEnd();
-
- immUnbindProgram();
-
- if (depth_test_enabled)
- GPU_depth_test(true);
- }
-
- if (tc->mode & CON_AXIS0) {
- drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
- }
- if (tc->mode & CON_AXIS1) {
- drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
- }
- if (tc->mode & CON_AXIS2) {
- drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
- }
- }
+ TransCon *tc = &(t->con);
+
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
+ return;
+ if (!(tc->mode & CON_APPLY))
+ return;
+ if (t->flag & T_NO_CONSTRAINT)
+ return;
+
+ if (tc->drawExtra) {
+ tc->drawExtra(t);
+ }
+ else {
+ if (tc->mode & CON_SELECT) {
+ float vec[3];
+ 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, t->center_global);
+
+ 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);
+
+ depth_test_enabled = GPU_depth_test_enabled();
+ if (depth_test_enabled)
+ GPU_depth_test(false);
+
+ const uint shdr_pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 2.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, t->center_global);
+ immVertex3fv(shdr_pos, vec);
+ immEnd();
+
+ immUnbindProgram();
+
+ if (depth_test_enabled)
+ GPU_depth_test(true);
+ }
+
+ if (tc->mode & CON_AXIS0) {
+ drawLine(t, t->center_global, tc->mtx[0], 'X', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS1) {
+ drawLine(t, t->center_global, tc->mtx[1], 'Y', DRAWLIGHT);
+ }
+ if (tc->mode & CON_AXIS2) {
+ drawLine(t, t->center_global, tc->mtx[2], 'Z', DRAWLIGHT);
+ }
+ }
}
/* called from drawview.c, as an extra per-window draw option */
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];
- int depth_test_enabled;
-
- if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) {
- copy_m4_m4(tmat, rv3d->viewmat);
- invert_m4_m4(imat, tmat);
- }
- else {
- unit_m4(tmat);
- unit_m4(imat);
- }
-
- GPU_matrix_push();
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* pass */
- }
- else if (t->spacetype == SPACE_IMAGE) {
- GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
- }
- else if (ELEM(t->spacetype, SPACE_GRAPH, 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);
- GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask));
- }
-
- depth_test_enabled = GPU_depth_test_enabled();
- if (depth_test_enabled)
- GPU_depth_test(false);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor(TH_GRID);
-
- set_inverted_drawing(1);
- imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- set_inverted_drawing(0);
-
- immUnbindProgram();
-
- if (depth_test_enabled)
- GPU_depth_test(true);
-
- GPU_matrix_pop();
- }
+ if (t->flag & T_PROP_EDIT) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float tmat[4][4], imat[4][4];
+ int depth_test_enabled;
+
+ if (t->spacetype == SPACE_VIEW3D && rv3d != NULL) {
+ copy_m4_m4(tmat, rv3d->viewmat);
+ invert_m4_m4(imat, tmat);
+ }
+ else {
+ unit_m4(tmat);
+ unit_m4(imat);
+ }
+
+ GPU_matrix_push();
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
+ }
+ else if (ELEM(t->spacetype, SPACE_GRAPH, 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);
+ GPU_matrix_scale_2f(1.0f, (ysize / xsize) * (xmask / ymask));
+ }
+
+ depth_test_enabled = GPU_depth_test_enabled();
+ if (depth_test_enabled)
+ GPU_depth_test(false);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+
+ set_inverted_drawing(1);
+ imm_drawcircball(t->center_global, t->prop_size, imat, pos);
+ set_inverted_drawing(0);
+
+ immUnbindProgram();
+
+ if (depth_test_enabled)
+ GPU_depth_test(true);
+
+ GPU_matrix_pop();
+ }
}
static void drawObjectConstraint(TransInfo *t)
{
- /* Draw the first one lighter because that's the one who controls the others.
- * Meaning the transformation is projected on that one and just copied on the others
- * constraint space.
- * In a nutshell, the object with light axis is controlled by the user and the others follow.
- * Without drawing the first light, users have little clue what they are doing.
- */
- short options = DRAWLIGHT;
- int i;
- float tmp_axismtx[3][3];
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float co[3];
- float (*axismtx)[3];
-
- if (t->flag & T_PROP_EDIT) {
- /* we're sorted, so skip the rest */
- if (td->factor == 0.0f) {
- break;
- }
- }
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* only draw a constraint line for one point, otherwise we can't see anything */
- if ((options & DRAWLIGHT) == 0) {
- break;
- }
- }
-
- if (t->flag & T_OBJECT) {
- copy_v3_v3(co, td->ob->obmat[3]);
- axismtx = td->axismtx;
- }
- else if (t->flag & T_EDIT) {
- mul_v3_m4v3(co, tc->mat, td->center);
-
- mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
- axismtx = tmp_axismtx;
- }
- else if (t->flag & T_POSE) {
- mul_v3_m4v3(co, tc->mat, td->center);
- axismtx = td->axismtx;
- }
- else {
- copy_v3_v3(co, td->center);
- axismtx = td->axismtx;
- }
-
- if (t->con.mode & CON_AXIS0) {
- drawLine(t, co, axismtx[0], 'X', options);
- }
- if (t->con.mode & CON_AXIS1) {
- drawLine(t, co, axismtx[1], 'Y', options);
- }
- if (t->con.mode & CON_AXIS2) {
- drawLine(t, co, axismtx[2], 'Z', options);
- }
- options &= ~DRAWLIGHT;
- }
- }
+ /* Draw the first one lighter because that's the one who controls the others.
+ * Meaning the transformation is projected on that one and just copied on the others
+ * constraint space.
+ * In a nutshell, the object with light axis is controlled by the user and the others follow.
+ * Without drawing the first light, users have little clue what they are doing.
+ */
+ short options = DRAWLIGHT;
+ int i;
+ float tmp_axismtx[3][3];
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float co[3];
+ float(*axismtx)[3];
+
+ if (t->flag & T_PROP_EDIT) {
+ /* we're sorted, so skip the rest */
+ if (td->factor == 0.0f) {
+ break;
+ }
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* only draw a constraint line for one point, otherwise we can't see anything */
+ if ((options & DRAWLIGHT) == 0) {
+ break;
+ }
+ }
+
+ if (t->flag & T_OBJECT) {
+ copy_v3_v3(co, td->ob->obmat[3]);
+ axismtx = td->axismtx;
+ }
+ else if (t->flag & T_EDIT) {
+ mul_v3_m4v3(co, tc->mat, td->center);
+
+ mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
+ axismtx = tmp_axismtx;
+ }
+ else if (t->flag & T_POSE) {
+ mul_v3_m4v3(co, tc->mat, td->center);
+ axismtx = td->axismtx;
+ }
+ else {
+ copy_v3_v3(co, td->center);
+ axismtx = td->axismtx;
+ }
+
+ if (t->con.mode & CON_AXIS0) {
+ drawLine(t, co, axismtx[0], 'X', options);
+ }
+ if (t->con.mode & CON_AXIS1) {
+ drawLine(t, co, axismtx[1], 'Y', options);
+ }
+ if (t->con.mode & CON_AXIS2) {
+ drawLine(t, co, axismtx[2], 'Z', options);
+ }
+ options &= ~DRAWLIGHT;
+ }
+ }
}
/*--------------------- START / STOP CONSTRAINTS ---------------------- */
void startConstraint(TransInfo *t)
{
- t->con.mode |= CON_APPLY;
- *t->con.text = ' ';
- t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max);
+ t->con.mode |= CON_APPLY;
+ *t->con.text = ' ';
+ t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max);
}
void stopConstraint(TransInfo *t)
{
- t->con.mode &= ~(CON_APPLY | CON_SELECT);
- *t->con.text = '\0';
- t->num.idx_max = t->idx_max;
+ t->con.mode &= ~(CON_APPLY | CON_SELECT);
+ *t->con.text = '\0';
+ t->num.idx_max = t->idx_max;
}
void getConstraintMatrix(TransInfo *t)
{
- float mat[3][3];
- invert_m3_m3(t->con.imtx, t->con.mtx);
- unit_m3(t->con.pmtx);
+ float mat[3][3];
+ invert_m3_m3(t->con.imtx, t->con.mtx);
+ unit_m3(t->con.pmtx);
- if (!(t->con.mode & CON_AXIS0)) {
- zero_v3(t->con.pmtx[0]);
- }
+ if (!(t->con.mode & CON_AXIS0)) {
+ zero_v3(t->con.pmtx[0]);
+ }
- if (!(t->con.mode & CON_AXIS1)) {
- zero_v3(t->con.pmtx[1]);
- }
+ if (!(t->con.mode & CON_AXIS1)) {
+ zero_v3(t->con.pmtx[1]);
+ }
- if (!(t->con.mode & CON_AXIS2)) {
- zero_v3(t->con.pmtx[2]);
- }
+ if (!(t->con.mode & CON_AXIS2)) {
+ zero_v3(t->con.pmtx[2]);
+ }
- mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
- mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat);
+ mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
+ mul_m3_m3m3(t->con.pmtx, t->con.mtx, mat);
}
/*------------------------- MMB Select -------------------------------*/
void initSelectConstraint(TransInfo *t, float mtx[3][3])
{
- copy_m3_m3(t->con.mtx, mtx);
- t->con.mode |= CON_APPLY;
- t->con.mode |= CON_SELECT;
-
- setNearestAxis(t);
- t->con.drawExtra = NULL;
- t->con.applyVec = applyAxisConstraintVec;
- t->con.applySize = applyAxisConstraintSize;
- t->con.applyRot = applyAxisConstraintRot;
+ copy_m3_m3(t->con.mtx, mtx);
+ t->con.mode |= CON_APPLY;
+ t->con.mode |= CON_SELECT;
+
+ setNearestAxis(t);
+ t->con.drawExtra = NULL;
+ t->con.applyVec = applyAxisConstraintVec;
+ t->con.applySize = applyAxisConstraintSize;
+ t->con.applyRot = applyAxisConstraintRot;
}
void selectConstraint(TransInfo *t)
{
- if (t->con.mode & CON_SELECT) {
- setNearestAxis(t);
- startConstraint(t);
- }
+ if (t->con.mode & CON_SELECT) {
+ setNearestAxis(t);
+ startConstraint(t);
+ }
}
void postSelectConstraint(TransInfo *t)
{
- if (!(t->con.mode & CON_SELECT))
- return;
+ if (!(t->con.mode & CON_SELECT))
+ return;
- t->con.mode &= ~CON_AXIS0;
- t->con.mode &= ~CON_AXIS1;
- t->con.mode &= ~CON_AXIS2;
- t->con.mode &= ~CON_SELECT;
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+ t->con.mode &= ~CON_SELECT;
- setNearestAxis(t);
+ setNearestAxis(t);
- startConstraint(t);
- t->redraw = TREDRAW_HARD;
+ startConstraint(t);
+ t->redraw = TREDRAW_HARD;
}
static void setNearestAxis2d(TransInfo *t)
{
- /* no correction needed... just use whichever one is lower */
- if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1])) {
- t->con.mode |= CON_AXIS1;
- BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text));
- }
- else {
- t->con.mode |= CON_AXIS0;
- BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text));
- }
+ /* no correction needed... just use whichever one is lower */
+ if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1])) {
+ t->con.mode |= CON_AXIS1;
+ BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text));
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text));
+ }
}
static void setNearestAxis3d(TransInfo *t)
{
- float zfac;
- float mvec[3], proj[3];
- float len[3];
- int i;
-
- /* calculate mouse movement */
- mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
- mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
- mvec[2] = 0.0f;
-
- /* We need to correct axis length for the current zoom-level of view,
- * this to prevent projected values to be clipped behind the camera
- * and to overflow the short integers.
- * The formula used is a bit stupid, just a simplification of the subtraction
- * of two 2D points 30 pixels apart (that's the last factor in the formula) after
- * projecting them with ED_view3d_win_to_delta and then get the length of that vector.
- */
- zfac = mul_project_m4_v3_zfac(t->persmat, t->center_global);
- zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;
-
- for (i = 0; i < 3; i++) {
- float axis[3], axis_2d[2];
-
- copy_v3_v3(axis, t->con.mtx[i]);
-
- mul_v3_fl(axis, zfac);
- /* now we can project to get window coordinate */
- add_v3_v3(axis, t->center_global);
- projectFloatView(t, axis, axis_2d);
-
- sub_v2_v2v2(axis, axis_2d, t->center2d);
- axis[2] = 0.0f;
-
- if (normalize_v3(axis) > 1e-3f) {
- project_v3_v3v3(proj, mvec, axis);
- sub_v3_v3v3(axis, mvec, proj);
- len[i] = normalize_v3(axis);
- }
- else {
- len[i] = 1e10f;
- }
- }
-
- if (len[0] <= len[1] && len[0] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS1 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS0;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename);
- }
- }
- else if (len[1] <= len[0] && len[1] <= len[2]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS0 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS1;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename);
- }
- }
- else if (len[2] <= len[1] && len[2] <= len[0]) {
- if (t->modifiers & MOD_CONSTRAINT_PLANE) {
- t->con.mode |= (CON_AXIS0 | CON_AXIS1);
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename);
- }
- else {
- t->con.mode |= CON_AXIS2;
- BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename);
- }
- }
+ float zfac;
+ float mvec[3], proj[3];
+ float len[3];
+ int i;
+
+ /* calculate mouse movement */
+ mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
+ mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
+ mvec[2] = 0.0f;
+
+ /* We need to correct axis length for the current zoom-level of view,
+ * this to prevent projected values to be clipped behind the camera
+ * and to overflow the short integers.
+ * The formula used is a bit stupid, just a simplification of the subtraction
+ * of two 2D points 30 pixels apart (that's the last factor in the formula) after
+ * projecting them with ED_view3d_win_to_delta and then get the length of that vector.
+ */
+ zfac = mul_project_m4_v3_zfac(t->persmat, t->center_global);
+ zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;
+
+ for (i = 0; i < 3; i++) {
+ float axis[3], axis_2d[2];
+
+ copy_v3_v3(axis, t->con.mtx[i]);
+
+ mul_v3_fl(axis, zfac);
+ /* now we can project to get window coordinate */
+ add_v3_v3(axis, t->center_global);
+ projectFloatView(t, axis, axis_2d);
+
+ sub_v2_v2v2(axis, axis_2d, t->center2d);
+ axis[2] = 0.0f;
+
+ if (normalize_v3(axis) > 1e-3f) {
+ project_v3_v3v3(proj, mvec, axis);
+ sub_v3_v3v3(axis, mvec, proj);
+ len[i] = normalize_v3(axis);
+ }
+ else {
+ len[i] = 1e10f;
+ }
+ }
+
+ if (len[0] <= len[1] && len[0] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS1 | CON_AXIS2);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS0;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename);
+ }
+ }
+ else if (len[1] <= len[0] && len[1] <= len[2]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0 | CON_AXIS2);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS1;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename);
+ }
+ }
+ else if (len[2] <= len[1] && len[2] <= len[0]) {
+ if (t->modifiers & MOD_CONSTRAINT_PLANE) {
+ t->con.mode |= (CON_AXIS0 | CON_AXIS1);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename);
+ }
+ else {
+ t->con.mode |= CON_AXIS2;
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename);
+ }
+ }
}
void setNearestAxis(TransInfo *t)
{
- /* clear any prior constraint flags */
- t->con.mode &= ~CON_AXIS0;
- t->con.mode &= ~CON_AXIS1;
- t->con.mode &= ~CON_AXIS2;
-
- /* constraint setting - depends on spacetype */
- if (t->spacetype == SPACE_VIEW3D) {
- /* 3d-view */
- setNearestAxis3d(t);
- }
- else {
- /* assume that this means a 2D-Editor */
- setNearestAxis2d(t);
- }
-
- getConstraintMatrix(t);
+ /* clear any prior constraint flags */
+ t->con.mode &= ~CON_AXIS0;
+ t->con.mode &= ~CON_AXIS1;
+ t->con.mode &= ~CON_AXIS2;
+
+ /* constraint setting - depends on spacetype */
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* 3d-view */
+ setNearestAxis3d(t);
+ }
+ else {
+ /* assume that this means a 2D-Editor */
+ setNearestAxis2d(t);
+ }
+
+ getConstraintMatrix(t);
}
/*-------------- HELPER FUNCTIONS ----------------*/
int constraintModeToIndex(const TransInfo *t)
{
- if ((t->con.mode & CON_APPLY) == 0) {
- return -1;
- }
- switch (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
- case (CON_AXIS0):
- case (CON_AXIS1 | CON_AXIS2):
- return 0;
- case (CON_AXIS1):
- case (CON_AXIS0 | CON_AXIS2):
- return 1;
- case (CON_AXIS2):
- case (CON_AXIS0 | CON_AXIS1):
- return 2;
- default:
- return -1;
- }
+ if ((t->con.mode & CON_APPLY) == 0) {
+ return -1;
+ }
+ switch (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
+ case (CON_AXIS0):
+ case (CON_AXIS1 | CON_AXIS2):
+ return 0;
+ case (CON_AXIS1):
+ case (CON_AXIS0 | CON_AXIS2):
+ return 1;
+ case (CON_AXIS2):
+ case (CON_AXIS0 | CON_AXIS1):
+ return 2;
+ default:
+ return -1;
+ }
}
char constraintModeToChar(const TransInfo *t)
{
- int index = constraintModeToIndex(t);
- if (index == -1) {
- return '\0';
- }
- BLI_assert((uint)index < 3);
- return 'X' + index;
+ int index = constraintModeToIndex(t);
+ if (index == -1) {
+ return '\0';
+ }
+ BLI_assert((uint)index < 3);
+ return 'X' + index;
}
bool isLockConstraint(TransInfo *t)
{
- int mode = t->con.mode;
+ int mode = t->con.mode;
- if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
- return true;
+ if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1))
+ return true;
- if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
- return true;
+ if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2))
+ return true;
- if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
- return true;
+ if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2))
+ return true;
- return false;
+ return false;
}
/*
@@ -1148,19 +1172,19 @@ bool isLockConstraint(TransInfo *t)
int getConstraintSpaceDimension(TransInfo *t)
{
- int n = 0;
+ int n = 0;
- if (t->con.mode & CON_AXIS0)
- n++;
+ if (t->con.mode & CON_AXIS0)
+ n++;
- if (t->con.mode & CON_AXIS1)
- n++;
+ if (t->con.mode & CON_AXIS1)
+ n++;
- if (t->con.mode & CON_AXIS2)
- n++;
+ if (t->con.mode & CON_AXIS2)
+ n++;
- return n;
-/*
+ return n;
+ /*
* Someone willing to do it cryptically could do the following instead:
*
* return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 217dd194f57..b682617f348 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -102,7 +102,7 @@
#include "ED_mask.h"
#include "ED_gpencil.h"
-#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
+#include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
#include "WM_types.h"
#include "UI_view2d.h"
@@ -123,18 +123,17 @@
*/
static void transform_around_single_fallback(TransInfo *t)
{
- if ((t->data_len_all == 1) &&
- (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
- (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
- {
- t->around = V3D_AROUND_LOCAL_ORIGINS;
- }
+ if ((t->data_len_all == 1) &&
+ (ELEM(t->around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN, V3D_AROUND_ACTIVE)) &&
+ (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) {
+ t->around = V3D_AROUND_LOCAL_ORIGINS;
+ }
}
/* when transforming islands */
struct TransIslandData {
- float co[3];
- float axismtx[3][3];
+ float co[3];
+ float axismtx[3][3];
};
/* local function prototype - for Object/Bone Constraints */
@@ -144,151 +143,160 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list);
static int trans_data_compare_dist(const void *a, const void *b)
{
- const TransData *td_a = (const TransData *)a;
- const TransData *td_b = (const TransData *)b;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_a->dist < td_b->dist) return -1;
- else if (td_a->dist > td_b->dist) return 1;
- else return 0;
+ if (td_a->dist < td_b->dist)
+ return -1;
+ else if (td_a->dist > td_b->dist)
+ return 1;
+ else
+ return 0;
}
static int trans_data_compare_rdist(const void *a, const void *b)
{
- const TransData *td_a = (const TransData *)a;
- const TransData *td_b = (const TransData *)b;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_a->rdist < td_b->rdist) return -1;
- else if (td_a->rdist > td_b->rdist) return 1;
- else return 0;
+ if (td_a->rdist < td_b->rdist)
+ return -1;
+ else if (td_a->rdist > td_b->rdist)
+ return 1;
+ else
+ return 0;
}
static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
{
- TransData *start = tc->data;
- int i;
+ TransData *start = tc->data;
+ int i;
- for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
- start++;
- }
+ for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
+ start++;
+ }
- if (i < tc->data_len) {
- if (t->flag & T_PROP_CONNECTED) {
- qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
- }
- else {
- qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
- }
- }
+ if (i < tc->data_len) {
+ if (t->flag & T_PROP_CONNECTED) {
+ qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
+ }
+ else {
+ qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
+ }
+ }
}
void sort_trans_data_dist(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_dist_container(t, tc);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sort_trans_data_dist_container(t, tc);
+ }
}
static void sort_trans_data_container(TransDataContainer *tc)
{
- TransData *sel, *unsel;
- TransData temp;
- unsel = tc->data;
- sel = tc->data;
- sel += tc->data_len - 1;
- while (sel > unsel) {
- while (unsel->flag & TD_SELECTED) {
- unsel++;
- if (unsel == sel) {
- return;
- }
- }
- while (!(sel->flag & TD_SELECTED)) {
- sel--;
- if (unsel == sel) {
- return;
- }
- }
- temp = *unsel;
- *unsel = *sel;
- *sel = temp;
- sel--;
- unsel++;
- }
+ TransData *sel, *unsel;
+ TransData temp;
+ unsel = tc->data;
+ sel = tc->data;
+ sel += tc->data_len - 1;
+ while (sel > unsel) {
+ while (unsel->flag & TD_SELECTED) {
+ unsel++;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ while (!(sel->flag & TD_SELECTED)) {
+ sel--;
+ if (unsel == sel) {
+ return;
+ }
+ }
+ temp = *unsel;
+ *unsel = *sel;
+ *sel = temp;
+ sel--;
+ unsel++;
+ }
}
static void sort_trans_data(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_container(tc);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ sort_trans_data_container(tc);
+ }
}
/* distance calculated from not-selected vertex to nearest selected vertex
* warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
static void set_prop_dist(TransInfo *t, const bool with_dist)
{
- int a;
-
- float _proj_vec[3];
- const float *proj_vec = NULL;
-
- /* support for face-islands */
- const bool use_island = transdata_check_local_islands(t, t->around);
-
- if (t->flag & T_PROP_PROJECTED) {
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = t->ar->regiondata;
- normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
- proj_vec = _proj_vec;
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *tob = tc->data;
- for (a = 0; a < tc->data_len; a++, tob++) {
-
- tob->rdist = 0.0f; // init, it was mallocced
-
- if ((tob->flag & TD_SELECTED) == 0) {
- TransData *td;
- int i;
- float dist_sq, vec[3];
-
- tob->rdist = -1.0f; // signal for next loop
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SELECTED) {
- if (use_island) {
- sub_v3_v3v3(vec, tob->iloc, td->iloc);
- }
- else {
- sub_v3_v3v3(vec, tob->center, td->center);
- }
- mul_m3_v3(tob->mtx, vec);
-
- if (proj_vec) {
- float vec_p[3];
- project_v3_v3v3(vec_p, vec, proj_vec);
- sub_v3_v3(vec, vec_p);
- }
-
- dist_sq = len_squared_v3(vec);
- if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
- tob->rdist = sqrtf(dist_sq);
- if (use_island) {
- copy_v3_v3(tob->center, td->center);
- copy_m3_m3(tob->axismtx, td->axismtx);
- }
- }
- }
- else {
- break; /* by definition transdata has selected items in beginning */
- }
- }
- if (with_dist) {
- tob->dist = tob->rdist;
- }
- }
- }
- }
+ int a;
+
+ float _proj_vec[3];
+ const float *proj_vec = NULL;
+
+ /* support for face-islands */
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
+ if (t->flag & T_PROP_PROJECTED) {
+ if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = t->ar->regiondata;
+ normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
+ proj_vec = _proj_vec;
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *tob = tc->data;
+ for (a = 0; a < tc->data_len; a++, tob++) {
+
+ tob->rdist = 0.0f; // init, it was mallocced
+
+ if ((tob->flag & TD_SELECTED) == 0) {
+ TransData *td;
+ int i;
+ float dist_sq, vec[3];
+
+ tob->rdist = -1.0f; // signal for next loop
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SELECTED) {
+ if (use_island) {
+ sub_v3_v3v3(vec, tob->iloc, td->iloc);
+ }
+ else {
+ sub_v3_v3v3(vec, tob->center, td->center);
+ }
+ mul_m3_v3(tob->mtx, vec);
+
+ if (proj_vec) {
+ float vec_p[3];
+ project_v3_v3v3(vec_p, vec, proj_vec);
+ sub_v3_v3(vec, vec_p);
+ }
+
+ dist_sq = len_squared_v3(vec);
+ if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
+ tob->rdist = sqrtf(dist_sq);
+ if (use_island) {
+ copy_v3_v3(tob->center, td->center);
+ copy_m3_m3(tob->axismtx, td->axismtx);
+ }
+ }
+ }
+ else {
+ break; /* by definition transdata has selected items in beginning */
+ }
+ }
+ if (with_dist) {
+ tob->dist = tob->rdist;
+ }
+ }
+ }
+ }
}
/* ************************** CONVERSIONS ************************* */
@@ -297,55 +305,54 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
static void createTransTexspace(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- TransData *td;
- Object *ob;
- ID *id;
- short *texflag;
+ ViewLayer *view_layer = t->view_layer;
+ TransData *td;
+ Object *ob;
+ ID *id;
+ short *texflag;
- ob = OBACT(view_layer);
+ ob = OBACT(view_layer);
- if (ob == NULL) { // Shouldn't logically happen, but still...
- return;
- }
+ if (ob == NULL) { // Shouldn't logically happen, but still...
+ return;
+ }
- id = ob->data;
- if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
- BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
- return;
- }
+ id = ob->data;
+ if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
+ return;
+ }
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
- return;
- }
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
+ return;
+ }
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, ob->obmat[3]);
+ td->ob = ob;
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, ob->obmat[3]);
- td->ob = ob;
+ copy_m3_m4(td->mtx, ob->obmat);
+ copy_m3_m4(td->axismtx, ob->obmat);
+ normalize_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- copy_m3_m4(td->mtx, ob->obmat);
- copy_m3_m4(td->axismtx, ob->obmat);
- normalize_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
+ ob->dtx |= OB_TEXSPACE;
+ *texflag &= ~ME_AUTOSPACE;
+ }
- if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
- ob->dtx |= OB_TEXSPACE;
- *texflag &= ~ME_AUTOSPACE;
- }
-
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->ext->irot, td->ext->rot);
- copy_v3_v3(td->ext->isize, td->ext->size);
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->ext->irot, td->ext->rot);
+ copy_v3_v3(td->ext->isize, td->ext->size);
}
/* -------------------------------------------------------------------- */
@@ -357,87 +364,87 @@ static void createTransTexspace(TransInfo *t)
static void createTransCursor_image(TransInfo *t)
{
- TransData *td;
- SpaceImage *sima = t->sa->spacedata.first;
- float *cursor_location = sima->cursor;
+ TransData *td;
+ SpaceImage *sima = t->sa->spacedata.first;
+ float *cursor_location = sima->cursor;
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, cursor_location);
- td->ob = NULL;
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, cursor_location);
+ td->ob = NULL;
- unit_m3(td->mtx);
- unit_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ unit_m3(td->mtx);
+ unit_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- td->loc = cursor_location;
- copy_v3_v3(td->iloc, cursor_location);
+ td->loc = cursor_location;
+ copy_v3_v3(td->iloc, cursor_location);
}
static void createTransCursor_view3d(TransInfo *t)
{
- TransData *td;
-
- Scene *scene = t->scene;
- if (ID_IS_LINKED(scene)) {
- BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
- return;
- }
-
- View3DCursor *cursor = &scene->cursor;
- {
- BLI_assert(t->data_container_len == 1);
- TransDataContainer *tc = t->data_container;
- tc->data_len = 1;
- td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
- td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
- }
-
- td->flag = TD_SELECTED;
- copy_v3_v3(td->center, cursor->location);
- td->ob = NULL;
-
- unit_m3(td->mtx);
- BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx);
- normalize_m3(td->axismtx);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
-
- td->loc = cursor->location;
- copy_v3_v3(td->iloc, cursor->location);
-
- if (cursor->rotation_mode > 0) {
- td->ext->rot = cursor->rotation_euler;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, cursor->rotation_euler);
- }
- else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = cursor->rotation_axis;
- td->ext->rotAngle = &cursor->rotation_angle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = cursor->rotation_angle;
- copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis);
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = cursor->rotation_quaternion;
-
- copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion);
- }
- td->ext->rotOrder = cursor->rotation_mode;
+ TransData *td;
+
+ Scene *scene = t->scene;
+ if (ID_IS_LINKED(scene)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
+ return;
+ }
+
+ View3DCursor *cursor = &scene->cursor;
+ {
+ BLI_assert(t->data_container_len == 1);
+ TransDataContainer *tc = t->data_container;
+ tc->data_len = 1;
+ td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace");
+ td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
+ }
+
+ td->flag = TD_SELECTED;
+ copy_v3_v3(td->center, cursor->location);
+ td->ob = NULL;
+
+ unit_m3(td->mtx);
+ BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx);
+ normalize_m3(td->axismtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+
+ td->loc = cursor->location;
+ copy_v3_v3(td->iloc, cursor->location);
+
+ if (cursor->rotation_mode > 0) {
+ td->ext->rot = cursor->rotation_euler;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, cursor->rotation_euler);
+ }
+ else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = cursor->rotation_axis;
+ td->ext->rotAngle = &cursor->rotation_angle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = cursor->rotation_angle;
+ copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis);
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = cursor->rotation_quaternion;
+
+ copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion);
+ }
+ td->ext->rotOrder = cursor->rotation_mode;
}
/** \} */
@@ -446,1293 +453,1308 @@ static void createTransCursor_view3d(TransInfo *t)
static void createTransEdge(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- TransData *td = NULL;
- BMEdge *eed;
- BMIter iter;
- float mtx[3][3], smtx[3][3];
- int count = 0, countsel = 0;
- 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 (is_prop_edit) count++;
- }
- }
-
- if (countsel == 0) {
- tc->data_len = 0;
- continue;
- }
-
- if (is_prop_edit) {
- tc->data_len = count;
- }
- else {
- tc->data_len = countsel;
- }
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- /* create data we need */
- if (t->mode == TFM_BWEIGHT) {
- BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT);
- cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
- }
- else { //if (t->mode == TFM_CREASE) {
- BLI_assert(t->mode == TFM_CREASE);
- BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE);
- cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
- }
-
- 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) || is_prop_edit)) {
- float *fl_ptr;
- /* need to set center for center calculations */
- mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
-
- td->loc = NULL;
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
- td->flag = TD_SELECTED;
- else
- td->flag = 0;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = NULL;
-
- fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
- td->val = fl_ptr;
- td->ival = *fl_ptr;
-
- td++;
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ TransData *td = NULL;
+ BMEdge *eed;
+ BMIter iter;
+ float mtx[3][3], smtx[3][3];
+ int count = 0, countsel = 0;
+ 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 (is_prop_edit)
+ count++;
+ }
+ }
+
+ if (countsel == 0) {
+ tc->data_len = 0;
+ continue;
+ }
+
+ if (is_prop_edit) {
+ tc->data_len = count;
+ }
+ else {
+ tc->data_len = countsel;
+ }
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransCrease");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ /* create data we need */
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
+ }
+ else { //if (t->mode == TFM_CREASE) {
+ BLI_assert(t->mode == TFM_CREASE);
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_CREASE);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
+ }
+
+ 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) || is_prop_edit)) {
+ float *fl_ptr;
+ /* need to set center for center calculations */
+ mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
+
+ td->loc = NULL;
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = NULL;
+
+ fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
+ td->val = fl_ptr;
+ td->ival = *fl_ptr;
+
+ td++;
+ }
+ }
+ }
}
/* ********************* pose mode ************* */
static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
{
- bConstraint *con = pchan->constraints.first;
+ bConstraint *con = pchan->constraints.first;
- for (; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
- bKinematicConstraint *data = con->data;
+ for (; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
+ bKinematicConstraint *data = con->data;
- if (data->tar == NULL)
- return data;
- if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)
- return data;
- }
- }
- return NULL;
+ if (data->tar == NULL)
+ return data;
+ if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)
+ return data;
+ }
+ }
+ return NULL;
}
static short apply_targetless_ik(Object *ob)
{
- bPoseChannel *pchan, *parchan, *chanlist[256];
- bKinematicConstraint *data;
- int segcount, apply = 0;
-
- /* now we got a difficult situation... we have to find the
- * target-less IK pchans, and apply transformation to the all
- * pchans that were in the chain */
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- data = has_targetless_ik(pchan);
- if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
-
- /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
- segcount = 0;
-
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP))
- parchan = pchan->parent;
- else
- parchan = pchan;
-
- /* Find the chain's root & count the segments needed */
- for (; parchan; parchan = parchan->parent) {
- chanlist[segcount] = parchan;
- segcount++;
-
- if (segcount == data->rootbone || segcount > 255) break; // 255 is weak
- }
- for (; segcount; segcount--) {
- Bone *bone;
- float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
-
- /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
- /* we put in channel the entire result of rmat = (channel * constraint * IK) */
- /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
- /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
-
- parchan = chanlist[segcount - 1];
- bone = parchan->bone;
- bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
-
- BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
-
- /* apply and decompose, doesn't work for constraints or non-uniform scale well */
- {
- float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
-
- copy_m3_m4(rmat3, rmat);
-
- /* rotation */
- /* [#22409] is partially caused by this, as slight numeric error introduced during
- * the solving process leads to locked-axis values changing. However, we cannot modify
- * the values here, or else there are huge discrepancies between IK-solver (interactive)
- * and applied poses.
- */
- if (parchan->rotmode > 0)
- mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
- else if (parchan->rotmode == ROT_MODE_AXISANGLE)
- mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
- else
- mat3_to_quat(parchan->quat, rmat3);
-
- /* for size, remove rotation */
- /* causes problems with some constraints (so apply only if needed) */
- if (data->flag & CONSTRAINT_IK_STRETCH) {
- if (parchan->rotmode > 0)
- eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
- else if (parchan->rotmode == ROT_MODE_AXISANGLE)
- axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
- else
- quat_to_mat3(qrmat, parchan->quat);
-
- invert_m3_m3(imat3, qrmat);
- mul_m3_m3m3(smat, rmat3, imat3);
- mat3_to_size(parchan->size, smat);
- }
-
- /* causes problems with some constraints (e.g. childof), so disable this */
- /* as it is IK shouldn't affect location directly */
- /* copy_v3_v3(parchan->loc, rmat[3]); */
- }
-
- }
-
- apply = 1;
- data->flag &= ~CONSTRAINT_IK_AUTO;
- }
- }
-
- return apply;
-}
-
-static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
-{
- Bone *bone = pchan->bone;
- float pmat[3][3], omat[3][3];
- float cmat[3][3], tmat[3][3];
- float vec[3];
-
- copy_v3_v3(vec, pchan->pose_mat[3]);
- copy_v3_v3(td->center, vec);
-
- td->ob = ob;
- td->flag = TD_SELECTED;
- if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
- td->flag |= TD_NOCENTER;
- }
-
- if (bone->flag & BONE_TRANSFORM_CHILD) {
- td->flag |= TD_NOCENTER;
- td->flag |= TD_NO_LOC;
- }
-
- td->protectflag = pchan->protectflag;
-
- td->loc = pchan->loc;
- copy_v3_v3(td->iloc, pchan->loc);
-
- td->ext->size = pchan->size;
- copy_v3_v3(td->ext->isize, pchan->size);
-
- if (pchan->rotmode > 0) {
- td->ext->rot = pchan->eul;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, pchan->eul);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = pchan->rotAxis;
- td->ext->rotAngle = &pchan->rotAngle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = pchan->rotAngle;
- copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = pchan->quat;
-
- copy_qt_qt(td->ext->iquat, pchan->quat);
- }
- td->ext->rotOrder = pchan->rotmode;
-
-
- /* proper way to get parent transform + own transform + constraints transform */
- copy_m3_m4(omat, ob->obmat);
-
- /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
- {
- BoneParentTransform bpt;
- float rpmat[3][3];
-
- BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt);
- if (t->mode == TFM_TRANSLATION)
- copy_m3_m4(pmat, bpt.loc_mat);
- else
- copy_m3_m4(pmat, bpt.rotscale_mat);
-
- /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
- * and want align snapping, we just need both loc_mat and rotscale_mat.
- * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
- * Ugly to need such hacks! :/ */
- copy_m3_m4(rpmat, bpt.rotscale_mat);
-
- if (constraints_list_needinv(t, &pchan->constraints)) {
- copy_m3_m4(tmat, pchan->constinv);
- invert_m3_m3(cmat, tmat);
- mul_m3_series(td->mtx, cmat, omat, pmat);
- mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
- }
- else {
- mul_m3_series(td->mtx, omat, pmat);
- mul_m3_series(td->ext->r_mtx, omat, rpmat);
- }
- invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
- }
-
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
-
- /* exceptional case: rotate the pose bone which also applies transformation
- * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
- if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
- if (pchan->parent) {
- /* same as td->smtx but without pchan->bone->bone_mat */
- td->flag |= TD_PBONE_LOCAL_MTX_C;
- mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
- }
- else {
- td->flag |= TD_PBONE_LOCAL_MTX_P;
- }
- }
-
- /* for axismat we use bone's own transform */
- copy_m3_m4(pmat, pchan->pose_mat);
- mul_m3_m3m3(td->axismtx, omat, pmat);
- normalize_m3(td->axismtx);
-
- if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- bArmature *arm = tc->poseobj->data;
-
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
- td->loc = NULL;
- td->val = &bone->dist;
- td->ival = bone->dist;
- }
- else {
- // abusive storage of scale in the loc pointer :)
- td->loc = &bone->xwidth;
- copy_v3_v3(td->iloc, td->loc);
- td->val = NULL;
- }
- }
-
- /* in this case we can do target-less IK grabbing */
- if (t->mode == TFM_TRANSLATION) {
- bKinematicConstraint *data = has_targetless_ik(pchan);
- if (data) {
- if (data->flag & CONSTRAINT_IK_TIP) {
- copy_v3_v3(data->grabtarget, pchan->pose_tail);
- }
- else {
- copy_v3_v3(data->grabtarget, pchan->pose_head);
- }
- td->loc = data->grabtarget;
- copy_v3_v3(td->iloc, td->loc);
- data->flag |= CONSTRAINT_IK_AUTO;
-
- /* only object matrix correction */
- copy_m3_m3(td->mtx, omat);
- pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
- }
- }
-
- /* store reference to first constraint */
- td->con = pchan->constraints.first;
+ bPoseChannel *pchan, *parchan, *chanlist[256];
+ bKinematicConstraint *data;
+ int segcount, apply = 0;
+
+ /* now we got a difficult situation... we have to find the
+ * target-less IK pchans, and apply transformation to the all
+ * pchans that were in the chain */
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ data = has_targetless_ik(pchan);
+ if (data && (data->flag & CONSTRAINT_IK_AUTO)) {
+
+ /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
+ segcount = 0;
+
+ /* exclude tip from chain? */
+ if (!(data->flag & CONSTRAINT_IK_TIP))
+ parchan = pchan->parent;
+ else
+ parchan = pchan;
+
+ /* Find the chain's root & count the segments needed */
+ for (; parchan; parchan = parchan->parent) {
+ chanlist[segcount] = parchan;
+ segcount++;
+
+ if (segcount == data->rootbone || segcount > 255)
+ break; // 255 is weak
+ }
+ for (; segcount; segcount--) {
+ Bone *bone;
+ float rmat[4][4] /*, tmat[4][4], imat[4][4]*/;
+
+ /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
+ /* we put in channel the entire result of rmat = (channel * constraint * IK) */
+ /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
+ /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */
+
+ parchan = chanlist[segcount - 1];
+ bone = parchan->bone;
+ bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
+
+ BKE_armature_mat_pose_to_bone(parchan, parchan->pose_mat, rmat);
+
+ /* apply and decompose, doesn't work for constraints or non-uniform scale well */
+ {
+ float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
+
+ copy_m3_m4(rmat3, rmat);
+
+ /* rotation */
+ /* [#22409] is partially caused by this, as slight numeric error introduced during
+ * the solving process leads to locked-axis values changing. However, we cannot modify
+ * the values here, or else there are huge discrepancies between IK-solver (interactive)
+ * and applied poses.
+ */
+ if (parchan->rotmode > 0)
+ mat3_to_eulO(parchan->eul, parchan->rotmode, rmat3);
+ else if (parchan->rotmode == ROT_MODE_AXISANGLE)
+ mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle, rmat3);
+ else
+ mat3_to_quat(parchan->quat, rmat3);
+
+ /* for size, remove rotation */
+ /* causes problems with some constraints (so apply only if needed) */
+ if (data->flag & CONSTRAINT_IK_STRETCH) {
+ if (parchan->rotmode > 0)
+ eulO_to_mat3(qrmat, parchan->eul, parchan->rotmode);
+ else if (parchan->rotmode == ROT_MODE_AXISANGLE)
+ axis_angle_to_mat3(qrmat, parchan->rotAxis, parchan->rotAngle);
+ else
+ quat_to_mat3(qrmat, parchan->quat);
+
+ invert_m3_m3(imat3, qrmat);
+ mul_m3_m3m3(smat, rmat3, imat3);
+ mat3_to_size(parchan->size, smat);
+ }
+
+ /* causes problems with some constraints (e.g. childof), so disable this */
+ /* as it is IK shouldn't affect location directly */
+ /* copy_v3_v3(parchan->loc, rmat[3]); */
+ }
+ }
+
+ apply = 1;
+ data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ return apply;
+}
+
+static void add_pose_transdata(
+ TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
+{
+ Bone *bone = pchan->bone;
+ float pmat[3][3], omat[3][3];
+ float cmat[3][3], tmat[3][3];
+ float vec[3];
+
+ copy_v3_v3(vec, pchan->pose_mat[3]);
+ copy_v3_v3(td->center, vec);
+
+ td->ob = ob;
+ td->flag = TD_SELECTED;
+ if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ td->flag |= TD_NOCENTER;
+ }
+
+ if (bone->flag & BONE_TRANSFORM_CHILD) {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ td->protectflag = pchan->protectflag;
+
+ td->loc = pchan->loc;
+ copy_v3_v3(td->iloc, pchan->loc);
+
+ td->ext->size = pchan->size;
+ copy_v3_v3(td->ext->isize, pchan->size);
+
+ if (pchan->rotmode > 0) {
+ td->ext->rot = pchan->eul;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, pchan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = pchan->rotAxis;
+ td->ext->rotAngle = &pchan->rotAngle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = pchan->rotAngle;
+ copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = pchan->quat;
+
+ copy_qt_qt(td->ext->iquat, pchan->quat);
+ }
+ td->ext->rotOrder = pchan->rotmode;
+
+ /* proper way to get parent transform + own transform + constraints transform */
+ copy_m3_m4(omat, ob->obmat);
+
+ /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */
+ {
+ BoneParentTransform bpt;
+ float rpmat[3][3];
+
+ BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt);
+ if (t->mode == TFM_TRANSLATION)
+ copy_m3_m4(pmat, bpt.loc_mat);
+ else
+ copy_m3_m4(pmat, bpt.rotscale_mat);
+
+ /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal,
+ * and want align snapping, we just need both loc_mat and rotscale_mat.
+ * So simply always store rotscale mat in td->ext, and always use it to apply rotations...
+ * Ugly to need such hacks! :/ */
+ copy_m3_m4(rpmat, bpt.rotscale_mat);
+
+ if (constraints_list_needinv(t, &pchan->constraints)) {
+ copy_m3_m4(tmat, pchan->constinv);
+ invert_m3_m3(cmat, tmat);
+ mul_m3_series(td->mtx, cmat, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
+ }
+ else {
+ mul_m3_series(td->mtx, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, omat, rpmat);
+ }
+ invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
+ }
+
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+
+ /* exceptional case: rotate the pose bone which also applies transformation
+ * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
+ if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) &&
+ (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
+ if (pchan->parent) {
+ /* same as td->smtx but without pchan->bone->bone_mat */
+ td->flag |= TD_PBONE_LOCAL_MTX_C;
+ mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
+ }
+ else {
+ td->flag |= TD_PBONE_LOCAL_MTX_P;
+ }
+ }
+
+ /* for axismat we use bone's own transform */
+ copy_m3_m4(pmat, pchan->pose_mat);
+ mul_m3_m3m3(td->axismtx, omat, pmat);
+ normalize_m3(td->axismtx);
+
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ bArmature *arm = tc->poseobj->data;
+
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
+ td->loc = NULL;
+ td->val = &bone->dist;
+ td->ival = bone->dist;
+ }
+ else {
+ // abusive storage of scale in the loc pointer :)
+ td->loc = &bone->xwidth;
+ copy_v3_v3(td->iloc, td->loc);
+ td->val = NULL;
+ }
+ }
+
+ /* in this case we can do target-less IK grabbing */
+ if (t->mode == TFM_TRANSLATION) {
+ bKinematicConstraint *data = has_targetless_ik(pchan);
+ if (data) {
+ if (data->flag & CONSTRAINT_IK_TIP) {
+ copy_v3_v3(data->grabtarget, pchan->pose_tail);
+ }
+ else {
+ copy_v3_v3(data->grabtarget, pchan->pose_head);
+ }
+ td->loc = data->grabtarget;
+ copy_v3_v3(td->iloc, td->loc);
+ data->flag |= CONSTRAINT_IK_AUTO;
+
+ /* only object matrix correction */
+ copy_m3_m3(td->mtx, omat);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
+ }
+ }
+
+ /* store reference to first constraint */
+ td->con = pchan->constraints.first;
}
static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
{
- Bone *bone = lb->first;
+ Bone *bone = lb->first;
- for (; bone; bone = bone->next) {
- if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
- bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
- }
- else if ((bone->flag & BONE_TRANSFORM) &&
- (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
- (around == V3D_AROUND_LOCAL_ORIGINS))
- {
- bone->flag |= BONE_TRANSFORM_CHILD;
- }
- else {
- bone->flag &= ~BONE_TRANSFORM;
- }
+ for (; bone; bone = bone->next) {
+ if ((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED)) {
+ bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
+ }
+ else if ((bone->flag & BONE_TRANSFORM) && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) &&
+ (around == V3D_AROUND_LOCAL_ORIGINS)) {
+ bone->flag |= BONE_TRANSFORM_CHILD;
+ }
+ else {
+ bone->flag &= ~BONE_TRANSFORM;
+ }
- bone_children_clear_transflag(mode, around, &bone->childbase);
- }
+ bone_children_clear_transflag(mode, around, &bone->childbase);
+ }
}
/* sets transform flags in the bones
* returns total number of bones with BONE_TRANSFORM */
-int count_set_pose_transflags(Object *ob, const int mode, const short around, bool has_translate_rotate[2])
-{
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- Bone *bone;
- int total = 0;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (PBONE_VISIBLE(arm, bone)) {
- if ((bone->flag & BONE_SELECTED))
- bone->flag |= BONE_TRANSFORM;
- else
- bone->flag &= ~BONE_TRANSFORM;
-
- bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
- bone->flag &= ~BONE_TRANSFORM_CHILD;
- }
- else
- bone->flag &= ~BONE_TRANSFORM;
- }
-
- /* 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 (!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)
- bone_children_clear_transflag(mode, around, &bone->childbase);
- }
- }
- /* now count, and check if we have autoIK or have to switch from translate to rotate */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
- if (bone->flag & BONE_TRANSFORM) {
- total++;
-
- if (has_translate_rotate != NULL) {
- if (has_targetless_ik(pchan) == NULL) {
- if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
- if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
- has_translate_rotate[0] = true;
- }
- }
- else {
- if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
- has_translate_rotate[0] = true;
- }
- }
- if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
- has_translate_rotate[1] = true;
- }
- }
- else {
- has_translate_rotate[0] = true;
- }
- }
- }
- }
-
- return total;
+int count_set_pose_transflags(Object *ob,
+ const int mode,
+ const short around,
+ bool has_translate_rotate[2])
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+ int total = 0;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ if (PBONE_VISIBLE(arm, bone)) {
+ if ((bone->flag & BONE_SELECTED))
+ bone->flag |= BONE_TRANSFORM;
+ else
+ bone->flag &= ~BONE_TRANSFORM;
+
+ bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
+ bone->flag &= ~BONE_TRANSFORM_CHILD;
+ }
+ else
+ bone->flag &= ~BONE_TRANSFORM;
+ }
+
+ /* 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 (!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)
+ bone_children_clear_transflag(mode, around, &bone->childbase);
+ }
+ }
+ /* now count, and check if we have autoIK or have to switch from translate to rotate */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ if (bone->flag & BONE_TRANSFORM) {
+ total++;
+
+ if (has_translate_rotate != NULL) {
+ if (has_targetless_ik(pchan) == NULL) {
+ if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
+ if (pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ else {
+ if ((pchan->protectflag & OB_LOCK_LOC) != OB_LOCK_LOC) {
+ has_translate_rotate[0] = true;
+ }
+ }
+ if ((pchan->protectflag & OB_LOCK_ROT) != OB_LOCK_ROT) {
+ has_translate_rotate[1] = true;
+ }
+ }
+ else {
+ has_translate_rotate[0] = true;
+ }
+ }
+ }
+ }
+
+ return total;
}
-
/* -------- Auto-IK ---------- */
/* adjust pose-channel's auto-ik chainlen */
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
{
- bConstraint *con;
- bool changed = false;
-
- /* don't bother to search if no valid constraints */
- if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
- return changed;
- }
-
- /* check if pchan has ik-constraint */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
- bKinematicConstraint *data = con->data;
-
- /* only accept if a temporary one (for auto-ik) */
- if (data->flag & CONSTRAINT_IK_TEMP) {
- /* chainlen is new chainlen, but is limited by maximum chainlen */
- const int old_rootbone = data->rootbone;
- if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
- data->rootbone = data->max_rootbone;
- }
- else {
- data->rootbone = chainlen;
- }
- changed |= (data->rootbone != old_rootbone);
- }
- }
- }
-
- return changed;
+ bConstraint *con;
+ bool changed = false;
+
+ /* don't bother to search if no valid constraints */
+ if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
+ return changed;
+ }
+
+ /* check if pchan has ik-constraint */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
+ bKinematicConstraint *data = con->data;
+
+ /* only accept if a temporary one (for auto-ik) */
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ /* chainlen is new chainlen, but is limited by maximum chainlen */
+ const int old_rootbone = data->rootbone;
+ if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
+ data->rootbone = data->max_rootbone;
+ }
+ else {
+ data->rootbone = chainlen;
+ }
+ changed |= (data->rootbone != old_rootbone);
+ }
+ }
+ }
+
+ return changed;
}
/* change the chain-length of auto-ik */
void transform_autoik_update(TransInfo *t, short mode)
{
- Main *bmain = CTX_data_main(t->context);
-
- short *chainlen = &t->settings->autoik_chainlen;
- bPoseChannel *pchan;
-
- /* mode determines what change to apply to chainlen */
- if (mode == 1) {
- /* mode=1 is from WHEELMOUSEDOWN... increases len */
- (*chainlen)++;
- }
- else if (mode == -1) {
- /* mode==-1 is from WHEELMOUSEUP... decreases len */
- if (*chainlen > 0) {
- (*chainlen)--;
- }
- else {
- /* IK length did not change, skip updates. */
- return;
- }
- }
-
- /* apply to all pose-channels */
- bool changed = false;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
- if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
- continue;
- }
-
- for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
- changed |= pchan_autoik_adjust(pchan, *chainlen);
- }
- }
-
- if (changed) {
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
- }
+ Main *bmain = CTX_data_main(t->context);
+
+ short *chainlen = &t->settings->autoik_chainlen;
+ bPoseChannel *pchan;
+
+ /* mode determines what change to apply to chainlen */
+ if (mode == 1) {
+ /* mode=1 is from WHEELMOUSEDOWN... increases len */
+ (*chainlen)++;
+ }
+ else if (mode == -1) {
+ /* mode==-1 is from WHEELMOUSEUP... decreases len */
+ if (*chainlen > 0) {
+ (*chainlen)--;
+ }
+ else {
+ /* IK length did not change, skip updates. */
+ return;
+ }
+ }
+
+ /* apply to all pose-channels */
+ bool changed = false;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
+ if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
+ continue;
+ }
+
+ for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
+ changed |= pchan_autoik_adjust(pchan, *chainlen);
+ }
+ }
+
+ if (changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
+ }
}
/* frees temporal IKs */
static void pose_grab_with_ik_clear(Main *bmain, Object *ob)
{
- bKinematicConstraint *data;
- bPoseChannel *pchan;
- bConstraint *con, *next;
- bool relations_changed = false;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* clear all temporary lock flags */
- pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
-
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
-
- /* remove all temporary IK-constraints added */
- for (con = pchan->constraints.first; con; con = next) {
- next = con->next;
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- data = con->data;
- if (data->flag & CONSTRAINT_IK_TEMP) {
- relations_changed = true;
-
- /* iTaSC needs clear for removed constraints */
- BIK_clear_data(ob->pose);
-
- BLI_remlink(&pchan->constraints, con);
- MEM_freeN(con->data);
- MEM_freeN(con);
- continue;
- }
- pchan->constflag |= PCHAN_HAS_IK;
- if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
- pchan->constflag |= PCHAN_HAS_TARGET;
- }
- }
- }
-
- if (relations_changed) {
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
- }
+ bKinematicConstraint *data;
+ bPoseChannel *pchan;
+ bConstraint *con, *next;
+ bool relations_changed = false;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* clear all temporary lock flags */
+ pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP | BONE_IK_NO_YDOF_TEMP | BONE_IK_NO_ZDOF_TEMP);
+
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
+
+ /* remove all temporary IK-constraints added */
+ for (con = pchan->constraints.first; con; con = next) {
+ next = con->next;
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ data = con->data;
+ if (data->flag & CONSTRAINT_IK_TEMP) {
+ relations_changed = true;
+
+ /* iTaSC needs clear for removed constraints */
+ BIK_clear_data(ob->pose);
+
+ BLI_remlink(&pchan->constraints, con);
+ MEM_freeN(con->data);
+ MEM_freeN(con);
+ continue;
+ }
+ pchan->constflag |= PCHAN_HAS_IK;
+ if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0))
+ pchan->constflag |= PCHAN_HAS_TARGET;
+ }
+ }
+ }
+
+ if (relations_changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
+ }
}
/* adds the IK to pchan - returns if added */
static short pose_grab_with_ik_add(bPoseChannel *pchan)
{
- bKinematicConstraint *targetless = NULL;
- bKinematicConstraint *data;
- bConstraint *con;
-
- /* Sanity check */
- if (pchan == NULL)
- return 0;
-
- /* Rule: not if there's already an IK on this channel */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- data = con->data;
-
- if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
- /* make reference to constraint to base things off later
- * (if it's the last targetless constraint encountered) */
- targetless = (bKinematicConstraint *)con->data;
-
- /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
- if (con->enforce != 0.0f) {
- data->flag |= CONSTRAINT_IK_AUTO;
-
- /* if no chain length has been specified,
- * just make things obey standard rotation locks too */
- if (data->rootbone == 0) {
- for (; pchan; pchan = pchan->parent) {
- /* here, we set ik-settings for bone from pchan->protectflag */
- // XXX: careful with quats/axis-angle rotations where we're locking 4d components
- if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
- }
- }
-
- return 0;
- }
- }
-
- if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
- return 0;
- }
- }
-
- con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
-
- /* for draw, but also for detecting while pose solving */
- pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);
-
- data = con->data;
- if (targetless) {
- /* if exists, use values from last targetless (but disabled) IK-constraint as base */
- *data = *targetless;
- }
- else
- data->flag = CONSTRAINT_IK_TIP;
- data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
- copy_v3_v3(data->grabtarget, pchan->pose_tail);
-
- /* watch-it! has to be 0 here, since we're still on the
- * same bone for the first time through the loop T25885. */
- data->rootbone = 0;
-
- /* we only include bones that are part of a continual connected chain */
- do {
- /* here, we set ik-settings for bone from pchan->protectflag */
- // XXX: careful with quats/axis-angle rotations where we're locking 4d components
- if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
- if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
-
- /* now we count this pchan as being included */
- data->rootbone++;
-
- /* continue to parent, but only if we're connected to it */
- if (pchan->bone->flag & BONE_CONNECTED)
- pchan = pchan->parent;
- else
- pchan = NULL;
- } while (pchan);
-
- /* make a copy of maximum chain-length */
- data->max_rootbone = data->rootbone;
-
- return 1;
+ bKinematicConstraint *targetless = NULL;
+ bKinematicConstraint *data;
+ bConstraint *con;
+
+ /* Sanity check */
+ if (pchan == NULL)
+ return 0;
+
+ /* Rule: not if there's already an IK on this channel */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ data = con->data;
+
+ if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == '\0')) {
+ /* make reference to constraint to base things off later
+ * (if it's the last targetless constraint encountered) */
+ targetless = (bKinematicConstraint *)con->data;
+
+ /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
+ if (con->enforce != 0.0f) {
+ data->flag |= CONSTRAINT_IK_AUTO;
+
+ /* if no chain length has been specified,
+ * just make things obey standard rotation locks too */
+ if (data->rootbone == 0) {
+ for (; pchan; pchan = pchan->parent) {
+ /* here, we set ik-settings for bone from pchan->protectflag */
+ // XXX: careful with quats/axis-angle rotations where we're locking 4d components
+ if (pchan->protectflag & OB_LOCK_ROTX)
+ pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTY)
+ pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+ if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f))
+ return 0;
+ }
+ }
+
+ con = BKE_constraint_add_for_pose(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+
+ /* for draw, but also for detecting while pose solving */
+ pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET);
+
+ data = con->data;
+ if (targetless) {
+ /* if exists, use values from last targetless (but disabled) IK-constraint as base */
+ *data = *targetless;
+ }
+ else
+ data->flag = CONSTRAINT_IK_TIP;
+ data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS;
+ copy_v3_v3(data->grabtarget, pchan->pose_tail);
+
+ /* watch-it! has to be 0 here, since we're still on the
+ * same bone for the first time through the loop T25885. */
+ data->rootbone = 0;
+
+ /* we only include bones that are part of a continual connected chain */
+ do {
+ /* here, we set ik-settings for bone from pchan->protectflag */
+ // XXX: careful with quats/axis-angle rotations where we're locking 4d components
+ if (pchan->protectflag & OB_LOCK_ROTX)
+ pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTY)
+ pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
+
+ /* now we count this pchan as being included */
+ data->rootbone++;
+
+ /* continue to parent, but only if we're connected to it */
+ if (pchan->bone->flag & BONE_CONNECTED)
+ pchan = pchan->parent;
+ else
+ pchan = NULL;
+ } while (pchan);
+
+ /* make a copy of maximum chain-length */
+ data->max_rootbone = data->rootbone;
+
+ return 1;
}
/* bone is a candidate to get IK, but we don't do it if it has children connected */
static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
{
- Bone *bonec;
- short wentdeeper = 0, added = 0;
+ Bone *bonec;
+ short wentdeeper = 0, added = 0;
- /* go deeper if children & children are connected */
- for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
- if (bonec->flag & BONE_CONNECTED) {
- wentdeeper = 1;
- added += pose_grab_with_ik_children(pose, bonec);
- }
- }
- if (wentdeeper == 0) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
- if (pchan)
- added += pose_grab_with_ik_add(pchan);
- }
+ /* go deeper if children & children are connected */
+ for (bonec = bone->childbase.first; bonec; bonec = bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ wentdeeper = 1;
+ added += pose_grab_with_ik_children(pose, bonec);
+ }
+ }
+ if (wentdeeper == 0) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (pchan)
+ added += pose_grab_with_ik_add(pchan);
+ }
- return added;
+ return added;
}
/* main call which adds temporal IK chains */
static short pose_grab_with_ik(Main *bmain, Object *ob)
{
- bArmature *arm;
- bPoseChannel *pchan, *parent;
- Bone *bonec;
- short tot_ik = 0;
-
- if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
- return 0;
-
- arm = ob->data;
-
- /* Rule: allow multiple Bones
- * (but they must be selected, and only one ik-solver per chain should get added) */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->layer & arm->layer) {
- if (pchan->bone->flag & BONE_SELECTED) {
- /* Rule: no IK for solitatry (unconnected) bones */
- for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
- if (bonec->flag & BONE_CONNECTED) {
- break;
- }
- }
- if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
- continue;
-
- /* rule: if selected Bone is not a root bone, it gets a temporal IK */
- if (pchan->parent) {
- /* only adds if there's no IK yet (and no parent bone was selected) */
- for (parent = pchan->parent; parent; parent = parent->parent) {
- if (parent->bone->flag & BONE_SELECTED)
- break;
- }
- if (parent == NULL)
- tot_ik += pose_grab_with_ik_add(pchan);
- }
- else {
- /* rule: go over the children and add IK to the tips */
- tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
- }
- }
- }
- }
-
- /* iTaSC needs clear for new IK constraints */
- if (tot_ik) {
- BIK_clear_data(ob->pose);
- /* TODO(sergey): Consider doing partial update only. */
- DEG_relations_tag_update(bmain);
- }
-
- return (tot_ik) ? 1 : 0;
+ bArmature *arm;
+ bPoseChannel *pchan, *parent;
+ Bone *bonec;
+ short tot_ik = 0;
+
+ if ((ob == NULL) || (ob->pose == NULL) || (ob->mode & OB_MODE_POSE) == 0)
+ return 0;
+
+ arm = ob->data;
+
+ /* Rule: allow multiple Bones
+ * (but they must be selected, and only one ik-solver per chain should get added) */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->layer & arm->layer) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ /* Rule: no IK for solitatry (unconnected) bones */
+ for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) {
+ if (bonec->flag & BONE_CONNECTED) {
+ break;
+ }
+ }
+ if ((pchan->bone->flag & BONE_CONNECTED) == 0 && (bonec == NULL))
+ continue;
+
+ /* rule: if selected Bone is not a root bone, it gets a temporal IK */
+ if (pchan->parent) {
+ /* only adds if there's no IK yet (and no parent bone was selected) */
+ for (parent = pchan->parent; parent; parent = parent->parent) {
+ if (parent->bone->flag & BONE_SELECTED)
+ break;
+ }
+ if (parent == NULL)
+ tot_ik += pose_grab_with_ik_add(pchan);
+ }
+ else {
+ /* rule: go over the children and add IK to the tips */
+ tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
+ }
+ }
+ }
+ }
+
+ /* iTaSC needs clear for new IK constraints */
+ if (tot_ik) {
+ BIK_clear_data(ob->pose);
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(bmain);
+ }
+
+ return (tot_ik) ? 1 : 0;
}
-
/**
* When objects array is NULL, use 't->data_container' as is.
*/
static void createTransPose(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
-
- t->data_len_all = 0;
-
- bool has_translate_rotate_buf[2] = {false, false};
- bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : NULL;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->poseobj;
-
- bArmature *arm;
- short ik_on = 0;
-
- /* check validity of state */
- arm = BKE_armature_from_object(tc->poseobj);
- if ((arm == NULL) || (ob->pose == NULL)) {
- continue;
- }
-
- /* set flags and count total */
- tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
- if (tc->data_len == 0) {
- continue;
- }
-
- if (arm->flag & ARM_RESTPOS) {
- if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
- BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
- tc->data_len = 0;
- continue;
- }
- }
-
- /* do we need to add temporal IK chains? */
- if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
- ik_on = pose_grab_with_ik(bmain, ob);
- if (ik_on) {
- t->flag |= T_AUTOIK;
- has_translate_rotate[0] = true;
- }
- }
- }
-
- /* if there are no translatable bones, do rotation */
- if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
- if (has_translate_rotate[1]) {
- t->mode = TFM_ROTATION;
- }
- else {
- t->mode = TFM_RESIZE;
- }
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len == 0) {
- continue;
- }
- Object *ob = tc->poseobj;
- TransData *td;
- TransDataExtension *tdx;
- short ik_on = 0;
- int i;
-
- tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
-
- /* init trans data */
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone");
- tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransPoseBoneExt");
- for (i = 0; i < tc->data_len; i++, td++, tdx++) {
- td->ext = tdx;
- td->val = NULL;
- }
-
- /* use pose channels to fill trans data */
- td = tc->data;
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- add_pose_transdata(t, pchan, ob, tc, td);
- td++;
- }
- }
-
- if (td != (tc->data + tc->data_len)) {
- BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
- }
-
- /* initialize initial auto=ik chainlen's? */
- if (ik_on) {
- transform_autoik_update(t, 0);
- }
- }
-
- t->flag |= T_POSE;
- /* disable PET, its not usable in pose mode yet [#32444] */
- t->flag &= ~T_PROP_EDIT_ALL;
-
+ Main *bmain = CTX_data_main(t->context);
+
+ t->data_len_all = 0;
+
+ bool has_translate_rotate_buf[2] = {false, false};
+ bool *has_translate_rotate = (t->mode == TFM_TRANSLATION) ? has_translate_rotate_buf : NULL;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->poseobj;
+
+ bArmature *arm;
+ short ik_on = 0;
+
+ /* check validity of state */
+ arm = BKE_armature_from_object(tc->poseobj);
+ if ((arm == NULL) || (ob->pose == NULL)) {
+ continue;
+ }
+
+ /* set flags and count total */
+ tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
+ if (tc->data_len == 0) {
+ continue;
+ }
+
+ if (arm->flag & ARM_RESTPOS) {
+ if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
+ BKE_report(t->reports, RPT_ERROR, "Cannot change Pose when 'Rest Position' is enabled");
+ tc->data_len = 0;
+ continue;
+ }
+ }
+
+ /* do we need to add temporal IK chains? */
+ if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
+ ik_on = pose_grab_with_ik(bmain, ob);
+ if (ik_on) {
+ t->flag |= T_AUTOIK;
+ has_translate_rotate[0] = true;
+ }
+ }
+ }
+
+ /* if there are no translatable bones, do rotation */
+ if ((t->mode == TFM_TRANSLATION) && !has_translate_rotate[0]) {
+ if (has_translate_rotate[1]) {
+ t->mode = TFM_ROTATION;
+ }
+ else {
+ t->mode = TFM_RESIZE;
+ }
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len == 0) {
+ continue;
+ }
+ Object *ob = tc->poseobj;
+ TransData *td;
+ TransDataExtension *tdx;
+ short ik_on = 0;
+ int i;
+
+ tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
+
+ /* init trans data */
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone");
+ tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "TransPoseBoneExt");
+ for (i = 0; i < tc->data_len; i++, td++, tdx++) {
+ td->ext = tdx;
+ td->val = NULL;
+ }
+
+ /* use pose channels to fill trans data */
+ td = tc->data;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ add_pose_transdata(t, pchan, ob, tc, td);
+ td++;
+ }
+ }
+
+ if (td != (tc->data + tc->data_len)) {
+ BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
+ }
+
+ /* initialize initial auto=ik chainlen's? */
+ if (ik_on) {
+ transform_autoik_update(t, 0);
+ }
+ }
+
+ t->flag |= T_POSE;
+ /* disable PET, its not usable in pose mode yet [#32444] */
+ t->flag &= ~T_PROP_EDIT_ALL;
}
void restoreBones(TransDataContainer *tc)
{
- bArmature *arm = tc->obedit->data;
- BoneInitData *bid = tc->custom.type.data;
- EditBone *ebo;
+ bArmature *arm = tc->obedit->data;
+ BoneInitData *bid = tc->custom.type.data;
+ EditBone *ebo;
- while (bid->bone) {
- ebo = bid->bone;
+ while (bid->bone) {
+ ebo = bid->bone;
- ebo->dist = bid->dist;
- ebo->rad_tail = bid->rad_tail;
- ebo->roll = bid->roll;
- ebo->xwidth = bid->xwidth;
- ebo->zwidth = bid->zwidth;
- copy_v3_v3(ebo->head, bid->head);
- copy_v3_v3(ebo->tail, bid->tail);
+ ebo->dist = bid->dist;
+ ebo->rad_tail = bid->rad_tail;
+ ebo->roll = bid->roll;
+ ebo->xwidth = bid->xwidth;
+ ebo->zwidth = bid->zwidth;
+ copy_v3_v3(ebo->head, bid->head);
+ copy_v3_v3(ebo->tail, bid->tail);
- if (arm->flag & ARM_MIRROR_EDIT) {
- EditBone *ebo_child;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ EditBone *ebo_child;
- /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
- for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
- if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
- copy_v3_v3(ebo_child->head, ebo->tail);
- ebo_child->rad_head = ebo->rad_tail;
- }
- }
+ /* Also move connected ebo_child, in case ebo_child's name aren't mirrored properly */
+ for (ebo_child = arm->edbo->first; ebo_child; ebo_child = ebo_child->next) {
+ if ((ebo_child->flag & BONE_CONNECTED) && (ebo_child->parent == ebo)) {
+ copy_v3_v3(ebo_child->head, ebo->tail);
+ ebo_child->rad_head = ebo->rad_tail;
+ }
+ }
- /* Also move connected parent, in case parent's name isn't mirrored properly */
- if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
- EditBone *parent = ebo->parent;
- copy_v3_v3(parent->tail, ebo->head);
- parent->rad_tail = ebo->rad_head;
- }
- }
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
+ EditBone *parent = ebo->parent;
+ copy_v3_v3(parent->tail, ebo->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
- bid++;
- }
+ bid++;
+ }
}
-
/* ********************* armature ************** */
static void createTransArmatureVerts(TransInfo *t)
{
- t->data_len_all = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EditBone *ebo, *eboflip;
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
- int total_mirrored = 0;
-
- tc->data_len = 0;
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- const int data_len_prev = tc->data_len;
-
- if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- if (ebo->flag & BONE_SELECTED)
- tc->data_len++;
- }
- else if (t->mode == TFM_BONE_ROLL) {
- if (ebo->flag & BONE_SELECTED)
- tc->data_len++;
- }
- else {
- if (ebo->flag & BONE_TIPSEL)
- tc->data_len++;
- if (ebo->flag & BONE_ROOTSEL)
- tc->data_len++;
- }
- }
-
- if (mirror && (data_len_prev < tc->data_len)) {
- eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
- if (eboflip)
- total_mirrored++;
- }
- }
- if (!tc->data_len) {
- continue;
- }
-
- if (mirror) {
- BoneInitData *bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
-
- /* trick to terminate iteration */
- bid[total_mirrored].bone = NULL;
-
- tc->custom.type.data = bid;
- tc->custom.type.use_free = true;
- }
- t->data_len_all += tc->data_len;
- }
-
- transform_around_single_fallback(t);
- t->data_len_all = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (!tc->data_len) {
- continue;
- }
-
- EditBone *ebo, *eboflip;
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- TransData *td, *td_old;
- float mtx[3][3], smtx[3][3], bonemat[3][3];
- bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
- BoneInitData *bid = tc->custom.type.data;
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
- int i = 0;
-
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- td_old = td;
- ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
-
- if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
- if (t->mode == TFM_BONE_ENVELOPE) {
- if (ebo->flag & BONE_ROOTSEL) {
- td->val = &ebo->rad_head;
- td->ival = *td->val;
-
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->loc = NULL;
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- if (ebo->flag & BONE_TIPSEL) {
- td->val = &ebo->rad_tail;
- td->ival = *td->val;
- copy_v3_v3(td->center, ebo->tail);
- td->flag = TD_SELECTED;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->loc = NULL;
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
-
- }
- else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- if (ebo->flag & BONE_SELECTED) {
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
- td->loc = NULL;
- td->val = &ebo->dist;
- td->ival = ebo->dist;
- }
- else {
- // abusive storage of scale in the loc pointer :)
- td->loc = &ebo->xwidth;
- copy_v3_v3(td->iloc, td->loc);
- td->val = NULL;
- }
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- /* use local bone matrix */
- ED_armature_ebone_to_mat3(ebo, bonemat);
- mul_m3_m3m3(td->mtx, mtx, bonemat);
- invert_m3_m3(td->smtx, td->mtx);
-
- copy_m3_m3(td->axismtx, td->mtx);
- normalize_m3(td->axismtx);
-
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- else if (t->mode == TFM_BONE_ROLL) {
- if (ebo->flag & BONE_SELECTED) {
- td->loc = NULL;
- td->val = &(ebo->roll);
- td->ival = ebo->roll;
-
- copy_v3_v3(td->center, ebo->head);
- td->flag = TD_SELECTED;
-
- td->ext = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- else {
- if (ebo->flag & BONE_TIPSEL) {
- copy_v3_v3(td->iloc, ebo->tail);
-
- /* Don't allow single selected tips to have a modified center,
- * causes problem with snapping (see T45974).
- * However, in rotation mode, we want to keep that 'rotate bone around root with
- * only its tip selected' behavior (see T46325). */
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL)))
- {
- copy_v3_v3(td->center, ebo->head);
- }
- else {
- copy_v3_v3(td->center, td->iloc);
- }
-
- td->loc = ebo->tail;
- td->flag = TD_SELECTED;
- if (ebo->flag & BONE_EDITMODE_LOCKED)
- td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- ED_armature_ebone_to_mat3(ebo, td->axismtx);
-
- if ((ebo->flag & BONE_ROOTSEL) == 0) {
- td->extra = ebo;
- td->ival = ebo->roll;
- }
-
- td->ext = NULL;
- td->val = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- if (ebo->flag & BONE_ROOTSEL) {
- copy_v3_v3(td->iloc, ebo->head);
- copy_v3_v3(td->center, td->iloc);
- td->loc = ebo->head;
- td->flag = TD_SELECTED;
- if (ebo->flag & BONE_EDITMODE_LOCKED)
- td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- ED_armature_ebone_to_mat3(ebo, td->axismtx);
-
- td->extra = ebo; /* to fix roll */
- td->ival = ebo->roll;
-
- td->ext = NULL;
- td->val = NULL;
- td->ob = tc->obedit;
-
- td++;
- }
- }
- }
-
- if (mirror && (td_old != td)) {
- eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
- if (eboflip) {
- bid[i].bone = eboflip;
- bid[i].dist = eboflip->dist;
- bid[i].rad_tail = eboflip->rad_tail;
- bid[i].roll = eboflip->roll;
- bid[i].xwidth = eboflip->xwidth;
- bid[i].zwidth = eboflip->zwidth;
- copy_v3_v3(bid[i].head, eboflip->head);
- copy_v3_v3(bid[i].tail, eboflip->tail);
- i++;
- }
- }
- }
-
- if (mirror) {
- /* trick to terminate iteration */
- BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
- bid[i].bone = NULL;
- }
- }
+ t->data_len_all = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EditBone *ebo, *eboflip;
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
+ int total_mirrored = 0;
+
+ tc->data_len = 0;
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ const int data_len_prev = tc->data_len;
+
+ if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
+ if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ if (ebo->flag & BONE_SELECTED)
+ tc->data_len++;
+ }
+ else if (t->mode == TFM_BONE_ROLL) {
+ if (ebo->flag & BONE_SELECTED)
+ tc->data_len++;
+ }
+ else {
+ if (ebo->flag & BONE_TIPSEL)
+ tc->data_len++;
+ if (ebo->flag & BONE_ROOTSEL)
+ tc->data_len++;
+ }
+ }
+
+ if (mirror && (data_len_prev < tc->data_len)) {
+ eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
+ if (eboflip)
+ total_mirrored++;
+ }
+ }
+ if (!tc->data_len) {
+ continue;
+ }
+
+ if (mirror) {
+ BoneInitData *bid = MEM_mallocN((total_mirrored + 1) * sizeof(BoneInitData), "BoneInitData");
+
+ /* trick to terminate iteration */
+ bid[total_mirrored].bone = NULL;
+
+ tc->custom.type.data = bid;
+ tc->custom.type.use_free = true;
+ }
+ t->data_len_all += tc->data_len;
+ }
+
+ transform_around_single_fallback(t);
+ t->data_len_all = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (!tc->data_len) {
+ continue;
+ }
+
+ EditBone *ebo, *eboflip;
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ TransData *td, *td_old;
+ float mtx[3][3], smtx[3][3], bonemat[3][3];
+ bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
+ BoneInitData *bid = tc->custom.type.data;
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone");
+ int i = 0;
+
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ td_old = td;
+ ebo->oldlength =
+ ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
+
+ if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) {
+ if (t->mode == TFM_BONE_ENVELOPE) {
+ if (ebo->flag & BONE_ROOTSEL) {
+ td->val = &ebo->rad_head;
+ td->ival = *td->val;
+
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ if (ebo->flag & BONE_TIPSEL) {
+ td->val = &ebo->rad_tail;
+ td->ival = *td->val;
+ copy_v3_v3(td->center, ebo->tail);
+ td->flag = TD_SELECTED;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->loc = NULL;
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
+ if (ebo->flag & BONE_SELECTED) {
+ if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
+ td->loc = NULL;
+ td->val = &ebo->dist;
+ td->ival = ebo->dist;
+ }
+ else {
+ // abusive storage of scale in the loc pointer :)
+ td->loc = &ebo->xwidth;
+ copy_v3_v3(td->iloc, td->loc);
+ td->val = NULL;
+ }
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ /* use local bone matrix */
+ ED_armature_ebone_to_mat3(ebo, bonemat);
+ mul_m3_m3m3(td->mtx, mtx, bonemat);
+ invert_m3_m3(td->smtx, td->mtx);
+
+ copy_m3_m3(td->axismtx, td->mtx);
+ normalize_m3(td->axismtx);
+
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else if (t->mode == TFM_BONE_ROLL) {
+ if (ebo->flag & BONE_SELECTED) {
+ td->loc = NULL;
+ td->val = &(ebo->roll);
+ td->ival = ebo->roll;
+
+ copy_v3_v3(td->center, ebo->head);
+ td->flag = TD_SELECTED;
+
+ td->ext = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ else {
+ if (ebo->flag & BONE_TIPSEL) {
+ copy_v3_v3(td->iloc, ebo->tail);
+
+ /* Don't allow single selected tips to have a modified center,
+ * causes problem with snapping (see T45974).
+ * However, in rotation mode, we want to keep that 'rotate bone around root with
+ * only its tip selected' behavior (see T46325). */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) {
+ copy_v3_v3(td->center, ebo->head);
+ }
+ else {
+ copy_v3_v3(td->center, td->iloc);
+ }
+
+ td->loc = ebo->tail;
+ td->flag = TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ ED_armature_ebone_to_mat3(ebo, td->axismtx);
+
+ if ((ebo->flag & BONE_ROOTSEL) == 0) {
+ td->extra = ebo;
+ td->ival = ebo->roll;
+ }
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ copy_v3_v3(td->iloc, ebo->head);
+ copy_v3_v3(td->center, td->iloc);
+ td->loc = ebo->head;
+ td->flag = TD_SELECTED;
+ if (ebo->flag & BONE_EDITMODE_LOCKED)
+ td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ ED_armature_ebone_to_mat3(ebo, td->axismtx);
+
+ td->extra = ebo; /* to fix roll */
+ td->ival = ebo->roll;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->ob = tc->obedit;
+
+ td++;
+ }
+ }
+ }
+
+ if (mirror && (td_old != td)) {
+ eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
+ if (eboflip) {
+ bid[i].bone = eboflip;
+ bid[i].dist = eboflip->dist;
+ bid[i].rad_tail = eboflip->rad_tail;
+ bid[i].roll = eboflip->roll;
+ bid[i].xwidth = eboflip->xwidth;
+ bid[i].zwidth = eboflip->zwidth;
+ copy_v3_v3(bid[i].head, eboflip->head);
+ copy_v3_v3(bid[i].tail, eboflip->tail);
+ i++;
+ }
+ }
+ }
+
+ if (mirror) {
+ /* trick to terminate iteration */
+ BLI_assert(i + 1 == (MEM_allocN_len(bid) / sizeof(*bid)));
+ bid[i].bone = NULL;
+ }
+ }
}
/* ********************* meta elements ********* */
static void createTransMBallVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- MetaBall *mb = (MetaBall *)tc->obedit->data;
- MetaElem *ml;
- TransData *td;
- TransDataExtension *tx;
- float mtx[3][3], smtx[3][3];
- int count = 0, countsel = 0;
- 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 (is_prop_edit) count++;
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- continue;
- }
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(MBall EditMode)");
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "MetaElement_TransExtension");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- 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);
-
- quat_to_mat3(td->axismtx, ml->quat);
-
- if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
- else td->flag = TD_USEQUAT;
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = tx;
-
- /* Radius of MetaElem (mass of MetaElem influence) */
- if (ml->flag & MB_SCALE_RAD) {
- td->val = &ml->rad;
- td->ival = ml->rad;
- }
- else {
- td->val = &ml->s;
- td->ival = ml->s;
- }
-
- /* expx/expy/expz determine "shape" of some MetaElem types */
- tx->size = &ml->expx;
- tx->isize[0] = ml->expx;
- tx->isize[1] = ml->expy;
- tx->isize[2] = ml->expz;
-
- /* quat is used for rotation of MetaElem */
- tx->quat = ml->quat;
- copy_qt_qt(tx->iquat, ml->quat);
-
- tx->rot = NULL;
-
- td++;
- tx++;
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ MetaBall *mb = (MetaBall *)tc->obedit->data;
+ MetaElem *ml;
+ TransData *td;
+ TransDataExtension *tx;
+ float mtx[3][3], smtx[3][3];
+ int count = 0, countsel = 0;
+ 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 (is_prop_edit)
+ count++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ continue;
+ }
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(MBall EditMode)");
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "MetaElement_TransExtension");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ 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);
+
+ quat_to_mat3(td->axismtx, ml->quat);
+
+ if (ml->flag & SELECT)
+ td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
+ else
+ td->flag = TD_USEQUAT;
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = tx;
+
+ /* Radius of MetaElem (mass of MetaElem influence) */
+ if (ml->flag & MB_SCALE_RAD) {
+ td->val = &ml->rad;
+ td->ival = ml->rad;
+ }
+ else {
+ td->val = &ml->s;
+ td->ival = ml->s;
+ }
+
+ /* expx/expy/expz determine "shape" of some MetaElem types */
+ tx->size = &ml->expx;
+ tx->isize[0] = ml->expx;
+ tx->isize[1] = ml->expy;
+ tx->isize[2] = ml->expz;
+
+ /* quat is used for rotation of MetaElem */
+ tx->quat = ml->quat;
+ copy_qt_qt(tx->iquat, ml->quat);
+
+ tx->rot = NULL;
+
+ td++;
+ tx++;
+ }
+ }
+ }
}
/* ********************* curve/surface ********* */
static void calc_distanceCurveVerts(TransData *head, TransData *tail)
{
- TransData *td, *td_near = NULL;
- for (td = head; td <= tail; td++) {
- if (td->flag & TD_SELECTED) {
- td_near = td;
- td->dist = 0.0f;
- }
- else if (td_near) {
- float dist;
- dist = len_v3v3(td_near->center, td->center);
- if (dist < (td - 1)->dist) {
- td->dist = (td - 1)->dist;
- }
- else {
- td->dist = dist;
- }
- }
- else {
- td->dist = FLT_MAX;
- td->flag |= TD_NOTCONNECTED;
- }
- }
- td_near = NULL;
- for (td = tail; td >= head; td--) {
- if (td->flag & TD_SELECTED) {
- td_near = td;
- td->dist = 0.0f;
- }
- else if (td_near) {
- float dist;
- dist = len_v3v3(td_near->center, td->center);
- if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
- td->flag &= ~TD_NOTCONNECTED;
- if (dist < (td + 1)->dist) {
- td->dist = (td + 1)->dist;
- }
- else {
- td->dist = dist;
- }
- }
- }
- }
+ TransData *td, *td_near = NULL;
+ for (td = head; td <= tail; td++) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if (td_near) {
+ float dist;
+ dist = len_v3v3(td_near->center, td->center);
+ if (dist < (td - 1)->dist) {
+ td->dist = (td - 1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ else {
+ td->dist = FLT_MAX;
+ td->flag |= TD_NOTCONNECTED;
+ }
+ }
+ td_near = NULL;
+ for (td = tail; td >= head; td--) {
+ if (td->flag & TD_SELECTED) {
+ td_near = td;
+ td->dist = 0.0f;
+ }
+ else if (td_near) {
+ float dist;
+ dist = len_v3v3(td_near->center, td->center);
+ if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) {
+ td->flag &= ~TD_NOTCONNECTED;
+ if (dist < (td + 1)->dist) {
+ td->dist = (td + 1)->dist;
+ }
+ else {
+ td->dist = dist;
+ }
+ }
+ }
+ }
}
/* Utility function for getting the handle data from bezier's */
static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
{
- TransDataCurveHandleFlags *hdata;
- td->flag |= TD_BEZTRIPLE;
- hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
- hdata->ih1 = bezt->h1;
- hdata->h1 = &bezt->h1;
- hdata->ih2 = bezt->h2; /* in case the second is not selected */
- hdata->h2 = &bezt->h2;
- return hdata;
+ TransDataCurveHandleFlags *hdata;
+ td->flag |= TD_BEZTRIPLE;
+ hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
+ hdata->ih1 = bezt->h1;
+ hdata->h1 = &bezt->h1;
+ hdata->ih2 = bezt->h2; /* in case the second is not selected */
+ hdata->h2 = &bezt->h2;
+ return hdata;
}
/**
* For the purpose of transform code we need to behave as if handles are selected,
* even when they aren't (see special case below).
*/
-static int bezt_select_to_transform_triple_flag(
- const BezTriple *bezt, const bool hide_handles)
-{
- int flag = 0;
-
- if (hide_handles) {
- if (bezt->f2 & SELECT) {
- flag = (1 << 0) | (1 << 1) | (1 << 2);
- }
- }
- else {
- flag = (
- ((bezt->f1 & SELECT) ? (1 << 0) : 0) |
- ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
- ((bezt->f3 & SELECT) ? (1 << 2) : 0)
- );
- }
-
- /* Special case for auto & aligned handles:
- * When a center point is being moved without the handles,
- * leaving the handles stationary makes no sense and only causes strange behavior,
- * where one handle is arbitrarily anchored, the other one is aligned and lengthened
- * based on where the center point is moved. Also a bug when cancelling, see: T52007.
- *
- * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
- * However that doesn't resolve odd behavior, so best transform the handles in this case.
- */
- if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
- if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) &&
- ELEM(bezt->h2, HD_AUTO, HD_ALIGN))
- {
- flag = (1 << 0) | (1 << 1) | (1 << 2);
- }
- }
-
- return flag;
+static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const bool hide_handles)
+{
+ int flag = 0;
+
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+ else {
+ flag = (((bezt->f1 & SELECT) ? (1 << 0) : 0) | ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
+ ((bezt->f3 & SELECT) ? (1 << 2) : 0));
+ }
+
+ /* Special case for auto & aligned handles:
+ * When a center point is being moved without the handles,
+ * leaving the handles stationary makes no sense and only causes strange behavior,
+ * where one handle is arbitrarily anchored, the other one is aligned and lengthened
+ * based on where the center point is moved. Also a bug when cancelling, see: T52007.
+ *
+ * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
+ * However that doesn't resolve odd behavior, so best transform the handles in this case.
+ */
+ if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+
+ return flag;
}
static void createTransCurveVerts(TransInfo *t)
@@ -1742,288 +1764,320 @@ static void createTransCurveVerts(TransInfo *t)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
- t->data_len_all = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Curve *cu = tc->obedit->data;
- BLI_assert(cu->editnurb != NULL);
- BezTriple *bezt;
- BPoint *bp;
- int a;
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ? ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) : false;
-
- /* count total of vertices, check identical as in 2nd loop for making transdata! */
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
- if (bezt_tx & SEL_F1) { countsel++; }
- if (bezt_tx & SEL_F2) { countsel++; }
- if (bezt_tx & SEL_F3) { countsel++; }
- if (is_prop_edit) count += 3;
-
- }
- }
- }
- else {
- for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
- if (bp->hide == 0) {
- if (is_prop_edit) count++;
- if (bp->f1 & SELECT) countsel++;
- }
- }
- }
- }
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- tc->data_len = 0;
- continue;
- }
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
-
- t->data_len_all += tc->data_len;
- }
-
- transform_around_single_fallback(t);
- t->data_len_all = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len == 0) {
- continue;
- }
-
- Curve *cu = tc->obedit->data;
- BezTriple *bezt;
- BPoint *bp;
- int a;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- View3D *v3d = t->view;
- short hide_handles = (v3d != NULL) ? ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) : false;
-
- float mtx[3][3], smtx[3][3];
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- TransData *td = tc->data;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- TransData *head, *tail;
- head = tail = td;
- for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
- if (bezt->hide == 0) {
- TransDataCurveHandleFlags *hdata = NULL;
- float axismtx[3][3];
-
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- float normal[3], plane[3];
-
- BKE_nurb_bezt_calc_normal(nu, bezt, normal);
- BKE_nurb_bezt_calc_plane(nu, bezt, plane);
-
- if (createSpaceNormalTangent(axismtx, normal, plane)) {
- /* pass */
- }
- else {
- normalize_v3(normal);
- axis_dominant_v3_to_m3(axismtx, normal);
- invert_m3(axismtx);
- }
- }
-
- /* Elements that will be transform (not always a match to selection). */
- const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
-
- if (is_prop_edit || bezt_tx & SEL_F1) {
- copy_v3_v3(td->iloc, bezt->vec[0]);
- td->loc = bezt->vec[0];
- copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
- (bezt->f2 & SELECT)) ? 1 : 0]);
- if (hide_handles) {
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- else {
- if (bezt->f1 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- td->ext = NULL;
- td->val = NULL;
-
- hdata = initTransDataCurveHandles(td, bezt);
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- td++;
- tail++;
- }
-
- /* This is the Curve Point, the other two are handles */
- if (is_prop_edit || bezt_tx & SEL_F2) {
- copy_v3_v3(td->iloc, bezt->vec[1]);
- td->loc = bezt->vec[1];
- copy_v3_v3(td->center, td->loc);
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- td->ext = NULL;
-
- /* TODO - make points scale */
- if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
- td->val = &(bezt->radius);
- td->ival = bezt->radius;
- }
- else if (t->mode == TFM_TILT) {
- td->val = &(bezt->tilt);
- td->ival = bezt->tilt;
- }
- else {
- td->val = NULL;
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
- /* If the middle is selected but the sides arnt, this is needed */
- if (hdata == NULL) {
- /* if the handle was not saved by the previous handle */
- hdata = initTransDataCurveHandles(td, bezt);
- }
-
- td++;
- tail++;
- }
- if (is_prop_edit || bezt_tx & SEL_F3) {
- copy_v3_v3(td->iloc, bezt->vec[2]);
- td->loc = bezt->vec[2];
- copy_v3_v3(td->center, bezt->vec[(hide_handles ||
- (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
- (bezt->f2 & SELECT)) ? 1 : 2]);
- if (hide_handles) {
- if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- else {
- if (bezt->f3 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- }
- td->ext = NULL;
- td->val = NULL;
-
- if (hdata == NULL) {
- /* if the handle was not saved by the previous handle */
- hdata = initTransDataCurveHandles(td, bezt);
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_m3_m3(td->axismtx, axismtx);
- }
-
- td++;
- tail++;
- }
-
- (void)hdata; /* quiet warning */
- }
- else if (is_prop_edit && head != tail) {
- calc_distanceCurveVerts(head, tail - 1);
- 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
- * but for now just don't change handle types */
- if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
- /* sets the handles based on their selection,
- * do this after the data is copied to the TransData */
- BKE_nurb_handles_test(nu, !hide_handles);
- }
- }
- else {
- TransData *head, *tail;
- head = tail = td;
- for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
- if (bp->hide == 0) {
- if (is_prop_edit || (bp->f1 & SELECT)) {
- float axismtx[3][3];
-
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- if (nu->pntsv == 1) {
- float normal[3], plane[3];
-
- BKE_nurb_bpoint_calc_normal(nu, bp, normal);
- BKE_nurb_bpoint_calc_plane(nu, bp, plane);
-
- if (createSpaceNormalTangent(axismtx, normal, plane)) {
- /* pass */
- }
- else {
- normalize_v3(normal);
- axis_dominant_v3_to_m3(axismtx, normal);
- invert_m3(axismtx);
- }
- }
- }
-
- copy_v3_v3(td->iloc, bp->vec);
- td->loc = bp->vec;
- copy_v3_v3(td->center, td->loc);
- if (bp->f1 & SELECT) td->flag = TD_SELECTED;
- else td->flag = 0;
- td->ext = NULL;
-
- if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
- td->val = &(bp->radius);
- td->ival = bp->radius;
- }
- else {
- td->val = &(bp->tilt);
- td->ival = bp->tilt;
- }
-
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- if (nu->pntsv == 1) {
- copy_m3_m3(td->axismtx, axismtx);
- }
- }
-
- td++;
- tail++;
- }
- }
- else if (is_prop_edit && head != tail) {
- calc_distanceCurveVerts(head, tail - 1);
- head = tail;
- }
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
- }
+ t->data_len_all = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Curve *cu = tc->obedit->data;
+ BLI_assert(cu->editnurb != NULL);
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ /* count total of vertices, check identical as in 2nd loop for making transdata! */
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+ if (bezt_tx & SEL_F1) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F2) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F3) {
+ countsel++;
+ }
+ if (is_prop_edit)
+ count += 3;
+ }
+ }
+ }
+ else {
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit)
+ count++;
+ if (bp->f1 & SELECT)
+ countsel++;
+ }
+ }
+ }
+ }
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ tc->data_len = 0;
+ continue;
+ }
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
+
+ t->data_len_all += tc->data_len;
+ }
+
+ transform_around_single_fallback(t);
+ t->data_len_all = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len == 0) {
+ continue;
+ }
+
+ Curve *cu = tc->obedit->data;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ float mtx[3][3], smtx[3][3];
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ TransData *td = tc->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ TransDataCurveHandleFlags *hdata = NULL;
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+ BKE_nurb_bezt_calc_plane(nu, bezt, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+
+ /* Elements that will be transform (not always a match to selection). */
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+
+ if (is_prop_edit || bezt_tx & SEL_F1) {
+ copy_v3_v3(td->iloc, bezt->vec[0]);
+ td->loc = bezt->vec[0];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 0]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ else {
+ if (bezt->f1 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ hdata = initTransDataCurveHandles(td, bezt);
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ /* This is the Curve Point, the other two are handles */
+ if (is_prop_edit || bezt_tx & SEL_F2) {
+ copy_v3_v3(td->iloc, bezt->vec[1]);
+ td->loc = bezt->vec[1];
+ copy_v3_v3(td->center, td->loc);
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ td->ext = NULL;
+
+ /* TODO - make points scale */
+ if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
+ td->val = &(bezt->radius);
+ td->ival = bezt->radius;
+ }
+ else if (t->mode == TFM_TILT) {
+ td->val = &(bezt->tilt);
+ td->ival = bezt->tilt;
+ }
+ else {
+ td->val = NULL;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0)
+ /* If the middle is selected but the sides arnt, this is needed */
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ td++;
+ tail++;
+ }
+ if (is_prop_edit || bezt_tx & SEL_F3) {
+ copy_v3_v3(td->iloc, bezt->vec[2]);
+ td->loc = bezt->vec[2];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 2]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ else {
+ if (bezt->f3 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ (void)hdata; /* quiet warning */
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ 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
+ * but for now just don't change handle types */
+ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
+ /* sets the handles based on their selection,
+ * do this after the data is copied to the TransData */
+ BKE_nurb_handles_test(nu, !hide_handles);
+ }
+ }
+ else {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+ }
+
+ copy_v3_v3(td->iloc, bp->vec);
+ td->loc = bp->vec;
+ copy_v3_v3(td->center, td->loc);
+ if (bp->f1 & SELECT)
+ td->flag = TD_SELECTED;
+ else
+ td->flag = 0;
+ td->ext = NULL;
+
+ if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
+ td->val = &(bp->radius);
+ td->ival = bp->radius;
+ }
+ else {
+ td->val = &(bp->tilt);
+ td->ival = bp->tilt;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+ }
+
+ td++;
+ tail++;
+ }
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ head = tail;
+ }
+ }
+ if (is_prop_edit && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
@@ -2033,262 +2087,281 @@ static void createTransCurveVerts(TransInfo *t)
static void createTransLatticeVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- Lattice *latt = ((Lattice *)tc->obedit->data)->editlatt->latt;
- TransData *td = NULL;
- BPoint *bp;
- float mtx[3][3], smtx[3][3];
- int a;
- int count = 0, countsel = 0;
- 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 (is_prop_edit) count++;
- }
- bp++;
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) return;
-
- if (is_prop_edit) tc->data_len = count;
- else tc->data_len = countsel;
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- td = tc->data;
- bp = latt->def;
- a = latt->pntsu * latt->pntsv * latt->pntsw;
- while (a--) {
- if (is_prop_edit || (bp->f1 & SELECT)) {
- if (bp->hide == 0) {
- copy_v3_v3(td->iloc, bp->vec);
- td->loc = bp->vec;
- copy_v3_v3(td->center, td->loc);
- if (bp->f1 & SELECT) {
- td->flag = TD_SELECTED;
- }
- else {
- td->flag = 0;
- }
- copy_m3_m3(td->smtx, smtx);
- copy_m3_m3(td->mtx, mtx);
-
- td->ext = NULL;
- td->val = NULL;
-
- td++;
- }
- }
- bp++;
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ Lattice *latt = ((Lattice *)tc->obedit->data)->editlatt->latt;
+ TransData *td = NULL;
+ BPoint *bp;
+ float mtx[3][3], smtx[3][3];
+ int a;
+ int count = 0, countsel = 0;
+ 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 (is_prop_edit)
+ count++;
+ }
+ bp++;
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0)
+ return;
+
+ if (is_prop_edit)
+ tc->data_len = count;
+ else
+ tc->data_len = countsel;
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Lattice EditMode)");
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ td = tc->data;
+ bp = latt->def;
+ a = latt->pntsu * latt->pntsv * latt->pntsw;
+ while (a--) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
+ if (bp->hide == 0) {
+ copy_v3_v3(td->iloc, bp->vec);
+ td->loc = bp->vec;
+ copy_v3_v3(td->center, td->loc);
+ if (bp->f1 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td++;
+ }
+ }
+ bp++;
+ }
+ }
}
/* ******************* particle edit **************** */
static void createTransParticleVerts(bContext *C, TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td = NULL;
- TransDataExtension *tx;
- Object *ob = CTX_data_active_object(C);
- ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, ob);
- ParticleSystem *psys = NULL;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- float mat[4][4];
- int i, k, transformparticle;
- int count = 0, hasselected = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
-
- psys = edit->psys;
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- point->flag &= ~PEP_TRANSFORM;
- transformparticle = 0;
-
- if ((point->flag & PEP_HIDE) == 0) {
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if ((key->flag & PEK_HIDE) == 0) {
- if (key->flag & PEK_SELECT) {
- hasselected = 1;
- transformparticle = 1;
- }
- else if (is_prop_edit)
- transformparticle = 1;
- }
- }
- }
-
- if (transformparticle) {
- count += point->totkey;
- point->flag |= PEP_TRANSFORM;
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (hasselected == 0) return;
-
- tc->data_len = count;
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)");
-
- if (t->mode == TFM_BAKE_TIME)
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "Particle_TransExtension");
- else
- tx = tc->data_ext = NULL;
-
- unit_m4(mat);
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- TransData *head, *tail;
- head = tail = td;
-
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
- }
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if (key->flag & PEK_USE_WCO) {
- copy_v3_v3(key->world_co, key->co);
- mul_m4_v3(mat, key->world_co);
- td->loc = key->world_co;
- }
- else
- td->loc = key->co;
-
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
-
- if (key->flag & PEK_SELECT)
- td->flag |= TD_SELECTED;
- else if (!is_prop_edit)
- td->flag |= TD_SKIP;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- /* don't allow moving roots */
- if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
- td->protectflag |= OB_LOCK_LOC;
-
- td->ob = ob;
- td->ext = tx;
- if (t->mode == TFM_BAKE_TIME) {
- td->val = key->time;
- td->ival = *(key->time);
- /* abuse size and quat for min/max values */
- td->flag |= TD_NO_EXT;
- if (k == 0) tx->size = NULL;
- else tx->size = (key - 1)->time;
-
- if (k == point->totkey - 1) tx->quat = NULL;
- else tx->quat = (key + 1)->time;
- }
-
- td++;
- if (tx)
- tx++;
- tail++;
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td = NULL;
+ TransDataExtension *tx;
+ Object *ob = CTX_data_active_object(C);
+ ParticleEditSettings *pset = PE_settings(t->scene);
+ PTCacheEdit *edit = PE_get_current(t->scene, ob);
+ ParticleSystem *psys = NULL;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ float mat[4][4];
+ int i, k, transformparticle;
+ int count = 0, hasselected = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH)
+ return;
+
+ psys = edit->psys;
+
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
+ point->flag &= ~PEP_TRANSFORM;
+ transformparticle = 0;
+
+ if ((point->flag & PEP_HIDE) == 0) {
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ if ((key->flag & PEK_HIDE) == 0) {
+ if (key->flag & PEK_SELECT) {
+ hasselected = 1;
+ transformparticle = 1;
+ }
+ else if (is_prop_edit)
+ transformparticle = 1;
+ }
+ }
+ }
+
+ if (transformparticle) {
+ count += point->totkey;
+ point->flag |= PEP_TRANSFORM;
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (hasselected == 0)
+ return;
+
+ tc->data_len = count;
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Particle Mode)");
+
+ if (t->mode == TFM_BAKE_TIME)
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "Particle_TransExtension");
+ else
+ tx = tc->data_ext = NULL;
+
+ unit_m4(mat);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
+ TransData *head, *tail;
+ head = tail = td;
+
+ if (!(point->flag & PEP_TRANSFORM))
+ continue;
+
+ if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+ }
+
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ if (key->flag & PEK_USE_WCO) {
+ copy_v3_v3(key->world_co, key->co);
+ mul_m4_v3(mat, key->world_co);
+ td->loc = key->world_co;
+ }
+ else
+ td->loc = key->co;
+
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
+
+ if (key->flag & PEK_SELECT)
+ td->flag |= TD_SELECTED;
+ else if (!is_prop_edit)
+ td->flag |= TD_SKIP;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ /* don't allow moving roots */
+ if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
+ td->protectflag |= OB_LOCK_LOC;
+
+ td->ob = ob;
+ td->ext = tx;
+ if (t->mode == TFM_BAKE_TIME) {
+ td->val = key->time;
+ td->ival = *(key->time);
+ /* abuse size and quat for min/max values */
+ td->flag |= TD_NO_EXT;
+ if (k == 0)
+ tx->size = NULL;
+ else
+ tx->size = (key - 1)->time;
+
+ if (k == point->totkey - 1)
+ tx->quat = NULL;
+ else
+ tx->quat = (key + 1)->time;
+ }
+
+ td++;
+ if (tx)
+ tx++;
+ tail++;
+ }
+ if (is_prop_edit && head != tail)
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
}
void flushTransParticles(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- TransData *td;
- float mat[4][4], imat[4][4], co[3];
- int i, k;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- /* we do transform in world space, so flush world space position
- * back to particle local space (only for hair particles) */
- td = tc->data;
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
- psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
- invert_m4_m4(imat, mat);
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- copy_v3_v3(co, key->world_co);
- mul_m4_v3(imat, co);
-
-
- /* optimization for proportional edit */
- if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
- copy_v3_v3(key->co, co);
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
- else
- point->flag |= PEP_EDIT_RECALC;
- }
-
- PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
- DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ ParticleSystem *psys = edit->psys;
+ PTCacheEditPoint *point;
+ PTCacheEditKey *key;
+ TransData *td;
+ float mat[4][4], imat[4][4], co[3];
+ int i, k;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ /* we do transform in world space, so flush world space position
+ * back to particle local space (only for hair particles) */
+ td = tc->data;
+ for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
+ if (!(point->flag & PEP_TRANSFORM))
+ continue;
+
+ if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ psys_mat_hair_to_global(
+ ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+ invert_m4_m4(imat, mat);
+
+ for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ copy_v3_v3(co, key->world_co);
+ mul_m4_v3(imat, co);
+
+ /* optimization for proportional edit */
+ if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
+ copy_v3_v3(key->co, co);
+ point->flag |= PEP_EDIT_RECALC;
+ }
+ }
+ }
+ else
+ point->flag |= PEP_EDIT_RECALC;
+ }
+
+ PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
+ DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
+ }
}
/* ********************* mesh ****************** */
-static bool bmesh_test_dist_add(
- BMVert *v, BMVert *v_other,
- float *dists, const float *dists_prev,
- /* optionally track original index */
- int *index, const int *index_prev,
- float mtx[3][3])
-{
- if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
- (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
- {
- const int i = BM_elem_index_get(v);
- const int i_other = BM_elem_index_get(v_other);
- float vec[3];
- float dist_other;
- sub_v3_v3v3(vec, v->co, v_other->co);
- mul_m3_v3(mtx, vec);
-
- dist_other = dists_prev[i] + len_v3(vec);
- if (dist_other < dists[i_other]) {
- dists[i_other] = dist_other;
- if (index != NULL) {
- index[i_other] = index_prev[i];
- }
- return true;
- }
- }
-
- return false;
+static bool bmesh_test_dist_add(BMVert *v,
+ BMVert *v_other,
+ float *dists,
+ const float *dists_prev,
+ /* optionally track original index */
+ int *index,
+ const int *index_prev,
+ float mtx[3][3])
+{
+ if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
+ (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) {
+ const int i = BM_elem_index_get(v);
+ const int i_other = BM_elem_index_get(v_other);
+ float vec[3];
+ float dist_other;
+ sub_v3_v3v3(vec, v->co, v_other->co);
+ mul_m3_v3(mtx, vec);
+
+ dist_other = dists_prev[i] + len_v3(vec);
+ if (dist_other < dists[i_other]) {
+ dists[i_other] = dist_other;
+ if (index != NULL) {
+ index[i_other] = index_prev[i];
+ }
+ return true;
+ }
+ }
+
+ return false;
}
/**
@@ -2296,680 +2369,679 @@ static bool bmesh_test_dist_add(
* \param dists: Store the closest connected distance to selected vertices.
* \param index: Optionally store the original index we're measuring the distance to (can be NULL).
*/
-static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
-{
- BLI_LINKSTACK_DECLARE(queue, BMVert *);
-
- /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
- BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
-
- BLI_LINKSTACK_INIT(queue);
- BLI_LINKSTACK_INIT(queue_next);
-
- {
- BMIter viter;
- BMVert *v;
- 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)) {
- dist = FLT_MAX;
- if (index != NULL) {
- index[i] = i;
- }
- }
- else {
- BLI_LINKSTACK_PUSH(queue, v);
- dist = 0.0f;
- if (index != NULL) {
- index[i] = i;
- }
- }
-
- dists[i] = dist;
- }
- bm->elem_index_dirty &= ~BM_VERT;
- }
-
- /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
- float *dists_prev = MEM_dupallocN(dists);
- int *index_prev = MEM_dupallocN(index); /* may be NULL */
-
- do {
- BMVert *v;
- LinkNode *lnk;
-
- /* this is correct but slow to do each iteration,
- * instead sync the dist's while clearing BM_ELEM_TAG (below) */
+static void editmesh_set_connectivity_distance(BMesh *bm,
+ float mtx[3][3],
+ float *dists,
+ int *index)
+{
+ BLI_LINKSTACK_DECLARE(queue, BMVert *);
+
+ /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
+ BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
+
+ BLI_LINKSTACK_INIT(queue);
+ BLI_LINKSTACK_INIT(queue_next);
+
+ {
+ BMIter viter;
+ BMVert *v;
+ 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)) {
+ dist = FLT_MAX;
+ if (index != NULL) {
+ index[i] = i;
+ }
+ }
+ else {
+ BLI_LINKSTACK_PUSH(queue, v);
+ dist = 0.0f;
+ if (index != NULL) {
+ index[i] = i;
+ }
+ }
+
+ dists[i] = dist;
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+ }
+
+ /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
+ float *dists_prev = MEM_dupallocN(dists);
+ int *index_prev = MEM_dupallocN(index); /* may be NULL */
+
+ do {
+ 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);
+ memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
#endif
- while ((v = BLI_LINKSTACK_POP(queue))) {
- BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
-
- /* connected edge-verts */
- if (v->e != NULL) {
- BMEdge *e_iter, *e_first;
-
- e_iter = e_first = v->e;
-
- /* 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_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, index, index_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, index, index_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) {
- BMVert *v_link = lnk->link;
- const int i = BM_elem_index_get(v_link);
-
- BM_elem_flag_disable(v_link, BM_ELEM_TAG);
-
- /* keep in sync, avoid having to do full memcpy each iteration */
- dists_prev[i] = dists[i];
- if (index != NULL) {
- index_prev[i] = index[i];
- }
- }
-
- BLI_LINKSTACK_SWAP(queue, queue_next);
-
- /* none should be tagged now since 'queue_next' is empty */
- BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
-
- } while (BLI_LINKSTACK_SIZE(queue));
-
- BLI_LINKSTACK_FREE(queue);
- BLI_LINKSTACK_FREE(queue_next);
-
- MEM_freeN(dists_prev);
- if (index_prev != NULL) {
- MEM_freeN(index_prev);
- }
-}
-
-static struct TransIslandData *editmesh_islands_info_calc(
- BMEditMesh *em, int *r_island_tot, int **r_island_vert_map,
- bool calc_single_islands)
-{
- BMesh *bm = em->bm;
- struct TransIslandData *trans_islands;
- char htype;
- char itype;
- int i;
-
- /* group vars */
- int *groups_array;
- int (*group_index)[2];
- int group_tot;
- void **ele_array;
-
- int *vert_map;
-
- if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
- group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT);
-
- htype = BM_EDGE;
- itype = BM_VERTS_OF_EDGE;
-
- }
- else { /* (bm->selectmode & SCE_SELECT_FACE) */
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index,
- NULL, NULL,
- BM_ELEM_SELECT, BM_VERT);
-
- htype = BM_FACE;
- itype = BM_VERTS_OF_FACE;
- }
-
-
- trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
-
- 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 that's not in a face,
- * for now best not crash in that case. */
- 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;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- /* may be an edge OR a face array */
- for (i = 0; i < group_tot; i++) {
- BMEditSelection ese = {NULL};
-
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- float co[3], no[3], tangent[3];
- int j;
-
- zero_v3(co);
- zero_v3(no);
- zero_v3(tangent);
-
- ese.htype = htype;
-
- /* loop on each face in this group:
- * - assign r_vert_map
- * - calculate (co, no)
- */
- for (j = 0; j < fg_len; j++) {
- float tmp_co[3], tmp_no[3], tmp_tangent[3];
-
- ese.ele = ele_array[groups_array[fg_sta + j]];
-
- BM_editselection_center(&ese, tmp_co);
- BM_editselection_normal(&ese, tmp_no);
- BM_editselection_plane(&ese, tmp_tangent);
-
- add_v3_v3(co, tmp_co);
- add_v3_v3(no, tmp_no);
- add_v3_v3(tangent, tmp_tangent);
-
- {
- /* setup vertex map */
- BMIter iter;
- BMVert *v;
-
- /* connected edge-verts */
- BM_ITER_ELEM (v, &iter, ese.ele, itype) {
- vert_map[BM_elem_index_get(v)] = i;
- }
- }
- }
-
- mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
-
- if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
- /* pass */
- }
- else {
- if (normalize_v3(no) != 0.0f) {
- axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
- invert_m3(trans_islands[i].axismtx);
- }
- else {
- unit_m3(trans_islands[i].axismtx);
- }
- }
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
-
- /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
- if (calc_single_islands) {
- BMIter viter;
- BMVert *v;
- int group_tot_single = 0;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
- group_tot_single += 1;
- }
- }
-
- if (group_tot_single != 0) {
- trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (group_tot + group_tot_single));
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
- struct TransIslandData *v_island = &trans_islands[group_tot];
- vert_map[i] = group_tot;
-
- copy_v3_v3(v_island->co, v->co);
-
- if (is_zero_v3(v->no) != 0.0f) {
- axis_dominant_v3_to_m3(v_island->axismtx, v->no);
- invert_m3(v_island->axismtx);
- }
- else {
- unit_m3(v_island->axismtx);
- }
-
- group_tot += 1;
- }
- }
- }
- }
-
- *r_island_tot = group_tot;
- *r_island_vert_map = vert_map;
-
- return trans_islands;
+ while ((v = BLI_LINKSTACK_POP(queue))) {
+ BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX);
+
+ /* connected edge-verts */
+ if (v->e != NULL) {
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+
+ /* 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_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, index, index_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, index, index_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) {
+ BMVert *v_link = lnk->link;
+ const int i = BM_elem_index_get(v_link);
+
+ BM_elem_flag_disable(v_link, BM_ELEM_TAG);
+
+ /* keep in sync, avoid having to do full memcpy each iteration */
+ dists_prev[i] = dists[i];
+ if (index != NULL) {
+ index_prev[i] = index[i];
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(queue, queue_next);
+
+ /* none should be tagged now since 'queue_next' is empty */
+ BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
+
+ } while (BLI_LINKSTACK_SIZE(queue));
+
+ BLI_LINKSTACK_FREE(queue);
+ BLI_LINKSTACK_FREE(queue_next);
+
+ MEM_freeN(dists_prev);
+ if (index_prev != NULL) {
+ MEM_freeN(index_prev);
+ }
+}
+
+static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
+ int *r_island_tot,
+ int **r_island_vert_map,
+ bool calc_single_islands)
+{
+ BMesh *bm = em->bm;
+ struct TransIslandData *trans_islands;
+ char htype;
+ char itype;
+ int i;
+
+ /* group vars */
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ void **ele_array;
+
+ int *vert_map;
+
+ if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
+ group_tot = BM_mesh_calc_edge_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
+
+ htype = BM_EDGE;
+ itype = BM_VERTS_OF_EDGE;
+ }
+ else { /* (bm->selectmode & SCE_SELECT_FACE) */
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
+
+ htype = BM_FACE;
+ itype = BM_VERTS_OF_FACE;
+ }
+
+ trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__);
+
+ 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 that's not in a face,
+ * for now best not crash in that case. */
+ 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;
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* may be an edge OR a face array */
+ for (i = 0; i < group_tot; i++) {
+ BMEditSelection ese = {NULL};
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ float co[3], no[3], tangent[3];
+ int j;
+
+ zero_v3(co);
+ zero_v3(no);
+ zero_v3(tangent);
+
+ ese.htype = htype;
+
+ /* loop on each face in this group:
+ * - assign r_vert_map
+ * - calculate (co, no)
+ */
+ for (j = 0; j < fg_len; j++) {
+ float tmp_co[3], tmp_no[3], tmp_tangent[3];
+
+ ese.ele = ele_array[groups_array[fg_sta + j]];
+
+ BM_editselection_center(&ese, tmp_co);
+ BM_editselection_normal(&ese, tmp_no);
+ BM_editselection_plane(&ese, tmp_tangent);
+
+ add_v3_v3(co, tmp_co);
+ add_v3_v3(no, tmp_no);
+ add_v3_v3(tangent, tmp_tangent);
+
+ {
+ /* setup vertex map */
+ BMIter iter;
+ BMVert *v;
+
+ /* connected edge-verts */
+ BM_ITER_ELEM (v, &iter, ese.ele, itype) {
+ vert_map[BM_elem_index_get(v)] = i;
+ }
+ }
+ }
+
+ mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len);
+
+ if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) {
+ /* pass */
+ }
+ else {
+ if (normalize_v3(no) != 0.0f) {
+ axis_dominant_v3_to_m3(trans_islands[i].axismtx, no);
+ invert_m3(trans_islands[i].axismtx);
+ }
+ else {
+ unit_m3(trans_islands[i].axismtx);
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
+ if (calc_single_islands) {
+ BMIter viter;
+ BMVert *v;
+ int group_tot_single = 0;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ group_tot_single += 1;
+ }
+ }
+
+ if (group_tot_single != 0) {
+ trans_islands = MEM_reallocN(trans_islands,
+ sizeof(*trans_islands) * (group_tot + group_tot_single));
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ struct TransIslandData *v_island = &trans_islands[group_tot];
+ vert_map[i] = group_tot;
+
+ copy_v3_v3(v_island->co, v->co);
+
+ if (is_zero_v3(v->no) != 0.0f) {
+ axis_dominant_v3_to_m3(v_island->axismtx, v->no);
+ invert_m3(v_island->axismtx);
+ }
+ else {
+ unit_m3(v_island->axismtx);
+ }
+
+ group_tot += 1;
+ }
+ }
+ }
+ }
+
+ *r_island_tot = group_tot;
+ *r_island_vert_map = vert_map;
+
+ return trans_islands;
}
/* way to overwrite what data is edited with transform */
-static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx,
- BMEditMesh *em, BMVert *eve, float *bweight,
- struct TransIslandData *v_island, const bool no_island_center)
-{
- float *no, _no[3];
- BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
-
- td->flag = 0;
- //if (key)
- // td->loc = key->co;
- //else
- td->loc = eve->co;
- copy_v3_v3(td->iloc, td->loc);
-
- if ((t->mode == TFM_SHRINKFATTEN) &&
- (em->selectmode & SCE_SELECT_FACE) &&
- BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
- (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no)))
- {
- no = _no;
- }
- else {
- no = eve->no;
- }
-
- if (v_island) {
- if (no_island_center) {
- copy_v3_v3(td->center, td->loc);
- }
- else {
- copy_v3_v3(td->center, v_island->co);
- }
- copy_m3_m3(td->axismtx, v_island->axismtx);
- }
- else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- copy_v3_v3(td->center, td->loc);
- createSpaceNormal(td->axismtx, no);
- }
- else {
- copy_v3_v3(td->center, td->loc);
-
- /* Setting normals */
- copy_v3_v3(td->axismtx[2], no);
- td->axismtx[0][0] =
- td->axismtx[0][1] =
- td->axismtx[0][2] =
- td->axismtx[1][0] =
- td->axismtx[1][1] =
- td->axismtx[1][2] = 0.0f;
- }
-
-
- td->ext = NULL;
- td->val = NULL;
- td->extra = NULL;
- if (t->mode == TFM_BWEIGHT) {
- td->val = bweight;
- td->ival = *bweight;
- }
- else if (t->mode == TFM_SKIN_RESIZE) {
- MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
- eve->head.data,
- CD_MVERT_SKIN);
- /* skin node size */
- td->ext = tx;
- copy_v3_v3(tx->isize, vs->radius);
- tx->size = vs->radius;
- td->val = vs->radius;
- }
- else if (t->mode == TFM_SHRINKFATTEN) {
- td->ext = tx;
- tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
- }
+static void VertsToTransData(TransInfo *t,
+ TransData *td,
+ TransDataExtension *tx,
+ BMEditMesh *em,
+ BMVert *eve,
+ float *bweight,
+ struct TransIslandData *v_island,
+ const bool no_island_center)
+{
+ float *no, _no[3];
+ BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
+
+ td->flag = 0;
+ //if (key)
+ // td->loc = key->co;
+ //else
+ td->loc = eve->co;
+ copy_v3_v3(td->iloc, td->loc);
+
+ if ((t->mode == TFM_SHRINKFATTEN) && (em->selectmode & SCE_SELECT_FACE) &&
+ BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
+ (BM_vert_calc_normal_ex(eve, BM_ELEM_SELECT, _no))) {
+ no = _no;
+ }
+ else {
+ no = eve->no;
+ }
+
+ if (v_island) {
+ if (no_island_center) {
+ copy_v3_v3(td->center, td->loc);
+ }
+ else {
+ copy_v3_v3(td->center, v_island->co);
+ }
+ copy_m3_m3(td->axismtx, v_island->axismtx);
+ }
+ else if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_v3_v3(td->center, td->loc);
+ createSpaceNormal(td->axismtx, no);
+ }
+ else {
+ copy_v3_v3(td->center, td->loc);
+
+ /* Setting normals */
+ copy_v3_v3(td->axismtx[2], no);
+ td->axismtx[0][0] = td->axismtx[0][1] = td->axismtx[0][2] = td->axismtx[1][0] =
+ td->axismtx[1][1] = td->axismtx[1][2] = 0.0f;
+ }
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->extra = NULL;
+ if (t->mode == TFM_BWEIGHT) {
+ td->val = bweight;
+ td->ival = *bweight;
+ }
+ else if (t->mode == TFM_SKIN_RESIZE) {
+ MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
+ /* skin node size */
+ td->ext = tx;
+ copy_v3_v3(tx->isize, vs->radius);
+ tx->size = vs->radius;
+ td->val = vs->radius;
+ }
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ td->ext = tx;
+ tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
+ }
}
static void createTransEditVerts(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *tob = NULL;
- TransDataExtension *tx = NULL;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- Mesh *me = tc->obedit->data;
- BMesh *bm = em->bm;
- BMVert *eve;
- BMIter iter;
- float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
- float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
- float *dists = NULL;
- int a;
- 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;
-
- struct TransIslandData *island_info = NULL;
- int island_info_tot;
- int *island_vert_map = NULL;
-
- /* Snap rotation along normal needs a common axis for whole islands,
- * otherwise one get random crazy results, see T59104.
- * However, we do not want to use the island center for the pivot/translation reference. */
- const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
- /* There is not guarantee that snapping
- * is initialized yet at this point... */
- (usingSnappingNormal(t) || (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
- (t->around != V3D_AROUND_LOCAL_ORIGINS));
- /* Even for translation this is needed because of island-orientation, see: T51651. */
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
- /* Original index of our connected vertex when connected distances are calculated.
- * Optional, allocate if needed. */
- int *dists_index = NULL;
-
- if (tc->mirror.axis_flag) {
- EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
- mirror = 1;
- }
-
- /**
- * Quick check if we can transform.
- *
- * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
- * \note in prop mode we need at least 1 selected.
- */
- if (bm->totvertsel == 0) {
- goto cleanup;
- }
-
- if (t->mode == TFM_BWEIGHT) {
- BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
- cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- }
-
- 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)) {
- count++;
- }
- }
-
- tc->data_len = count;
-
- /* allocating scratch arrays */
- if (prop_mode & T_PROP_CONNECTED) {
- dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
- if (is_island_center) {
- dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
- }
- }
- }
- else {
- tc->data_len = bm->totvertsel;
- }
-
- tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
- if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
- /* warning, this is overkill, we only need 2 extra floats,
- * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
- * since we may not use the 'alt' transform mode to maintain shell thickness,
- * but with generic transform code its hard to lazy init vars */
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObData ext");
- }
-
- copy_m3_m4(mtx, tc->obedit->obmat);
- /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
- * matrix inversion still works and we can still moving along the other */
- pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
-
- if (prop_mode & T_PROP_CONNECTED) {
- editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
- }
-
- if (is_island_center) {
- /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
- const bool calc_single_islands = (
- (prop_mode & T_PROP_CONNECTED) &&
- (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (em->selectmode & SCE_SELECT_VERTEX));
-
- island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
- }
-
- /* detect CrazySpace [tm] */
- if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
- int totleft = -1;
- if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
- /* Use evaluated state because we need b-bone cache. */
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
- Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
- BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
- /* check if we can use deform matrices for modifier from the
- * start up to stack, they are more accurate than quats */
- totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
- t->depsgraph, scene_eval, obedit_eval, em_eval,
- &defmats, &defcos);
- }
-
- /* if we still have more modifiers, also do crazyspace
- * correction with quats, relative to the coordinates after
- * the modifiers that support deform matrices (defcos) */
-
-#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
- if ((totleft > 0) || (totleft == -1))
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *tob = NULL;
+ TransDataExtension *tx = NULL;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ Mesh *me = tc->obedit->data;
+ BMesh *bm = em->bm;
+ BMVert *eve;
+ BMIter iter;
+ float(*mappedcos)[3] = NULL, (*quats)[4] = NULL;
+ float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
+ float *dists = NULL;
+ int a;
+ 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;
+
+ struct TransIslandData *island_info = NULL;
+ int island_info_tot;
+ int *island_vert_map = NULL;
+
+ /* Snap rotation along normal needs a common axis for whole islands,
+ * otherwise one get random crazy results, see T59104.
+ * However, we do not want to use the island center for the pivot/translation reference. */
+ const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
+ /* There is not guarantee that snapping
+ * is initialized yet at this point... */
+ (usingSnappingNormal(t) ||
+ (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
+ (t->around != V3D_AROUND_LOCAL_ORIGINS));
+ /* Even for translation this is needed because of island-orientation, see: T51651. */
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
+ /* Original index of our connected vertex when connected distances are calculated.
+ * Optional, allocate if needed. */
+ int *dists_index = NULL;
+
+ if (tc->mirror.axis_flag) {
+ EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
+ mirror = 1;
+ }
+
+ /**
+ * Quick check if we can transform.
+ *
+ * \note ignore modes here, even in edge/face modes, transform data is created by selected vertices.
+ * \note in prop mode we need at least 1 selected.
+ */
+ if (bm->totvertsel == 0) {
+ goto cleanup;
+ }
+
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ }
+
+ 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)) {
+ count++;
+ }
+ }
+
+ tc->data_len = count;
+
+ /* allocating scratch arrays */
+ if (prop_mode & T_PROP_CONNECTED) {
+ dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
+ if (is_island_center) {
+ dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
+ }
+ }
+ }
+ else {
+ tc->data_len = bm->totvertsel;
+ }
+
+ tob = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
+ if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
+ /* warning, this is overkill, we only need 2 extra floats,
+ * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
+ * since we may not use the 'alt' transform mode to maintain shell thickness,
+ * but with generic transform code its hard to lazy init vars */
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "TransObData ext");
+ }
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ /* we use a pseudo-inverse so that when one of the axes is scaled to 0,
+ * matrix inversion still works and we can still moving along the other */
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ if (prop_mode & T_PROP_CONNECTED) {
+ editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
+ }
+
+ if (is_island_center) {
+ /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
+ const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
+ (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (em->selectmode & SCE_SELECT_VERTEX));
+
+ island_info = editmesh_islands_info_calc(
+ em, &island_info_tot, &island_vert_map, calc_single_islands);
+ }
+
+ /* detect CrazySpace [tm] */
+ if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) {
+ int totleft = -1;
+ if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) {
+ /* Use evaluated state because we need b-bone cache. */
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(t->depsgraph, &t->scene->id);
+ Object *obedit_eval = (Object *)DEG_get_evaluated_id(t->depsgraph, &tc->obedit->id);
+ BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
+ /* check if we can use deform matrices for modifier from the
+ * start up to stack, they are more accurate than quats */
+ totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(
+ t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos);
+ }
+
+ /* if we still have more modifiers, also do crazyspace
+ * correction with quats, relative to the coordinates after
+ * the modifiers that support deform matrices (defcos) */
+
+#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
+ if ((totleft > 0) || (totleft == -1))
#else
- if (totleft > 0)
+ if (totleft > 0)
#endif
- {
- mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, t->scene, tc->obedit);
- quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
- BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
- if (mappedcos)
- MEM_freeN(mappedcos);
- }
-
- if (defcos) {
- MEM_freeN(defcos);
- }
- }
-
- /* find out which half we do */
- if (mirror) {
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
- if (eve->co[0] < 0.0f) {
- tc->mirror.sign = -1.0f;
- mirror = -1;
- }
- break;
- }
- }
- }
-
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- struct TransIslandData *v_island = NULL;
- float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
-
- if (island_info) {
- const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
- v_island = (island_vert_map[connected_index] != -1) ?
- &island_info[island_vert_map[connected_index]] : NULL;
- }
-
-
- /* Do not use the island center in case we are using islands
- * only to get axis for snap/rotate to normal... */
- VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
- if (tx)
- tx++;
-
- /* selected */
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
- tob->flag |= TD_SELECTED;
-
- if (prop_mode) {
- if (prop_mode & T_PROP_CONNECTED) {
- tob->dist = dists[a];
- }
- else {
- tob->flag |= TD_NOTCONNECTED;
- tob->dist = FLT_MAX;
- }
- }
-
- /* CrazySpace */
- if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
- float mat[3][3], qmat[3][3], imat[3][3];
-
- /* use both or either quat and defmat correction */
- if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
- quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
-
- if (defmats)
- mul_m3_series(mat, defmats[a], qmat, mtx);
- else
- mul_m3_m3m3(mat, mtx, qmat);
- }
- else
- mul_m3_m3m3(mat, mtx, defmats[a]);
-
- invert_m3_m3(imat, mat);
-
- copy_m3_m3(tob->smtx, imat);
- copy_m3_m3(tob->mtx, mat);
- }
- else {
- copy_m3_m3(tob->smtx, smtx);
- copy_m3_m3(tob->mtx, mtx);
- }
-
- /* Mirror? */
- if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
- BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
- if (vmir && vmir != eve) {
- tob->extra = vmir;
- }
- }
- tob++;
- }
- }
- }
-
- if (island_info) {
- MEM_freeN(island_info);
- MEM_freeN(island_vert_map);
- }
-
- if (mirror != 0) {
- tob = tc->data;
- for (a = 0; a < tc->data_len; a++, tob++) {
- if (ABS(tob->loc[0]) <= 0.00001f) {
- tob->flag |= TD_MIRROR_EDGE;
- }
- }
- }
-
-cleanup:
- /* crazy space free */
- if (quats)
- MEM_freeN(quats);
- if (defmats)
- MEM_freeN(defmats);
- if (dists)
- MEM_freeN(dists);
- if (dists_index)
- MEM_freeN(dists_index);
-
- if (tc->mirror.axis_flag) {
- EDBM_verts_mirror_cache_end(em);
- }
- }
+ {
+ mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, t->scene, tc->obedit);
+ quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
+ BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
+ if (mappedcos)
+ MEM_freeN(mappedcos);
+ }
+
+ if (defcos) {
+ MEM_freeN(defcos);
+ }
+ }
+
+ /* find out which half we do */
+ if (mirror) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve->co[0] != 0.0f) {
+ if (eve->co[0] < 0.0f) {
+ tc->mirror.sign = -1.0f;
+ mirror = -1;
+ }
+ break;
+ }
+ }
+ }
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ struct TransIslandData *v_island = NULL;
+ float *bweight = (cd_vert_bweight_offset != -1) ?
+ BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) :
+ NULL;
+
+ if (island_info) {
+ const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
+ v_island = (island_vert_map[connected_index] != -1) ?
+ &island_info[island_vert_map[connected_index]] :
+ NULL;
+ }
+
+ /* Do not use the island center in case we are using islands
+ * only to get axis for snap/rotate to normal... */
+ VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate);
+ if (tx)
+ tx++;
+
+ /* selected */
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
+ tob->flag |= TD_SELECTED;
+
+ if (prop_mode) {
+ if (prop_mode & T_PROP_CONNECTED) {
+ tob->dist = dists[a];
+ }
+ else {
+ tob->flag |= TD_NOTCONNECTED;
+ tob->dist = FLT_MAX;
+ }
+ }
+
+ /* CrazySpace */
+ if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
+ float mat[3][3], qmat[3][3], imat[3][3];
+
+ /* use both or either quat and defmat correction */
+ if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
+ quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
+
+ if (defmats)
+ mul_m3_series(mat, defmats[a], qmat, mtx);
+ else
+ mul_m3_m3m3(mat, mtx, qmat);
+ }
+ else
+ mul_m3_m3m3(mat, mtx, defmats[a]);
+
+ invert_m3_m3(imat, mat);
+
+ copy_m3_m3(tob->smtx, imat);
+ copy_m3_m3(tob->mtx, mat);
+ }
+ else {
+ copy_m3_m3(tob->smtx, smtx);
+ copy_m3_m3(tob->mtx, mtx);
+ }
+
+ /* Mirror? */
+ if ((mirror > 0 && tob->iloc[0] > 0.0f) || (mirror < 0 && tob->iloc[0] < 0.0f)) {
+ BMVert *vmir = EDBM_verts_mirror_get(em, eve); //t->obedit, em, eve, tob->iloc, a);
+ if (vmir && vmir != eve) {
+ tob->extra = vmir;
+ }
+ }
+ tob++;
+ }
+ }
+ }
+
+ if (island_info) {
+ MEM_freeN(island_info);
+ MEM_freeN(island_vert_map);
+ }
+
+ if (mirror != 0) {
+ tob = tc->data;
+ for (a = 0; a < tc->data_len; a++, tob++) {
+ if (ABS(tob->loc[0]) <= 0.00001f) {
+ tob->flag |= TD_MIRROR_EDGE;
+ }
+ }
+ }
+
+ cleanup:
+ /* crazy space free */
+ if (quats)
+ MEM_freeN(quats);
+ if (defmats)
+ MEM_freeN(defmats);
+ if (dists)
+ MEM_freeN(dists);
+ if (dists_index)
+ MEM_freeN(dists_index);
+
+ if (tc->mirror.axis_flag) {
+ EDBM_verts_mirror_cache_end(em);
+ }
+ }
}
/* *** NODE EDITOR *** */
void flushTransNodes(TransInfo *t)
{
- const float dpi_fac = UI_DPI_FAC;
+ const float dpi_fac = UI_DPI_FAC;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- int a;
- TransData *td;
- TransData2D *td2d;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ int a;
+ TransData *td;
+ TransData2D *td2d;
- applyGridAbsolute(t);
+ applyGridAbsolute(t);
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
- bNode *node = td->extra;
- float locx, locy;
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+ bNode *node = td->extra;
+ float locx, locy;
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
#ifdef USE_NODE_CENTER
- locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
- locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
+ locx = (td2d->loc[0] - (BLI_rctf_size_x(&node->totr)) * +0.5f) / dpi_fac;
+ locy = (td2d->loc[1] - (BLI_rctf_size_y(&node->totr)) * -0.5f) / dpi_fac;
#else
- locx = td2d->loc[0] / dpi_fac;
- locy = td2d->loc[1] / dpi_fac;
+ locx = td2d->loc[0] / dpi_fac;
+ locy = td2d->loc[1] / dpi_fac;
#endif
- /* account for parents (nested nodes) */
- if (node->parent) {
- nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
- }
- else {
- node->locx = locx;
- node->locy = locy;
- }
- }
+ /* account for parents (nested nodes) */
+ if (node->parent) {
+ nodeFromView(node->parent, locx, locy, &node->locx, &node->locy);
+ }
+ else {
+ node->locx = locx;
+ node->locy = locy;
+ }
+ }
- /* handle intersection with noodles */
- if (tc->data_len == 1) {
- ED_node_link_intersect_test(t->sa, 1);
- }
- }
+ /* handle intersection with noodles */
+ if (tc->data_len == 1) {
+ ED_node_link_intersect_test(t->sa, 1);
+ }
+ }
}
/* *** SEQUENCE EDITOR *** */
@@ -2981,476 +3053,485 @@ void flushTransNodes(TransInfo *t)
BLI_INLINE void trans_update_seq(Scene *sce, Sequence *seq, int old_start, int sel_flag)
{
- if (seq->depth == 0) {
- /* Calculate this strip and all nested strips.
- * Children are ALWAYS transformed first so we don't need to do this in another loop.
- */
- BKE_sequence_calc(sce, seq);
- }
- else {
- BKE_sequence_calc_disp(sce, seq);
- }
+ if (seq->depth == 0) {
+ /* Calculate this strip and all nested strips.
+ * Children are ALWAYS transformed first so we don't need to do this in another loop.
+ */
+ BKE_sequence_calc(sce, seq);
+ }
+ else {
+ BKE_sequence_calc_disp(sce, seq);
+ }
- if (sel_flag == SELECT)
- BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
+ if (sel_flag == SELECT)
+ BKE_sequencer_offset_animdata(sce, seq, seq->start - old_start);
}
void flushTransSeq(TransInfo *t)
{
- /* Editing null check already done */
- ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
-
- int a, new_frame;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataSeq *tdsq = NULL;
- Sequence *seq;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* prevent updating the same seq twice
- * if the transdata order is changed this will mess up
- * but so will TransDataSeq */
- Sequence *seq_prev = NULL;
- int old_start_prev = 0, sel_flag_prev = 0;
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
- int old_start;
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
- old_start = seq->start;
- new_frame = round_fl_to_int(td2d->loc[0]);
-
- switch (tdsq->sel_flag) {
- case SELECT:
+ /* Editing null check already done */
+ ListBase *seqbasep = BKE_sequencer_editing_get(t->scene, false)->seqbasep;
+
+ int a, new_frame;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataSeq *tdsq = NULL;
+ Sequence *seq;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev = NULL;
+ int old_start_prev = 0, sel_flag_prev = 0;
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+ int old_start;
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+ old_start = seq->start;
+ new_frame = round_fl_to_int(td2d->loc[0]);
+
+ switch (tdsq->sel_flag) {
+ case SELECT:
#ifdef SEQ_TX_NESTED_METAS
- if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
- /* for meta's, their children move */
- seq->start = new_frame - tdsq->start_offset;
- }
+ if ((seq->depth != 0 || BKE_sequence_tx_test(seq))) {
+ /* for meta's, their children move */
+ seq->start = new_frame - tdsq->start_offset;
+ }
#else
- if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
- /* for meta's, their children move */
- seq->start = new_frame - tdsq->start_offset;
- }
+ if (seq->type != SEQ_TYPE_META && (seq->depth != 0 || seq_tx_test(seq))) {
+ /* for meta's, their children move */
+ seq->start = new_frame - tdsq->start_offset;
+ }
#endif
- if (seq->depth == 0) {
- seq->machine = round_fl_to_int(td2d->loc[1]);
- CLAMP(seq->machine, 1, MAXSEQ);
- }
- break;
- case SEQ_LEFTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_left(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
-
- /* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
- break;
- case SEQ_RIGHTSEL: /* no vertical transform */
- BKE_sequence_tx_set_final_right(seq, new_frame);
- BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
-
- /* todo - move this into aftertrans update? - old seq tx needed it anyway */
- BKE_sequence_single_fix(seq);
- break;
- }
-
- /* Update *previous* seq! Else, we would update a seq after its first transform, and if it has more than one
- * (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), the others are not updated! See T38469.
- */
- if (seq != seq_prev) {
- if (seq_prev) {
- trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
- }
-
- seq_prev = seq;
- old_start_prev = old_start;
- sel_flag_prev = tdsq->sel_flag;
- }
- else {
- /* We want to accumulate *all* sel_flags for this seq! */
- sel_flag_prev |= tdsq->sel_flag;
- }
- }
-
- /* Don't forget to update the last seq! */
- if (seq_prev) {
- trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
- }
-
- /* originally TFM_TIME_EXTEND, transform changes */
- if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
- /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
-
- /* calc all meta's then effects [#27953] */
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
-
- /* update effects inside meta's */
- for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d;
- a < tc->data_len;
- a++, td++, td2d++, seq_prev = seq)
- {
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
- if ((seq != seq_prev) && (seq->depth != 0)) {
- if (seq->seq1 || seq->seq2 || seq->seq3) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- }
- }
-
- /* need to do the overlap check in a new loop otherwise adjacent strips
- * will not be updated and we'll get false positives */
- seq_prev = NULL;
- for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
-
- tdsq = (TransDataSeq *)td->extra;
- seq = tdsq->seq;
-
- if (seq != seq_prev) {
- if (seq->depth == 0) {
- /* test overlap, displays red outline */
- seq->flag &= ~SEQ_OVERLAP;
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
- seq->flag |= SEQ_OVERLAP;
- }
- }
- }
- seq_prev = seq;
- }
+ if (seq->depth == 0) {
+ seq->machine = round_fl_to_int(td2d->loc[1]);
+ CLAMP(seq->machine, 1, MAXSEQ);
+ }
+ break;
+ case SEQ_LEFTSEL: /* no vertical transform */
+ BKE_sequence_tx_set_final_left(seq, new_frame);
+ BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+
+ /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ BKE_sequence_single_fix(seq);
+ break;
+ case SEQ_RIGHTSEL: /* no vertical transform */
+ BKE_sequence_tx_set_final_right(seq, new_frame);
+ BKE_sequence_tx_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
+
+ /* todo - move this into aftertrans update? - old seq tx needed it anyway */
+ BKE_sequence_single_fix(seq);
+ break;
+ }
+
+ /* Update *previous* seq! Else, we would update a seq after its first transform, and if it has more than one
+ * (like e.g. SEQ_LEFTSEL and SEQ_RIGHTSEL), the others are not updated! See T38469.
+ */
+ if (seq != seq_prev) {
+ if (seq_prev) {
+ trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
+ }
+
+ seq_prev = seq;
+ old_start_prev = old_start;
+ sel_flag_prev = tdsq->sel_flag;
+ }
+ else {
+ /* We want to accumulate *all* sel_flags for this seq! */
+ sel_flag_prev |= tdsq->sel_flag;
+ }
+ }
+
+ /* Don't forget to update the last seq! */
+ if (seq_prev) {
+ trans_update_seq(t->scene, seq_prev, old_start_prev, sel_flag_prev);
+ }
+
+ /* originally TFM_TIME_EXTEND, transform changes */
+ if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
+ /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
+
+ /* calc all meta's then effects [#27953] */
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->type == SEQ_TYPE_META && seq->flag & SELECT) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+
+ /* update effects inside meta's */
+ for (a = 0, seq_prev = NULL, td = tc->data, td2d = tc->data_2d; a < tc->data_len;
+ a++, td++, td2d++, seq_prev = seq) {
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+ if ((seq != seq_prev) && (seq->depth != 0)) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ }
+ }
+
+ /* need to do the overlap check in a new loop otherwise adjacent strips
+ * will not be updated and we'll get false positives */
+ seq_prev = NULL;
+ for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
+
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+
+ if (seq != seq_prev) {
+ if (seq->depth == 0) {
+ /* test overlap, displays red outline */
+ seq->flag &= ~SEQ_OVERLAP;
+ if (BKE_sequence_test_overlap(seqbasep, seq)) {
+ seq->flag |= SEQ_OVERLAP;
+ }
+ }
+ }
+ seq_prev = seq;
+ }
}
/* ********************* UV ****************** */
-static void UVsToTransData(
- const float aspect[2], TransData *td, TransData2D *td2d,
- float *uv, const float *center, bool selected)
-{
- /* 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] * 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_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));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- if (selected) {
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
- }
- else {
- td->dist = FLT_MAX;
- }
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+static void UVsToTransData(const float aspect[2],
+ TransData *td,
+ TransData2D *td2d,
+ float *uv,
+ const float *center,
+ bool selected)
+{
+ /* 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] * 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_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));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+ }
+ else {
+ td->dist = FLT_MAX;
+ }
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
static void createTransUVs(bContext *C, TransInfo *t)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- Scene *scene = t->scene;
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- 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_AROUND_LOCAL_ORIGINS);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMFace *efa;
- 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 int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
- continue;
- }
-
- /* count */
- if (is_prop_connected || is_island_center) {
- /* create element map with island information */
- 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;
- }
-
- 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__);
- }
- }
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BMLoop *l;
-
- if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- continue;
- }
-
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- countsel++;
-
- if (is_prop_connected || island_center) {
- UvElement *element = BM_uv_element_get(elementmap, efa, l);
-
- 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 (is_prop_edit) {
- count++;
- }
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- 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);
- }
- }
-
- tc->data_len = (is_prop_edit) ? count : countsel;
- tc->data = MEM_callocN(tc->data_len * 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 */
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(UV Editing)");
-
- if (sima->flag & SI_CLIP_UV)
- t->flag |= T_CLIP_UV;
-
- td = tc->data;
- td2d = tc->data_2d;
-
- 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) {
- 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 (is_prop_connected || is_island_center) {
- UvElement *element = BM_uv_element_get(elementmap, efa, l);
-
- 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(t->aspect, td++, td2d++, luv->uv, center, selected);
- }
- }
-
- if (is_prop_connected) {
- tc->data_len -= count_rejected;
- }
-
- if (sima->flag & SI_LIVE_UNWRAP) {
- ED_uvedit_live_unwrap_begin(t->scene, tc->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);
- }
- }
- }
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+ Scene *scene = t->scene;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ 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_AROUND_LOCAL_ORIGINS);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMFace *efa;
+ 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 int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
+ continue;
+ }
+
+ /* count */
+ if (is_prop_connected || is_island_center) {
+ /* create element map with island information */
+ 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;
+ }
+
+ 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__);
+ }
+ }
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l;
+
+ if (!uvedit_face_visible_test(scene, tc->obedit, ima, efa)) {
+ BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ continue;
+ }
+
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ countsel++;
+
+ if (is_prop_connected || island_center) {
+ UvElement *element = BM_uv_element_get(elementmap, efa, l);
+
+ 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 (is_prop_edit) {
+ count++;
+ }
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ 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);
+ }
+ }
+
+ tc->data_len = (is_prop_edit) ? count : countsel;
+ tc->data = MEM_callocN(tc->data_len * 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 */
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(UV Editing)");
+
+ if (sima->flag & SI_CLIP_UV)
+ t->flag |= T_CLIP_UV;
+
+ td = tc->data;
+ td2d = tc->data_2d;
+
+ 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) {
+ 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 (is_prop_connected || is_island_center) {
+ UvElement *element = BM_uv_element_get(elementmap, efa, l);
+
+ 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(t->aspect, td++, td2d++, luv->uv, center, selected);
+ }
+ }
+
+ if (is_prop_connected) {
+ tc->data_len -= count_rejected;
+ }
+
+ if (sima->flag & SI_LIVE_UNWRAP) {
+ ED_uvedit_live_unwrap_begin(t->scene, tc->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;
- const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
- (t->state != TRANS_CANCEL));
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData2D *td;
- int a;
- float aspect_inv[2], size[2];
-
- 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 = tc->data_2d; a < tc->data_len; a++, td++) {
- td->loc2d[0] = td->loc[0] * aspect_inv[0];
- td->loc2d[1] = td->loc[1] * aspect_inv[1];
-
- if (use_pixel_snap) {
- td->loc2d[0] *= size[0];
- td->loc2d[1] *= size[1];
-
- switch (sima->pixel_snap_mode) {
- case SI_PIXEL_SNAP_CENTER:
- td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f;
- td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f;
- break;
- case SI_PIXEL_SNAP_CORNER:
- td->loc2d[0] = roundf(td->loc2d[0]);
- td->loc2d[1] = roundf(td->loc2d[1]);
- break;
- }
-
- td->loc2d[0] /= size[0];
- td->loc2d[1] /= size[1];
- }
- }
- }
+ SpaceImage *sima = t->sa->spacedata.first;
+ const bool use_pixel_snap = ((sima->pixel_snap_mode != SI_PIXEL_SNAP_DISABLED) &&
+ (t->state != TRANS_CANCEL));
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData2D *td;
+ int a;
+ float aspect_inv[2], size[2];
+
+ 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 = tc->data_2d; a < tc->data_len; a++, td++) {
+ td->loc2d[0] = td->loc[0] * aspect_inv[0];
+ td->loc2d[1] = td->loc[1] * aspect_inv[1];
+
+ if (use_pixel_snap) {
+ td->loc2d[0] *= size[0];
+ td->loc2d[1] *= size[1];
+
+ switch (sima->pixel_snap_mode) {
+ case SI_PIXEL_SNAP_CENTER:
+ td->loc2d[0] = roundf(td->loc2d[0] - 0.5f) + 0.5f;
+ td->loc2d[1] = roundf(td->loc2d[1] - 0.5f) + 0.5f;
+ break;
+ case SI_PIXEL_SNAP_CORNER:
+ td->loc2d[0] = roundf(td->loc2d[0]);
+ td->loc2d[1] = roundf(td->loc2d[1]);
+ break;
+ }
+
+ td->loc2d[0] /= size[0];
+ td->loc2d[1] /= size[1];
+ }
+ }
+ }
}
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
{
- bool clipx = true, clipy = true;
- float min[2], max[2];
-
- min[0] = min[1] = 0.0f;
- max[0] = t->aspect[0];
- max[1] = t->aspect[1];
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td;
- int a;
-
- for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
- minmax_v2v2_v2(min, max, td->loc);
- }
-
- if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f)
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0])
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
- else
- clipx = 0;
-
- if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f)
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1])
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
- else
- clipy = 0;
- }
- else {
- if (min[0] < 0.0f)
- vec[0] -= min[0];
- 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] > t->aspect[1])
- vec[1] -= max[1] - t->aspect[1];
- else
- clipy = 0;
- }
- }
-
- return (clipx || clipy);
+ bool clipx = true, clipy = true;
+ float min[2], max[2];
+
+ min[0] = min[1] = 0.0f;
+ max[0] = t->aspect[0];
+ max[1] = t->aspect[1];
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td;
+ int a;
+
+ for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
+ minmax_v2v2_v2(min, max, td->loc);
+ }
+
+ if (resize) {
+ if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f)
+ vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0])
+ vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ else
+ clipx = 0;
+
+ if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f)
+ vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1])
+ vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
+ else
+ clipy = 0;
+ }
+ else {
+ if (min[0] < 0.0f)
+ vec[0] -= min[0];
+ 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] > t->aspect[1])
+ vec[1] -= max[1] - t->aspect[1];
+ else
+ clipy = 0;
+ }
+ }
+
+ return (clipx || clipy);
}
void clipUVData(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_NOACTION)
- break;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (int a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
- if ((td->flag & TD_SKIP) || (!td->loc))
- continue;
+ if ((td->flag & TD_SKIP) || (!td->loc))
+ continue;
- 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]);
- }
- }
+ 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]);
+ }
+ }
}
/* ********************* ANIMATION EDITORS (GENERAL) ************************* */
@@ -3458,258 +3539,264 @@ void clipUVData(TransInfo *t)
/* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
static bool FrameOnMouseSide(char side, float frame, float cframe)
{
- /* both sides, so it doesn't matter */
- if (side == 'B') return true;
+ /* both sides, so it doesn't matter */
+ if (side == 'B')
+ return true;
- /* only on the named side */
- if (side == 'R')
- return (frame >= cframe);
- else
- return (frame <= cframe);
+ /* only on the named side */
+ if (side == 'R')
+ return (frame >= cframe);
+ else
+ return (frame <= cframe);
}
/* ********************* NLA EDITOR ************************* */
static void createTransNlaData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- SpaceNla *snla = NULL;
- TransData *td = NULL;
- TransDataNla *tdn = NULL;
-
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- int count = 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* determine what type of data we are operating on */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
- snla = (SpaceNla *)ac.sl;
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* which side of the current frame should be allowed */
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* loop 1: count how many strips are selected (consider each strip as 2 points) */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* make some meta-strips for chains of selected strips */
- BKE_nlastrips_make_metas(&nlt->strips, 1);
-
- /* only consider selected strips */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- // TODO: we can make strips have handles later on...
- /* transition strips can't get directly transformed */
- if (strip->type != NLASTRIP_TYPE_TRANSITION) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) count++;
- if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) count++;
- }
- }
- }
- }
-
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- /* clear temp metas that may have been created but aren't needed now
- * because they fell on the wrong side of CFRA
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
- td = tc->data;
- tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
- tc->custom.type.use_free = true;
-
- /* loop 2: build transdata array */
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* only if a real NLA-track */
- if (ale->type == ANIMTYPE_NLATRACK) {
- AnimData *adt = ale->adt;
- NlaTrack *nlt = (NlaTrack *)ale->data;
- NlaStrip *strip;
-
- /* only consider selected strips */
- for (strip = nlt->strips.first; strip; strip = strip->next) {
- // TODO: we can make strips have handles later on...
- /* transition strips can't get directly transformed */
- if (strip->type != NLASTRIP_TYPE_TRANSITION) {
- if (strip->flag & NLASTRIP_FLAG_SELECT) {
- /* our transform data is constructed as follows:
- * - only the handles on the right side of the current-frame get included
- * - td structs are transform-elements operated on by the transform system
- * and represent a single handle. The storage/pointer used (val or loc) depends on
- * whether we're scaling or transforming. Ultimately though, the handles
- * the td writes to will simply be a dummy in tdn
- * - for each strip being transformed, a single tdn struct is used, so in some
- * cases, there will need to be 1 of these tdn elements in the array skipped...
- */
- float center[3], yval;
-
- /* firstly, init tdn settings */
- tdn->id = ale->id;
- tdn->oldTrack = tdn->nlt = nlt;
- tdn->strip = strip;
- tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
-
- yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
-
- tdn->h1[0] = strip->start;
- tdn->h1[1] = yval;
- tdn->h2[0] = strip->end;
- tdn->h2[1] = yval;
-
- center[0] = (float)CFRA;
- center[1] = yval;
- center[2] = 0.0f;
-
- /* set td's based on which handles are applicable */
- if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
- /* just set tdn to assume that it only has one handle for now */
- tdn->handle = -1;
-
- /* now, link the transform data up to this data */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
- td->loc = tdn->h1;
- copy_v3_v3(td->iloc, tdn->h1);
-
- /* store all the other gunk that is required by transform */
- copy_v3_v3(td->center, center);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
- }
- else {
- /* time scaling only needs single value */
- td->val = &tdn->h1[0];
- td->ival = tdn->h1[0];
- }
-
- td->extra = tdn;
- td++;
- }
- if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
- /* if tdn is already holding the start handle,
- * then we're doing both, otherwise, only end */
- tdn->handle = (tdn->handle) ? 2 : 1;
-
- /* now, link the transform data up to this data */
- if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
- td->loc = tdn->h2;
- copy_v3_v3(td->iloc, tdn->h2);
-
- /* store all the other gunk that is required by transform */
- copy_v3_v3(td->center, center);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
- }
- else {
- /* time scaling only needs single value */
- td->val = &tdn->h2[0];
- td->ival = tdn->h2[0];
- }
-
- td->extra = tdn;
- td++;
- }
-
- /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
- * otherwise, just advance to the next one...
- */
- if (tdn->handle == 2)
- tdn += 2;
- else
- tdn++;
- }
- }
- }
- }
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
+ Scene *scene = t->scene;
+ SpaceNla *snla = NULL;
+ TransData *td = NULL;
+ TransDataNla *tdn = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ int count = 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* determine what type of data we are operating on */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+ snla = (SpaceNla *)ac.sl;
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
+ t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* loop 1: count how many strips are selected (consider each strip as 2 points) */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* make some meta-strips for chains of selected strips */
+ BKE_nlastrips_make_metas(&nlt->strips, 1);
+
+ /* only consider selected strips */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ // TODO: we can make strips have handles later on...
+ /* transition strips can't get directly transformed */
+ if (strip->type != NLASTRIP_TYPE_TRANSITION) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA))
+ count++;
+ if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA))
+ count++;
+ }
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* clear temp metas that may have been created but aren't needed now
+ * because they fell on the wrong side of CFRA
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
+ td = tc->data;
+ tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla),
+ "TransDataNla (NLA Editor)");
+ tc->custom.type.use_free = true;
+
+ /* loop 2: build transdata array */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* only if a real NLA-track */
+ if (ale->type == ANIMTYPE_NLATRACK) {
+ AnimData *adt = ale->adt;
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ /* only consider selected strips */
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ // TODO: we can make strips have handles later on...
+ /* transition strips can't get directly transformed */
+ if (strip->type != NLASTRIP_TYPE_TRANSITION) {
+ if (strip->flag & NLASTRIP_FLAG_SELECT) {
+ /* our transform data is constructed as follows:
+ * - only the handles on the right side of the current-frame get included
+ * - td structs are transform-elements operated on by the transform system
+ * and represent a single handle. The storage/pointer used (val or loc) depends on
+ * whether we're scaling or transforming. Ultimately though, the handles
+ * the td writes to will simply be a dummy in tdn
+ * - for each strip being transformed, a single tdn struct is used, so in some
+ * cases, there will need to be 1 of these tdn elements in the array skipped...
+ */
+ float center[3], yval;
+
+ /* firstly, init tdn settings */
+ tdn->id = ale->id;
+ tdn->oldTrack = tdn->nlt = nlt;
+ tdn->strip = strip;
+ tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
+
+ yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
+
+ tdn->h1[0] = strip->start;
+ tdn->h1[1] = yval;
+ tdn->h2[0] = strip->end;
+ tdn->h2[1] = yval;
+
+ center[0] = (float)CFRA;
+ center[1] = yval;
+ center[2] = 0.0f;
+
+ /* set td's based on which handles are applicable */
+ if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) {
+ /* just set tdn to assume that it only has one handle for now */
+ tdn->handle = -1;
+
+ /* now, link the transform data up to this data */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
+ td->loc = tdn->h1;
+ copy_v3_v3(td->iloc, tdn->h1);
+
+ /* store all the other gunk that is required by transform */
+ copy_v3_v3(td->center, center);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+ }
+ else {
+ /* time scaling only needs single value */
+ td->val = &tdn->h1[0];
+ td->ival = tdn->h1[0];
+ }
+
+ td->extra = tdn;
+ td++;
+ }
+ if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) {
+ /* if tdn is already holding the start handle,
+ * then we're doing both, otherwise, only end */
+ tdn->handle = (tdn->handle) ? 2 : 1;
+
+ /* now, link the transform data up to this data */
+ if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
+ td->loc = tdn->h2;
+ copy_v3_v3(td->iloc, tdn->h2);
+
+ /* store all the other gunk that is required by transform */
+ copy_v3_v3(td->center, center);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+ }
+ else {
+ /* time scaling only needs single value */
+ td->val = &tdn->h2[0];
+ td->ival = tdn->h2[0];
+ }
+
+ td->extra = tdn;
+ td++;
+ }
+
+ /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
+ * otherwise, just advance to the next one...
+ */
+ if (tdn->handle == 2)
+ tdn += 2;
+ else
+ tdn++;
+ }
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
}
/* ********************* ACTION EDITOR ****************** */
static int gpf_cmp_frame(void *thunk, const void *a, const void *b)
{
- const bGPDframe *frame_a = a;
- const bGPDframe *frame_b = b;
+ const bGPDframe *frame_a = a;
+ const bGPDframe *frame_b = b;
- if (frame_a->framenum < frame_b->framenum) return -1;
- if (frame_a->framenum > frame_b->framenum) return 1;
- *((bool *)thunk) = true;
- /* selected last */
- if ((frame_a->flag & GP_FRAME_SELECT) &&
- ((frame_b->flag & GP_FRAME_SELECT) == 0))
- {
- return 1;
- }
- return 0;
+ if (frame_a->framenum < frame_b->framenum)
+ return -1;
+ if (frame_a->framenum > frame_b->framenum)
+ return 1;
+ *((bool *)thunk) = true;
+ /* selected last */
+ if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
+ return 1;
+ }
+ return 0;
}
static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
{
- const MaskLayerShape *frame_a = a;
- const MaskLayerShape *frame_b = b;
+ const MaskLayerShape *frame_a = a;
+ const MaskLayerShape *frame_b = b;
- if (frame_a->frame < frame_b->frame) return -1;
- if (frame_a->frame > frame_b->frame) return 1;
- *((bool *)thunk) = true;
- /* selected last */
- if ((frame_a->flag & MASK_SHAPE_SELECT) &&
- ((frame_b->flag & MASK_SHAPE_SELECT) == 0))
- {
- return 1;
- }
- return 0;
+ if (frame_a->frame < frame_b->frame)
+ return -1;
+ if (frame_a->frame > frame_b->frame)
+ return 1;
+ *((bool *)thunk) = true;
+ /* selected last */
+ if ((frame_a->flag & MASK_SHAPE_SELECT) && ((frame_b->flag & MASK_SHAPE_SELECT) == 0)) {
+ return 1;
+ }
+ return 0;
}
/* Called by special_aftertrans_update to make sure selected gp-frames replace
@@ -3719,68 +3806,70 @@ static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b)
*/
static void posttrans_gpd_clean(bGPdata *gpd)
{
- bGPDlayer *gpl;
+ bGPDlayer *gpl;
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf, *gpfn;
- bool is_double = false;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *gpf, *gpfn;
+ bool is_double = false;
- BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
+ BLI_listbase_sort_r(&gpl->frames, gpf_cmp_frame, &is_double);
- if (is_double) {
- for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
- gpfn = gpf->next;
- if (gpfn && gpf->framenum == gpfn->framenum) {
- BKE_gpencil_layer_delframe(gpl, gpf);
- }
- }
- }
+ if (is_double) {
+ for (gpf = gpl->frames.first; gpf; gpf = gpfn) {
+ gpfn = gpf->next;
+ if (gpfn && gpf->framenum == gpfn->framenum) {
+ BKE_gpencil_layer_delframe(gpl, gpf);
+ }
+ }
+ }
#ifdef DEBUG
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum);
- }
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ BLI_assert(!gpf->next || gpf->framenum < gpf->next->framenum);
+ }
#endif
- }
- /* set cache flag to dirty */
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ /* set cache flag to dirty */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
static void posttrans_mask_clean(Mask *mask)
{
- MaskLayer *masklay;
+ MaskLayer *masklay;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskLayerShape *masklay_shape, *masklay_shape_next;
- bool is_double = false;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskLayerShape *masklay_shape, *masklay_shape_next;
+ bool is_double = false;
- BLI_listbase_sort_r(&masklay->splines_shapes, masklay_shape_cmp_frame, &is_double);
+ 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) {
- masklay_shape_next = masklay_shape->next;
- if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) {
- BKE_mask_layer_shape_unlink(masklay, masklay_shape);
- }
- }
- }
+ if (is_double) {
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape_next) {
+ masklay_shape_next = masklay_shape->next;
+ if (masklay_shape_next && masklay_shape->frame == masklay_shape_next->frame) {
+ BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+ }
+ }
+ }
#ifdef DEBUG
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame);
- }
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ BLI_assert(!masklay_shape->next || masklay_shape->frame < masklay_shape->next->frame);
+ }
#endif
- }
+ }
}
/* Time + Average value */
typedef struct tRetainedKeyframe {
- struct tRetainedKeyframe *next, *prev;
- float frame; /* frame to cluster around */
- float val; /* average value */
+ struct tRetainedKeyframe *next, *prev;
+ float frame; /* frame to cluster around */
+ float val; /* average value */
- size_t tot_count; /* number of keyframes that have been averaged */
- size_t del_count; /* number of keyframes of this sort that have been deleted so far */
+ size_t tot_count; /* number of keyframes that have been averaged */
+ size_t del_count; /* number of keyframes of this sort that have been deleted so far */
} tRetainedKeyframe;
/* Called during special_aftertrans_update to make sure selected keyframes replace
@@ -3788,152 +3877,152 @@ typedef struct tRetainedKeyframe {
*/
static void posttrans_fcurve_clean(FCurve *fcu, const bool use_handle)
{
- /* NOTE: We assume that all keys are sorted */
- ListBase retained_keys = {NULL, NULL};
- const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) == 0);
-
- /* sanity checks */
- if ((fcu->totvert == 0) || (fcu->bezt == NULL))
- return;
-
- /* 1) Identify selected keyframes, and average the values on those
- * in case there are collisions due to multiple keys getting scaled
- * to all end up on the same frame
- */
- for (int i = 0; i < fcu->totvert; i++) {
- BezTriple *bezt = &fcu->bezt[i];
-
- if (BEZT_ISSEL_ANY(bezt)) {
- bool found = false;
-
- /* If there's another selected frame here, merge it */
- for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
- if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
- rk->val += bezt->vec[1][1];
- rk->tot_count++;
-
- found = true;
- break;
- }
- else if (rk->frame < bezt->vec[1][0]) {
- /* Terminate early if have passed the supposed insertion point? */
- break;
- }
- }
-
- /* If nothing found yet, create a new one */
- if (found == false) {
- tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
-
- rk->frame = bezt->vec[1][0];
- rk->val = bezt->vec[1][1];
- rk->tot_count = 1;
-
- BLI_addtail(&retained_keys, rk);
- }
- }
- }
-
- if (BLI_listbase_is_empty(&retained_keys)) {
- /* This may happen if none of the points were selected... */
- if (G.debug & G_DEBUG) {
- printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
- }
- return;
- }
- else {
- /* Compute the average values for each retained keyframe */
- for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
- rk->val = rk->val / (float)rk->tot_count;
- }
- }
-
- /* 2) Delete all keyframes duplicating the "retained keys" found above
- * - Most of these will be unselected keyframes
- * - Some will be selected keyframes though. For those, we only keep the last one
- * (or else everything is gone), and replace its value with the averaged value.
- */
- for (int i = fcu->totvert - 1; i >= 0; i--) {
- BezTriple *bezt = &fcu->bezt[i];
-
- /* Is this keyframe a candidate for deletion? */
- /* TODO: Replace loop with an O(1) lookup instead */
- for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
- if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
- /* Selected keys are treated with greater care than unselected ones... */
- if (BEZT_ISSEL_ANY(bezt)) {
- /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
- * (or else we wouldn't have any keyframe left here)
- * - Otherwise, there are still other selected keyframes on this frame
- * to be merged down still ==> DELETE IT
- */
- if (rk->del_count == rk->tot_count - 1) {
- /* Update keyframe... */
- if (can_average_points) {
- /* TODO: update handles too? */
- bezt->vec[1][1] = rk->val;
- }
- }
- else {
- /* Delete Keyframe */
- delete_fcurve_key(fcu, i, 0);
- }
-
- /* Update count of how many we've deleted
- * - It should only matter that we're doing this for all but the last one
- */
- rk->del_count++;
- }
- else {
- /* Always delete - Unselected keys don't matter */
- delete_fcurve_key(fcu, i, 0);
- }
-
- /* Stop the RK search... we've found our match now */
- break;
- }
- }
- }
-
- /* 3) Recalculate handles */
- testhandles_fcurve(fcu, use_handle);
-
- /* cleanup */
- BLI_freelistN(&retained_keys);
+ /* NOTE: We assume that all keys are sorted */
+ ListBase retained_keys = {NULL, NULL};
+ const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
+ 0);
+
+ /* sanity checks */
+ if ((fcu->totvert == 0) || (fcu->bezt == NULL))
+ return;
+
+ /* 1) Identify selected keyframes, and average the values on those
+ * in case there are collisions due to multiple keys getting scaled
+ * to all end up on the same frame
+ */
+ for (int i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt = &fcu->bezt[i];
+
+ if (BEZT_ISSEL_ANY(bezt)) {
+ bool found = false;
+
+ /* If there's another selected frame here, merge it */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
+ rk->val += bezt->vec[1][1];
+ rk->tot_count++;
+
+ found = true;
+ break;
+ }
+ else if (rk->frame < bezt->vec[1][0]) {
+ /* Terminate early if have passed the supposed insertion point? */
+ break;
+ }
+ }
+
+ /* If nothing found yet, create a new one */
+ if (found == false) {
+ tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
+
+ rk->frame = bezt->vec[1][0];
+ rk->val = bezt->vec[1][1];
+ rk->tot_count = 1;
+
+ BLI_addtail(&retained_keys, rk);
+ }
+ }
+ }
+
+ if (BLI_listbase_is_empty(&retained_keys)) {
+ /* This may happen if none of the points were selected... */
+ if (G.debug & G_DEBUG) {
+ printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
+ }
+ return;
+ }
+ else {
+ /* Compute the average values for each retained keyframe */
+ for (tRetainedKeyframe *rk = retained_keys.first; rk; rk = rk->next) {
+ rk->val = rk->val / (float)rk->tot_count;
+ }
+ }
+
+ /* 2) Delete all keyframes duplicating the "retained keys" found above
+ * - Most of these will be unselected keyframes
+ * - Some will be selected keyframes though. For those, we only keep the last one
+ * (or else everything is gone), and replace its value with the averaged value.
+ */
+ for (int i = fcu->totvert - 1; i >= 0; i--) {
+ BezTriple *bezt = &fcu->bezt[i];
+
+ /* Is this keyframe a candidate for deletion? */
+ /* TODO: Replace loop with an O(1) lookup instead */
+ for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
+ if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
+ /* Selected keys are treated with greater care than unselected ones... */
+ if (BEZT_ISSEL_ANY(bezt)) {
+ /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
+ * (or else we wouldn't have any keyframe left here)
+ * - Otherwise, there are still other selected keyframes on this frame
+ * to be merged down still ==> DELETE IT
+ */
+ if (rk->del_count == rk->tot_count - 1) {
+ /* Update keyframe... */
+ if (can_average_points) {
+ /* TODO: update handles too? */
+ bezt->vec[1][1] = rk->val;
+ }
+ }
+ else {
+ /* Delete Keyframe */
+ delete_fcurve_key(fcu, i, 0);
+ }
+
+ /* Update count of how many we've deleted
+ * - It should only matter that we're doing this for all but the last one
+ */
+ rk->del_count++;
+ }
+ else {
+ /* Always delete - Unselected keys don't matter */
+ delete_fcurve_key(fcu, i, 0);
+ }
+
+ /* Stop the RK search... we've found our match now */
+ break;
+ }
+ }
+ }
+
+ /* 3) Recalculate handles */
+ testhandles_fcurve(fcu, use_handle);
+
+ /* cleanup */
+ BLI_freelistN(&retained_keys);
}
-
/* Called by special_aftertrans_update to make sure selected keyframes replace
* any other keyframes which may reside on that frame (that is not selected).
* remake_action_ipos should have already been called
*/
static void posttrans_action_clean(bAnimContext *ac, bAction *act)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(ac, &anim_data, filter, act, ANIMCONT_ACTION);
- /* loop through relevant data, removing keyframes as appropriate
- * - all keyframes are converted in/out of global time
- */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ /* loop through relevant data, removing keyframes as appropriate
+ * - all keyframes are converted in/out of global time
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
- posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
- }
- else
- posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
- }
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(ale->key_data, false); /* only use handles in graph editor */
+ }
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
+ /* free temp data */
+ ANIM_animdata_freelist(&anim_data);
}
/* ----------------------------- */
@@ -3941,92 +4030,93 @@ 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, bool is_prop_edit)
{
- BezTriple *bezt;
- int i, count = 0, count_all = 0;
+ BezTriple *bezt;
+ int i, count = 0, count_all = 0;
- if (ELEM(NULL, fcu, fcu->bezt))
- return count;
+ 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 (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 (bezt->f2 & SELECT)
- count++;
+ /* only include points that occur on the right side of cfra */
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ 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 (bezt->f2 & SELECT)
+ count++;
- count_all++;
- }
- }
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else 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, bool is_prop_edit)
{
- bGPDframe *gpf;
- int count = 0, count_all = 0;
+ bGPDframe *gpf;
+ int count = 0, count_all = 0;
- if (gpl == NULL)
- return count;
+ 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 (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
- if (gpf->flag & GP_FRAME_SELECT)
- count++;
- count_all++;
- }
- }
+ /* only include points that occur on the right side of cfra */
+ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
+ if (gpf->flag & GP_FRAME_SELECT)
+ count++;
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else
- 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, bool is_prop_edit)
{
- MaskLayerShape *masklayer_shape;
- int count = 0, count_all = 0;
+ MaskLayerShape *masklayer_shape;
+ int count = 0, count_all = 0;
- if (masklay == NULL)
- return count;
+ 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 (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
- if (masklayer_shape->flag & MASK_SHAPE_SELECT)
- count++;
- count_all++;
- }
- }
+ /* 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 (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra)) {
+ if (masklayer_shape->flag & MASK_SHAPE_SELECT)
+ count++;
+ count_all++;
+ }
+ }
- if (is_prop_edit && count > 0)
- return count_all;
- else
- 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, float ypos)
{
- /* memory is calloc'ed, so that should zero everything nicely for us */
- td->val = time;
- td->ival = *(time);
+ /* 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;
+ 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.
- */
- td->extra = adt;
+ /* store the AnimData where this keyframe exists as a keyframe of the
+ * active action as td->extra.
+ */
+ td->extra = adt;
}
/* This function advances the address to which td points to, so it must return
@@ -4036,61 +4126,68 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypo
* 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, bool is_prop_edit, float ypos)
+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;
- int i;
+ BezTriple *bezt;
+ TransData2D *td2d = *td2dv;
+ int i;
- if (ELEM(NULL, fcu, fcu->bezt))
- return td;
+ if (ELEM(NULL, fcu, fcu->bezt))
+ return td;
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- /* only add selected keyframes (for now, proportional edit is not enabled) */
- if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(),
- * so can't use BEZT_ISSEL_ANY() 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, ypos);
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* only add selected keyframes (for now, proportional edit is not enabled) */
+ if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(),
+ * so can't use BEZT_ISSEL_ANY() 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, ypos);
- if (bezt->f2 & SELECT)
- td->flag |= TD_SELECTED;
+ 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];
- td2d->h2 = bezt->vec[2];
+ /*set flags to move handles as necessary*/
+ td->flag |= TD_MOVEHANDLE1 | TD_MOVEHANDLE2;
+ td2d->h1 = bezt->vec[0];
+ td2d->h2 = bezt->vec[2];
- copy_v2_v2(td2d->ih1, td2d->h1);
- copy_v2_v2(td2d->ih2, td2d->h2);
+ copy_v2_v2(td2d->ih1, td2d->h1);
+ copy_v2_v2(td2d->ih2, td2d->h2);
- td++;
- td2d++;
- }
- }
- }
+ td++;
+ td2d++;
+ }
+ }
+ }
- *td2dv = td2d;
+ *td2dv = td2d;
- return td;
+ return td;
}
/* helper struct for gp-frame transforms (only used here) */
typedef struct tGPFtransdata {
- float val; /* where transdata writes transform */
- int *sdata; /* pointer to gpf->framenum */
+ float val; /* where transdata writes transform */
+ int *sdata; /* pointer to gpf->framenum */
} tGPFtransdata;
/* This function helps flush transdata written to tempdata into the gp-frames */
void flushTransIntFrameActionData(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tGPFtransdata *tfd = tc->custom.type.data;
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ tGPFtransdata *tfd = tc->custom.type.data;
- /* flush data! */
- for (int i = 0; i < tc->data_len; i++, tfd++) {
- *(tfd->sdata) = round_fl_to_int(tfd->val);
- }
+ /* flush data! */
+ for (int i = 0; i < tc->data_len; i++, tfd++) {
+ *(tfd->sdata) = round_fl_to_int(tfd->val);
+ }
}
/* This function advances the address to which td points to, so it must return
@@ -4100,916 +4197,1011 @@ 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, 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 (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;
-
- /* advance td now */
- td++;
- tfd++;
- count++;
- }
- }
- }
-
- return count;
+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 (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;
+
+ /* advance td now */
+ td++;
+ tfd++;
+ count++;
+ }
+ }
+ }
+
+ return count;
}
/* 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, 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 (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;
-
- /* advance td now */
- td++;
- tfd++;
- count++;
- }
- }
- }
-
- return count;
+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 (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;
+
+ /* advance td now */
+ td++;
+ tfd++;
+ count++;
+ }
+ }
+ }
+
+ return count;
}
-
static void createTransActionData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- 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;
-
- /* filter data */
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
- else
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* which side of the current frame should be allowed */
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* 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)
- */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)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)
- adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
- else if (ale->type == ANIMTYPE_MASKLAYER)
- 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 */
- if (count == 0) {
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(Action Editor)");
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "transdata2d");
- td = tc->data;
- td2d = tc->data_2d;
-
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
- tc->custom.type.use_free = true;
- }
-
- /* loop 2: build transdata array */
- for (ale = anim_data.first; ale; ale = ale->next) {
-
- if (is_prop_edit && !ale->tag)
- continue;
-
- cfra = (float)CFRA;
-
- {
- AnimData *adt;
- adt = ANIM_nla_mapping_get(&ac, ale);
- if (adt) {
- cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
- }
- }
-
- if (ale->type == ANIMTYPE_GPLAYER) {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
- int i;
-
- i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
- td += i;
- tfd += i;
- }
- else if (ale->type == ANIMTYPE_MASKLAYER) {
- MaskLayer *masklay = (MaskLayer *)ale->data;
- int i;
-
- i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
- td += i;
- tfd += i;
- }
- else {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
- }
- }
-
- /* calculate distances for proportional editing */
- if (is_prop_edit) {
- td = tc->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_iter->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);
+ Scene *scene = t->scene;
+ 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;
+
+ /* filter data */
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(&ac.ar->v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
+ t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* 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)
+ */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)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)
+ adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
+ else if (ale->type == ANIMTYPE_MASKLAYER)
+ 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 */
+ if (count == 0) {
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(Action Editor)");
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "transdata2d");
+ td = tc->data;
+ td2d = tc->data_2d;
+
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
+ tc->custom.type.use_free = true;
+ }
+
+ /* loop 2: build transdata array */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+
+ if (is_prop_edit && !ale->tag)
+ continue;
+
+ cfra = (float)CFRA;
+
+ {
+ AnimData *adt;
+ adt = ANIM_nla_mapping_get(&ac, ale);
+ if (adt) {
+ cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
+ }
+
+ if (ale->type == ANIMTYPE_GPLAYER) {
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ int i;
+
+ i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
+ td += i;
+ tfd += i;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ int i;
+
+ i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
+ td += i;
+ tfd += i;
+ }
+ else {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
+ }
+ }
+
+ /* calculate distances for proportional editing */
+ if (is_prop_edit) {
+ td = tc->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_iter->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);
}
/* ********************* GRAPH EDITOR ************************* */
typedef struct TransDataGraph {
- float unit_scale;
- float offset;
+ float unit_scale;
+ float offset;
} TransDataGraph;
/* Helper function for createTransGraphEditData, which is responsible for associating
* source data with transform data
*/
-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 offset)
-{
- float *loc = bezt->vec[bi];
- const float *cent = bezt->vec[1];
-
- /* New location from td gets dumped onto the old-location of td2d, which then
- * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
- *
- * Due to NLA mapping, we apply NLA mapping to some of the verts here,
- * and then that mapping will be undone after transform is done.
- */
-
- if (adt) {
- td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
- 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] + 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] + offset) * unit_scale;
- td2d->loc[2] = 0.0f;
- td2d->loc2d = loc;
-
- td->loc = td2d->loc;
- copy_v3_v3(td->center, cent);
- td->center[1] = (td->center[1] + offset) * unit_scale;
- copy_v3_v3(td->iloc, td->loc);
- }
-
- if (!ishandle) {
- td2d->h1 = bezt->vec[0];
- td2d->h2 = bezt->vec[2];
- copy_v2_v2(td2d->ih1, td2d->h1);
- copy_v2_v2(td2d->ih2, td2d->h2);
- }
- else {
- td2d->h1 = NULL;
- td2d->h2 = NULL;
- }
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL; td->val = NULL;
-
- /* store AnimData info in td->extra, for applying mapping when flushing */
- td->extra = adt;
-
- if (selected) {
- td->flag |= TD_SELECTED;
- td->dist = 0.0f;
- }
- else
- td->dist = FLT_MAX;
-
- if (ishandle)
- td->flag |= TD_NOTIMESNAP;
- if (intvals)
- td->flag |= TD_INTVALUES;
-
- /* copy space-conversion matrices for dealing with non-uniform scales */
- copy_m3_m3(td->mtx, mtx);
- copy_m3_m3(td->smtx, smtx);
-
- tdg->unit_scale = unit_scale;
- tdg->offset = offset;
+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 offset)
+{
+ float *loc = bezt->vec[bi];
+ const float *cent = bezt->vec[1];
+
+ /* New location from td gets dumped onto the old-location of td2d, which then
+ * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
+ *
+ * Due to NLA mapping, we apply NLA mapping to some of the verts here,
+ * and then that mapping will be undone after transform is done.
+ */
+
+ if (adt) {
+ td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
+ 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] + 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] + offset) * unit_scale;
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = loc;
+
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, cent);
+ td->center[1] = (td->center[1] + offset) * unit_scale;
+ copy_v3_v3(td->iloc, td->loc);
+ }
+
+ if (!ishandle) {
+ td2d->h1 = bezt->vec[0];
+ td2d->h2 = bezt->vec[2];
+ copy_v2_v2(td2d->ih1, td2d->h1);
+ copy_v2_v2(td2d->ih2, td2d->h2);
+ }
+ else {
+ td2d->h1 = NULL;
+ td2d->h2 = NULL;
+ }
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ /* store AnimData info in td->extra, for applying mapping when flushing */
+ td->extra = adt;
+
+ if (selected) {
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0f;
+ }
+ else
+ td->dist = FLT_MAX;
+
+ if (ishandle)
+ td->flag |= TD_NOTIMESNAP;
+ if (intvals)
+ td->flag |= TD_INTVALUES;
+
+ /* copy space-conversion matrices for dealing with non-uniform scales */
+ copy_m3_m3(td->mtx, mtx);
+ copy_m3_m3(td->smtx, smtx);
+
+ tdg->unit_scale = unit_scale;
+ tdg->offset = offset;
}
static bool graph_edit_is_translation_mode(TransInfo *t)
{
- return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
+ return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
}
static bool graph_edit_use_local_center(TransInfo *t)
{
- return ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (graph_edit_is_translation_mode(t) == false));
+ return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false));
}
-
-static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
+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;
+ 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;
+ 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]));
- }
+ if (sel1 || sel2 || sel3) {
+ td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
+ }
- td_iter += 3;
- }
- }
+ td_iter += 3;
+ }
+ }
}
static void createTransGraphEditData(bContext *C, TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- Scene *scene = t->scene;
- ARegion *ar = t->ar;
- View2D *v2d = &ar->v2d;
-
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataGraph *tdg = NULL;
-
- bAnimContext ac;
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- BezTriple *bezt;
- int count = 0, i;
- float mtx[3][3], smtx[3][3];
- 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 */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- anim_map_flag |= ANIM_get_normalization_flags(&ac);
-
- /* filter data */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* which side of the current frame should be allowed */
- // XXX we still want this mode, but how to get this using standard transform too?
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- float xmouse, ymouse;
-
- UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
-
- /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
- for (ale = anim_data.first; ale; ale = ale->next) {
- 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)
- 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 */
- 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 (is_prop_edit) {
- curvecount += 3;
- if (sel2 || sel1 || sel3)
- selected = true;
- }
- else {
- if (!is_translation_mode || !(sel2)) {
- if (sel1) {
- count++;
- }
-
- if (sel3) {
- count++;
- }
- }
-
- /* only include main vert if selected */
- if (sel2 && !use_local_center) {
- count++;
- }
- }
- }
- }
-
- if (is_prop_edit) {
- if (selected) {
- count += curvecount;
- ale->tag = true;
- }
- }
- }
-
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
- return;
- }
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* allocate memory for data */
- tc->data_len = count;
-
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
- /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
- tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
- tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
- tc->custom.type.use_free = true;
-
- td = tc->data;
- td2d = tc->data_2d;
- tdg = tc->custom.type.data;
-
- /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
- unit_m3(mtx);
- unit_m3(smtx);
-
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
- float xscale, yscale;
-
- /* apply scale factors to x and y axes of space-conversion matrices */
- UI_view2d_scale_get(v2d, &xscale, &yscale);
-
- /* mtx is data to global (i.e. view) conversion */
- mul_v3_fl(mtx[0], xscale);
- mul_v3_fl(mtx[1], yscale);
-
- /* smtx is global (i.e. view) to data conversion */
- if (IS_EQF(xscale, 0.0f) == 0) mul_v3_fl(smtx[0], 1.0f / xscale);
- if (IS_EQF(yscale, 0.0f) == 0) mul_v3_fl(smtx[1], 1.0f / yscale);
- }
-
- /* loop 2: build transdata arrays */
- for (ale = anim_data.first; ale; ale = ale->next) {
- 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, offset;
- float cfra;
-
- /* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL || (is_prop_edit && 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;
-
- 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++) {
- 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;
-
- TransDataCurveHandleFlags *hdata = NULL;
- /* short h1=1, h2=1; */ /* UNUSED */
-
- 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 */
- }
- }
-
- /* 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);
-
- }
- /* 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 = tc->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 {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
-
- if (sel2) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
-
- if (sel3 || sel2) {
- td->dist = td->rdist = 0.0f;
- }
- else {
- graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
- }
- td++;
- }
- }
- }
- }
-
- /* cleanup temp list */
- ANIM_animdata_freelist(&anim_data);
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+ ARegion *ar = t->ar;
+ View2D *v2d = &ar->v2d;
+
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataGraph *tdg = NULL;
+
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BezTriple *bezt;
+ int count = 0, i;
+ float mtx[3][3], smtx[3][3];
+ 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 */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ anim_map_flag |= ANIM_get_normalization_flags(&ac);
+
+ /* filter data */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* which side of the current frame should be allowed */
+ // XXX we still want this mode, but how to get this using standard transform too?
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ float xmouse, ymouse;
+
+ UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &xmouse, &ymouse);
+ t->frame_side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
+
+ /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ 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)
+ 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 */
+ 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 (is_prop_edit) {
+ curvecount += 3;
+ if (sel2 || sel1 || sel3)
+ selected = true;
+ }
+ else {
+ if (!is_translation_mode || !(sel2)) {
+ if (sel1) {
+ count++;
+ }
+
+ if (sel3) {
+ count++;
+ }
+ }
+
+ /* only include main vert if selected */
+ if (sel2 && !use_local_center) {
+ count++;
+ }
+ }
+ }
+ }
+
+ if (is_prop_edit) {
+ if (selected) {
+ count += curvecount;
+ ale->tag = true;
+ }
+ }
+ }
+
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
+ return;
+ }
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* allocate memory for data */
+ tc->data_len = count;
+
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
+ /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
+ tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
+ tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
+ tc->custom.type.use_free = true;
+
+ td = tc->data;
+ td2d = tc->data_2d;
+ tdg = tc->custom.type.data;
+
+ /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
+ unit_m3(mtx);
+ unit_m3(smtx);
+
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
+ float xscale, yscale;
+
+ /* apply scale factors to x and y axes of space-conversion matrices */
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
+
+ /* mtx is data to global (i.e. view) conversion */
+ mul_v3_fl(mtx[0], xscale);
+ mul_v3_fl(mtx[1], yscale);
+
+ /* smtx is global (i.e. view) to data conversion */
+ if (IS_EQF(xscale, 0.0f) == 0)
+ mul_v3_fl(smtx[0], 1.0f / xscale);
+ if (IS_EQF(yscale, 0.0f) == 0)
+ mul_v3_fl(smtx[1], 1.0f / yscale);
+ }
+
+ /* loop 2: build transdata arrays */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ 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, offset;
+ float cfra;
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt == NULL || (is_prop_edit && 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;
+
+ 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++) {
+ 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;
+
+ TransDataCurveHandleFlags *hdata = NULL;
+ /* short h1=1, h2=1; */ /* UNUSED */
+
+ 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 */
+ }
+ }
+
+ /* 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);
+ }
+ /* 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 = tc->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 {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+
+ if (sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+
+ if (sel3 || sel2) {
+ td->dist = td->rdist = 0.0f;
+ }
+ else {
+ graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
+ }
+ td++;
+ }
+ }
+ }
+ }
+
+ /* cleanup temp list */
+ ANIM_animdata_freelist(&anim_data);
}
-
/* ------------------------ */
/* struct for use in re-sorting BezTriples during Graph Editor transform */
typedef struct BeztMap {
- BezTriple *bezt;
- unsigned int oldIndex; /* index of bezt in fcu->bezt array before sorting */
- unsigned int newIndex; /* index of bezt in fcu->bezt array after sorting */
- short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
- char pipo, cipo; /* interpolation of current and next segments */
+ BezTriple *bezt;
+ unsigned int oldIndex; /* index of bezt in fcu->bezt array before sorting */
+ unsigned int newIndex; /* index of bezt in fcu->bezt array after sorting */
+ short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
+ char pipo, cipo; /* interpolation of current and next segments */
} BeztMap;
-
/* This function converts an FCurve's BezTriple array to a BeztMap array
* NOTE: this allocates memory that will need to get freed later
*/
static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert, const short UNUSED(use_handle))
{
- BezTriple *bezt = bezts;
- BezTriple *prevbezt = NULL;
- BeztMap *bezm, *bezms;
- int i;
+ BezTriple *bezt = bezts;
+ BezTriple *prevbezt = NULL;
+ BeztMap *bezm, *bezms;
+ int i;
- /* allocate memory for this array */
- if (totvert == 0 || bezts == NULL)
- return NULL;
- bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
+ /* allocate memory for this array */
+ if (totvert == 0 || bezts == NULL)
+ return NULL;
+ bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
- /* assign beztriples to beztmaps */
- for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
- bezm->bezt = bezt;
+ /* assign beztriples to beztmaps */
+ for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
+ bezm->bezt = bezt;
- bezm->oldIndex = i;
- bezm->newIndex = i;
+ bezm->oldIndex = i;
+ bezm->newIndex = i;
- bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
- bezm->cipo = bezt->ipo;
- }
+ bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
+ bezm->cipo = bezt->ipo;
+ }
- return bezms;
+ return bezms;
}
/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
static void sort_time_beztmaps(BeztMap *bezms, int totvert, const short UNUSED(use_handle))
{
- BeztMap *bezm;
- int i, ok = 1;
-
- /* keep repeating the process until nothing is out of place anymore */
- while (ok) {
- ok = 0;
-
- bezm = bezms;
- i = totvert;
- while (i--) {
- /* is current bezm out of order (i.e. occurs later than next)? */
- if (i > 0) {
- if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
- bezm->newIndex++;
- (bezm + 1)->newIndex--;
-
- SWAP(BeztMap, *bezm, *(bezm + 1));
-
- ok = 1;
- }
- }
-
- /* do we need to check if the handles need to be swapped?
- * optimization: this only needs to be performed in the first loop
- */
- if (bezm->swapHs == 0) {
- if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
- (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0]) )
- {
- /* handles need to be swapped */
- bezm->swapHs = 1;
- }
- else {
- /* handles need to be cleared */
- bezm->swapHs = -1;
- }
- }
-
- bezm++;
- }
- }
+ BeztMap *bezm;
+ int i, ok = 1;
+
+ /* keep repeating the process until nothing is out of place anymore */
+ while (ok) {
+ ok = 0;
+
+ bezm = bezms;
+ i = totvert;
+ while (i--) {
+ /* is current bezm out of order (i.e. occurs later than next)? */
+ if (i > 0) {
+ if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
+ bezm->newIndex++;
+ (bezm + 1)->newIndex--;
+
+ SWAP(BeztMap, *bezm, *(bezm + 1));
+
+ ok = 1;
+ }
+ }
+
+ /* do we need to check if the handles need to be swapped?
+ * optimization: this only needs to be performed in the first loop
+ */
+ if (bezm->swapHs == 0) {
+ if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
+ (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0])) {
+ /* handles need to be swapped */
+ bezm->swapHs = 1;
+ }
+ else {
+ /* handles need to be cleared */
+ bezm->swapHs = -1;
+ }
+ }
+
+ bezm++;
+ }
+ }
}
/* This function firstly adjusts the pointers that the transdata has to each BezTriple */
-static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
-{
- BezTriple *bezts = fcu->bezt;
- BeztMap *bezm;
- TransData2D *td2d;
- TransData *td;
- int i, j;
- char *adjusted;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* dynamically allocate an array of chars to mark whether an TransData's
- * pointers have been fixed already, so that we don't override ones that are
- * already done
- */
- adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
-
- /* for each beztmap item, find if it is used anywhere */
- bezm = bezms;
- for (i = 0; i < totvert; i++, bezm++) {
- /* loop through transdata, testing if we have a hit
- * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
- */
- td2d = tc->data_2d;
- td = tc->data;
- for (j = 0; j < tc->data_len; j++, td2d++, td++) {
- /* skip item if already marked */
- if (adjusted[j] != 0) continue;
-
- /* update all transdata pointers, no need to check for selections etc,
- * since only points that are really needed were created as transdata
- */
- if (td2d->loc2d == bezm->bezt->vec[0]) {
- if (bezm->swapHs == 1)
- td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
- else
- td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
- adjusted[j] = 1;
- }
- else if (td2d->loc2d == bezm->bezt->vec[2]) {
- if (bezm->swapHs == 1)
- td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
- else
- td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
- adjusted[j] = 1;
- }
- else if (td2d->loc2d == bezm->bezt->vec[1]) {
- td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
-
- /* if only control point is selected, the handle pointers need to be updated as well */
- if (td2d->h1)
- td2d->h1 = (bezts + bezm->newIndex)->vec[0];
- if (td2d->h2)
- td2d->h2 = (bezts + bezm->newIndex)->vec[2];
-
- adjusted[j] = 1;
- }
-
- /* the handle type pointer has to be updated too */
- if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
- if (bezm->swapHs == 1) {
- td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
- td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
- }
- else {
- td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
- td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
- }
- }
- }
-
- }
-
- /* free temp memory used for 'adjusted' array */
- MEM_freeN(adjusted);
+static void beztmap_to_data(
+ TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert, const short UNUSED(use_handle))
+{
+ BezTriple *bezts = fcu->bezt;
+ BeztMap *bezm;
+ TransData2D *td2d;
+ TransData *td;
+ int i, j;
+ char *adjusted;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* dynamically allocate an array of chars to mark whether an TransData's
+ * pointers have been fixed already, so that we don't override ones that are
+ * already done
+ */
+ adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
+
+ /* for each beztmap item, find if it is used anywhere */
+ bezm = bezms;
+ for (i = 0; i < totvert; i++, bezm++) {
+ /* loop through transdata, testing if we have a hit
+ * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
+ */
+ td2d = tc->data_2d;
+ td = tc->data;
+ for (j = 0; j < tc->data_len; j++, td2d++, td++) {
+ /* skip item if already marked */
+ if (adjusted[j] != 0)
+ continue;
+
+ /* update all transdata pointers, no need to check for selections etc,
+ * since only points that are really needed were created as transdata
+ */
+ if (td2d->loc2d == bezm->bezt->vec[0]) {
+ if (bezm->swapHs == 1)
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
+ else
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
+ adjusted[j] = 1;
+ }
+ else if (td2d->loc2d == bezm->bezt->vec[2]) {
+ if (bezm->swapHs == 1)
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
+ else
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
+ adjusted[j] = 1;
+ }
+ else if (td2d->loc2d == bezm->bezt->vec[1]) {
+ td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
+
+ /* if only control point is selected, the handle pointers need to be updated as well */
+ if (td2d->h1)
+ td2d->h1 = (bezts + bezm->newIndex)->vec[0];
+ if (td2d->h2)
+ td2d->h2 = (bezts + bezm->newIndex)->vec[2];
+
+ adjusted[j] = 1;
+ }
+
+ /* the handle type pointer has to be updated too */
+ if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
+ if (bezm->swapHs == 1) {
+ td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
+ td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
+ }
+ else {
+ td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
+ td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
+ }
+ }
+ }
+ }
+
+ /* free temp memory used for 'adjusted' array */
+ MEM_freeN(adjusted);
}
/* This function is called by recalcData during the Transform loop to recalculate
@@ -5021,33 +5213,33 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
*/
void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- bAnimListElem *ale;
- const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ bAnimListElem *ale;
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
- /* sort and reassign verts */
- for (ale = anim_data->first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
+ /* sort and reassign verts */
+ for (ale = anim_data->first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
- if (fcu->bezt) {
- BeztMap *bezm;
+ if (fcu->bezt) {
+ BeztMap *bezm;
- /* adjust transform-data pointers */
- /* note, none of these functions use 'use_handle', it could be removed */
- bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
- sort_time_beztmaps(bezm, fcu->totvert, use_handle);
- beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
+ /* adjust transform-data pointers */
+ /* note, none of these functions use 'use_handle', it could be removed */
+ bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert, use_handle);
+ sort_time_beztmaps(bezm, fcu->totvert, use_handle);
+ beztmap_to_data(t, fcu, bezm, fcu->totvert, use_handle);
- /* free mapping stuff */
- MEM_freeN(bezm);
+ /* free mapping stuff */
+ MEM_freeN(bezm);
- /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
- sort_time_fcurve(fcu);
+ /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
+ sort_time_fcurve(fcu);
- /* make sure handles are all set correctly */
- testhandles_fcurve(fcu, use_handle);
- }
- }
+ /* make sure handles are all set correctly */
+ testhandles_fcurve(fcu, use_handle);
+ }
+ }
}
/* this function is called on recalcData to apply the transforms applied
@@ -5055,94 +5247,92 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
*/
void flushTransGraphData(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- TransData *td;
- TransData2D *td2d;
- TransDataGraph *tdg;
- Scene *scene = t->scene;
- double secf = FPS;
- int a;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data;
- a < tc->data_len;
- a++, td++, td2d++, tdg++)
- {
- /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
- AnimData *adt = (AnimData *)td->extra;
-
- float inv_unit_scale = 1.0f / tdg->unit_scale;
-
- /* handle snapping for time values
- * - we should still be in NLA-mapping timespace
- * - only apply to keyframes (but never to handles)
- * - don't do this when canceling, or else these changes won't go away
- */
- if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0) {
- switch (sipo->autosnap) {
- case SACTSNAP_FRAME: /* snap to nearest frame */
- td2d->loc[0] = floor((double)td2d->loc[0] + 0.5);
- break;
-
- case SACTSNAP_SECOND: /* snap to nearest second */
- td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
- break;
-
- case SACTSNAP_MARKER: /* snap to nearest marker */
- td2d->loc[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]);
- break;
- }
- }
-
- /* we need to unapply the nla-mapping from the time in some situations */
- if (adt)
- td2d->loc2d[0] = BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
- else
- td2d->loc2d[0] = td2d->loc[0];
-
- /* Time-stepping auto-snapping modes don't get applied for Graph Editor transforms,
- * as these use the generic transform modes which don't account for this sort of thing.
- * These ones aren't affected by NLA mapping, so we do this after the conversion...
- *
- * NOTE: We also have to apply to td->loc, as that's what the handle-adjustment step below looks
- * to, otherwise we get "swimming handles"
- * NOTE: We don't do this when canceling transforms, or else these changes don't go away
- */
- if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0 &&
- ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP))
- {
- switch (sipo->autosnap) {
- case SACTSNAP_STEP: /* frame step */
- td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5);
- td->loc[0] = floor((double)td->loc[0] + 0.5);
- break;
-
- case SACTSNAP_TSTEP: /* second step */
- /* XXX: the handle behavior in this case is still not quite right... */
- td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
- td->loc[0] = floor(((double)td->loc[0] / secf) + 0.5) * secf;
- break;
- }
- }
-
- /* if int-values only, truncate to integers */
- if (td->flag & TD_INTVALUES)
- td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f);
- else
- 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];
- td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
- }
-
- if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
- td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
- td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
- }
- }
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ TransData *td;
+ TransData2D *td2d;
+ TransDataGraph *tdg;
+ Scene *scene = t->scene;
+ double secf = FPS;
+ int a;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data; a < tc->data_len;
+ a++, td++, td2d++, tdg++) {
+ /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
+ AnimData *adt = (AnimData *)td->extra;
+
+ float inv_unit_scale = 1.0f / tdg->unit_scale;
+
+ /* handle snapping for time values
+ * - we should still be in NLA-mapping timespace
+ * - only apply to keyframes (but never to handles)
+ * - don't do this when canceling, or else these changes won't go away
+ */
+ if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0) {
+ switch (sipo->autosnap) {
+ case SACTSNAP_FRAME: /* snap to nearest frame */
+ td2d->loc[0] = floor((double)td2d->loc[0] + 0.5);
+ break;
+
+ case SACTSNAP_SECOND: /* snap to nearest second */
+ td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
+ break;
+
+ case SACTSNAP_MARKER: /* snap to nearest marker */
+ td2d->loc[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers,
+ td2d->loc[0]);
+ break;
+ }
+ }
+
+ /* we need to unapply the nla-mapping from the time in some situations */
+ if (adt)
+ td2d->loc2d[0] = BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
+ else
+ td2d->loc2d[0] = td2d->loc[0];
+
+ /* Time-stepping auto-snapping modes don't get applied for Graph Editor transforms,
+ * as these use the generic transform modes which don't account for this sort of thing.
+ * These ones aren't affected by NLA mapping, so we do this after the conversion...
+ *
+ * NOTE: We also have to apply to td->loc, as that's what the handle-adjustment step below looks
+ * to, otherwise we get "swimming handles"
+ * NOTE: We don't do this when canceling transforms, or else these changes don't go away
+ */
+ if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0 &&
+ ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP)) {
+ switch (sipo->autosnap) {
+ case SACTSNAP_STEP: /* frame step */
+ td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5);
+ td->loc[0] = floor((double)td->loc[0] + 0.5);
+ break;
+
+ case SACTSNAP_TSTEP: /* second step */
+ /* XXX: the handle behavior in this case is still not quite right... */
+ td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf;
+ td->loc[0] = floor(((double)td->loc[0] / secf) + 0.5) * secf;
+ break;
+ }
+ }
+
+ /* if int-values only, truncate to integers */
+ if (td->flag & TD_INTVALUES)
+ td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f);
+ else
+ 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];
+ td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ }
+
+ if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
+ td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+ }
+ }
}
/* ******************* Sequencer Transform data ******************* */
@@ -5157,540 +5347,543 @@ void flushTransGraphData(TransInfo *t)
*/
static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag)
{
- /* for extend we need to do some tricks */
- if (t->mode == TFM_TIME_EXTEND) {
-
- /* *** Extend Transform *** */
-
- Scene *scene = t->scene;
- int cfra = CFRA;
- int left = BKE_sequence_tx_get_final_left(seq, true);
- int right = BKE_sequence_tx_get_final_right(seq, true);
-
- if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
- *recursive = false;
- *count = 0;
- *flag = 0;
- }
- else if (seq->type == SEQ_TYPE_META) {
-
- /* for meta's we only ever need to extend their children, no matter what depth
- * just check the meta's are in the bounds */
- if (t->frame_side == 'R' && right <= cfra) *recursive = false;
- else if (t->frame_side == 'L' && left >= cfra) *recursive = false;
- else *recursive = true;
-
- *count = 1;
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- }
- else {
-
- *recursive = false; /* not a meta, so no thinking here */
- *count = 1; /* unless its set to 0, extend will never set 2 handles at once */
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
-
- if (t->frame_side == 'R') {
- if (right <= cfra) { *count = *flag = 0; } /* ignore */
- else if (left > cfra) { } /* keep the selection */
- else *flag |= SEQ_RIGHTSEL;
- }
- else {
- if (left >= cfra) { *count = *flag = 0; } /* ignore */
- else if (right < cfra) { } /* keep the selection */
- else *flag |= SEQ_LEFTSEL;
- }
- }
- }
- else {
-
- t->frame_side = 'B';
-
- /* *** Normal Transform *** */
-
- if (seq->depth == 0) {
-
- /* Count */
-
- /* Non nested strips (resect selection and handles) */
- if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
- *recursive = false;
- *count = 0;
- *flag = 0;
- }
- else {
- if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- *flag = seq->flag;
- *count = 2; /* we need 2 transdata's */
- }
- else {
- *flag = seq->flag;
- *count = 1; /* selected or with a handle selected */
- }
-
- /* Recursive */
-
- if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
- /* if any handles are selected, don't recurse */
- *recursive = true;
- }
- else {
- *recursive = false;
- }
- }
- }
- else {
- /* Nested, different rules apply */
+ /* for extend we need to do some tricks */
+ if (t->mode == TFM_TIME_EXTEND) {
+
+ /* *** Extend Transform *** */
+
+ Scene *scene = t->scene;
+ int cfra = CFRA;
+ int left = BKE_sequence_tx_get_final_left(seq, true);
+ int right = BKE_sequence_tx_get_final_right(seq, true);
+
+ if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) {
+ *recursive = false;
+ *count = 0;
+ *flag = 0;
+ }
+ else if (seq->type == SEQ_TYPE_META) {
+
+ /* for meta's we only ever need to extend their children, no matter what depth
+ * just check the meta's are in the bounds */
+ if (t->frame_side == 'R' && right <= cfra)
+ *recursive = false;
+ else if (t->frame_side == 'L' && left >= cfra)
+ *recursive = false;
+ else
+ *recursive = true;
+
+ *count = 1;
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ }
+ else {
+
+ *recursive = false; /* not a meta, so no thinking here */
+ *count = 1; /* unless its set to 0, extend will never set 2 handles at once */
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+
+ if (t->frame_side == 'R') {
+ if (right <= cfra) {
+ *count = *flag = 0;
+ } /* ignore */
+ else if (left > cfra) {
+ } /* keep the selection */
+ else
+ *flag |= SEQ_RIGHTSEL;
+ }
+ else {
+ if (left >= cfra) {
+ *count = *flag = 0;
+ } /* ignore */
+ else if (right < cfra) {
+ } /* keep the selection */
+ else
+ *flag |= SEQ_LEFTSEL;
+ }
+ }
+ }
+ else {
+
+ t->frame_side = 'B';
+
+ /* *** Normal Transform *** */
+
+ if (seq->depth == 0) {
+
+ /* Count */
+
+ /* Non nested strips (resect selection and handles) */
+ if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) {
+ *recursive = false;
+ *count = 0;
+ *flag = 0;
+ }
+ else {
+ if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ *flag = seq->flag;
+ *count = 2; /* we need 2 transdata's */
+ }
+ else {
+ *flag = seq->flag;
+ *count = 1; /* selected or with a handle selected */
+ }
+
+ /* Recursive */
+
+ if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
+ /* if any handles are selected, don't recurse */
+ *recursive = true;
+ }
+ else {
+ *recursive = false;
+ }
+ }
+ }
+ else {
+ /* Nested, different rules apply */
#ifdef SEQ_TX_NESTED_METAS
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *count = 1; /* ignore the selection for nested */
- *recursive = (seq->type == SEQ_TYPE_META);
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *count = 1; /* ignore the selection for nested */
+ *recursive = (seq->type == SEQ_TYPE_META);
#else
- if (seq->type == SEQ_TYPE_META) {
- /* Meta's can only directly be moved between channels since they
- * don't have their start and length set directly (children affect that)
- * since this Meta is nested we don't need any of its data in fact.
- * BKE_sequence_calc() will update its settings when run on the toplevel meta */
- *flag = 0;
- *count = 0;
- *recursive = true;
- }
- else {
- *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
- *count = 1; /* ignore the selection for nested */
- *recursive = false;
- }
+ if (seq->type == SEQ_TYPE_META) {
+ /* Meta's can only directly be moved between channels since they
+ * don't have their start and length set directly (children affect that)
+ * since this Meta is nested we don't need any of its data in fact.
+ * BKE_sequence_calc() will update its settings when run on the toplevel meta */
+ *flag = 0;
+ *count = 0;
+ *recursive = true;
+ }
+ else {
+ *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
+ *count = 1; /* ignore the selection for nested */
+ *recursive = false;
+ }
#endif
- }
- }
+ }
+ }
}
-
-
static int SeqTransCount(TransInfo *t, Sequence *parent, ListBase *seqbase, int depth)
{
- Sequence *seq;
- int tot = 0, recursive, count, flag;
+ Sequence *seq;
+ int tot = 0, recursive, count, flag;
- for (seq = seqbase->first; seq; seq = seq->next) {
- seq->depth = depth;
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ seq->depth = depth;
- /* seq->tmp is used by seq_tx_get_final_{left, right} to check sequence's range and clamp to it if needed.
- * it's first place where digging into sequences tree, so store link to parent here */
- seq->tmp = parent;
+ /* seq->tmp is used by seq_tx_get_final_{left, right} to check sequence's range and clamp to it if needed.
+ * it's first place where digging into sequences tree, so store link to parent here */
+ seq->tmp = parent;
- SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */
- tot += count;
+ SeqTransInfo(t, seq, &recursive, &count, &flag); /* ignore the flag */
+ tot += count;
- if (recursive) {
- tot += SeqTransCount(t, seq, &seq->seqbase, depth + 1);
- }
- }
+ if (recursive) {
+ tot += SeqTransCount(t, seq, &seq->seqbase, depth + 1);
+ }
+ }
- return tot;
+ return tot;
}
-
-static TransData *SeqToTransData(TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag)
+static TransData *SeqToTransData(
+ TransData *td, TransData2D *td2d, TransDataSeq *tdsq, Sequence *seq, int flag, int sel_flag)
{
- int start_left;
-
- switch (sel_flag) {
- case SELECT:
- /* Use seq_tx_get_final_left() and an offset here
- * so transform has the left hand location of the strip.
- * tdsq->start_offset is used when flushing the tx data back */
- start_left = BKE_sequence_tx_get_final_left(seq, false);
- td2d->loc[0] = start_left;
- tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
- break;
- case SEQ_LEFTSEL:
- start_left = BKE_sequence_tx_get_final_left(seq, false);
- td2d->loc[0] = start_left;
- break;
- case SEQ_RIGHTSEL:
- td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false);
- break;
- }
+ int start_left;
- td2d->loc[1] = seq->machine; /* channel - Y location */
- td2d->loc[2] = 0.0f;
- td2d->loc2d = NULL;
+ switch (sel_flag) {
+ case SELECT:
+ /* Use seq_tx_get_final_left() and an offset here
+ * so transform has the left hand location of the strip.
+ * tdsq->start_offset is used when flushing the tx data back */
+ start_left = BKE_sequence_tx_get_final_left(seq, false);
+ td2d->loc[0] = start_left;
+ tdsq->start_offset = start_left - seq->start; /* use to apply the original location */
+ break;
+ case SEQ_LEFTSEL:
+ start_left = BKE_sequence_tx_get_final_left(seq, false);
+ td2d->loc[0] = start_left;
+ break;
+ case SEQ_RIGHTSEL:
+ td2d->loc[0] = BKE_sequence_tx_get_final_right(seq, false);
+ break;
+ }
+ td2d->loc[1] = seq->machine; /* channel - Y location */
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = NULL;
- tdsq->seq = seq;
+ tdsq->seq = seq;
- /* Use instead of seq->flag for nested strips and other
- * cases where the selection may need to be modified */
- tdsq->flag = flag;
- tdsq->sel_flag = sel_flag;
+ /* Use instead of seq->flag for nested strips and other
+ * cases where the selection may need to be modified */
+ tdsq->flag = flag;
+ tdsq->sel_flag = sel_flag;
+ td->extra = (void *)tdsq; /* allow us to update the strip from here */
- td->extra = (void *)tdsq; /* allow us to update the strip from here */
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, td->loc);
+ copy_v3_v3(td->iloc, td->loc);
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
- copy_v3_v3(td->iloc, td->loc);
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ td->ext = NULL;
+ td->val = NULL;
- td->ext = NULL; td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ /* Time Transform (extend) */
+ td->val = td2d->loc;
+ td->ival = td2d->loc[0];
- /* Time Transform (extend) */
- td->val = td2d->loc;
- td->ival = td2d->loc[0];
-
- return td;
+ return td;
}
-static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
+static int SeqToTransData_Recursive(
+ TransInfo *t, ListBase *seqbase, TransData *td, TransData2D *td2d, TransDataSeq *tdsq)
{
- Sequence *seq;
- int recursive, count, flag;
- int tot = 0;
+ Sequence *seq;
+ int recursive, count, flag;
+ int tot = 0;
- for (seq = seqbase->first; seq; seq = seq->next) {
+ for (seq = seqbase->first; seq; seq = seq->next) {
- SeqTransInfo(t, seq, &recursive, &count, &flag);
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
- /* add children first so recalculating metastrips does nested strips first */
- if (recursive) {
- int tot_children = SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq);
+ /* add children first so recalculating metastrips does nested strips first */
+ if (recursive) {
+ int tot_children = SeqToTransData_Recursive(t, &seq->seqbase, td, td2d, tdsq);
- td = td + tot_children;
- td2d = td2d + tot_children;
- tdsq = tdsq + tot_children;
+ td = td + tot_children;
+ td2d = td2d + tot_children;
+ tdsq = tdsq + tot_children;
- tot += tot_children;
- }
+ tot += tot_children;
+ }
- /* use 'flag' which is derived from seq->flag but modified for special cases */
- if (flag & SELECT) {
- if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- if (flag & SEQ_LEFTSEL) {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL);
- tot++;
- }
- if (flag & SEQ_RIGHTSEL) {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL);
- tot++;
- }
- }
- else {
- SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT);
- tot++;
- }
- }
- }
- return tot;
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_LEFTSEL);
+ tot++;
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SEQ_RIGHTSEL);
+ tot++;
+ }
+ }
+ else {
+ SeqToTransData(td++, td2d++, tdsq++, seq, flag, SELECT);
+ tot++;
+ }
+ }
+ }
+ return tot;
}
-
static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
{
- Sequence *seq;
- int recursive, count, flag;
- int max = INT32_MIN, min = INT32_MAX;
-
- for (seq = seqbase->first; seq; seq = seq->next) {
-
- /* just to get the flag since there are corner cases where this isn't totally obvious */
- SeqTransInfo(t, seq, &recursive, &count, &flag);
-
- /* use 'flag' which is derived from seq->flag but modified for special cases */
- if (flag & SELECT) {
- if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
- if (flag & SEQ_LEFTSEL) {
- min = min_ii(seq->startdisp, min);
- max = max_ii(seq->startdisp, max);
- }
- if (flag & SEQ_RIGHTSEL) {
- min = min_ii(seq->enddisp, min);
- max = max_ii(seq->enddisp, max);
- }
- }
- else {
- min = min_ii(seq->startdisp, min);
- max = max_ii(seq->enddisp, max);
- }
- }
- }
-
- if (ts) {
- ts->max = max;
- ts->min = min;
- }
+ Sequence *seq;
+ int recursive, count, flag;
+ int max = INT32_MIN, min = INT32_MAX;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+
+ /* just to get the flag since there are corner cases where this isn't totally obvious */
+ SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+ /* use 'flag' which is derived from seq->flag but modified for special cases */
+ if (flag & SELECT) {
+ if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+ if (flag & SEQ_LEFTSEL) {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->startdisp, max);
+ }
+ if (flag & SEQ_RIGHTSEL) {
+ min = min_ii(seq->enddisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ else {
+ min = min_ii(seq->startdisp, min);
+ max = max_ii(seq->enddisp, max);
+ }
+ }
+ }
+
+ if (ts) {
+ ts->max = max;
+ ts->min = min;
+ }
}
-
static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- Editing *ed = BKE_sequencer_editing_get(t->scene, false);
-
- if (ed != NULL) {
-
-
- ListBase *seqbasep = ed->seqbasep;
- TransData *td = tc->data;
- int a;
-
- /* prevent updating the same seq twice
- * if the transdata order is changed this will mess up
- * but so will TransDataSeq */
- Sequence *seq_prev = NULL;
- Sequence *seq;
-
-
- if (!(t->state == TRANS_CANCEL)) {
-
-#if 0 // default 2.4 behavior
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0; a < t->total; a++, td++) {
- if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
- seq = ((TransDataSeq *)td->extra)->seq;
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
- }
-
- seq_prev = seq;
- }
-
-#else // durian hack
- {
- int overlap = 0;
-
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
- overlap = 1;
- break;
- }
- }
-
- if (overlap) {
- bool has_effect_root = false, has_effect_any = false;
- for (seq = seqbasep->first; seq; seq = seq->next)
- seq->tmp = NULL;
-
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
- /* check effects strips, we cant change their time */
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- has_effect_any = true;
- if (seq->depth == 0) {
- has_effect_root = true;
- }
- }
- else {
- /* Tag seq with a non zero value, used by
- * BKE_sequence_base_shuffle_time to identify the ones to shuffle */
- if (seq->depth == 0) {
- seq->tmp = (void *)1;
- }
- }
- }
-
- }
-
- if (t->flag & T_ALT_TRANSFORM) {
- int minframe = MAXFRAME;
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- minframe = min_ii(minframe, seq->startdisp);
- }
- }
-
-
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (!(seq->flag & SELECT)) {
- if (seq->startdisp >= minframe) {
- seq->machine += MAXSEQ * 2;
- }
- }
- }
-
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
-
- for (seq = seqbasep->first; seq; seq = seq->next) {
- if (seq->machine >= MAXSEQ * 2) {
- seq->machine -= MAXSEQ * 2;
- seq->tmp = (void *)1;
- }
- else {
- seq->tmp = NULL;
- }
- }
-
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
- }
- else {
- BKE_sequence_base_shuffle_time(seqbasep, t->scene);
- }
-
- if (has_effect_any) {
- /* update effects strips based on strips just moved in time */
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- BKE_sequence_calc(t->scene, seq);
- }
- }
- }
- }
-
- if (has_effect_root) {
- /* now if any effects _still_ overlap, we need to move them up */
- td = tc->data;
- for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- if (BKE_sequence_test_overlap(seqbasep, seq)) {
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
- }
- }
- }
- }
- /* done with effects */
- }
- }
- }
+ Editing *ed = BKE_sequencer_editing_get(t->scene, false);
+
+ if (ed != NULL) {
+
+ ListBase *seqbasep = ed->seqbasep;
+ TransData *td = tc->data;
+ int a;
+
+ /* prevent updating the same seq twice
+ * if the transdata order is changed this will mess up
+ * but so will TransDataSeq */
+ Sequence *seq_prev = NULL;
+ Sequence *seq;
+
+ if (!(t->state == TRANS_CANCEL)) {
+
+#if 0 // default 2.4 behavior
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0; a < t->total; a++, td++) {
+ if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ }
+
+ seq_prev = seq;
+ }
+
+#else // durian hack
+ {
+ int overlap = 0;
+
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
+ overlap = 1;
+ break;
+ }
+ }
+
+ if (overlap) {
+ bool has_effect_root = false, has_effect_any = false;
+ for (seq = seqbasep->first; seq; seq = seq->next)
+ seq->tmp = NULL;
+
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev)) {
+ /* check effects strips, we cant change their time */
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ has_effect_any = true;
+ if (seq->depth == 0) {
+ has_effect_root = true;
+ }
+ }
+ else {
+ /* Tag seq with a non zero value, used by
+ * BKE_sequence_base_shuffle_time to identify the ones to shuffle */
+ if (seq->depth == 0) {
+ seq->tmp = (void *)1;
+ }
+ }
+ }
+ }
+
+ if (t->flag & T_ALT_TRANSFORM) {
+ int minframe = MAXFRAME;
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ minframe = min_ii(minframe, seq->startdisp);
+ }
+ }
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (!(seq->flag & SELECT)) {
+ if (seq->startdisp >= minframe) {
+ seq->machine += MAXSEQ * 2;
+ }
+ }
+ }
+
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ if (seq->machine >= MAXSEQ * 2) {
+ seq->machine -= MAXSEQ * 2;
+ seq->tmp = (void *)1;
+ }
+ else {
+ seq->tmp = NULL;
+ }
+ }
+
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+ }
+ else {
+ BKE_sequence_base_shuffle_time(seqbasep, t->scene);
+ }
+
+ if (has_effect_any) {
+ /* update effects strips based on strips just moved in time */
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ }
+ }
+
+ if (has_effect_root) {
+ /* now if any effects _still_ overlap, we need to move them up */
+ td = tc->data;
+ for (a = 0, seq_prev = NULL; a < tc->data_len; a++, td++, seq_prev = seq) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
+ if (BKE_sequence_test_overlap(seqbasep, seq)) {
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+ }
+ }
+ }
+ }
+ /* done with effects */
+ }
+ }
+ }
#endif
- for (seq = seqbasep->first; seq; seq = seq->next) {
- /* We might want to build a list of effects that need to be updated during transform */
- if (seq->type & SEQ_TYPE_EFFECT) {
- if (seq->seq1 && seq->seq1->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- else if (seq->seq2 && seq->seq2->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- else if (seq->seq3 && seq->seq3->flag & SELECT) BKE_sequence_calc(t->scene, seq);
- }
- }
-
- BKE_sequencer_sort(t->scene);
- }
- else {
- /* Canceled, need to update the strips display */
- for (a = 0; a < tc->data_len; a++, td++) {
- seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev) && (seq->depth == 0)) {
- if (seq->flag & SEQ_OVERLAP)
- BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
-
- BKE_sequence_calc_disp(t->scene, seq);
- }
- seq_prev = seq;
- }
- }
- }
-
- if ((custom_data->data != NULL) && custom_data->use_free) {
- TransSeq *ts = custom_data->data;
- MEM_freeN(ts->tdseq);
- MEM_freeN(custom_data->data);
- custom_data->data = NULL;
- }
+ for (seq = seqbasep->first; seq; seq = seq->next) {
+ /* We might want to build a list of effects that need to be updated during transform */
+ if (seq->type & SEQ_TYPE_EFFECT) {
+ if (seq->seq1 && seq->seq1->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ else if (seq->seq2 && seq->seq2->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ else if (seq->seq3 && seq->seq3->flag & SELECT)
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+
+ BKE_sequencer_sort(t->scene);
+ }
+ else {
+ /* Canceled, need to update the strips display */
+ for (a = 0; a < tc->data_len; a++, td++) {
+ seq = ((TransDataSeq *)td->extra)->seq;
+ if ((seq != seq_prev) && (seq->depth == 0)) {
+ if (seq->flag & SEQ_OVERLAP)
+ BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
+
+ BKE_sequence_calc_disp(t->scene, seq);
+ }
+ seq_prev = seq;
+ }
+ }
+ }
+
+ if ((custom_data->data != NULL) && custom_data->use_free) {
+ TransSeq *ts = custom_data->data;
+ MEM_freeN(ts->tdseq);
+ MEM_freeN(custom_data->data);
+ custom_data->data = NULL;
+ }
}
static void createTransSeqData(bContext *C, TransInfo *t)
{
#define XXX_DURIAN_ANIM_TX_HACK
- View2D *v2d = UI_view2d_fromcontext(C);
- Scene *scene = t->scene;
- Editing *ed = BKE_sequencer_editing_get(t->scene, false);
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataSeq *tdsq = NULL;
- TransSeq *ts = NULL;
- int xmouse;
+ View2D *v2d = UI_view2d_fromcontext(C);
+ Scene *scene = t->scene;
+ Editing *ed = BKE_sequencer_editing_get(t->scene, false);
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataSeq *tdsq = NULL;
+ TransSeq *ts = NULL;
+ int xmouse;
- int count = 0;
+ int count = 0;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- if (ed == NULL) {
- tc->data_len = 0;
- return;
- }
+ if (ed == NULL) {
+ tc->data_len = 0;
+ return;
+ }
- tc->custom.type.free_cb = freeSeqData;
+ tc->custom.type.free_cb = freeSeqData;
- xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
+ xmouse = (int)UI_view2d_region_to_view_x(v2d, t->mouse.imval[0]);
- /* which side of the current frame should be allowed */
- if (t->mode == TFM_TIME_EXTEND) {
- /* only side on which mouse is gets transformed */
- t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
- }
- else {
- /* normal transform - both sides of current frame are considered */
- t->frame_side = 'B';
- }
+ /* which side of the current frame should be allowed */
+ if (t->mode == TFM_TIME_EXTEND) {
+ /* only side on which mouse is gets transformed */
+ t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
+ }
+ else {
+ /* normal transform - both sides of current frame are considered */
+ t->frame_side = 'B';
+ }
#ifdef XXX_DURIAN_ANIM_TX_HACK
- {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- /* hack */
- if ((seq->flag & SELECT) == 0 && seq->type & SEQ_TYPE_EFFECT) {
- Sequence *seq_user;
- int i;
- for (i = 0; i < 3; i++) {
- seq_user = *((&seq->seq1) + i);
- if (seq_user && (seq_user->flag & SELECT) &&
- !(seq_user->flag & SEQ_LOCK) &&
- !(seq_user->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)))
- {
- seq->flag |= SELECT;
- }
- }
- }
- }
- }
+ {
+ Sequence *seq;
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ /* hack */
+ if ((seq->flag & SELECT) == 0 && seq->type & SEQ_TYPE_EFFECT) {
+ Sequence *seq_user;
+ int i;
+ for (i = 0; i < 3; i++) {
+ seq_user = *((&seq->seq1) + i);
+ if (seq_user && (seq_user->flag & SELECT) && !(seq_user->flag & SEQ_LOCK) &&
+ !(seq_user->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL))) {
+ seq->flag |= SELECT;
+ }
+ }
+ }
+ }
+ }
#endif
- count = SeqTransCount(t, NULL, ed->seqbasep, 0);
+ count = SeqTransCount(t, NULL, ed->seqbasep, 0);
- /* allocate memory for data */
- tc->data_len = count;
+ /* allocate memory for data */
+ tc->data_len = count;
- /* stop if trying to build list if nothing selected */
- if (count == 0) {
- return;
- }
+ /* stop if trying to build list if nothing selected */
+ if (count == 0) {
+ return;
+ }
- tc->custom.type.data = ts = MEM_callocN(sizeof(TransSeq), "transseq");
- tc->custom.type.use_free = true;
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransSeq TransData2D");
- ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+ tc->custom.type.data = ts = MEM_callocN(sizeof(TransSeq), "transseq");
+ tc->custom.type.use_free = true;
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransSeq TransData2D");
+ ts->tdseq = tdsq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq");
- /* loop 2: build transdata array */
- SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
- SeqTransDataBounds(t, ed->seqbasep, ts);
+ /* loop 2: build transdata array */
+ SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+ SeqTransDataBounds(t, ed->seqbasep, ts);
- /* set the snap mode based on how close the mouse is at the end/start points */
- if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
- ts->snap_left = true;
+ /* set the snap mode based on how close the mouse is at the end/start points */
+ if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
+ ts->snap_left = true;
#undef XXX_DURIAN_ANIM_TX_HACK
}
-
/* *********************** Object Transform data ******************* */
/* Little helper function for ObjectToTransData used to give certain
@@ -5701,381 +5894,375 @@ static void createTransSeqData(bContext *C, TransInfo *t)
*/
static bool constraints_list_needinv(TransInfo *t, ListBase *list)
{
- bConstraint *con;
-
- /* loop through constraints, checking if there's one of the mentioned
- * constraints needing special crazyspace corrections
- */
- if (list) {
- for (con = list->first; con; con = con->next) {
- /* only consider constraint if it is enabled, and has influence on result */
- if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
- /* (affirmative) returns for specific constraints here... */
- /* constraints that require this regardless */
- if (ELEM(con->type,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_ARMATURE,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_FOLLOWTRACK))
- {
- return true;
- }
-
- /* constraints that require this only under special conditions */
- if (con->type == CONSTRAINT_TYPE_CHILDOF) {
- /* ChildOf constraint only works when using all location components, see T42256. */
- bChildOfConstraint *data = (bChildOfConstraint *)con->data;
-
- if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) && (data->flag & CHILDOF_LOCZ))
- return true;
- }
- else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
- /* CopyRot constraint only does this when rotating, and offset is on */
- bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
-
- if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
- return true;
- }
- else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
- /* Transform constraint needs it for rotation at least (r.57309),
- * but doing so when translating may also mess things up [#36203]
- */
-
- if (t->mode == TFM_ROTATION)
- return true;
- /* ??? (t->mode == TFM_SCALE) ? */
- }
- }
- }
- }
-
- /* no appropriate candidates found */
- return false;
+ bConstraint *con;
+
+ /* loop through constraints, checking if there's one of the mentioned
+ * constraints needing special crazyspace corrections
+ */
+ if (list) {
+ for (con = list->first; con; con = con->next) {
+ /* only consider constraint if it is enabled, and has influence on result */
+ if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
+ /* (affirmative) returns for specific constraints here... */
+ /* constraints that require this regardless */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_ARMATURE,
+ CONSTRAINT_TYPE_OBJECTSOLVER,
+ CONSTRAINT_TYPE_FOLLOWTRACK)) {
+ return true;
+ }
+
+ /* constraints that require this only under special conditions */
+ if (con->type == CONSTRAINT_TYPE_CHILDOF) {
+ /* ChildOf constraint only works when using all location components, see T42256. */
+ bChildOfConstraint *data = (bChildOfConstraint *)con->data;
+
+ if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) &&
+ (data->flag & CHILDOF_LOCZ))
+ return true;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ /* CopyRot constraint only does this when rotating, and offset is on */
+ bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
+
+ if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
+ return true;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
+ /* Transform constraint needs it for rotation at least (r.57309),
+ * but doing so when translating may also mess things up [#36203]
+ */
+
+ if (t->mode == TFM_ROTATION)
+ return true;
+ /* ??? (t->mode == TFM_SCALE) ? */
+ }
+ }
+ }
+ }
+
+ /* no appropriate candidates found */
+ return false;
}
/* transcribe given object into TransData for Transforming */
static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
{
- Scene *scene = t->scene;
- bool constinv;
- bool skip_invert = false;
-
- if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
- float rot[3][3], scale[3];
- float ctime = BKE_scene_frame_get(scene);
-
- /* only use rigid body transform if simulation is running,
- * avoids problems with initial setup of rigid bodies */
- if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) {
-
- /* save original object transform */
- copy_v3_v3(td->ext->oloc, ob->loc);
-
- if (ob->rotmode > 0) {
- copy_v3_v3(td->ext->orot, ob->rot);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->orotAngle = ob->rotAngle;
- copy_v3_v3(td->ext->orotAxis, ob->rotAxis);
- }
- else {
- copy_qt_qt(td->ext->oquat, ob->quat);
- }
- /* update object's loc/rot to get current rigid body transform */
- mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
- sub_v3_v3(ob->loc, ob->dloc);
- BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
- }
- }
-
- /* axismtx has the real orientation */
- copy_m3_m4(td->axismtx, ob->obmat);
- normalize_m3(td->axismtx);
-
- td->con = ob->constraints.first;
-
- /* hack: temporarily disable tracking and/or constraints when getting
- * object matrix, if tracking is on, or if constraints don't need
- * inverse correction to stop it from screwing up space conversion
- * matrix later
- */
- constinv = constraints_list_needinv(t, &ob->constraints);
-
- /* disable constraints inversion for dummy pass */
- if (t->mode == TFM_DUMMY)
- skip_invert = true;
-
- /* NOTE: This is not really following copy-on-write design and we should not
- * be re-evaluating the evaluated object. But as the comment above mentioned
- * this is part of a hack.
- * More proper solution would be to make a shallow copy of the object and
- * evaluate that, and access matrix of that evaluated copy of the object.
- * Might be more tricky than it sounds, if some logic later on accesses the
- * object matrix via td->ob->obmat. */
- Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob);
- if (skip_invert == false && constinv == false) {
- object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */
- /* It is possible to have transform data initialization prior to a
- * complete dependency graph evaluated. Happens, for example, when
- * changing transformation mode. */
- BKE_object_tfm_copy(object_eval, ob);
- BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
- object_eval->transflag &= ~OB_NO_CONSTRAINTS;
- }
- else {
- BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
- }
- /* Copy newly evaluated fields to the original object, similar to how
- * active dependency graph will do it. */
- copy_m4_m4(ob->obmat, object_eval->obmat);
- /* Only copy negative scale flag, this is the only flag which is modified by
- * the BKE_object_where_is_calc(). The rest of the flags we need to keep,
- * otherwise we might loose dupli flags (see T61787). */
- ob->transflag &= ~OB_NEG_SCALE;
- ob->transflag |= (object_eval->transflag & OB_NEG_SCALE);
-
- td->ob = ob;
-
- td->loc = ob->loc;
- copy_v3_v3(td->iloc, td->loc);
-
- if (ob->rotmode > 0) {
- td->ext->rot = ob->rot;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = NULL;
-
- copy_v3_v3(td->ext->irot, ob->rot);
- copy_v3_v3(td->ext->drot, ob->drot);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- td->ext->rot = NULL;
- td->ext->rotAxis = ob->rotAxis;
- td->ext->rotAngle = &ob->rotAngle;
- td->ext->quat = NULL;
-
- td->ext->irotAngle = ob->rotAngle;
- copy_v3_v3(td->ext->irotAxis, ob->rotAxis);
- // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented
- // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented
- }
- else {
- td->ext->rot = NULL;
- td->ext->rotAxis = NULL;
- td->ext->rotAngle = NULL;
- td->ext->quat = ob->quat;
-
- copy_qt_qt(td->ext->iquat, ob->quat);
- copy_qt_qt(td->ext->dquat, ob->dquat);
- }
- td->ext->rotOrder = ob->rotmode;
-
- td->ext->size = ob->scale;
- copy_v3_v3(td->ext->isize, ob->scale);
- copy_v3_v3(td->ext->dscale, ob->dscale);
-
- copy_v3_v3(td->center, ob->obmat[3]);
-
- copy_m4_m4(td->ext->obmat, ob->obmat);
-
- /* is there a need to set the global<->data space conversion matrices? */
- if (ob->parent || constinv) {
- float obmtx[3][3], totmat[3][3], obinv[3][3];
-
- /* Get the effect of parenting, and/or certain constraints.
- * NOTE: some Constraints, and also Tracking should never get this
- * done, as it doesn't work well.
- */
- BKE_object_to_mat3(ob, obmtx);
- copy_m3_m4(totmat, ob->obmat);
- invert_m3_m3(obinv, totmat);
- mul_m3_m3m3(td->smtx, obmtx, obinv);
- invert_m3_m3(td->mtx, td->smtx);
- }
- else {
- /* no conversion to/from dataspace */
- unit_m3(td->smtx);
- unit_m3(td->mtx);
- }
+ Scene *scene = t->scene;
+ bool constinv;
+ bool skip_invert = false;
+
+ if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
+ float rot[3][3], scale[3];
+ float ctime = BKE_scene_frame_get(scene);
+
+ /* only use rigid body transform if simulation is running,
+ * avoids problems with initial setup of rigid bodies */
+ if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) {
+
+ /* save original object transform */
+ copy_v3_v3(td->ext->oloc, ob->loc);
+
+ if (ob->rotmode > 0) {
+ copy_v3_v3(td->ext->orot, ob->rot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->orotAngle = ob->rotAngle;
+ copy_v3_v3(td->ext->orotAxis, ob->rotAxis);
+ }
+ else {
+ copy_qt_qt(td->ext->oquat, ob->quat);
+ }
+ /* update object's loc/rot to get current rigid body transform */
+ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
+ sub_v3_v3(ob->loc, ob->dloc);
+ BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */
+ }
+ }
+
+ /* axismtx has the real orientation */
+ copy_m3_m4(td->axismtx, ob->obmat);
+ normalize_m3(td->axismtx);
+
+ td->con = ob->constraints.first;
+
+ /* hack: temporarily disable tracking and/or constraints when getting
+ * object matrix, if tracking is on, or if constraints don't need
+ * inverse correction to stop it from screwing up space conversion
+ * matrix later
+ */
+ constinv = constraints_list_needinv(t, &ob->constraints);
+
+ /* disable constraints inversion for dummy pass */
+ if (t->mode == TFM_DUMMY)
+ skip_invert = true;
+
+ /* NOTE: This is not really following copy-on-write design and we should not
+ * be re-evaluating the evaluated object. But as the comment above mentioned
+ * this is part of a hack.
+ * More proper solution would be to make a shallow copy of the object and
+ * evaluate that, and access matrix of that evaluated copy of the object.
+ * Might be more tricky than it sounds, if some logic later on accesses the
+ * object matrix via td->ob->obmat. */
+ Object *object_eval = DEG_get_evaluated_object(t->depsgraph, ob);
+ if (skip_invert == false && constinv == false) {
+ object_eval->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc checks this */
+ /* It is possible to have transform data initialization prior to a
+ * complete dependency graph evaluated. Happens, for example, when
+ * changing transformation mode. */
+ BKE_object_tfm_copy(object_eval, ob);
+ BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
+ object_eval->transflag &= ~OB_NO_CONSTRAINTS;
+ }
+ else {
+ BKE_object_where_is_calc(t->depsgraph, t->scene, object_eval);
+ }
+ /* Copy newly evaluated fields to the original object, similar to how
+ * active dependency graph will do it. */
+ copy_m4_m4(ob->obmat, object_eval->obmat);
+ /* Only copy negative scale flag, this is the only flag which is modified by
+ * the BKE_object_where_is_calc(). The rest of the flags we need to keep,
+ * otherwise we might loose dupli flags (see T61787). */
+ ob->transflag &= ~OB_NEG_SCALE;
+ ob->transflag |= (object_eval->transflag & OB_NEG_SCALE);
+
+ td->ob = ob;
+
+ td->loc = ob->loc;
+ copy_v3_v3(td->iloc, td->loc);
+
+ if (ob->rotmode > 0) {
+ td->ext->rot = ob->rot;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = NULL;
+
+ copy_v3_v3(td->ext->irot, ob->rot);
+ copy_v3_v3(td->ext->drot, ob->drot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = ob->rotAxis;
+ td->ext->rotAngle = &ob->rotAngle;
+ td->ext->quat = NULL;
+
+ td->ext->irotAngle = ob->rotAngle;
+ copy_v3_v3(td->ext->irotAxis, ob->rotAxis);
+ // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented
+ // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented
+ }
+ else {
+ td->ext->rot = NULL;
+ td->ext->rotAxis = NULL;
+ td->ext->rotAngle = NULL;
+ td->ext->quat = ob->quat;
+
+ copy_qt_qt(td->ext->iquat, ob->quat);
+ copy_qt_qt(td->ext->dquat, ob->dquat);
+ }
+ td->ext->rotOrder = ob->rotmode;
+
+ td->ext->size = ob->scale;
+ copy_v3_v3(td->ext->isize, ob->scale);
+ copy_v3_v3(td->ext->dscale, ob->dscale);
+
+ copy_v3_v3(td->center, ob->obmat[3]);
+
+ copy_m4_m4(td->ext->obmat, ob->obmat);
+
+ /* is there a need to set the global<->data space conversion matrices? */
+ if (ob->parent || constinv) {
+ float obmtx[3][3], totmat[3][3], obinv[3][3];
+
+ /* Get the effect of parenting, and/or certain constraints.
+ * NOTE: some Constraints, and also Tracking should never get this
+ * done, as it doesn't work well.
+ */
+ BKE_object_to_mat3(ob, obmtx);
+ copy_m3_m4(totmat, ob->obmat);
+ invert_m3_m3(obinv, totmat);
+ mul_m3_m3m3(td->smtx, obmtx, obinv);
+ invert_m3_m3(td->mtx, td->smtx);
+ }
+ else {
+ /* no conversion to/from dataspace */
+ unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ }
}
static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->object->id.tag &= ~LIB_TAG_DOIT;
- }
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
}
static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
{
- /* Here we only handle object IDs. */
- if (GS(id->name) != ID_OB) {
- return;
- }
- id->tag |= LIB_TAG_DOIT;
+ /* Here we only handle object IDs. */
+ if (GS(id->name) != ID_OB) {
+ return;
+ }
+ id->tag |= LIB_TAG_DOIT;
}
static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
{
- object->id.tag |= LIB_TAG_DOIT;
- DEG_foreach_dependent_ID(depsgraph, &object->id,
- set_trans_object_base_deps_flag_cb, NULL);
+ object->id.tag |= LIB_TAG_DOIT;
+ DEG_foreach_dependent_ID(depsgraph, &object->id, set_trans_object_base_deps_flag_cb, NULL);
}
static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.tag & LIB_TAG_DOIT) {
- base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
- }
- }
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.tag & LIB_TAG_DOIT) {
+ base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+ }
+ }
}
/* sets flags in Bases to define whether they take part in transform */
/* it deselects Bases, so we have to call the clear function always after */
static void set_trans_object_base_flags(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Scene *scene = t->scene;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- /* NOTE: if Base selected and has parent selected:
- * base->flag_legacy = BA_WAS_SEL
- */
- /* Don't do it if we're not actually going to recalculate anything. */
- if (t->mode == TFM_DUMMY) {
- return;
- }
- /* Makes sure base flags and object flags are identical. */
- BKE_scene_base_flag_to_objects(t->view_layer);
- /* Make sure depsgraph is here. */
- DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
- /* Clear all flags we need. It will be used to detect dependencies. */
- trans_object_base_deps_flag_prepare(view_layer);
- /* Traverse all bases and set all possible flags. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->flag_legacy &= ~BA_WAS_SEL;
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- Object *ob = base->object;
- Object *parsel = ob->parent;
- /* If parent selected, deselect. */
- while (parsel != NULL) {
- if (parsel->base_flag & BASE_SELECTED) {
- Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
- if (parbase != NULL) { /* in rare cases this can fail */
- if (BASE_SELECTED_EDITABLE(v3d, parbase)) {
- break;
- }
- }
- }
- parsel = parsel->parent;
- }
- if (parsel != NULL) {
- /* Rotation around local centers are allowed to propagate. */
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
- {
- base->flag_legacy |= BA_TRANSFORM_CHILD;
- }
- else {
- base->flag &= ~BASE_SELECTED;
- base->flag_legacy |= BA_WAS_SEL;
- }
- }
- flush_trans_object_base_deps_flag(depsgraph, ob);
- }
- }
- /* Store temporary bits in base indicating that base is being modified
- * (directly or indirectly) by transforming objects.
- */
- trans_object_base_deps_flag_finish(view_layer);
+ Main *bmain = CTX_data_main(t->context);
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Scene *scene = t->scene;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* NOTE: if Base selected and has parent selected:
+ * base->flag_legacy = BA_WAS_SEL
+ */
+ /* Don't do it if we're not actually going to recalculate anything. */
+ if (t->mode == TFM_DUMMY) {
+ return;
+ }
+ /* Makes sure base flags and object flags are identical. */
+ BKE_scene_base_flag_to_objects(t->view_layer);
+ /* Make sure depsgraph is here. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Traverse all bases and set all possible flags. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag_legacy &= ~BA_WAS_SEL;
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ Object *ob = base->object;
+ Object *parsel = ob->parent;
+ /* If parent selected, deselect. */
+ while (parsel != NULL) {
+ if (parsel->base_flag & BASE_SELECTED) {
+ Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
+ if (parbase != NULL) { /* in rare cases this can fail */
+ if (BASE_SELECTED_EDITABLE(v3d, parbase)) {
+ break;
+ }
+ }
+ }
+ parsel = parsel->parent;
+ }
+ if (parsel != NULL) {
+ /* Rotation around local centers are allowed to propagate. */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) {
+ base->flag_legacy |= BA_TRANSFORM_CHILD;
+ }
+ else {
+ base->flag &= ~BASE_SELECTED;
+ base->flag_legacy |= BA_WAS_SEL;
+ }
+ }
+ flush_trans_object_base_deps_flag(depsgraph, ob);
+ }
+ }
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
}
static bool mark_children(Object *ob)
{
- if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
- return true;
+ if (ob->flag & (SELECT | BA_TRANSFORM_CHILD))
+ return true;
- if (ob->parent) {
- if (mark_children(ob->parent)) {
- ob->flag |= BA_TRANSFORM_CHILD;
- return true;
- }
- }
+ if (ob->parent) {
+ if (mark_children(ob->parent)) {
+ ob->flag |= BA_TRANSFORM_CHILD;
+ return true;
+ }
+ }
- return false;
+ return false;
}
static int count_proportional_objects(TransInfo *t)
{
- int total = 0;
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Scene *scene = t->scene;
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- /* Clear all flags we need. It will be used to detect dependencies. */
- trans_object_base_deps_flag_prepare(view_layer);
- /* Rotations around local centers are allowed to propagate, so we take all objects. */
- if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)))
- {
- /* Mark all parents. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- Object *parent = base->object->parent;
- /* flag all parents */
- while (parent != NULL) {
- parent->flag |= BA_TRANSFORM_PARENT;
- parent = parent->parent;
- }
- }
- }
- /* Mark all children. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- /* all base not already selected or marked that is editable */
- if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (base->flag & BASE_SELECTED) == 0 &&
- (BASE_EDITABLE(v3d, base)))
- {
- mark_children(base->object);
- }
- }
- }
- /* Flush changed flags to all dependencies. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
- /* If base is not selected, not a parent of selection or not a child of
- * selection and it is editable.
- */
- if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (base->flag & BASE_SELECTED) == 0 &&
- (BASE_EDITABLE(v3d, base)))
- {
- flush_trans_object_base_deps_flag(depsgraph, ob);
- total += 1;
- }
- }
- /* Store temporary bits in base indicating that base is being modified
- * (directly or indirectly) by transforming objects.
- */
- trans_object_base_deps_flag_finish(view_layer);
- return total;
+ int total = 0;
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Scene *scene = t->scene;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Rotations around local centers are allowed to propagate, so we take all objects. */
+ if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))) {
+ /* Mark all parents. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ Object *parent = base->object->parent;
+ /* flag all parents */
+ while (parent != NULL) {
+ parent->flag |= BA_TRANSFORM_PARENT;
+ parent = parent->parent;
+ }
+ }
+ }
+ /* Mark all children. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ /* all base not already selected or marked that is editable */
+ if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 && (BASE_EDITABLE(v3d, base))) {
+ mark_children(base->object);
+ }
+ }
+ }
+ /* Flush changed flags to all dependencies. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ /* If base is not selected, not a parent of selection or not a child of
+ * selection and it is editable.
+ */
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 && (BASE_EDITABLE(v3d, base))) {
+ flush_trans_object_base_deps_flag(depsgraph, ob);
+ total += 1;
+ }
+ }
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
+ return total;
}
static void clear_trans_object_base_flags(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- Base *base;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base;
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (base->flag_legacy & BA_WAS_SEL) {
- base->flag |= BASE_SELECTED;
- }
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag_legacy & BA_WAS_SEL) {
+ base->flag |= BASE_SELECTED;
+ }
- base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
- }
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG |
+ BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ }
}
/* auto-keyframing feature - for objects
@@ -6084,123 +6271,131 @@ static void clear_trans_object_base_flags(TransInfo *t)
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
void autokeyframe_object(bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode)
{
- Main *bmain = CTX_data_main(C);
- ID *id = &ob->id;
- FCurve *fcu;
-
- // TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- ListBase dsources = {NULL, NULL};
- float cfra = (float)CFRA; // xxx this will do for now
- short flag = 0;
-
- /* get flags used for inserting keyframes */
- flag = ANIM_get_keyframing_flags(scene, 1);
-
- /* add datasource override for the object */
- ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
-
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
- /* only insert into active keyingset
- * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden
- */
- ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
- AnimData *adt = ob->adt;
-
- /* only key on available channels */
- if (adt && adt->action) {
- ListBase nla_cache = {NULL, NULL};
-
- for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
- fcu->flag &= ~FCURVE_SELECTED;
- insert_keyframe(bmain, depsgraph, reports, id, adt->action,
- (fcu->grp ? fcu->grp->name : NULL),
- fcu->rna_path, fcu->array_index, cfra,
- ts->keyframe_type, &nla_cache, flag);
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
- }
- }
- else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
- bool do_loc = false, do_rot = false, do_scale = false;
-
- /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
- if (tmode == TFM_TRANSLATION) {
- do_loc = true;
- }
- else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- if (ob != OBACT(view_layer))
- do_loc = true;
- }
- else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_rot = true;
- }
- }
- else if (tmode == TFM_RESIZE) {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- if (ob != OBACT(view_layer))
- do_loc = true;
- }
- else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_scale = true;
- }
- }
-
- /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
- if (do_loc) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_rot) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_scale) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- }
- /* insert keyframe in all (transform) channels */
- else {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
-
- /* free temp info */
- BLI_freelistN(&dsources);
- }
+ Main *bmain = CTX_data_main(C);
+ ID *id = &ob->id;
+ FCurve *fcu;
+
+ // TODO: this should probably be done per channel instead...
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
+ ListBase dsources = {NULL, NULL};
+ float cfra = (float)CFRA; // xxx this will do for now
+ short flag = 0;
+
+ /* get flags used for inserting keyframes */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ /* add datasource override for the object */
+ ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
+
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
+ /* only insert into active keyingset
+ * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden
+ */
+ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
+ AnimData *adt = ob->adt;
+
+ /* only key on available channels */
+ if (adt && adt->action) {
+ ListBase nla_cache = {NULL, NULL};
+
+ for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
+ fcu->flag &= ~FCURVE_SELECTED;
+ insert_keyframe(bmain,
+ depsgraph,
+ reports,
+ id,
+ adt->action,
+ (fcu->grp ? fcu->grp->name : NULL),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+ }
+ }
+ else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
+ bool do_loc = false, do_rot = false, do_scale = false;
+
+ /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+ if (tmode == TFM_TRANSLATION) {
+ do_loc = true;
+ }
+ else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ if (ob != OBACT(view_layer))
+ do_loc = true;
+ }
+ else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_rot = true;
+ }
+ }
+ else if (tmode == TFM_RESIZE) {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ if (ob != OBACT(view_layer))
+ do_loc = true;
+ }
+ else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_scale = true;
+ }
+ }
+
+ /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
+ if (do_loc) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_rot) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_scale) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ }
+ /* insert keyframe in all (transform) channels */
+ else {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
+ }
}
/* Return if we need to update motion paths, only if they already exist,
* and we will insert a keyframe at the end of transform. */
bool motionpath_need_update_object(Scene *scene, Object *ob)
{
- /* XXX: there's potential here for problems with unkeyed rotations/scale,
- * but for now (until proper data-locality for baking operations),
- * this should be a better fix for T24451 and T37755
- */
+ /* XXX: there's potential here for problems with unkeyed rotations/scale,
+ * but for now (until proper data-locality for baking operations),
+ * this should be a better fix for T24451 and T37755
+ */
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
/* auto-keyframing feature - for poses/pose-channels
@@ -6210,286 +6405,296 @@ bool motionpath_need_update_object(Scene *scene, Object *ob)
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short targetless_ik)
{
- Main *bmain = CTX_data_main(C);
- ID *id = &ob->id;
- AnimData *adt = ob->adt;
- bAction *act = (adt) ? adt->action : NULL;
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
- FCurve *fcu;
-
- // TODO: this should probably be done per channel instead...
- if (autokeyframe_cfra_can_key(scene, id)) {
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- ListBase nla_cache = {NULL, NULL};
- float cfra = (float)CFRA;
- short flag = 0;
-
- /* flag is initialized from UserPref keyframing settings
- * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
- * visual keyframes even if flag not set, as it's not that useful otherwise
- * (for quick animation recording)
- */
- flag = ANIM_get_keyframing_flags(scene, 1);
-
- if (targetless_ik)
- flag |= INSERTKEY_MATRIX;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- ListBase dsources = {NULL, NULL};
-
- /* clear any 'unkeyed' flag it may have */
- pchan->bone->flag &= ~BONE_UNKEYED;
-
- /* add datasource override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
-
- /* only insert into active keyingset? */
- if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
- /* run the active Keying Set on the current datasource */
- ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- /* only insert into available channels? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
- if (act) {
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
- /* only insert keyframes for this F-Curve if it affects the current bone */
- if (strstr(fcu->rna_path, "bones")) {
- char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
-
- /* only if bone name matches too...
- * NOTE: this will do constraints too, but those are ok to do here too?
- */
- if (pchanName && STREQ(pchanName, pchan->name)) {
- insert_keyframe(bmain, depsgraph, reports, id, act,
- ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, fcu->array_index, cfra,
- ts->keyframe_type, &nla_cache, flag);
- }
-
- if (pchanName) MEM_freeN(pchanName);
- }
- }
- }
- }
- /* only insert keyframe if needed? */
- else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
- bool do_loc = false, do_rot = false, do_scale = false;
-
- /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
- if (tmode == TFM_TRANSLATION) {
- if (targetless_ik)
- do_rot = true;
- else
- do_loc = true;
- }
- else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
- if (ELEM(scene->toolsettings->transform_pivot_point, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_rot = true;
- }
- }
- else if (tmode == TFM_RESIZE) {
- if (ELEM(scene->toolsettings->transform_pivot_point, V3D_AROUND_CURSOR, V3D_AROUND_ACTIVE)) {
- do_loc = true;
- }
-
- if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
- do_scale = true;
- }
- }
-
- if (do_loc) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_rot) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_scale) {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- }
- /* insert keyframe in all (transform) channels */
- else {
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
-
- /* free temp info */
- BLI_freelistN(&dsources);
- }
- }
-
- BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
- }
- else {
- /* tag channels that should have unkeyed data */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_TRANSFORM) {
- /* tag this channel */
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
- }
+ Main *bmain = CTX_data_main(C);
+ ID *id = &ob->id;
+ AnimData *adt = ob->adt;
+ bAction *act = (adt) ? adt->action : NULL;
+ bPose *pose = ob->pose;
+ bPoseChannel *pchan;
+ FCurve *fcu;
+
+ // TODO: this should probably be done per channel instead...
+ if (autokeyframe_cfra_can_key(scene, id)) {
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ReportList *reports = CTX_wm_reports(C);
+ ToolSettings *ts = scene->toolsettings;
+ KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
+ ListBase nla_cache = {NULL, NULL};
+ float cfra = (float)CFRA;
+ short flag = 0;
+
+ /* flag is initialized from UserPref keyframing settings
+ * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
+ * visual keyframes even if flag not set, as it's not that useful otherwise
+ * (for quick animation recording)
+ */
+ flag = ANIM_get_keyframing_flags(scene, 1);
+
+ if (targetless_ik)
+ flag |= INSERTKEY_MATRIX;
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ ListBase dsources = {NULL, NULL};
+
+ /* clear any 'unkeyed' flag it may have */
+ pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
+
+ /* only insert into active keyingset? */
+ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
+ /* run the active Keying Set on the current datasource */
+ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ /* only insert into available channels? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
+ if (act) {
+ for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ /* only insert keyframes for this F-Curve if it affects the current bone */
+ if (strstr(fcu->rna_path, "bones")) {
+ char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
+
+ /* only if bone name matches too...
+ * NOTE: this will do constraints too, but those are ok to do here too?
+ */
+ if (pchanName && STREQ(pchanName, pchan->name)) {
+ insert_keyframe(bmain,
+ depsgraph,
+ reports,
+ id,
+ act,
+ ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ fcu->rna_path,
+ fcu->array_index,
+ cfra,
+ ts->keyframe_type,
+ &nla_cache,
+ flag);
+ }
+
+ if (pchanName)
+ MEM_freeN(pchanName);
+ }
+ }
+ }
+ }
+ /* only insert keyframe if needed? */
+ else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) {
+ bool do_loc = false, do_rot = false, do_scale = false;
+
+ /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
+ if (tmode == TFM_TRANSLATION) {
+ if (targetless_ik)
+ do_rot = true;
+ else
+ do_loc = true;
+ }
+ else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_rot = true;
+ }
+ }
+ else if (tmode == TFM_RESIZE) {
+ if (ELEM(scene->toolsettings->transform_pivot_point,
+ V3D_AROUND_CURSOR,
+ V3D_AROUND_ACTIVE)) {
+ do_loc = true;
+ }
+
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
+ do_scale = true;
+ }
+ }
+
+ if (do_loc) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_rot) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_scale) {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ }
+ /* insert keyframe in all (transform) channels */
+ else {
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
+ }
+ }
+
+ BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
+ }
+ else {
+ /* tag channels that should have unkeyed data */
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone->flag & BONE_TRANSFORM) {
+ /* tag this channel */
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ }
}
/* Return if we need to update motion paths, only if they already exist,
* and we will insert a keyframe at the end of transform. */
bool motionpath_need_update_pose(Scene *scene, Object *ob)
{
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- const int framenr = ED_space_clip_get_clip_frame_number(sc);
- /* Update coordinates of modified plane tracks. */
- for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- bool do_update = false;
- if (plane_track->flag & PLANE_TRACK_HIDDEN) {
- continue;
- }
- do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
- if (do_update == false) {
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- MovieTrackingTrack *track = plane_track->point_tracks[i];
- if (TRACK_VIEW_SELECTED(sc, track)) {
- do_update = true;
- break;
- }
- }
- }
- }
- if (do_update) {
- BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
- }
- }
- if (t->scene->nodetree != NULL) {
- /* Tracks can be used for stabilization nodes,
- * flush update for such nodes.
- */
- nodeUpdateID(t->scene->nodetree, &clip->id);
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
- }
+ SpaceClip *sc = t->sa->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ const int framenr = ED_space_clip_get_clip_frame_number(sc);
+ /* Update coordinates of modified plane tracks. */
+ for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track;
+ plane_track = plane_track->next) {
+ bool do_update = false;
+ if (plane_track->flag & PLANE_TRACK_HIDDEN) {
+ continue;
+ }
+ do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0;
+ if (do_update == false) {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ MovieTrackingTrack *track = plane_track->point_tracks[i];
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ do_update = true;
+ break;
+ }
+ }
+ }
+ }
+ if (do_update) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+ }
+ if (t->scene->nodetree != NULL) {
+ /* Tracks can be used for stabilization nodes,
+ * flush update for such nodes.
+ */
+ nodeUpdateID(t->scene->nodetree, &clip->id);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
+ }
}
static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
{
- Mask *mask = NULL;
-
- if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
- mask = ED_space_clip_get_mask(sc);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = t->sa->spacedata.first;
- mask = ED_space_image_get_mask(sima);
- }
- else {
- BLI_assert(0);
- }
-
- if (t->scene->nodetree) {
- /* tracks can be used for stabilization nodes,
- * flush update for such nodes */
- //if (nodeUpdateID(t->scene->nodetree, &mask->id))
- {
- WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
- }
- }
-
- /* TODO - dont key all masks... */
- if (IS_AUTOKEY_ON(t->scene)) {
- Scene *scene = t->scene;
-
- ED_mask_layer_shape_auto_key_select(mask, CFRA);
- }
+ Mask *mask = NULL;
+
+ if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+ mask = ED_space_clip_get_mask(sc);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = t->sa->spacedata.first;
+ mask = ED_space_image_get_mask(sima);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (t->scene->nodetree) {
+ /* tracks can be used for stabilization nodes,
+ * flush update for such nodes */
+ //if (nodeUpdateID(t->scene->nodetree, &mask->id))
+ {
+ WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id);
+ }
+ }
+
+ /* TODO - dont key all masks... */
+ if (IS_AUTOKEY_ON(t->scene)) {
+ Scene *scene = t->scene;
+
+ ED_mask_layer_shape_auto_key_select(mask, CFRA);
+ }
}
static void special_aftertrans_update__node(bContext *C, TransInfo *t)
{
- Main *bmain = CTX_data_main(C);
- const bool canceled = (t->state == TRANS_CANCEL);
+ Main *bmain = CTX_data_main(C);
+ const bool canceled = (t->state == TRANS_CANCEL);
- if (canceled && t->remove_on_cancel) {
- /* remove selected nodes on cancel */
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
- bNodeTree *ntree = snode->edittree;
- if (ntree) {
- bNode *node, *node_next;
- for (node = ntree->nodes.first; node; node = node_next) {
- node_next = node->next;
- if (node->flag & NODE_SELECT)
- nodeRemoveNode(bmain, ntree, node, true);
- }
- }
- }
+ if (canceled && t->remove_on_cancel) {
+ /* remove selected nodes on cancel */
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ bNodeTree *ntree = snode->edittree;
+ if (ntree) {
+ bNode *node, *node_next;
+ for (node = ntree->nodes.first; node; node = node_next) {
+ node_next = node->next;
+ if (node->flag & NODE_SELECT)
+ nodeRemoveNode(bmain, ntree, node, true);
+ }
+ }
+ }
}
static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
- /* so automerge supports mirror */
- if ((t->scene->toolsettings->automerge) &&
- ((t->flag & T_EDIT) && t->obedit_type == OB_MESH))
- {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ /* so automerge supports mirror */
+ if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- BMesh *bm = em->bm;
- char hflag;
- bool has_face_sel = (bm->totfacesel != 0);
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ BMesh *bm = em->bm;
+ char hflag;
+ bool has_face_sel = (bm->totfacesel != 0);
- if (tc->mirror.axis_flag) {
- TransData *td;
- int i;
+ if (tc->mirror.axis_flag) {
+ TransData *td;
+ int i;
- /* Rather then adjusting the selection (which the user would notice)
- * tag all mirrored verts, then auto-merge those. */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+ /* Rather then adjusting the selection (which the user would notice)
+ * tag all mirrored verts, then auto-merge those. */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->extra) {
- BM_elem_flag_enable((BMVert *)td->extra, BM_ELEM_TAG);
- }
- }
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ if (td->extra) {
+ BM_elem_flag_enable((BMVert *)td->extra, BM_ELEM_TAG);
+ }
+ }
- hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
- }
- else {
- hflag = BM_ELEM_SELECT;
- }
+ hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
+ }
+ else {
+ hflag = BM_ELEM_SELECT;
+ }
- EDBM_automerge(t->scene, tc->obedit, true, hflag);
+ EDBM_automerge(t->scene, tc->obedit, true, hflag);
- /* Special case, this is needed or faces won't re-select.
- * Flush selected edges to faces. */
- if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
- EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
- }
- }
- }
+ /* Special case, this is needed or faces won't re-select.
+ * Flush selected edges to faces. */
+ if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
+ }
+ }
+ }
}
/* inserting keys, pointcache, redraw events... */
@@ -6499,704 +6704,704 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
* */
void special_aftertrans_update(bContext *C, TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- BLI_assert(bmain == CTX_data_main(C));
-
- Object *ob;
-// short redrawipo=0, resetslowpar=1;
- const bool canceled = (t->state == TRANS_CANCEL);
- const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
-
- /* early out when nothing happened */
- if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
- return;
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- if (t->flag & T_EDIT) {
- /* Special Exception:
- * We don't normally access 't->custom.mode' here, but its needed in this case. */
-
- if (canceled == 0) {
- /* we need to delete the temporary faces before automerging */
- if (t->mode == TFM_EDGE_SLIDE) {
- /* handle multires re-projection, done
- * on transform completion since it's
- * really slow -joeedh */
- projectEdgeSlideData(t, true);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
-
- /* Free temporary faces to avoid auto-merging and deleting
- * during cleanup - psy-fi. */
- freeEdgeSlideTempFaces(sld);
- }
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- /* as above */
- projectVertSlideData(t, true);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- VertSlideData *sld = tc->custom.mode.data;
- freeVertSlideTempFaces(sld);
- }
- }
-
- if (t->obedit_type == OB_MESH) {
- special_aftertrans_update__mesh(C, t);
- }
- }
- else {
- if (t->mode == TFM_EDGE_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
- slp->perc = 0.0;
- projectEdgeSlideData(t, false);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- EdgeSlideParams *slp = t->custom.mode.data;
- slp->perc = 0.0;
- projectVertSlideData(t, false);
- }
- }
- }
- }
-
-
- if (t->options & CTX_GPENCIL_STROKES) {
- /* pass */
- }
- else if (t->spacetype == SPACE_SEQ) {
- /* freeSeqData in transform_conversions.c does this
- * keep here so the else at the end wont run... */
-
- SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
-
- /* marker transform, not especially nice but we may want to move markers
- * at the same time as keyframes in the dope sheet. */
- if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
- /* cant use TFM_TIME_EXTEND
- * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
-
- if (t->mode == TFM_SEQ_SLIDE) {
- if (t->frame_side == 'B')
- ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side);
- }
- else if (ELEM(t->frame_side, 'L', 'R')) {
- ED_markers_post_apply_transform(&t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side);
- }
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
- special_aftertrans_update__mask(C, t);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
- special_aftertrans_update__node(C, t);
- if (canceled == 0) {
- ED_node_post_apply_transform(C, snode->edittree);
-
- ED_node_link_insert(bmain, t->sa);
- }
-
- /* clear link line */
- ED_node_link_intersect_test(t->sa, 0);
- }
- else if (t->spacetype == SPACE_CLIP) {
- if (t->options & CTX_MOVIECLIP) {
- special_aftertrans_update__movieclip(C, t);
- }
- else if (t->options & CTX_MASK) {
- special_aftertrans_update__mask(C, t);
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
- bAnimContext ac;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- ob = ac.obact;
-
- if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* these should all be F-Curves */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)) )
- {
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
- posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
- }
- else
- posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
- }
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
- }
- else if (ac.datatype == ANIMCONT_ACTION) { // TODO: just integrate into the above...
- /* Depending on the lock status, draw necessary views */
- // fixme... some of this stuff is not good
- if (ob) {
- if (ob->pose || BKE_key_from_object(ob))
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed.
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these.
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- posttrans_action_clean(&ac, (bAction *)ac.data);
- }
- }
- else if (ac.datatype == ANIMCONT_GPENCIL) {
- /* remove duplicate frames and also make sure points are in order! */
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- bGPdata *gpd;
-
- // XXX: BAD! this get gpencil datablocks directly from main db...
- // but that's how this currently works :/
- for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- if (ID_REAL_USERS(gpd))
- posttrans_gpd_clean(gpd);
- }
- }
- }
- else if (ac.datatype == ANIMCONT_MASK) {
- /* remove duplicate frames and also make sure points are in order! */
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
- */
- if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- Mask *mask;
-
- // XXX: BAD! this get gpencil datablocks directly from main db...
- // but that's how this currently works :/
- for (mask = bmain->masks.first; mask; mask = mask->id.next) {
- if (ID_REAL_USERS(mask))
- posttrans_mask_clean(mask);
- }
- }
- }
-
- /* marker transform, not especially nice but we may want to move markers
- * at the same time as keyframes in the dope sheet.
- */
- if ((saction->flag & SACTION_MARKERS_MOVE) && (canceled == 0)) {
- if (t->mode == TFM_TIME_TRANSLATE) {
+ Main *bmain = CTX_data_main(t->context);
+ BLI_assert(bmain == CTX_data_main(C));
+
+ Object *ob;
+ // short redrawipo=0, resetslowpar=1;
+ const bool canceled = (t->state == TRANS_CANCEL);
+ const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
+
+ /* early out when nothing happened */
+ if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
+ return;
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->flag & T_EDIT) {
+ /* Special Exception:
+ * We don't normally access 't->custom.mode' here, but its needed in this case. */
+
+ if (canceled == 0) {
+ /* we need to delete the temporary faces before automerging */
+ if (t->mode == TFM_EDGE_SLIDE) {
+ /* handle multires re-projection, done
+ * on transform completion since it's
+ * really slow -joeedh */
+ projectEdgeSlideData(t, true);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ EdgeSlideData *sld = tc->custom.mode.data;
+
+ /* Free temporary faces to avoid auto-merging and deleting
+ * during cleanup - psy-fi. */
+ freeEdgeSlideTempFaces(sld);
+ }
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ /* as above */
+ projectVertSlideData(t, true);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ VertSlideData *sld = tc->custom.mode.data;
+ freeVertSlideTempFaces(sld);
+ }
+ }
+
+ if (t->obedit_type == OB_MESH) {
+ special_aftertrans_update__mesh(C, t);
+ }
+ }
+ else {
+ if (t->mode == TFM_EDGE_SLIDE) {
+ EdgeSlideParams *slp = t->custom.mode.data;
+ slp->perc = 0.0;
+ projectEdgeSlideData(t, false);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ EdgeSlideParams *slp = t->custom.mode.data;
+ slp->perc = 0.0;
+ projectVertSlideData(t, false);
+ }
+ }
+ }
+ }
+
+ if (t->options & CTX_GPENCIL_STROKES) {
+ /* pass */
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ /* freeSeqData in transform_conversions.c does this
+ * keep here so the else at the end wont run... */
+
+ SpaceSeq *sseq = (SpaceSeq *)t->sa->spacedata.first;
+
+ /* marker transform, not especially nice but we may want to move markers
+ * at the same time as keyframes in the dope sheet. */
+ if ((sseq->flag & SEQ_MARKER_TRANS) && (canceled == 0)) {
+ /* cant use TFM_TIME_EXTEND
+ * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */
+
+ if (t->mode == TFM_SEQ_SLIDE) {
+ if (t->frame_side == 'B')
+ ED_markers_post_apply_transform(
+ &t->scene->markers, t->scene, TFM_TIME_TRANSLATE, t->values[0], t->frame_side);
+ }
+ else if (ELEM(t->frame_side, 'L', 'R')) {
+ ED_markers_post_apply_transform(
+ &t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values[0], t->frame_side);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & CTX_MASK) {
+ special_aftertrans_update__mask(C, t);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ special_aftertrans_update__node(C, t);
+ if (canceled == 0) {
+ ED_node_post_apply_transform(C, snode->edittree);
+
+ ED_node_link_insert(bmain, t->sa);
+ }
+
+ /* clear link line */
+ ED_node_link_intersect_test(t->sa, 0);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ if (t->options & CTX_MOVIECLIP) {
+ special_aftertrans_update__movieclip(C, t);
+ }
+ else if (t->options & CTX_MASK) {
+ special_aftertrans_update__mask(C, t);
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+ bAnimContext ac;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ ob = ac.obact;
+
+ if (ELEM(ac.datatype, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY, ANIMCONT_TIMELINE)) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* these should all be F-Curves */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(fcu, false); /* only use handles in graph editor */
+ }
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+ else if (ac.datatype == ANIMCONT_ACTION) { // TODO: just integrate into the above...
+ /* Depending on the lock status, draw necessary views */
+ // fixme... some of this stuff is not good
+ if (ob) {
+ if (ob->pose || BKE_key_from_object(ob))
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed.
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these.
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ posttrans_action_clean(&ac, (bAction *)ac.data);
+ }
+ }
+ else if (ac.datatype == ANIMCONT_GPENCIL) {
+ /* remove duplicate frames and also make sure points are in order! */
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ bGPdata *gpd;
+
+ // XXX: BAD! this get gpencil datablocks directly from main db...
+ // but that's how this currently works :/
+ for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ if (ID_REAL_USERS(gpd))
+ posttrans_gpd_clean(gpd);
+ }
+ }
+ }
+ else if (ac.datatype == ANIMCONT_MASK) {
+ /* remove duplicate frames and also make sure points are in order! */
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
+ */
+ if ((saction->flag & SACTION_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ Mask *mask;
+
+ // XXX: BAD! this get gpencil datablocks directly from main db...
+ // but that's how this currently works :/
+ for (mask = bmain->masks.first; mask; mask = mask->id.next) {
+ if (ID_REAL_USERS(mask))
+ posttrans_mask_clean(mask);
+ }
+ }
+ }
+
+ /* marker transform, not especially nice but we may want to move markers
+ * at the same time as keyframes in the dope sheet.
+ */
+ if ((saction->flag & SACTION_MARKERS_MOVE) && (canceled == 0)) {
+ if (t->mode == TFM_TIME_TRANSLATE) {
#if 0
- if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */
- /* same as below */
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- else /* TFM_TIME_TRANSLATE */
+ if (ELEM(t->frame_side, 'L', 'R')) { /* TFM_TIME_EXTEND */
+ /* same as below */
+ ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ else /* TFM_TIME_TRANSLATE */
#endif
- {
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- }
- else if (t->mode == TFM_TIME_SCALE) {
- ED_markers_post_apply_transform(ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
- }
- }
-
- /* make sure all F-Curves are set correctly */
- if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
- ANIM_editkeyframes_refresh(&ac);
-
- /* clear flag that was set for time-slide drawing */
- saction->flag &= ~SACTION_MOVING;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- bAnimContext ac;
- const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- if (ac.datatype) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* 3 cases here for curve cleanups:
- * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
- * 2) canceled == 0 -> user confirmed the transform,
- * so duplicates should be removed
- * 3) canceled + duplicate -> user canceled the transform,
- * but we made duplicates, so get rid of these
- */
- if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 &&
- ((canceled == 0) || (duplicate)))
- {
- if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
- posttrans_fcurve_clean(fcu, use_handle);
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
- }
- else
- posttrans_fcurve_clean(fcu, use_handle);
- }
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
- }
-
- /* Make sure all F-Curves are set correctly, but not if transform was
- * canceled, since then curves were already restored to initial state.
- * Note: if the refresh is really needed after cancel then some way
- * has to be added to not update handle types (see bug 22289).
- */
- if (!canceled)
- ANIM_editkeyframes_refresh(&ac);
- }
- else if (t->spacetype == SPACE_NLA) {
- bAnimContext ac;
-
- /* initialize relevant anim-context 'context' data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return;
-
- if (ac.datatype) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
-
- /* get channels to work on */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- NlaTrack *nlt = (NlaTrack *)ale->data;
-
- /* make sure strips are in order again */
- BKE_nlatrack_sort_strips(nlt);
-
- /* remove the temp metas */
- BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
- }
-
- /* free temp memory */
- ANIM_animdata_freelist(&anim_data);
-
- /* perform after-transfrom validation */
- ED_nla_postop_refresh(&ac);
- }
- }
- else if (t->flag & T_EDIT) {
- if (t->obedit_type == OB_MESH) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- /* table needs to be created for each edit command, since vertices can move etc */
- ED_mesh_mirror_spatial_table(tc->obedit, em, NULL, NULL, 'e');
- /* TODO(campbell): xform: We need support for many mirror objects at once! */
- break;
- }
- }
- }
- else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
- /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
- * in pose mode (to use bone orientation matrix),
- * in that case we don't do operations like autokeyframing. */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- ob = tc->poseobj;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
- else if (t->flag & T_POSE) {
- GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- bArmature *arm;
- bPoseChannel *pchan;
- short targetless_ik = 0;
-
- ob = tc->poseobj;
- arm = ob->data;
-
- if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
- /* when running transform non-interactively (operator exec),
- * we need to update the pose otherwise no updates get called during
- * transform and the auto-ik is not applied. see [#26164] */
- struct Object *pose_ob = tc->poseobj;
- BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
- }
-
- /* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */
- if (!canceled && (t->mode != TFM_DUMMY)) {
- count_set_pose_transflags(ob, t->mode, t->around, NULL);
- }
-
- /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
- if (!canceled && t->mode == TFM_TRANSLATION)
- targetless_ik = apply_targetless_ik(ob);
- else {
- /* not forget to clear the auto flag */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bKinematicConstraint *data = has_targetless_ik(pchan);
- if (data) data->flag &= ~CONSTRAINT_IK_AUTO;
- }
- }
-
- if (t->mode == TFM_TRANSLATION)
- pose_grab_with_ik_clear(bmain, ob);
-
- /* automatic inserting of keys and unkeyed tagging -
- * only if transform wasn't canceled (or TFM_DUMMY) */
- if (!canceled && (t->mode != TFM_DUMMY)) {
- autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else if (arm->flag & ARM_DELAYDEFORM) {
- /* TODO(sergey): Armature is already updated by recalcData(), so we
- * might save some time by skipping re-evaluating it. But this isn't
- * possible yet within new dependency graph, and also other contexts
- * might need to update their CoW copies.
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
-
- if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
- BLI_gset_insert(motionpath_updates, ob);
- }
- }
-
- /* Update motion paths once for all transformed bones in an object. */
- GSetIterator gs_iter;
- GSET_ITER (gs_iter, motionpath_updates) {
- bool current_frame_only = canceled;
- ob = BLI_gsetIterator_getKey(&gs_iter);
- ED_pose_recalculate_paths(C, t->scene, ob, current_frame_only);
- }
- BLI_gset_free(motionpath_updates, NULL);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- /* pass */
- }
- else if ((t->view_layer->basact) &&
- (ob = t->view_layer->basact->object) &&
- (ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, ob))
- {
- /* do nothing */
- }
- else if (t->flag & T_CURSOR) {
- /* do nothing */
- }
- else { /* Objects */
- BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- bool motionpath_update = false;
-
- for (int i = 0; i < tc->data_len; i++) {
- TransData *td = tc->data + i;
- ListBase pidlist;
- PTCacheID *pid;
- ob = td->ob;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) {
- /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- }
- BLI_freelistN(&pidlist);
-
- /* pointcache refresh */
- if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- /* Needed for proper updating of "quick cached" dynamics. */
- /* Creates troubles for moving animated objects without */
- /* autokey though, probably needed is an anim sys override? */
- /* Please remove if some other solution is found. -jahka */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- /* Set autokey if necessary */
- if (!canceled) {
- autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
- }
-
- motionpath_update |= motionpath_need_update_object(t->scene, ob);
-
- /* restore rigid body transform */
- if (ob->rigidbody_object && canceled) {
- float ctime = BKE_scene_frame_get(t->scene);
- if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime))
- BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
- }
- }
-
- if (motionpath_update) {
- /* Update motion paths once for all transformed objects. */
- bool current_frame_only = canceled;
- ED_objects_recalculate_paths(C, t->scene, current_frame_only);
- }
- }
-
- clear_trans_object_base_flags(t);
+ {
+ ED_markers_post_apply_transform(
+ ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ }
+ else if (t->mode == TFM_TIME_SCALE) {
+ ED_markers_post_apply_transform(
+ ED_context_get_markers(C), t->scene, t->mode, t->values[0], t->frame_side);
+ }
+ }
+
+ /* make sure all F-Curves are set correctly */
+ if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* clear flag that was set for time-slide drawing */
+ saction->flag &= ~SACTION_MOVING;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ bAnimContext ac;
+ const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ if (ac.datatype) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* 3 cases here for curve cleanups:
+ * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
+ * 2) canceled == 0 -> user confirmed the transform,
+ * so duplicates should be removed
+ * 3) canceled + duplicate -> user canceled the transform,
+ * but we made duplicates, so get rid of these
+ */
+ if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ posttrans_fcurve_clean(fcu, use_handle);
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ }
+ else
+ posttrans_fcurve_clean(fcu, use_handle);
+ }
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ /* Make sure all F-Curves are set correctly, but not if transform was
+ * canceled, since then curves were already restored to initial state.
+ * Note: if the refresh is really needed after cancel then some way
+ * has to be added to not update handle types (see bug 22289).
+ */
+ if (!canceled)
+ ANIM_editkeyframes_refresh(&ac);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ bAnimContext ac;
+
+ /* initialize relevant anim-context 'context' data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return;
+
+ if (ac.datatype) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
+
+ /* get channels to work on */
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+
+ /* make sure strips are in order again */
+ BKE_nlatrack_sort_strips(nlt);
+
+ /* remove the temp metas */
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
+ /* free temp memory */
+ ANIM_animdata_freelist(&anim_data);
+
+ /* perform after-transfrom validation */
+ ED_nla_postop_refresh(&ac);
+ }
+ }
+ else if (t->flag & T_EDIT) {
+ if (t->obedit_type == OB_MESH) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ /* table needs to be created for each edit command, since vertices can move etc */
+ ED_mesh_mirror_spatial_table(tc->obedit, em, NULL, NULL, 'e');
+ /* TODO(campbell): xform: We need support for many mirror objects at once! */
+ break;
+ }
+ }
+ }
+ else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
+ /* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
+ * in pose mode (to use bone orientation matrix),
+ * in that case we don't do operations like autokeyframing. */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ ob = tc->poseobj;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ else if (t->flag & T_POSE) {
+ GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ bArmature *arm;
+ bPoseChannel *pchan;
+ short targetless_ik = 0;
+
+ ob = tc->poseobj;
+ arm = ob->data;
+
+ if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) {
+ /* when running transform non-interactively (operator exec),
+ * we need to update the pose otherwise no updates get called during
+ * transform and the auto-ik is not applied. see [#26164] */
+ struct Object *pose_ob = tc->poseobj;
+ BKE_pose_where_is(t->depsgraph, t->scene, pose_ob);
+ }
+
+ /* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */
+ if (!canceled && (t->mode != TFM_DUMMY)) {
+ count_set_pose_transflags(ob, t->mode, t->around, NULL);
+ }
+
+ /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
+ if (!canceled && t->mode == TFM_TRANSLATION)
+ targetless_ik = apply_targetless_ik(ob);
+ else {
+ /* not forget to clear the auto flag */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bKinematicConstraint *data = has_targetless_ik(pchan);
+ if (data)
+ data->flag &= ~CONSTRAINT_IK_AUTO;
+ }
+ }
+
+ if (t->mode == TFM_TRANSLATION)
+ pose_grab_with_ik_clear(bmain, ob);
+
+ /* automatic inserting of keys and unkeyed tagging -
+ * only if transform wasn't canceled (or TFM_DUMMY) */
+ if (!canceled && (t->mode != TFM_DUMMY)) {
+ autokeyframe_pose(C, t->scene, ob, t->mode, targetless_ik);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else if (arm->flag & ARM_DELAYDEFORM) {
+ /* TODO(sergey): Armature is already updated by recalcData(), so we
+ * might save some time by skipping re-evaluating it. But this isn't
+ * possible yet within new dependency graph, and also other contexts
+ * might need to update their CoW copies.
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+
+ if (t->mode != TFM_DUMMY && motionpath_need_update_pose(t->scene, ob)) {
+ BLI_gset_insert(motionpath_updates, ob);
+ }
+ }
+
+ /* Update motion paths once for all transformed bones in an object. */
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, motionpath_updates) {
+ bool current_frame_only = canceled;
+ ob = BLI_gsetIterator_getKey(&gs_iter);
+ ED_pose_recalculate_paths(C, t->scene, ob, current_frame_only);
+ }
+ BLI_gset_free(motionpath_updates, NULL);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
+ else if ((t->view_layer->basact) && (ob = t->view_layer->basact->object) &&
+ (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, ob)) {
+ /* do nothing */
+ }
+ else if (t->flag & T_CURSOR) {
+ /* do nothing */
+ }
+ else { /* Objects */
+ BLI_assert(t->flag & (T_OBJECT | T_TEXTURE));
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ bool motionpath_update = false;
+
+ for (int i = 0; i < tc->data_len; i++) {
+ TransData *td = tc->data + i;
+ ListBase pidlist;
+ PTCacheID *pid;
+ ob = td->ob;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* flag object caches as outdated */
+ BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ if (pid->type != PTCACHE_TYPE_PARTICLES) {
+ /* particles don't need reset on geometry change */
+ pid->cache->flag |= PTCACHE_OUTDATED;
+ }
+ }
+ BLI_freelistN(&pidlist);
+
+ /* pointcache refresh */
+ if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* Needed for proper updating of "quick cached" dynamics. */
+ /* Creates troubles for moving animated objects without */
+ /* autokey though, probably needed is an anim sys override? */
+ /* Please remove if some other solution is found. -jahka */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ /* Set autokey if necessary */
+ if (!canceled) {
+ autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode);
+ }
+
+ motionpath_update |= motionpath_need_update_object(t->scene, ob);
+
+ /* restore rigid body transform */
+ if (ob->rigidbody_object && canceled) {
+ float ctime = BKE_scene_frame_get(t->scene);
+ if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime))
+ BKE_rigidbody_aftertrans_update(ob,
+ td->ext->oloc,
+ td->ext->orot,
+ td->ext->oquat,
+ td->ext->orotAxis,
+ td->ext->orotAngle);
+ }
+ }
+
+ if (motionpath_update) {
+ /* Update motion paths once for all transformed objects. */
+ bool current_frame_only = canceled;
+ ED_objects_recalculate_paths(C, t->scene, current_frame_only);
+ }
+ }
+
+ clear_trans_object_base_flags(t);
}
int special_transform_moving(TransInfo *t)
{
- if (t->spacetype == SPACE_SEQ) {
- return G_TRANSFORM_SEQ;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- return G_TRANSFORM_FCURVES;
- }
- else if ((t->flag & T_EDIT) || (t->flag & T_POSE)) {
- return G_TRANSFORM_EDIT;
- }
- else if (t->flag & (T_OBJECT | T_TEXTURE)) {
- return G_TRANSFORM_OBJ;
- }
+ if (t->spacetype == SPACE_SEQ) {
+ return G_TRANSFORM_SEQ;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ return G_TRANSFORM_FCURVES;
+ }
+ else if ((t->flag & T_EDIT) || (t->flag & T_POSE)) {
+ return G_TRANSFORM_EDIT;
+ }
+ else if (t->flag & (T_OBJECT | T_TEXTURE)) {
+ return G_TRANSFORM_OBJ;
+ }
- return 0;
+ return 0;
}
static void createTransObject(bContext *C, TransInfo *t)
{
- TransData *td = NULL;
- TransDataExtension *tx;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- set_trans_object_base_flags(t);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = CTX_DATA_COUNT(C, selected_bases);
-
- if (!tc->data_len) {
- /* clear here, main transform function escapes too */
- clear_trans_object_base_flags(t);
- return;
- }
-
- if (is_prop_edit) {
- tc->data_len += count_proportional_objects(t);
- }
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
-
- CTX_DATA_BEGIN(C, Base *, base, selected_bases)
- {
- Object *ob = base->object;
-
- td->flag = TD_SELECTED;
- td->protectflag = ob->protectflag;
- td->ext = tx;
- td->ext->rotOrder = ob->rotmode;
-
- if (base->flag & BA_TRANSFORM_CHILD) {
- td->flag |= TD_NOCENTER;
- td->flag |= TD_NO_LOC;
- }
-
- /* select linked objects, but skip them later */
- if (ID_IS_LINKED(ob)) {
- td->flag |= TD_SKIP;
- }
-
- ObjectToTransData(t, td, ob);
- td->val = NULL;
- td++;
- tx++;
- }
- CTX_DATA_END;
-
- if (is_prop_edit) {
- ViewLayer *view_layer = t->view_layer;
- View3D *v3d = t->view;
- Base *base;
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
-
- /* if base is not selected, not a parent of selection
- * or not a child of selection and it is editable */
- if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- (base->flag & BASE_SELECTED) == 0 &&
- BASE_EDITABLE(v3d, base))
- {
- td->protectflag = ob->protectflag;
- td->ext = tx;
- td->ext->rotOrder = ob->rotmode;
-
- ObjectToTransData(t, td, ob);
- td->val = NULL;
- td++;
- tx++;
- }
- }
- }
+ TransData *td = NULL;
+ TransDataExtension *tx;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+
+ set_trans_object_base_flags(t);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = CTX_DATA_COUNT(C, selected_bases);
+
+ if (!tc->data_len) {
+ /* clear here, main transform function escapes too */
+ clear_trans_object_base_flags(t);
+ return;
+ }
+
+ if (is_prop_edit) {
+ tc->data_len += count_proportional_objects(t);
+ }
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ Object *ob = base->object;
+
+ td->flag = TD_SELECTED;
+ td->protectflag = ob->protectflag;
+ td->ext = tx;
+ td->ext->rotOrder = ob->rotmode;
+
+ if (base->flag & BA_TRANSFORM_CHILD) {
+ td->flag |= TD_NOCENTER;
+ td->flag |= TD_NO_LOC;
+ }
+
+ /* select linked objects, but skip them later */
+ if (ID_IS_LINKED(ob)) {
+ td->flag |= TD_SKIP;
+ }
+
+ ObjectToTransData(t, td, ob);
+ td->val = NULL;
+ td++;
+ tx++;
+ }
+ CTX_DATA_END;
+
+ if (is_prop_edit) {
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+ Base *base;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* if base is not selected, not a parent of selection
+ * or not a child of selection and it is editable */
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 && BASE_EDITABLE(v3d, base)) {
+ td->protectflag = ob->protectflag;
+ td->ext = tx;
+ td->ext->rotOrder = ob->rotmode;
+
+ ObjectToTransData(t, td, ob);
+ td->val = NULL;
+ td++;
+ tx++;
+ }
+ }
+ }
}
/* transcribe given node into TransData2D for Transforming */
static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node, const float dpi_fac)
{
- float locx, locy;
+ float locx, locy;
- /* account for parents (nested nodes) */
- if (node->parent) {
- nodeToView(node->parent, node->locx, node->locy, &locx, &locy);
- }
- else {
- locx = node->locx;
- locy = node->locy;
- }
+ /* account for parents (nested nodes) */
+ if (node->parent) {
+ nodeToView(node->parent, node->locx, node->locy, &locx, &locy);
+ }
+ else {
+ locx = node->locx;
+ locy = node->locy;
+ }
- /* use top-left corner as the transform origin for nodes */
- /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ /* use top-left corner as the transform origin for nodes */
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
#ifdef USE_NODE_CENTER
- td2d->loc[0] = (locx * dpi_fac) + (BLI_rctf_size_x(&node->totr) * +0.5f);
- td2d->loc[1] = (locy * dpi_fac) + (BLI_rctf_size_y(&node->totr) * -0.5f);
+ td2d->loc[0] = (locx * dpi_fac) + (BLI_rctf_size_x(&node->totr) * +0.5f);
+ td2d->loc[1] = (locy * dpi_fac) + (BLI_rctf_size_y(&node->totr) * -0.5f);
#else
- td2d->loc[0] = locx * dpi_fac;
- td2d->loc[1] = locy * dpi_fac;
+ td2d->loc[0] = locx * dpi_fac;
+ td2d->loc[1] = locy * dpi_fac;
#endif
- td2d->loc[2] = 0.0f;
- td2d->loc2d = td2d->loc; /* current location */
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = td2d->loc; /* current location */
- td->flag = 0;
+ td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
- /* use node center instead of origin (top-left corner) */
- td->center[0] = td2d->loc[0];
- td->center[1] = td2d->loc[1];
- td->center[2] = 0.0f;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+ /* use node center instead of origin (top-left corner) */
+ td->center[0] = td2d->loc[0];
+ td->center[1] = td2d->loc[1];
+ td->center[2] = 0.0f;
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL; td->val = NULL;
+ td->ext = NULL;
+ td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- td->extra = node;
+ td->extra = node;
}
static bool is_node_parent_select(bNode *node)
{
- while ((node = node->parent)) {
- if (node->flag & NODE_TRANSFORM) {
- return true;
- }
- }
- return false;
+ while ((node = node->parent)) {
+ if (node->flag & NODE_TRANSFORM) {
+ return true;
+ }
+ }
+ return false;
}
static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
{
- const float dpi_fac = UI_DPI_FAC;
- TransData *td;
- TransData2D *td2d;
- SpaceNode *snode = t->sa->spacedata.first;
- bNode *node;
+ const float dpi_fac = UI_DPI_FAC;
+ TransData *td;
+ TransData2D *td2d;
+ SpaceNode *snode = t->sa->spacedata.first;
+ bNode *node;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tc->data_len = 0;
+ tc->data_len = 0;
- if (!snode->edittree) {
- return;
- }
+ if (!snode->edittree) {
+ return;
+ }
- /* nodes dont support PET and probably never will */
- t->flag &= ~T_PROP_EDIT_ALL;
+ /* nodes dont support PET and probably never will */
+ t->flag &= ~T_PROP_EDIT_ALL;
- /* set transform flags on nodes */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT && is_node_parent_select(node) == false) {
- node->flag |= NODE_TRANSFORM;
- tc->data_len++;
- }
- else {
- node->flag &= ~NODE_TRANSFORM;
- }
- }
+ /* set transform flags on nodes */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_SELECT && is_node_parent_select(node) == false) {
+ node->flag |= NODE_TRANSFORM;
+ tc->data_len++;
+ }
+ else {
+ node->flag &= ~NODE_TRANSFORM;
+ }
+ }
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D");
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransNode TransData2D");
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TRANSFORM) {
- NodeToTransData(td++, td2d++, node, dpi_fac);
- }
- }
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (node->flag & NODE_TRANSFORM) {
+ NodeToTransData(td++, td2d++, node, dpi_fac);
+ }
+ }
}
/* *** CLIP EDITOR *** */
@@ -7204,1782 +7409,1872 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
/* * motion tracking * */
enum transDataTracking_Mode {
- transDataTracking_ModeTracks = 0,
- transDataTracking_ModeCurves = 1,
- transDataTracking_ModePlaneTracks = 2,
+ transDataTracking_ModeTracks = 0,
+ transDataTracking_ModeCurves = 1,
+ transDataTracking_ModePlaneTracks = 2,
};
typedef struct TransDataTracking {
- int mode, flag;
+ int mode, flag;
- /* tracks transformation from main window */
- int area;
- const float *relative, *loc;
- float soffset[2], srelative[2];
- float offset[2];
+ /* tracks transformation from main window */
+ int area;
+ const float *relative, *loc;
+ float soffset[2], srelative[2];
+ float offset[2];
- float (*smarkers)[2];
- int markersnr;
- MovieTrackingMarker *markers;
+ float (*smarkers)[2];
+ int markersnr;
+ MovieTrackingMarker *markers;
- /* marker transformation from curves editor */
- float *prev_pos, scale;
- short coord;
+ /* marker transformation from curves editor */
+ float *prev_pos, scale;
+ short coord;
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
} 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], const float aspect[2])
-{
- int anchor = area == TRACK_AREA_POINT && off;
-
- tdt->mode = transDataTracking_ModeTracks;
-
- if (anchor) {
- 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] * aspect[0]; /* hold original location */
- td2d->loc[1] = loc[1] * aspect[1];
-
- td2d->loc2d = loc; /* current location */
- }
- td2d->loc[2] = 0.0f;
-
- tdt->relative = rel;
- tdt->area = area;
-
- tdt->markersnr = track->markersnr;
- tdt->markers = track->markers;
- tdt->track = track;
-
- if (rel) {
- if (!anchor) {
- td2d->loc[0] += rel[0] * aspect[0];
- td2d->loc[1] += rel[1] * aspect[1];
- }
-
- copy_v2_v2(tdt->srelative, rel);
- }
-
- if (off)
- copy_v2_v2(tdt->soffset, off);
-
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
-
- //copy_v3_v3(td->center, td->loc);
- td->flag |= TD_INDIVIDUAL_SCALE;
- 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;
-
- td->ext = NULL;
- td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-}
-
-static void trackToTransData(
- const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingTrack *track, const float aspect[2])
+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],
+ const float aspect[2])
{
- MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
-
- tdt->flag = marker->flag;
- marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
-
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- track->offset, marker->pos, track->offset, aspect);
-
- if (track->flag & SELECT) {
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT,
- marker->pos, NULL, NULL, aspect);
- }
-
- if (track->pat_flag & SELECT) {
- int a;
-
- for (a = 0; a < 4; a++) {
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_PAT,
- 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, aspect);
-
- markerToTransDataInit(td++, td2d++, tdt++, track, marker, TRACK_AREA_SEARCH,
- marker->search_max, marker->pos, NULL, aspect);
- }
-}
-
-static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingPlaneTrack *plane_track, float corner[2],
+ int anchor = area == TRACK_AREA_POINT && off;
+
+ tdt->mode = transDataTracking_ModeTracks;
+
+ if (anchor) {
+ 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] * aspect[0]; /* hold original location */
+ td2d->loc[1] = loc[1] * aspect[1];
+
+ td2d->loc2d = loc; /* current location */
+ }
+ td2d->loc[2] = 0.0f;
+
+ tdt->relative = rel;
+ tdt->area = area;
+
+ tdt->markersnr = track->markersnr;
+ tdt->markers = track->markers;
+ tdt->track = track;
+
+ if (rel) {
+ if (!anchor) {
+ td2d->loc[0] += rel[0] * aspect[0];
+ td2d->loc[1] += rel[1] * aspect[1];
+ }
+
+ copy_v2_v2(tdt->srelative, rel);
+ }
+
+ if (off)
+ copy_v2_v2(tdt->soffset, off);
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+
+ //copy_v3_v3(td->center, td->loc);
+ td->flag |= TD_INDIVIDUAL_SCALE;
+ 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;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+}
+
+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);
+
+ tdt->flag = marker->flag;
+ marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
+
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_POINT,
+ track->offset,
+ marker->pos,
+ track->offset,
+ aspect);
+
+ if (track->flag & SELECT) {
+ markerToTransDataInit(
+ td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect);
+ }
+
+ if (track->pat_flag & SELECT) {
+ int a;
+
+ for (a = 0; a < 4; a++) {
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_PAT,
+ 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,
+ aspect);
+
+ markerToTransDataInit(td++,
+ td2d++,
+ tdt++,
+ track,
+ marker,
+ TRACK_AREA_SEARCH,
+ marker->search_max,
+ marker->pos,
+ NULL,
+ aspect);
+ }
+}
+
+static void planeMarkerToTransDataInit(TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingPlaneTrack *plane_track,
+ float corner[2],
const float aspect[2])
{
- tdt->mode = transDataTracking_ModePlaneTracks;
- tdt->plane_track = plane_track;
+ tdt->mode = transDataTracking_ModePlaneTracks;
+ tdt->plane_track = plane_track;
- td2d->loc[0] = corner[0] * aspect[0]; /* hold original location */
- td2d->loc[1] = corner[1] * aspect[1];
+ 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;
+ td2d->loc2d = corner; /* current location */
+ td2d->loc[2] = 0.0f;
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
+ td->ext = NULL;
+ td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
-static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
- TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
+static void planeTrackToTransData(const int framenr,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingPlaneTrack *plane_track,
const float aspect[2])
{
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
- int i;
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+ int i;
- tdt->flag = plane_marker->flag;
- plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+ tdt->flag = plane_marker->flag;
+ plane_marker->flag &= ~PLANE_MARKER_TRACKED;
- for (i = 0; i < 4; i++) {
- planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
- }
+ for (i = 0; i < 4; i++) {
+ planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect);
+ }
}
-static void transDataTrackingFree(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data)
+static void transDataTrackingFree(TransInfo *UNUSED(t),
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
{
- if (custom_data->data) {
- TransDataTracking *tdt = custom_data->data;
- if (tdt->smarkers)
- MEM_freeN(tdt->smarkers);
+ if (custom_data->data) {
+ TransDataTracking *tdt = custom_data->data;
+ if (tdt->smarkers)
+ MEM_freeN(tdt->smarkers);
- MEM_freeN(tdt);
- custom_data->data = NULL;
- }
+ MEM_freeN(tdt);
+ custom_data->data = NULL;
+ }
}
static void createTransTrackingTracksData(bContext *C, TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- MovieTrackingPlaneTrack *plane_track;
- TransDataTracking *tdt;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = 0;
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- tc->data_len++; /* offset */
-
- if (track->flag & SELECT)
- tc->data_len++;
-
- if (track->pat_flag & SELECT)
- tc->data_len += 4;
-
- if (track->search_flag & SELECT)
- tc->data_len += 2;
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- tc->data_len += 4;
- }
- }
-
- if (tc->data_len == 0)
- return;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D");
- tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), "TransTracking TransDataTracking");
-
- tc->custom.type.free_cb = transDataTrackingFree;
-
- /* create actual data */
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
-
- /* offset */
- td++;
- td2d++;
- tdt++;
-
- if (track->flag & SELECT) {
- td++;
- td2d++;
- tdt++;
- }
-
- if (track->pat_flag & SELECT) {
- td += 4;
- td2d += 4;
- tdt += 4;
- }
-
- if (track->search_flag & SELECT) {
- td += 2;
- td2d += 2;
- tdt += 2;
- }
- }
-
- track = track->next;
- }
-
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = plane_track->next)
- {
- if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
- td += 4;
- td2d += 4;
- tdt += 4;
- }
- }
-}
-
-static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingTrack *track, MovieTrackingMarker *marker,
- MovieTrackingMarker *prev_marker, short coord, float size)
-{
- float frames_delta = (marker->framenr - prev_marker->framenr);
-
- tdt->flag = marker->flag;
- marker->flag &= ~MARKER_TRACKED;
-
- tdt->mode = transDataTracking_ModeCurves;
- tdt->coord = coord;
- tdt->scale = 1.0f / size * frames_delta;
- tdt->prev_pos = prev_marker->pos;
- tdt->track = track;
+ TransData *td;
+ TransData2D *td2d;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ TransDataTracking *tdt;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = 0;
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ tc->data_len++; /* offset */
+
+ if (track->flag & SELECT)
+ tc->data_len++;
+
+ if (track->pat_flag & SELECT)
+ tc->data_len += 4;
+
+ if (track->search_flag & SELECT)
+ tc->data_len += 2;
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ tc->data_len += 4;
+ }
+ }
+
+ if (tc->data_len == 0)
+ return;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransTracking TransData2D");
+ tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
+ "TransTracking TransDataTracking");
+
+ tc->custom.type.free_cb = transDataTrackingFree;
+
+ /* create actual data */
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ trackToTransData(framenr, td, td2d, tdt, track, t->aspect);
+
+ /* offset */
+ td++;
+ td2d++;
+ tdt++;
+
+ if (track->flag & SELECT) {
+ td++;
+ td2d++;
+ tdt++;
+ }
+
+ if (track->pat_flag & SELECT) {
+ td += 4;
+ td2d += 4;
+ tdt += 4;
+ }
+
+ if (track->search_flag & SELECT) {
+ td += 2;
+ td2d += 2;
+ tdt += 2;
+ }
+ }
+
+ track = track->next;
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
+ planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect);
+ td += 4;
+ td2d += 4;
+ tdt += 4;
+ }
+ }
+}
+
+static void markerToTransCurveDataInit(TransData *td,
+ TransData2D *td2d,
+ TransDataTracking *tdt,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker,
+ MovieTrackingMarker *prev_marker,
+ short coord,
+ float size)
+{
+ float frames_delta = (marker->framenr - prev_marker->framenr);
+
+ tdt->flag = marker->flag;
+ marker->flag &= ~MARKER_TRACKED;
+
+ tdt->mode = transDataTracking_ModeCurves;
+ tdt->coord = coord;
+ tdt->scale = 1.0f / size * frames_delta;
+ tdt->prev_pos = prev_marker->pos;
+ tdt->track = track;
+
+ /* calculate values depending on marker's speed */
+ td2d->loc[0] = marker->framenr;
+ td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
+ td2d->loc[2] = 0.0f;
+
+ td2d->loc2d = marker->pos; /* current location */
- /* calculate values depending on marker's speed */
- td2d->loc[0] = marker->framenr;
- td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
- td2d->loc[2] = 0.0f;
-
- td2d->loc2d = marker->pos; /* current location */
-
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, td->loc);
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
- td->val = NULL;
-
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, td->loc);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
}
static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker, *prev_marker;
- TransDataTracking *tdt;
- int i, width, height;
-
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* count */
- tc->data_len = 0;
-
- if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
- return;
- }
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- for (i = 1; i < track->markersnr; i++) {
- marker = &track->markers[i];
- prev_marker = &track->markers[i - 1];
-
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
-
- if (marker->flag & MARKER_GRAPH_SEL_X)
- tc->data_len += 1;
-
- if (marker->flag & MARKER_GRAPH_SEL_Y)
- tc->data_len += 1;
- }
- }
-
- track = track->next;
- }
-
- if (tc->data_len == 0)
- return;
-
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D");
- tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTracking), "TransTracking TransDataTracking");
- tc->custom.type.free_cb = transDataTrackingFree;
-
- /* create actual data */
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- for (i = 1; i < track->markersnr; i++) {
- marker = &track->markers[i];
- prev_marker = &track->markers[i - 1];
-
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
-
- if (marker->flag & MARKER_GRAPH_SEL_X) {
- markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
- td += 1;
- td2d += 1;
- tdt += 1;
- }
-
- if (marker->flag & MARKER_GRAPH_SEL_Y) {
- markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
-
- td += 1;
- td2d += 1;
- tdt += 1;
- }
- }
- }
-
- track = track->next;
- }
+ TransData *td;
+ TransData2D *td2d;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingMarker *marker, *prev_marker;
+ TransDataTracking *tdt;
+ int i, width, height;
+
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* count */
+ tc->data_len = 0;
+
+ if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
+ return;
+ }
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ for (i = 1; i < track->markersnr; i++) {
+ marker = &track->markers[i];
+ prev_marker = &track->markers[i - 1];
+
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
+
+ if (marker->flag & MARKER_GRAPH_SEL_X)
+ tc->data_len += 1;
+
+ if (marker->flag & MARKER_GRAPH_SEL_Y)
+ tc->data_len += 1;
+ }
+ }
+
+ track = track->next;
+ }
+
+ if (tc->data_len == 0)
+ return;
+
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransTracking TransData2D");
+ tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
+ "TransTracking TransDataTracking");
+ tc->custom.type.free_cb = transDataTrackingFree;
+
+ /* create actual data */
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ for (i = 1; i < track->markersnr; i++) {
+ marker = &track->markers[i];
+ prev_marker = &track->markers[i - 1];
+
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
+
+ if (marker->flag & MARKER_GRAPH_SEL_X) {
+ markerToTransCurveDataInit(
+ td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
+ td += 1;
+ td2d += 1;
+ tdt += 1;
+ }
+
+ if (marker->flag & MARKER_GRAPH_SEL_Y) {
+ markerToTransCurveDataInit(
+ td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
+
+ td += 1;
+ td2d += 1;
+ tdt += 1;
+ }
+ }
+ }
+
+ track = track->next;
+ }
}
static void createTransTrackingData(bContext *C, TransInfo *t)
{
- ARegion *ar = CTX_wm_region(C);
- SpaceClip *sc = CTX_wm_space_clip(C);
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int width, height;
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int width, height;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- tc->data_len = 0;
+ tc->data_len = 0;
- if (!clip)
- return;
+ if (!clip)
+ return;
- BKE_movieclip_get_size(clip, &sc->user, &width, &height);
+ BKE_movieclip_get_size(clip, &sc->user, &width, &height);
- if (width == 0 || height == 0)
- return;
+ if (width == 0 || height == 0)
+ return;
- if (ar->regiontype == RGN_TYPE_PREVIEW) {
- /* transformation was called from graph editor */
- createTransTrackingCurvesData(C, t);
- }
- else {
- createTransTrackingTracksData(C, t);
- }
+ if (ar->regiontype == RGN_TYPE_PREVIEW) {
+ /* transformation was called from graph editor */
+ createTransTrackingCurvesData(C, t);
+ }
+ else {
+ createTransTrackingTracksData(C, t);
+ }
}
static void cancelTransTracking(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- SpaceClip *sc = t->sa->spacedata.first;
- int i, framenr = ED_space_clip_get_clip_frame_number(sc);
- TransDataTracking *tdt_array = tc->custom.type.data;
-
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ SpaceClip *sc = t->sa->spacedata.first;
+ int i, framenr = ED_space_clip_get_clip_frame_number(sc);
+ TransDataTracking *tdt_array = tc->custom.type.data;
- i = 0;
- while (i < tc->data_len) {
- TransDataTracking *tdt = &tdt_array[i];
+ i = 0;
+ while (i < tc->data_len) {
+ TransDataTracking *tdt = &tdt_array[i];
- if (tdt->mode == transDataTracking_ModeTracks) {
- MovieTrackingTrack *track = tdt->track;
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ if (tdt->mode == transDataTracking_ModeTracks) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- marker->flag = tdt->flag;
+ marker->flag = tdt->flag;
- if (track->flag & SELECT)
- i++;
+ if (track->flag & SELECT)
+ i++;
- if (track->pat_flag & SELECT)
- i += 4;
+ if (track->pat_flag & SELECT)
+ i += 4;
- if (track->search_flag & SELECT)
- i += 2;
- }
- else if (tdt->mode == transDataTracking_ModeCurves) {
- MovieTrackingTrack *track = tdt->track;
- MovieTrackingMarker *marker, *prev_marker;
- int a;
+ if (track->search_flag & SELECT)
+ i += 2;
+ }
+ else if (tdt->mode == transDataTracking_ModeCurves) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker, *prev_marker;
+ int a;
- for (a = 1; a < track->markersnr; a++) {
- marker = &track->markers[a];
- prev_marker = &track->markers[a - 1];
+ for (a = 1; a < track->markersnr; a++) {
+ marker = &track->markers[a];
+ prev_marker = &track->markers[a - 1];
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
- if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
- marker->flag = tdt->flag;
- }
- }
- }
- else if (tdt->mode == transDataTracking_ModePlaneTracks) {
- MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
- MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
+ marker->flag = tdt->flag;
+ }
+ }
+ }
+ else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+ MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
- plane_marker->flag = tdt->flag;
- i += 3;
- }
+ plane_marker->flag = tdt->flag;
+ i += 3;
+ }
- i++;
- }
+ i++;
+ }
}
void flushTransTracking(TransInfo *t)
{
- TransData *td;
- TransData2D *td2d;
- TransDataTracking *tdt;
- int a;
-
- if (t->state == TRANS_CANCEL)
- cancelTransTracking(t);
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data, td2d = tc->data_2d, tdt = tc->custom.type.data; a < tc->data_len; a++, td2d++, td++, tdt++) {
- if (tdt->mode == transDataTracking_ModeTracks) {
- float loc2d[2];
-
- if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
- continue;
- }
-
- 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) {
- if (tdt->area != TRACK_AREA_PAT)
- continue;
- }
- else if (t->mode == TFM_TRANSLATION) {
- if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
- float d[2], d2[2];
-
- if (!tdt->smarkers) {
- tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers) * tdt->markersnr, "flushTransTracking markers");
- for (a = 0; a < tdt->markersnr; a++)
- copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
- }
-
- sub_v2_v2v2(d, loc2d, tdt->soffset);
- sub_v2_v2(d, tdt->srelative);
-
- sub_v2_v2v2(d2, loc2d, tdt->srelative);
-
- for (a = 0; a < tdt->markersnr; a++)
- add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
-
- negate_v2_v2(td2d->loc2d, d);
- }
- }
- }
-
- if (tdt->area != TRACK_AREA_POINT || tdt->relative == NULL) {
- td2d->loc2d[0] = loc2d[0];
- td2d->loc2d[1] = loc2d[1];
-
- if (tdt->relative)
- sub_v2_v2(td2d->loc2d, tdt->relative);
- }
- }
- else if (tdt->mode == transDataTracking_ModeCurves) {
- 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] / t->aspect[0];
- td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
- }
- }
+ TransData *td;
+ TransData2D *td2d;
+ TransDataTracking *tdt;
+ int a;
+
+ if (t->state == TRANS_CANCEL)
+ cancelTransTracking(t);
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data, td2d = tc->data_2d, tdt = tc->custom.type.data; a < tc->data_len;
+ a++, td2d++, td++, tdt++) {
+ if (tdt->mode == transDataTracking_ModeTracks) {
+ float loc2d[2];
+
+ if (t->mode == TFM_ROTATION && tdt->area == TRACK_AREA_SEARCH) {
+ continue;
+ }
+
+ 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) {
+ if (tdt->area != TRACK_AREA_PAT)
+ continue;
+ }
+ else if (t->mode == TFM_TRANSLATION) {
+ if (tdt->area == TRACK_AREA_POINT && tdt->relative) {
+ float d[2], d2[2];
+
+ if (!tdt->smarkers) {
+ tdt->smarkers = MEM_callocN(sizeof(*tdt->smarkers) * tdt->markersnr,
+ "flushTransTracking markers");
+ for (a = 0; a < tdt->markersnr; a++)
+ copy_v2_v2(tdt->smarkers[a], tdt->markers[a].pos);
+ }
+
+ sub_v2_v2v2(d, loc2d, tdt->soffset);
+ sub_v2_v2(d, tdt->srelative);
+
+ sub_v2_v2v2(d2, loc2d, tdt->srelative);
+
+ for (a = 0; a < tdt->markersnr; a++)
+ add_v2_v2v2(tdt->markers[a].pos, tdt->smarkers[a], d2);
+
+ negate_v2_v2(td2d->loc2d, d);
+ }
+ }
+ }
+
+ if (tdt->area != TRACK_AREA_POINT || tdt->relative == NULL) {
+ td2d->loc2d[0] = loc2d[0];
+ td2d->loc2d[1] = loc2d[1];
+
+ if (tdt->relative)
+ sub_v2_v2(td2d->loc2d, tdt->relative);
+ }
+ }
+ else if (tdt->mode == transDataTracking_ModeCurves) {
+ 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] / t->aspect[0];
+ td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];
+ }
+ }
}
/* * masking * */
typedef struct TransDataMasking {
- bool is_handle;
+ bool is_handle;
- float handle[2], orig_handle[2];
- float vec[3][3];
- MaskSplinePoint *point;
- float parent_matrix[3][3];
- float parent_inverse_matrix[3][3];
- char orig_handle_type;
+ float handle[2], orig_handle[2];
+ float vec[3][3];
+ MaskSplinePoint *point;
+ float parent_matrix[3][3];
+ float parent_inverse_matrix[3][3];
+ char orig_handle_type;
- eMaskWhichHandle which_handle;
+ eMaskWhichHandle which_handle;
} TransDataMasking;
-static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which_handle,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+static void MaskHandleToTransData(MaskSplinePoint *point,
+ eMaskWhichHandle which_handle,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataMasking *tdm,
const float asp[2],
/*const*/ float parent_matrix[3][3],
/*const*/ float parent_inverse_matrix[3][3])
{
- BezTriple *bezt = &point->bezt;
- const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
+ BezTriple *bezt = &point->bezt;
+ const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
- tdm->point = point;
- copy_m3_m3(tdm->vec, bezt->vec);
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
- tdm->is_handle = true;
- copy_m3_m3(tdm->parent_matrix, parent_matrix);
- copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+ tdm->is_handle = true;
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
- BKE_mask_point_handle(point, which_handle, tdm->handle);
- tdm->which_handle = which_handle;
+ BKE_mask_point_handle(point, which_handle, tdm->handle);
+ tdm->which_handle = which_handle;
- copy_v2_v2(tdm->orig_handle, tdm->handle);
+ copy_v2_v2(tdm->orig_handle, tdm->handle);
- mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
- td2d->loc[0] *= asp[0];
- td2d->loc[1] *= asp[1];
- td2d->loc[2] = 0.0f;
+ mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
+ td2d->loc[2] = 0.0f;
- td2d->loc2d = tdm->handle;
+ td2d->loc2d = tdm->handle;
- td->flag = 0;
- td->loc = td2d->loc;
- mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
- td->center[0] *= asp[0];
- td->center[1] *= asp[1];
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
- td->val = NULL;
-
- if (is_sel_any) {
- td->flag |= TD_SELECTED;
- }
-
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- if (which_handle == MASK_WHICH_HANDLE_LEFT) {
- tdm->orig_handle_type = bezt->h1;
- }
- else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
- tdm->orig_handle_type = bezt->h2;
- }
-}
-
-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);
- const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
- float parent_matrix[3][3], parent_inverse_matrix[3][3];
-
- BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
- invert_m3_m3(parent_inverse_matrix, parent_matrix);
-
- if (is_prop_edit || is_sel_point) {
- int i;
-
- tdm->point = point;
- copy_m3_m3(tdm->vec, bezt->vec);
-
- for (i = 0; i < 3; i++) {
- copy_m3_m3(tdm->parent_matrix, parent_matrix);
- copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
-
- /* CV coords are scaled by aspects. this is needed for rotations and
- * proportional editing to be consistent with the stretched CV coords
- * that are displayed. this also means that for display and numinput,
- * and when the CV coords are flushed, these are converted each time */
- mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
- td2d->loc[0] *= asp[0];
- td2d->loc[1] *= asp[1];
- td2d->loc[2] = 0.0f;
-
- td2d->loc2d = bezt->vec[i];
-
- td->flag = 0;
- td->loc = td2d->loc;
- mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
- td->center[0] *= asp[0];
- td->center[1] *= asp[1];
- copy_v3_v3(td->iloc, td->loc);
-
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
-
- td->ext = NULL;
-
- if (i == 1) {
- /* scaling weights */
- td->val = &bezt->weight;
- td->ival = *td->val;
- }
- else {
- td->val = NULL;
- }
-
- if (is_sel_any) {
- td->flag |= TD_SELECTED;
- }
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- if (i == 0) {
- tdm->orig_handle_type = bezt->h1;
- }
- else if (i == 2) {
- tdm->orig_handle_type = bezt->h2;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_STICK,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- td++;
- td2d++;
- tdm++;
- }
- else {
- if (bezt->f1 & SELECT) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_LEFT,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- if (bezt->h1 == HD_VECT) {
- bezt->h1 = HD_FREE;
- }
- else if (bezt->h1 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- if (bezt->f3 & SELECT) {
- MaskHandleToTransData(point, MASK_WHICH_HANDLE_RIGHT,
- td, td2d, tdm, asp, parent_matrix,
- parent_inverse_matrix);
-
- if (bezt->h2 == HD_VECT) {
- bezt->h2 = HD_FREE;
- }
- else if (bezt->h2 == HD_AUTO) {
- bezt->h1 = HD_ALIGN_DOUBLESIDE;
- bezt->h2 = HD_ALIGN_DOUBLESIDE;
- }
-
- td++;
- td2d++;
- tdm++;
- }
- }
- }
+ td->flag = 0;
+ td->loc = td2d->loc;
+ mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
+ td->center[0] *= asp[0];
+ td->center[1] *= asp[1];
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (is_sel_any) {
+ td->flag |= TD_SELECTED;
+ }
+
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+}
+
+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);
+ const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
+ float parent_matrix[3][3], parent_inverse_matrix[3][3];
+
+ BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
+ invert_m3_m3(parent_inverse_matrix, parent_matrix);
+
+ if (is_prop_edit || is_sel_point) {
+ int i;
+
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
+
+ for (i = 0; i < 3; i++) {
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+
+ /* CV coords are scaled by aspects. this is needed for rotations and
+ * proportional editing to be consistent with the stretched CV coords
+ * that are displayed. this also means that for display and numinput,
+ * and when the CV coords are flushed, these are converted each time */
+ mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
+ td2d->loc[2] = 0.0f;
+
+ td2d->loc2d = bezt->vec[i];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
+ td->center[0] *= asp[0];
+ td->center[1] *= asp[1];
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+
+ if (i == 1) {
+ /* scaling weights */
+ td->val = &bezt->weight;
+ td->ival = *td->val;
+ }
+ else {
+ td->val = NULL;
+ }
+
+ if (is_sel_any) {
+ td->flag |= TD_SELECTED;
+ }
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ if (i == 0) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (i == 2) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_STICK,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_LEFT,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ if (bezt->h1 == HD_VECT) {
+ bezt->h1 = HD_FREE;
+ }
+ else if (bezt->h1 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ MaskHandleToTransData(point,
+ MASK_WHICH_HANDLE_RIGHT,
+ td,
+ td2d,
+ tdm,
+ asp,
+ parent_matrix,
+ parent_inverse_matrix);
+
+ if (bezt->h2 == HD_VECT) {
+ bezt->h2 = HD_FREE;
+ }
+ else if (bezt->h2 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ }
}
static void createTransMaskingData(bContext *C, TransInfo *t)
{
- Scene *scene = CTX_data_scene(C);
- Mask *mask = CTX_data_edit_mask(C);
- MaskLayer *masklay;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataMasking *tdm = NULL;
- int count = 0, countsel = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT);
- float asp[2];
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- tc->data_len = 0;
-
- if (!mask)
- return;
-
- if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- if (!clip) {
- return;
- }
- }
-
- /* count */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (MASKPOINT_ISSEL_ANY(point)) {
- if (MASKPOINT_ISSEL_KNOT(point)) {
- countsel += 3;
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- countsel += 1;
- }
- else {
- BezTriple *bezt = &point->bezt;
- if (bezt->f1 & SELECT) {
- countsel++;
- }
- if (bezt->f3 & SELECT) {
- countsel++;
- }
- }
- }
- }
-
- if (is_prop_edit)
- count += 3;
- }
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (countsel == 0) {
- return;
- }
-
- ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
-
- tc->data_len = (is_prop_edit) ? count : countsel;
- td = tc->data = MEM_callocN(tc->data_len * 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 */
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransObData2D(Mask Editing)");
- tc->custom.type.data = tdm = MEM_callocN(tc->data_len * sizeof(TransDataMasking), "TransDataMasking(Mask Editing)");
- tc->custom.type.use_free = true;
-
- /* create data */
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
- continue;
- }
-
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
-
- if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
-
- if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
- td += 3;
- td2d += 3;
- tdm += 3;
- }
- else {
- if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
- td++;
- td2d++;
- tdm++;
- }
- else {
- BezTriple *bezt = &point->bezt;
- if (bezt->f1 & SELECT) {
- td++;
- td2d++;
- tdm++;
- }
- if (bezt->f3 & SELECT) {
- td++;
- td2d++;
- tdm++;
- }
- }
- }
- }
- }
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *masklay;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataMasking *tdm = NULL;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT);
+ float asp[2];
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ tc->data_len = 0;
+
+ if (!mask)
+ return;
+
+ if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sc = t->sa->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ if (!clip) {
+ return;
+ }
+ }
+
+ /* count */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (MASKPOINT_ISSEL_ANY(point)) {
+ if (MASKPOINT_ISSEL_KNOT(point)) {
+ countsel += 3;
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ countsel += 1;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ countsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ countsel++;
+ }
+ }
+ }
+ }
+
+ if (is_prop_edit)
+ count += 3;
+ }
+ }
+ }
+
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ return;
+ }
+
+ ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
+
+ tc->data_len = (is_prop_edit) ? count : countsel;
+ td = tc->data = MEM_callocN(tc->data_len * 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 */
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransObData2D(Mask Editing)");
+ tc->custom.type.data = tdm = MEM_callocN(tc->data_len * sizeof(TransDataMasking),
+ "TransDataMasking(Mask Editing)");
+ tc->custom.type.use_free = true;
+
+ /* create data */
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+
+ if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ continue;
+ }
+
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
+
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
+ MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
+
+ if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
+ td += 3;
+ td2d += 3;
+ tdm += 3;
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
void flushTransMasking(TransInfo *t)
{
- TransData2D *td;
- TransDataMasking *tdm;
- int a;
- float asp[2], inv[2];
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
- inv[0] = 1.0f / asp[0];
- inv[1] = 1.0f / asp[1];
-
- /* flush to 2d vector from internally used 3d vector */
- for (a = 0, td = tc->data_2d, tdm = tc->custom.type.data; a < tc->data_len; a++, td++, tdm++) {
- td->loc2d[0] = td->loc[0] * inv[0];
- td->loc2d[1] = td->loc[1] * inv[1];
- mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
-
- if (tdm->is_handle) {
- BKE_mask_point_set_handle(tdm->point, tdm->which_handle,
- td->loc2d,
- (t->flag & T_ALT_TRANSFORM) != 0,
- tdm->orig_handle, tdm->vec);
- }
-
- if (t->state == TRANS_CANCEL) {
- if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) {
- tdm->point->bezt.h1 = tdm->orig_handle_type;
- }
- else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) {
- tdm->point->bezt.h2 = tdm->orig_handle_type;
- }
- }
- }
+ TransData2D *td;
+ TransDataMasking *tdm;
+ int a;
+ float asp[2], inv[2];
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
+ inv[0] = 1.0f / asp[0];
+ inv[1] = 1.0f / asp[1];
+
+ /* flush to 2d vector from internally used 3d vector */
+ for (a = 0, td = tc->data_2d, tdm = tc->custom.type.data; a < tc->data_len; a++, td++, tdm++) {
+ td->loc2d[0] = td->loc[0] * inv[0];
+ td->loc2d[1] = td->loc[1] * inv[1];
+ mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
+
+ if (tdm->is_handle) {
+ BKE_mask_point_set_handle(tdm->point,
+ tdm->which_handle,
+ td->loc2d,
+ (t->flag & T_ALT_TRANSFORM) != 0,
+ tdm->orig_handle,
+ tdm->vec);
+ }
+
+ if (t->state == TRANS_CANCEL) {
+ if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->point->bezt.h1 = tdm->orig_handle_type;
+ }
+ else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->point->bezt.h2 = tdm->orig_handle_type;
+ }
+ }
+ }
}
typedef struct TransDataPaintCurve {
- PaintCurvePoint *pcp; /* initial curve point */
- char id;
+ PaintCurvePoint *pcp; /* initial curve point */
+ char id;
} TransDataPaintCurve;
-
#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT)
-static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
+static void PaintCurveConvertHandle(
+ PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
{
- BezTriple *bezt = &pcp->bez;
- copy_v2_v2(td2d->loc, bezt->vec[id]);
- td2d->loc[2] = 0.0f;
- td2d->loc2d = bezt->vec[id];
+ BezTriple *bezt = &pcp->bez;
+ copy_v2_v2(td2d->loc, bezt->vec[id]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[id];
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, bezt->vec[1]);
- copy_v3_v3(td->iloc, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- tdpc->id = id;
- tdpc->pcp = pcp;
+ tdpc->id = id;
+ tdpc->pcp = pcp;
}
-static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc)
+static void PaintCurvePointToTransData(PaintCurvePoint *pcp,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataPaintCurve *tdpc)
{
- BezTriple *bezt = &pcp->bez;
+ BezTriple *bezt = &pcp->bez;
- if (pcp->bez.f2 == SELECT) {
- int i;
- for (i = 0; i < 3; i++) {
- copy_v2_v2(td2d->loc, bezt->vec[i]);
- td2d->loc[2] = 0.0f;
- td2d->loc2d = bezt->vec[i];
+ if (pcp->bez.f2 == SELECT) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(td2d->loc, bezt->vec[i]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[i];
- td->flag = 0;
- td->loc = td2d->loc;
- copy_v3_v3(td->center, bezt->vec[1]);
- copy_v3_v3(td->iloc, td->loc);
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
- td->ext = NULL;
- td->val = NULL;
- td->flag |= TD_SELECTED;
- td->dist = 0.0;
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
- unit_m3(td->mtx);
- unit_m3(td->smtx);
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
- tdpc->id = i;
- tdpc->pcp = pcp;
+ tdpc->id = i;
+ tdpc->pcp = pcp;
- td++;
- td2d++;
- tdpc++;
- }
- }
- else {
- if (bezt->f3 & SELECT) {
- PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
- td2d++;
- tdpc++;
- td++;
- }
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ else {
+ if (bezt->f3 & SELECT) {
+ PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
+ td2d++;
+ tdpc++;
+ td++;
+ }
- if (bezt->f1 & SELECT) {
- PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
- }
- }
+ if (bezt->f1 & SELECT) {
+ PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
+ }
+ }
}
static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
{
- Paint *paint = BKE_paint_get_active_from_context(C);
- PaintCurve *pc;
- PaintCurvePoint *pcp;
- Brush *br;
- TransData *td = NULL;
- TransData2D *td2d = NULL;
- TransDataPaintCurve *tdpc = NULL;
- int i;
- int total = 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- tc->data_len = 0;
-
- if (!paint || !paint->brush || !paint->brush->paint_curve)
- return;
-
- br = paint->brush;
- pc = br->paint_curve;
-
- for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
- if (PC_IS_ANY_SEL(pcp)) {
- if (pcp->bez.f2 & SELECT) {
- total += 3;
- continue;
- }
- else {
- if (pcp->bez.f1 & SELECT)
- total++;
- if (pcp->bez.f3 & SELECT)
- total++;
- }
- }
- }
-
- if (!total)
- return;
-
- tc->data_len = total;
- td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D");
- td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData");
- tc->custom.type.data = tdpc = MEM_callocN(tc->data_len * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
- tc->custom.type.use_free = true;
-
- for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
- if (PC_IS_ANY_SEL(pcp)) {
- PaintCurvePointToTransData(pcp, td, td2d, tdpc);
-
- if (pcp->bez.f2 & SELECT) {
- td += 3;
- td2d += 3;
- tdpc += 3;
- }
- else {
- if (pcp->bez.f1 & SELECT) {
- td++;
- td2d++;
- tdpc++;
- }
- if (pcp->bez.f3 & SELECT) {
- td++;
- td2d++;
- tdpc++;
- }
- }
- }
- }
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ Brush *br;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataPaintCurve *tdpc = NULL;
+ int i;
+ int total = 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ tc->data_len = 0;
+
+ if (!paint || !paint->brush || !paint->brush->paint_curve)
+ return;
+
+ br = paint->brush;
+ pc = br->paint_curve;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ if (pcp->bez.f2 & SELECT) {
+ total += 3;
+ continue;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT)
+ total++;
+ if (pcp->bez.f3 & SELECT)
+ total++;
+ }
+ }
+ }
+
+ if (!total)
+ return;
+
+ tc->data_len = total;
+ td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D");
+ td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData");
+ tc->custom.type.data = tdpc = MEM_callocN(tc->data_len * sizeof(TransDataPaintCurve),
+ "TransDataPaintCurve");
+ tc->custom.type.use_free = true;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ PaintCurvePointToTransData(pcp, td, td2d, tdpc);
+
+ if (pcp->bez.f2 & SELECT) {
+ td += 3;
+ td2d += 3;
+ tdpc += 3;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ if (pcp->bez.f3 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ }
+ }
}
-
void flushTransPaintCurve(TransInfo *t)
{
- int i;
+ int i;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- TransData2D *td2d = tc->data_2d;
- TransDataPaintCurve *tdpc = tc->custom.type.data;
+ TransData2D *td2d = tc->data_2d;
+ TransDataPaintCurve *tdpc = tc->custom.type.data;
- for (i = 0; i < tc->data_len; i++, tdpc++, td2d++) {
- PaintCurvePoint *pcp = tdpc->pcp;
- copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
- }
+ for (i = 0; i < tc->data_len; i++, tdpc++, td2d++) {
+ PaintCurvePoint *pcp = tdpc->pcp;
+ copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
+ }
}
static void createTransGPencil_center_get(bGPDstroke *gps, float r_center[3])
{
- bGPDspoint *pt;
- int i;
+ bGPDspoint *pt;
+ int i;
- zero_v3(r_center);
- int tot_sel = 0;
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- add_v3_v3(r_center, &pt->x);
- tot_sel++;
- }
- }
+ zero_v3(r_center);
+ int tot_sel = 0;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ add_v3_v3(r_center, &pt->x);
+ tot_sel++;
+ }
+ }
- if (tot_sel > 0) {
- mul_v3_fl(r_center, 1.0f / tot_sel);
- }
+ if (tot_sel > 0) {
+ mul_v3_fl(r_center, 1.0f / tot_sel);
+ }
}
static void createTransGPencil(bContext *C, TransInfo *t)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bGPdata *gpd = ED_gpencil_data_get_active(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
-
- Object *obact = CTX_data_active_object(C);
- bGPDlayer *gpl;
- TransData *td = NULL;
- float mtx[3][3], smtx[3][3];
-
- const Scene *scene = CTX_data_scene(C);
- const int cfra_scene = CFRA;
-
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
- const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- /* == Grease Pencil Strokes to Transform Data ==
- * Grease Pencil stroke points can be a mixture of 2D (screen-space),
- * or 3D coordinates. However, they're always saved as 3D points.
- * For now, we just do these without creating TransData2D for the 2D
- * strokes. This may cause issues in future though.
- */
- tc->data_len = 0;
-
- if (gpd == NULL)
- return;
-
- /* initialize falloff curve */
- if (is_multiedit) {
- curvemapping_initialize(ts->gp_sculpt.cur_falloff);
- }
-
- /* First Pass: Count the number of data-points required for the strokes,
- * (and additional info about the configuration - e.g. 2D/3D?).
- */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
- bGPDframe *gpf;
- bGPDstroke *gps;
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
-
- for (gpf = init_gpf; gpf; gpf = gpf->next) {
- if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
- continue;
- }
-
- if (is_prop_edit) {
- /* Proportional Editing... */
- if (is_prop_edit_connected) {
- /* connected only - so only if selected */
- if (gps->flag & GP_STROKE_SELECT)
- tc->data_len += gps->totpoints;
- }
- else {
- /* everything goes - connection status doesn't matter */
- tc->data_len += gps->totpoints;
- }
- }
- else {
- /* only selected stroke points are considered */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- // TODO: 2D vs 3D?
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT)
- tc->data_len++;
- }
- }
- }
- }
- }
- /* if not multiedit out of loop */
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
-
- /* Stop trying if nothing selected */
- if (tc->data_len == 0) {
- return;
- }
-
- /* Allocate memory for data */
- tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
- td = tc->data;
-
- unit_m3(smtx);
- unit_m3(mtx);
-
- /* Second Pass: Build transdata array */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
- const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
- bGPDframe *gpf = gpl->actframe;
- bGPDstroke *gps;
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
-
- bGPDframe *init_gpf = gpl->actframe;
- if (is_multiedit) {
- init_gpf = gpl->frames.first;
- }
- /* init multiframe falloff options */
- int f_init = 0;
- int f_end = 0;
-
- if (use_multiframe_falloff) {
- BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
- }
-
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
- /* undo matrix */
- invert_m4_m4(inverse_diff_mat, diff_mat);
-
- /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
- * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
- * spent too much time editing the wrong frame...
- */
- // XXX: should this be allowed when framelock is enabled?
- if ((gpf->framenum != cfra) && (!is_multiedit)) {
- gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
- /* in some weird situations (framelock enabled) return NULL */
- if (gpf == NULL) {
- continue;
- }
- if (!is_multiedit) {
- init_gpf = gpf;
- }
- }
-
- /* Loop over strokes, adding TransData for points as needed... */
- for (gpf = init_gpf; gpf; gpf = gpf->next) {
- if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
-
- /* if multiframe and falloff, recalculate and save value */
- float falloff = 1.0f; /* by default no falloff */
- if ((is_multiedit) && (use_multiframe_falloff)) {
- /* Faloff depends on distance to active frame (relative to the overall frame range) */
- falloff = BKE_gpencil_multiframe_falloff_calc(
- gpf, gpl->actframe->framenum,
- f_init, f_end, ts->gp_sculpt.cur_falloff);
- }
-
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- TransData *head = td;
- TransData *tail = td;
- bool stroke_ok;
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
- continue;
- }
- /* What we need to include depends on proportional editing settings... */
- if (is_prop_edit) {
- if (is_prop_edit_connected) {
- /* A) "Connected" - Only those in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
- else {
- /* B) All points, always */
- stroke_ok = true;
- }
- }
- else {
- /* C) Only selected points in selected strokes */
- stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
- }
-
- /* Do stroke... */
- if (stroke_ok && gps->totpoints) {
- bGPDspoint *pt;
- int i;
-
- /* save falloff factor */
- gps->runtime.multi_frame_falloff = falloff;
-
- /* calculate stroke center */
- float center[3];
- createTransGPencil_center_get(gps, center);
-
- /* add all necessary points... */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- bool point_ok;
-
- /* include point? */
- if (is_prop_edit) {
- /* Always all points in strokes that get included */
- point_ok = true;
- }
- else {
- /* Only selected points in selected strokes */
- point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
- }
-
- /* do point... */
- if (point_ok) {
- copy_v3_v3(td->iloc, &pt->x);
- /* only copy center in local origins.
- * This allows get interesting effects also when move
- * using proportional editing */
- if ((gps->flag & GP_STROKE_SELECT) &&
- (ts->transform_pivot_point == V3D_AROUND_LOCAL_ORIGINS))
- {
- copy_v3_v3(td->center, center);
- }
- else {
- copy_v3_v3(td->center, &pt->x);
- }
-
- td->loc = &pt->x;
-
- td->flag = 0;
-
- if (pt->flag & GP_SPOINT_SELECT) {
- td->flag |= TD_SELECTED;
- }
-
- /* for other transform modes (e.g. shrink-fatten), need to additional data
- * but never for scale or mirror
- */
- if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
- if (t->mode != TFM_GPENCIL_OPACITY) {
- td->val = &pt->pressure;
- td->ival = pt->pressure;
- }
- else {
- td->val = &pt->strength;
- td->ival = pt->strength;
- }
- }
-
- /* screenspace needs special matrices... */
- if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) {
- /* screenspace */
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
- }
- else {
- /* configure 2D dataspace points so that they don't play up... */
- if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
- td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
- }
- }
- /* apply parent transformations */
- copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
- copy_m3_m4(td->mtx, diff_mat); /* display position */
- copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
-
- /* Triangulation must be calculated again,
- * so save the stroke for recalc function */
- td->extra = gps;
-
- /* save pointer to object */
- td->ob = obact;
-
- td++;
- tail++;
- }
- }
-
- /* March over these points, and calculate the proportional editing distances */
- if (is_prop_edit && (head != tail)) {
- /* XXX: for now, we are similar enough that this works... */
- calc_distanceCurveVerts(head, tail - 1);
- }
- }
- }
- }
- /* if not multiedit out of loop */
- if (!is_multiedit) {
- break;
- }
- }
- }
- }
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
+
+ Object *obact = CTX_data_active_object(C);
+ bGPDlayer *gpl;
+ TransData *td = NULL;
+ float mtx[3][3], smtx[3][3];
+
+ const Scene *scene = CTX_data_scene(C);
+ const int cfra_scene = CFRA;
+
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ /* == Grease Pencil Strokes to Transform Data ==
+ * Grease Pencil stroke points can be a mixture of 2D (screen-space),
+ * or 3D coordinates. However, they're always saved as 3D points.
+ * For now, we just do these without creating TransData2D for the 2D
+ * strokes. This may cause issues in future though.
+ */
+ tc->data_len = 0;
+
+ if (gpd == NULL)
+ return;
+
+ /* initialize falloff curve */
+ if (is_multiedit) {
+ curvemapping_initialize(ts->gp_sculpt.cur_falloff);
+ }
+
+ /* First Pass: Count the number of data-points required for the strokes,
+ * (and additional info about the configuration - e.g. 2D/3D?).
+ */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+
+ for (gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
+ continue;
+ }
+
+ if (is_prop_edit) {
+ /* Proportional Editing... */
+ if (is_prop_edit_connected) {
+ /* connected only - so only if selected */
+ if (gps->flag & GP_STROKE_SELECT)
+ tc->data_len += gps->totpoints;
+ }
+ else {
+ /* everything goes - connection status doesn't matter */
+ tc->data_len += gps->totpoints;
+ }
+ }
+ else {
+ /* only selected stroke points are considered */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ // TODO: 2D vs 3D?
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT)
+ tc->data_len++;
+ }
+ }
+ }
+ }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
+
+ /* Stop trying if nothing selected */
+ if (tc->data_len == 0) {
+ return;
+ }
+
+ /* Allocate memory for data */
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
+ td = tc->data;
+
+ unit_m3(smtx);
+ unit_m3(mtx);
+
+ /* Second Pass: Build transdata array */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene;
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ bGPDframe *init_gpf = gpl->actframe;
+ if (is_multiedit) {
+ init_gpf = gpl->frames.first;
+ }
+ /* init multiframe falloff options */
+ int f_init = 0;
+ int f_end = 0;
+
+ if (use_multiframe_falloff) {
+ BKE_gpencil_get_range_selected(gpl, &f_init, &f_end);
+ }
+
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ /* Make a new frame to work on if the layer's frame and the current scene frame don't match up
+ * - This is useful when animating as it saves that "uh-oh" moment when you realize you've
+ * spent too much time editing the wrong frame...
+ */
+ // XXX: should this be allowed when framelock is enabled?
+ if ((gpf->framenum != cfra) && (!is_multiedit)) {
+ gpf = BKE_gpencil_frame_addcopy(gpl, cfra);
+ /* in some weird situations (framelock enabled) return NULL */
+ if (gpf == NULL) {
+ continue;
+ }
+ if (!is_multiedit) {
+ init_gpf = gpf;
+ }
+ }
+
+ /* Loop over strokes, adding TransData for points as needed... */
+ for (gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+
+ /* if multiframe and falloff, recalculate and save value */
+ float falloff = 1.0f; /* by default no falloff */
+ if ((is_multiedit) && (use_multiframe_falloff)) {
+ /* Faloff depends on distance to active frame (relative to the overall frame range) */
+ falloff = BKE_gpencil_multiframe_falloff_calc(
+ gpf, gpl->actframe->framenum, f_init, f_end, ts->gp_sculpt.cur_falloff);
+ }
+
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ TransData *head = td;
+ TransData *tail = td;
+ bool stroke_ok;
+
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) {
+ continue;
+ }
+ /* What we need to include depends on proportional editing settings... */
+ if (is_prop_edit) {
+ if (is_prop_edit_connected) {
+ /* A) "Connected" - Only those in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+ else {
+ /* B) All points, always */
+ stroke_ok = true;
+ }
+ }
+ else {
+ /* C) Only selected points in selected strokes */
+ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
+ }
+
+ /* Do stroke... */
+ if (stroke_ok && gps->totpoints) {
+ bGPDspoint *pt;
+ int i;
+
+ /* save falloff factor */
+ gps->runtime.multi_frame_falloff = falloff;
+
+ /* calculate stroke center */
+ float center[3];
+ createTransGPencil_center_get(gps, center);
+
+ /* add all necessary points... */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bool point_ok;
+
+ /* include point? */
+ if (is_prop_edit) {
+ /* Always all points in strokes that get included */
+ point_ok = true;
+ }
+ else {
+ /* Only selected points in selected strokes */
+ point_ok = (pt->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* do point... */
+ if (point_ok) {
+ copy_v3_v3(td->iloc, &pt->x);
+ /* only copy center in local origins.
+ * This allows get interesting effects also when move
+ * using proportional editing */
+ if ((gps->flag & GP_STROKE_SELECT) &&
+ (ts->transform_pivot_point == V3D_AROUND_LOCAL_ORIGINS)) {
+ copy_v3_v3(td->center, center);
+ }
+ else {
+ copy_v3_v3(td->center, &pt->x);
+ }
+
+ td->loc = &pt->x;
+
+ td->flag = 0;
+
+ if (pt->flag & GP_SPOINT_SELECT) {
+ td->flag |= TD_SELECTED;
+ }
+
+ /* for other transform modes (e.g. shrink-fatten), need to additional data
+ * but never for scale or mirror
+ */
+ if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) {
+ if (t->mode != TFM_GPENCIL_OPACITY) {
+ td->val = &pt->pressure;
+ td->ival = pt->pressure;
+ }
+ else {
+ td->val = &pt->strength;
+ td->ival = pt->strength;
+ }
+ }
+
+ /* screenspace needs special matrices... */
+ if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) ==
+ 0) {
+ /* screenspace */
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ }
+ else {
+ /* configure 2D dataspace points so that they don't play up... */
+ if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) {
+ td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ;
+ }
+ }
+ /* apply parent transformations */
+ copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */
+ copy_m3_m4(td->mtx, diff_mat); /* display position */
+ copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */
+
+ /* Triangulation must be calculated again,
+ * so save the stroke for recalc function */
+ td->extra = gps;
+
+ /* save pointer to object */
+ td->ob = obact;
+
+ td++;
+ tail++;
+ }
+ }
+
+ /* March over these points, and calculate the proportional editing distances */
+ if (is_prop_edit && (head != tail)) {
+ /* XXX: for now, we are similar enough that this works... */
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
+ }
+ /* if not multiedit out of loop */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+ }
+ }
}
static int countAndCleanTransDataContainer(TransInfo *t)
{
- BLI_assert(ELEM(t->data_len_all, 0, -1));
- t->data_len_all = 0;
- uint data_container_len_orig = t->data_container_len;
- for (TransDataContainer *th_end = t->data_container - 1, *tc = t->data_container + (t->data_container_len - 1); tc != th_end; tc--) {
- if (tc->data_len == 0) {
- uint index = tc - t->data_container;
- if (index + 1 != t->data_container_len) {
- SWAP(TransDataContainer, t->data_container[index], t->data_container[t->data_container_len - 1]);
- }
- t->data_container_len -= 1;
- }
- else {
- t->data_len_all += tc->data_len;
- }
- }
- if (data_container_len_orig != t->data_container_len) {
- t->data_container = MEM_reallocN(t->data_container, sizeof(*t->data_container) * t->data_container_len);
- }
- return t->data_len_all;
+ BLI_assert(ELEM(t->data_len_all, 0, -1));
+ t->data_len_all = 0;
+ uint data_container_len_orig = t->data_container_len;
+ for (TransDataContainer *th_end = t->data_container - 1,
+ *tc = t->data_container + (t->data_container_len - 1);
+ tc != th_end;
+ tc--) {
+ if (tc->data_len == 0) {
+ uint index = tc - t->data_container;
+ if (index + 1 != t->data_container_len) {
+ SWAP(TransDataContainer,
+ t->data_container[index],
+ t->data_container[t->data_container_len - 1]);
+ }
+ t->data_container_len -= 1;
+ }
+ else {
+ t->data_len_all += tc->data_len;
+ }
+ }
+ if (data_container_len_orig != t->data_container_len) {
+ t->data_container = MEM_reallocN(t->data_container,
+ sizeof(*t->data_container) * t->data_container_len);
+ }
+ return t->data_len_all;
}
-
void createTransData(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
-
- bool has_transform_context = true;
- t->data_len_all = -1;
-
- /* if tests must match recalcData for correct updates */
- if (t->options & CTX_CURSOR) {
- t->flag |= T_CURSOR;
- t->obedit_type = -1;
-
- if (t->spacetype == SPACE_IMAGE) {
- createTransCursor_image(t);
- }
- else {
- createTransCursor_view3d(t);
- }
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_TEXTURE) {
- t->flag |= T_TEXTURE;
- t->obedit_type = -1;
-
- createTransTexspace(t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_EDGE) {
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->data_ext = NULL;
- }
- t->flag |= T_EDIT;
-
- createTransEdge(t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- t->options |= CTX_GPENCIL_STROKES;
- t->flag |= T_POINTS | T_EDIT;
-
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransGPencil(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- t->flag |= T_POINTS | T_2D_EDIT;
- if (t->options & CTX_MASK) {
-
- /* copied from below */
- createTransMaskingData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, true);
- sort_trans_data_dist(t);
- }
- }
- else if (t->options & CTX_PAINT_CURVE) {
- if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
- createTransPaintCurveVerts(C, t);
- countAndCleanTransDataContainer(t);
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->obedit_type == OB_MESH) {
-
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransUVs(C, t);
- countAndCleanTransDataContainer(t);
-
- t->flag |= T_EDIT;
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->spacetype == SPACE_ACTION) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransActionData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- /* don't do that, distance has been set in createTransActionData already */
- //set_prop_dist(t, false);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_NLA) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransNlaData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->spacetype == SPACE_SEQ) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
- createTransSeqData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransGraphEditData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- /* makes selected become first in array */
- sort_trans_data(t);
-
- /* don't do that, distance has been set in createTransGraphEditData already */
- set_prop_dist(t, false);
-
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- createTransNodeData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (t->spacetype == SPACE_CLIP) {
- t->flag |= T_POINTS | T_2D_EDIT;
- t->obedit_type = -1;
-
- if (t->options & CTX_MOVIECLIP) {
- createTransTrackingData(C, t);
- countAndCleanTransDataContainer(t);
- }
- else if (t->options & CTX_MASK) {
- /* copied from above */
- createTransMaskingData(C, t);
- countAndCleanTransDataContainer(t);
-
- if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, true);
- sort_trans_data_dist(t);
- }
- }
- else {
- has_transform_context = false;
- }
- }
- else if (t->obedit_type != -1) {
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->data_ext = NULL;
- }
- if (t->obedit_type == OB_MESH) {
- createTransEditVerts(t);
- }
- else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
- createTransCurveVerts(t);
- }
- else if (t->obedit_type == OB_LATTICE) {
- createTransLatticeVerts(t);
- }
- else if (t->obedit_type == OB_MBALL) {
- createTransMBallVerts(t);
- }
- else if (t->obedit_type == OB_ARMATURE) {
- t->flag &= ~T_PROP_EDIT;
- createTransArmatureVerts(t);
- }
- else {
- printf("edit type not implemented!\n");
- }
-
- countAndCleanTransDataContainer(t);
-
- t->flag |= T_EDIT | T_POINTS;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
- sort_trans_data(t); // makes selected become first in array
- if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
- /* already calculated by editmesh_set_connectivity_distance */
- }
- else {
- set_prop_dist(t, 0);
- }
- sort_trans_data_dist(t);
- }
- else {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
-
- /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
- if (t->mode == TFM_BONESIZE) {
- t->flag &= ~(T_EDIT | T_POINTS);
- t->flag |= T_POSE;
- t->obedit_type = -1;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->poseobj = tc->obedit;
- tc->obedit = NULL;
- }
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- // XXX this is currently limited to active armature only...
- // XXX active-layer checking isn't done as that should probably be checked through context instead
-
- /* Multi object editing. */
- initTransDataContainers_FromObjectData(t, ob, NULL, 0);
- createTransPose(t);
- countAndCleanTransDataContainer(t);
- }
- else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
- /* important that ob_armature can be set even when its not selected [#23412]
- * lines below just check is also visible */
- has_transform_context = false;
- Object *ob_armature = modifiers_isDeformedByArmature(ob);
- if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
- Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
- if (base_arm) {
- View3D *v3d = t->view;
- if (BASE_VISIBLE(v3d, base_arm)) {
- Object *objects[1];
- objects[0] = ob_armature;
- uint objects_len = 1;
- initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len);
- createTransPose(t);
- countAndCleanTransDataContainer(t);
- has_transform_context = true;
- }
- }
- }
- }
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
- createTransParticleVerts(C, t);
- countAndCleanTransDataContainer(t);
- t->flag |= T_POINTS;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
- else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
- if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
- t->flag |= T_POINTS | T_2D_EDIT;
- createTransPaintCurveVerts(C, t);
- countAndCleanTransDataContainer(t);
- }
- else {
- has_transform_context = false;
- }
- }
- else if ((ob) &&
- (ELEM(ob->mode, OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL)))
- {
- /* In grease pencil all transformations must be canceled if not Object or Edit. */
- has_transform_context = false;
- }
- else {
- createTransObject(C, t);
- countAndCleanTransDataContainer(t);
- t->flag |= T_OBJECT;
-
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- // selected objects are already first, no need to presort
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
-
- /* Check if we're transforming the camera from the camera */
- if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- View3D *v3d = t->view;
- RegionView3D *rv3d = t->ar->regiondata;
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
- /* we could have a flag to easily check an object is being transformed */
- if (v3d->camera->id.tag & LIB_TAG_DOIT) {
- t->flag |= T_CAMERA;
- }
- }
- }
- }
-
- /* Check that 'countAndCleanTransDataContainer' ran. */
- if (has_transform_context) {
- BLI_assert(t->data_len_all != -1);
- }
- else {
- BLI_assert(t->data_len_all == -1);
- t->data_len_all = 0;
- }
-
- BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
+ Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+
+ bool has_transform_context = true;
+ t->data_len_all = -1;
+
+ /* if tests must match recalcData for correct updates */
+ if (t->options & CTX_CURSOR) {
+ t->flag |= T_CURSOR;
+ t->obedit_type = -1;
+
+ if (t->spacetype == SPACE_IMAGE) {
+ createTransCursor_image(t);
+ }
+ else {
+ createTransCursor_view3d(t);
+ }
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
+ t->flag |= T_TEXTURE;
+ t->obedit_type = -1;
+
+ createTransTexspace(t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_EDGE) {
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->data_ext = NULL;
+ }
+ t->flag |= T_EDIT;
+
+ createTransEdge(t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->options |= CTX_GPENCIL_STROKES;
+ t->flag |= T_POINTS | T_EDIT;
+
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransGPencil(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ if (t->options & CTX_MASK) {
+
+ /* copied from below */
+ createTransMaskingData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, true);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ createTransPaintCurveVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->obedit_type == OB_MESH) {
+
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransUVs(C, t);
+ countAndCleanTransDataContainer(t);
+
+ t->flag |= T_EDIT;
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransActionData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ /* don't do that, distance has been set in createTransActionData already */
+ //set_prop_dist(t, false);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransNlaData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */
+ createTransSeqData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransGraphEditData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ /* makes selected become first in array */
+ sort_trans_data(t);
+
+ /* don't do that, distance has been set in createTransGraphEditData already */
+ set_prop_dist(t, false);
+
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ createTransNodeData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ t->obedit_type = -1;
+
+ if (t->options & CTX_MOVIECLIP) {
+ createTransTrackingData(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (t->options & CTX_MASK) {
+ /* copied from above */
+ createTransMaskingData(C, t);
+ countAndCleanTransDataContainer(t);
+
+ if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, true);
+ sort_trans_data_dist(t);
+ }
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if (t->obedit_type != -1) {
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->data_ext = NULL;
+ }
+ if (t->obedit_type == OB_MESH) {
+ createTransEditVerts(t);
+ }
+ else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
+ createTransCurveVerts(t);
+ }
+ else if (t->obedit_type == OB_LATTICE) {
+ createTransLatticeVerts(t);
+ }
+ else if (t->obedit_type == OB_MBALL) {
+ createTransMBallVerts(t);
+ }
+ else if (t->obedit_type == OB_ARMATURE) {
+ t->flag &= ~T_PROP_EDIT;
+ createTransArmatureVerts(t);
+ }
+ else {
+ printf("edit type not implemented!\n");
+ }
+
+ countAndCleanTransDataContainer(t);
+
+ t->flag |= T_EDIT | T_POINTS;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
+ sort_trans_data(t); // makes selected become first in array
+ if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
+ /* already calculated by editmesh_set_connectivity_distance */
+ }
+ else {
+ set_prop_dist(t, 0);
+ }
+ sort_trans_data_dist(t);
+ }
+ else {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+
+ /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
+ if (t->mode == TFM_BONESIZE) {
+ t->flag &= ~(T_EDIT | T_POINTS);
+ t->flag |= T_POSE;
+ t->obedit_type = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ tc->poseobj = tc->obedit;
+ tc->obedit = NULL;
+ }
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ // XXX this is currently limited to active armature only...
+ // XXX active-layer checking isn't done as that should probably be checked through context instead
+
+ /* Multi object editing. */
+ initTransDataContainers_FromObjectData(t, ob, NULL, 0);
+ createTransPose(t);
+ countAndCleanTransDataContainer(t);
+ }
+ else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
+ /* important that ob_armature can be set even when its not selected [#23412]
+ * lines below just check is also visible */
+ has_transform_context = false;
+ Object *ob_armature = modifiers_isDeformedByArmature(ob);
+ if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
+ Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
+ if (base_arm) {
+ View3D *v3d = t->view;
+ if (BASE_VISIBLE(v3d, base_arm)) {
+ Object *objects[1];
+ objects[0] = ob_armature;
+ uint objects_len = 1;
+ initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len);
+ createTransPose(t);
+ countAndCleanTransDataContainer(t);
+ has_transform_context = true;
+ }
+ }
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
+ createTransParticleVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ t->flag |= T_POINTS;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ sort_trans_data(t); // makes selected become first in array
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ createTransPaintCurveVerts(C, t);
+ countAndCleanTransDataContainer(t);
+ }
+ else {
+ has_transform_context = false;
+ }
+ }
+ else if ((ob) &&
+ (ELEM(
+ ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
+ /* In grease pencil all transformations must be canceled if not Object or Edit. */
+ has_transform_context = false;
+ }
+ else {
+ createTransObject(C, t);
+ countAndCleanTransDataContainer(t);
+ t->flag |= T_OBJECT;
+
+ if (t->data_len_all && t->flag & T_PROP_EDIT) {
+ // selected objects are already first, no need to presort
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
+ }
+
+ /* Check if we're transforming the camera from the camera */
+ if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ View3D *v3d = t->view;
+ RegionView3D *rv3d = t->ar->regiondata;
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
+ /* we could have a flag to easily check an object is being transformed */
+ if (v3d->camera->id.tag & LIB_TAG_DOIT) {
+ t->flag |= T_CAMERA;
+ }
+ }
+ }
+ }
+
+ /* Check that 'countAndCleanTransDataContainer' ran. */
+ if (has_transform_context) {
+ BLI_assert(t->data_len_all != -1);
+ }
+ else {
+ BLI_assert(t->data_len_all == -1);
+ t->data_len_all = 0;
+ }
+
+ BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 0f7992e0b4a..46e8447efc6 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -113,1063 +113,1070 @@
void getViewVector(const TransInfo *t, const float coord[3], float vec[3])
{
- if (t->persp != RV3D_ORTHO) {
- sub_v3_v3v3(vec, coord, t->viewinv[3]);
- }
- else {
- copy_v3_v3(vec, t->viewinv[2]);
- }
- normalize_v3(vec);
+ if (t->persp != RV3D_ORTHO) {
+ sub_v3_v3v3(vec, coord, t->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(vec, t->viewinv[2]);
+ }
+ normalize_v3(vec);
}
/* ************************** GENERICS **************************** */
-
static void clipMirrorModifier(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->obedit;
- ModifierData *md = ob->modifiers.first;
- float tolerance[3] = {0.0f, 0.0f, 0.0f};
- int axis = 0;
-
- for (; md; md = md->next) {
- if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
- MirrorModifierData *mmd = (MirrorModifierData *) md;
-
- if (mmd->flag & MOD_MIR_CLIPPING) {
- axis = 0;
- if (mmd->flag & MOD_MIR_AXIS_X) {
- axis |= 1;
- tolerance[0] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Y) {
- axis |= 2;
- tolerance[1] = mmd->tolerance;
- }
- if (mmd->flag & MOD_MIR_AXIS_Z) {
- axis |= 4;
- tolerance[2] = mmd->tolerance;
- }
- if (axis) {
- float mtx[4][4], imtx[4][4];
- int i;
-
- if (mmd->mirror_ob) {
- float obinv[4][4];
-
- invert_m4_m4(obinv, mmd->mirror_ob->obmat);
- mul_m4_m4m4(mtx, obinv, ob->obmat);
- invert_m4_m4(imtx, mtx);
- }
-
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- int clip;
- float loc[3], iloc[3];
-
- if (td->flag & TD_NOACTION)
- break;
- if (td->loc == NULL)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- copy_v3_v3(loc, td->loc);
- copy_v3_v3(iloc, td->iloc);
-
- if (mmd->mirror_ob) {
- mul_m4_v3(mtx, loc);
- mul_m4_v3(mtx, iloc);
- }
-
- clip = 0;
- if (axis & 1) {
- if (fabsf(iloc[0]) <= tolerance[0] ||
- loc[0] * iloc[0] < 0.0f)
- {
- loc[0] = 0.0f;
- clip = 1;
- }
- }
-
- if (axis & 2) {
- if (fabsf(iloc[1]) <= tolerance[1] ||
- loc[1] * iloc[1] < 0.0f)
- {
- loc[1] = 0.0f;
- clip = 1;
- }
- }
- if (axis & 4) {
- if (fabsf(iloc[2]) <= tolerance[2] ||
- loc[2] * iloc[2] < 0.0f)
- {
- loc[2] = 0.0f;
- clip = 1;
- }
- }
- if (clip) {
- if (mmd->mirror_ob) {
- mul_m4_v3(imtx, loc);
- }
- copy_v3_v3(td->loc, loc);
- }
- }
- }
-
- }
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->obedit;
+ ModifierData *md = ob->modifiers.first;
+ float tolerance[3] = {0.0f, 0.0f, 0.0f};
+ int axis = 0;
+
+ for (; md; md = md->next) {
+ if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+
+ if (mmd->flag & MOD_MIR_CLIPPING) {
+ axis = 0;
+ if (mmd->flag & MOD_MIR_AXIS_X) {
+ axis |= 1;
+ tolerance[0] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Y) {
+ axis |= 2;
+ tolerance[1] = mmd->tolerance;
+ }
+ if (mmd->flag & MOD_MIR_AXIS_Z) {
+ axis |= 4;
+ tolerance[2] = mmd->tolerance;
+ }
+ if (axis) {
+ float mtx[4][4], imtx[4][4];
+ int i;
+
+ if (mmd->mirror_ob) {
+ float obinv[4][4];
+
+ invert_m4_m4(obinv, mmd->mirror_ob->obmat);
+ mul_m4_m4m4(mtx, obinv, ob->obmat);
+ invert_m4_m4(imtx, mtx);
+ }
+
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ int clip;
+ float loc[3], iloc[3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc == NULL)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ copy_v3_v3(loc, td->loc);
+ copy_v3_v3(iloc, td->iloc);
+
+ if (mmd->mirror_ob) {
+ mul_m4_v3(mtx, loc);
+ mul_m4_v3(mtx, iloc);
+ }
+
+ clip = 0;
+ if (axis & 1) {
+ if (fabsf(iloc[0]) <= tolerance[0] || loc[0] * iloc[0] < 0.0f) {
+ loc[0] = 0.0f;
+ clip = 1;
+ }
+ }
+
+ if (axis & 2) {
+ if (fabsf(iloc[1]) <= tolerance[1] || loc[1] * iloc[1] < 0.0f) {
+ loc[1] = 0.0f;
+ clip = 1;
+ }
+ }
+ if (axis & 4) {
+ if (fabsf(iloc[2]) <= tolerance[2] || loc[2] * iloc[2] < 0.0f) {
+ loc[2] = 0.0f;
+ clip = 1;
+ }
+ }
+ if (clip) {
+ if (mmd->mirror_ob) {
+ mul_m4_v3(imtx, loc);
+ }
+ copy_v3_v3(td->loc, loc);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* assumes obedit set to mesh object */
static void editbmesh_apply_to_mirror(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->mirror.axis_flag) {
- TransData *td = tc->data;
- BMVert *eve;
- int i;
-
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION)
- break;
- if (td->loc == NULL)
- break;
- if (td->flag & TD_SKIP)
- continue;
-
- eve = td->extra;
- if (eve) {
- eve->co[0] = -td->loc[0];
- eve->co[1] = td->loc[1];
- eve->co[2] = td->loc[2];
- }
-
- if (td->flag & TD_MIRROR_EDGE) {
- td->loc[0] = 0;
- }
- }
- }
- }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->mirror.axis_flag) {
+ TransData *td = tc->data;
+ BMVert *eve;
+ int i;
+
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_NOACTION)
+ break;
+ if (td->loc == NULL)
+ break;
+ if (td->flag & TD_SKIP)
+ continue;
+
+ eve = td->extra;
+ if (eve) {
+ eve->co[0] = -td->loc[0];
+ eve->co[1] = td->loc[1];
+ eve->co[2] = td->loc[2];
+ }
+
+ if (td->flag & TD_MIRROR_EDGE) {
+ td->loc[0] = 0;
+ }
+ }
+ }
+ }
}
/* for the realtime animation recording feature, handle overlapping data */
static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
{
- ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
-
- /* sanity checks */
- if (ELEM(NULL, scene, id, sad))
- return;
-
- /* check if we need a new strip if:
- * - if animtimer is running
- * - we're not only keying for available channels
- * - the option to add new actions for each round is not enabled
- */
- if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
- /* if playback has just looped around,
- * we need to add a new NLA track+strip to allow a clean pass to occur */
- if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
- AnimData *adt = BKE_animdata_from_id(id);
- const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
-
- /* perform push-down manually with some differences
- * NOTE: BKE_nla_action_pushdown() sync warning...
- */
- if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
- float astart, aend;
-
- /* only push down if action is more than 1-2 frames long */
- calc_action_range(adt->action, &astart, &aend, 1);
- if (aend > astart + 2.0f) {
- NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
-
- /* clear reference to action now that we've pushed it onto the stack */
- id_us_min(&adt->action->id);
- adt->action = NULL;
-
- /* adjust blending + extend so that they will behave correctly */
- strip->extendmode = NLASTRIP_EXTEND_NOTHING;
- strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
-
- /* copy current "action blending" settings from adt to the strip,
- * as it was keyframed with these settings, so omitting them will
- * change the effect [T54766]
- */
- if (is_first == false) {
- strip->blendmode = adt->act_blendmode;
- strip->influence = adt->act_influence;
-
- if (adt->act_influence < 1.0f) {
- /* enable "user-controlled" influence (which will insert a default keyframe)
- * so that the influence doesn't get lost on the new update
- *
- * NOTE: An alternative way would have been to instead hack the influence
- * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
- * is disabled but auto-blending isn't being used. However, that approach
- * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
- * so it's better to just do it this way.
- */
- strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
- BKE_nlastrip_validate_fcurves(strip);
- }
- }
-
- /* also, adjust the AnimData's action extend mode to be on
- * 'nothing' so that previous result still play
- */
- adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
- }
- }
- }
- }
+ ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, id, sad))
+ return;
+
+ /* check if we need a new strip if:
+ * - if animtimer is running
+ * - we're not only keying for available channels
+ * - the option to add new actions for each round is not enabled
+ */
+ if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 &&
+ (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
+ /* if playback has just looped around,
+ * we need to add a new NLA track+strip to allow a clean pass to occur */
+ if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
+ AnimData *adt = BKE_animdata_from_id(id);
+ const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
+
+ /* perform push-down manually with some differences
+ * NOTE: BKE_nla_action_pushdown() sync warning...
+ */
+ if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
+ float astart, aend;
+
+ /* only push down if action is more than 1-2 frames long */
+ calc_action_range(adt->action, &astart, &aend, 1);
+ if (aend > astart + 2.0f) {
+ NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
+
+ /* clear reference to action now that we've pushed it onto the stack */
+ id_us_min(&adt->action->id);
+ adt->action = NULL;
+
+ /* adjust blending + extend so that they will behave correctly */
+ strip->extendmode = NLASTRIP_EXTEND_NOTHING;
+ strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT |
+ NLASTRIP_FLAG_ACTIVE);
+
+ /* copy current "action blending" settings from adt to the strip,
+ * as it was keyframed with these settings, so omitting them will
+ * change the effect [T54766]
+ */
+ if (is_first == false) {
+ strip->blendmode = adt->act_blendmode;
+ strip->influence = adt->act_influence;
+
+ if (adt->act_influence < 1.0f) {
+ /* enable "user-controlled" influence (which will insert a default keyframe)
+ * so that the influence doesn't get lost on the new update
+ *
+ * NOTE: An alternative way would have been to instead hack the influence
+ * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
+ * is disabled but auto-blending isn't being used. However, that approach
+ * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
+ * so it's better to just do it this way.
+ */
+ strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+ BKE_nlastrip_validate_fcurves(strip);
+ }
+ }
+
+ /* also, adjust the AnimData's action extend mode to be on
+ * 'nothing' so that previous result still play
+ */
+ adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
+ }
+ }
+ }
+ }
}
static bool fcu_test_selected(FCurve *fcu)
{
- BezTriple *bezt = fcu->bezt;
- unsigned int i;
+ BezTriple *bezt = fcu->bezt;
+ unsigned int i;
- if (bezt == NULL) /* ignore baked */
- return 0;
+ if (bezt == NULL) /* ignore baked */
+ return 0;
- for (i = 0; i < fcu->totvert; i++, bezt++) {
- if (BEZT_ISSEL_ANY(bezt)) return 1;
- }
+ for (i = 0; i < fcu->totvert; i++, bezt++) {
+ if (BEZT_ISSEL_ANY(bezt))
+ return 1;
+ }
- return 0;
+ return 0;
}
/* helper for recalcData() - for Action Editor transforms */
static void recalcData_actedit(TransInfo *t)
{
- ViewLayer *view_layer = t->view_layer;
- SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
- /* initialize relevant anim-context 'context' data from TransInfo data */
- /* NOTE: sync this with the code in ANIM_animdata_get_context() */
- ac.bmain = CTX_data_main(t->context);
- ac.scene = t->scene;
- ac.view_layer = t->view_layer;
- ac.obact = OBACT(view_layer);
- ac.sa = t->sa;
- ac.ar = t->ar;
- ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
- ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
- ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
-
- ANIM_animdata_context_getdata(&ac);
-
- /* perform flush */
- if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
- /* flush transform values back to actual coordinates */
- flushTransIntFrameActionData(t);
- }
-
- if (ac.datatype != ANIMCONT_MASK) {
- /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* just tag these animdata-blocks to recalc, assuming that some data there changed
- * BUT only do this if realtime updates are enabled
- */
- if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
- for (ale = anim_data.first; ale; ale = ale->next) {
- /* set refresh tags for objects using this animation */
- ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
- }
- }
-
- /* now free temp channels */
- ANIM_animdata_freelist(&anim_data);
- }
+ ViewLayer *view_layer = t->view_layer;
+ SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
+
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* initialize relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ ac.bmain = CTX_data_main(t->context);
+ ac.scene = t->scene;
+ ac.view_layer = t->view_layer;
+ ac.obact = OBACT(view_layer);
+ ac.sa = t->sa;
+ ac.ar = t->ar;
+ ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
+ ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
+ ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
+
+ ANIM_animdata_context_getdata(&ac);
+
+ /* perform flush */
+ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+ /* flush transform values back to actual coordinates */
+ flushTransIntFrameActionData(t);
+ }
+
+ if (ac.datatype != ANIMCONT_MASK) {
+ /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* just tag these animdata-blocks to recalc, assuming that some data there changed
+ * BUT only do this if realtime updates are enabled
+ */
+ if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* set refresh tags for objects using this animation */
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
+ }
+ }
+
+ /* now free temp channels */
+ ANIM_animdata_freelist(&anim_data);
+ }
}
/* helper for recalcData() - for Graph Editor transforms */
static void recalcData_graphedit(TransInfo *t)
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- ViewLayer *view_layer = t->view_layer;
-
- ListBase anim_data = {NULL, NULL};
- bAnimContext ac = {NULL};
- int filter;
-
- bAnimListElem *ale;
- int dosort = 0;
-
- /* initialize relevant anim-context 'context' data from TransInfo data */
- /* NOTE: sync this with the code in ANIM_animdata_get_context() */
- ac.bmain = CTX_data_main(t->context);
- ac.scene = t->scene;
- ac.view_layer = t->view_layer;
- ac.obact = OBACT(view_layer);
- ac.sa = t->sa;
- ac.ar = t->ar;
- ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
- ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
- ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
-
- ANIM_animdata_context_getdata(&ac);
-
- /* do the flush first */
- flushTransGraphData(t);
-
- /* get curves to check if a re-sort is needed */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* now test if there is a need to re-sort */
- for (ale = anim_data.first; ale; ale = ale->next) {
- FCurve *fcu = (FCurve *)ale->key_data;
-
- /* ignore FC-Curves without any selected verts */
- if (!fcu_test_selected(fcu))
- continue;
-
- /* watch it: if the time is wrong: do not correct handles yet */
- if (test_time_fcurve(fcu))
- dosort++;
- else
- calchandles_fcurve(fcu);
-
- /* set refresh tags for objects using this animation,
- * BUT only if realtime updates are enabled
- */
- if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
- ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
- }
-
- /* do resort and other updates? */
- if (dosort) remake_graph_transdata(t, &anim_data);
-
- /* now free temp channels */
- ANIM_animdata_freelist(&anim_data);
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ ViewLayer *view_layer = t->view_layer;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimContext ac = {NULL};
+ int filter;
+
+ bAnimListElem *ale;
+ int dosort = 0;
+
+ /* initialize relevant anim-context 'context' data from TransInfo data */
+ /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+ ac.bmain = CTX_data_main(t->context);
+ ac.scene = t->scene;
+ ac.view_layer = t->view_layer;
+ ac.obact = OBACT(view_layer);
+ ac.sa = t->sa;
+ ac.ar = t->ar;
+ ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
+ ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
+ ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
+
+ ANIM_animdata_context_getdata(&ac);
+
+ /* do the flush first */
+ flushTransGraphData(t);
+
+ /* get curves to check if a re-sort is needed */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* now test if there is a need to re-sort */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->key_data;
+
+ /* ignore FC-Curves without any selected verts */
+ if (!fcu_test_selected(fcu))
+ continue;
+
+ /* watch it: if the time is wrong: do not correct handles yet */
+ if (test_time_fcurve(fcu))
+ dosort++;
+ else
+ calchandles_fcurve(fcu);
+
+ /* set refresh tags for objects using this animation,
+ * BUT only if realtime updates are enabled
+ */
+ if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
+ ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
+ }
+
+ /* do resort and other updates? */
+ if (dosort)
+ remake_graph_transdata(t, &anim_data);
+
+ /* now free temp channels */
+ ANIM_animdata_freelist(&anim_data);
}
/* helper for recalcData() - for NLA Editor transforms */
static void recalcData_nla(TransInfo *t)
{
- SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
- Scene *scene = t->scene;
- double secf = FPS;
- int i;
-
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- TransDataNla *tdn = tc->custom.type.data;
-
- /* for each strip we've got, perform some additional validation of the values that got set before
- * using RNA to set the value (which does some special operations when setting these values to make
- * sure that everything works ok)
- */
- for (i = 0; i < tc->data_len; i++, tdn++) {
- NlaStrip *strip = tdn->strip;
- PointerRNA strip_ptr;
- short pExceeded, nExceeded, iter;
- int delta_y1, delta_y2;
-
- /* if this tdn has no handles, that means it is just a dummy that should be skipped */
- if (tdn->handle == 0)
- continue;
-
- /* set refresh tags for objects using this animation,
- * BUT only if realtime updates are enabled
- */
- if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
- ANIM_id_update(CTX_data_main(t->context), tdn->id);
-
- /* if canceling transform, just write the values without validating, then move on */
- if (t->state == TRANS_CANCEL) {
- /* clear the values by directly overwriting the originals, but also need to restore
- * endpoints of neighboring transition-strips
- */
-
- /* start */
- strip->start = tdn->h1[0];
-
- if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
- strip->prev->end = tdn->h1[0];
-
- /* end */
- strip->end = tdn->h2[0];
-
- if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
- strip->next->start = tdn->h2[0];
-
- /* flush transforms to child strips (since this should be a meta) */
- BKE_nlameta_flush_transforms(strip);
-
- /* restore to original track (if needed) */
- if (tdn->oldTrack != tdn->nlt) {
- /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
- BLI_remlink(&tdn->nlt->strips, strip);
- BLI_addtail(&tdn->oldTrack->strips, strip);
- }
-
- continue;
- }
-
- /* firstly, check if the proposed transform locations would overlap with any neighboring strips
- * (barring transitions) which are absolute barriers since they are not being moved
- *
- * this is done as a iterative procedure (done 5 times max for now)
- */
- for (iter = 0; iter < 5; iter++) {
- pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
- nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
-
- if ((pExceeded && nExceeded) || (iter == 4)) {
- /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
- * - simply crop strip to fit within the bounds of the strips bounding it
- * - if there were no neighbors, clear the transforms (make it default to the strip's current values)
- */
- if (strip->prev && strip->next) {
- tdn->h1[0] = strip->prev->end;
- tdn->h2[0] = strip->next->start;
- }
- else {
- tdn->h1[0] = strip->start;
- tdn->h2[0] = strip->end;
- }
- }
- else if (nExceeded) {
- /* move backwards */
- float offset = tdn->h2[0] - strip->next->start;
-
- tdn->h1[0] -= offset;
- tdn->h2[0] -= offset;
- }
- else if (pExceeded) {
- /* more forwards */
- float offset = strip->prev->end - tdn->h1[0];
-
- tdn->h1[0] += offset;
- tdn->h2[0] += offset;
- }
- else /* all is fine and well */
- break;
- }
-
- /* handle auto-snapping
- * NOTE: only do this when transform is still running, or we can't restore
- */
- if (t->state != TRANS_CANCEL) {
- switch (snla->autosnap) {
- case SACTSNAP_FRAME: /* snap to nearest frame */
- case SACTSNAP_STEP: /* frame step - this is basically the same,
- * since we don't have any remapping going on */
- {
- tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
- tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
- break;
- }
-
- case SACTSNAP_SECOND: /* snap to nearest second */
- case SACTSNAP_TSTEP: /* second step - this is basically the same,
- * since we don't have any remapping going on */
- {
- /* This case behaves differently from the rest, since lengths of strips
- * may not be multiples of a second. If we just naively resize adjust
- * the handles, things may not work correctly. Instead, we only snap
- * the first handle, and move the other to fit.
- *
- * FIXME: we do run into problems here when user attempts to negatively
- * scale the strip, as it then just compresses down and refuses
- * to expand out the other end.
- */
- float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
- float delta = h1_new - tdn->h1[0];
-
- tdn->h1[0] = h1_new;
- tdn->h2[0] += delta;
- break;
- }
-
- case SACTSNAP_MARKER: /* snap to nearest marker */
- {
- tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
- tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
- break;
- }
- }
- }
-
- /* Use RNA to write the values to ensure that constraints on these are obeyed
- * (e.g. for transition strips, the values are taken from the neighbors)
- *
- * NOTE: we write these twice to avoid truncation errors which can arise when
- * moving the strips a large distance using numeric input [#33852]
- */
- RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
-
- RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
- RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
-
- RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
- RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
-
- /* flush transforms to child strips (since this should be a meta) */
- BKE_nlameta_flush_transforms(strip);
-
-
- /* now, check if we need to try and move track
- * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
- */
- delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
- delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
-
- if (delta_y1 || delta_y2) {
- NlaTrack *track;
- int delta = (delta_y2) ? delta_y2 : delta_y1;
- int n;
-
- /* move in the requested direction, checking at each layer if there's space for strip to pass through,
- * stopping on the last track available or that we're able to fit in
- */
- if (delta > 0) {
- for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
- /* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
- /* move strip to this track */
- BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
-
- tdn->nlt = track;
- tdn->trackIndex++;
- }
- else /* can't move any further */
- break;
- }
- }
- else {
- /* make delta 'positive' before using it, since we now know to go backwards */
- delta = -delta;
-
- for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
- /* check if space in this track for the strip */
- if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
- /* move strip to this track */
- BLI_remlink(&tdn->nlt->strips, strip);
- BKE_nlatrack_add_strip(track, strip);
-
- tdn->nlt = track;
- tdn->trackIndex--;
- }
- else /* can't move any further */
- break;
- }
- }
- }
- }
+ SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+ double secf = FPS;
+ int i;
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataNla *tdn = tc->custom.type.data;
+
+ /* for each strip we've got, perform some additional validation of the values that got set before
+ * using RNA to set the value (which does some special operations when setting these values to make
+ * sure that everything works ok)
+ */
+ for (i = 0; i < tc->data_len; i++, tdn++) {
+ NlaStrip *strip = tdn->strip;
+ PointerRNA strip_ptr;
+ short pExceeded, nExceeded, iter;
+ int delta_y1, delta_y2;
+
+ /* if this tdn has no handles, that means it is just a dummy that should be skipped */
+ if (tdn->handle == 0)
+ continue;
+
+ /* set refresh tags for objects using this animation,
+ * BUT only if realtime updates are enabled
+ */
+ if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
+ ANIM_id_update(CTX_data_main(t->context), tdn->id);
+
+ /* if canceling transform, just write the values without validating, then move on */
+ if (t->state == TRANS_CANCEL) {
+ /* clear the values by directly overwriting the originals, but also need to restore
+ * endpoints of neighboring transition-strips
+ */
+
+ /* start */
+ strip->start = tdn->h1[0];
+
+ if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
+ strip->prev->end = tdn->h1[0];
+
+ /* end */
+ strip->end = tdn->h2[0];
+
+ if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
+ strip->next->start = tdn->h2[0];
+
+ /* flush transforms to child strips (since this should be a meta) */
+ BKE_nlameta_flush_transforms(strip);
+
+ /* restore to original track (if needed) */
+ if (tdn->oldTrack != tdn->nlt) {
+ /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BLI_addtail(&tdn->oldTrack->strips, strip);
+ }
+
+ continue;
+ }
+
+ /* firstly, check if the proposed transform locations would overlap with any neighboring strips
+ * (barring transitions) which are absolute barriers since they are not being moved
+ *
+ * this is done as a iterative procedure (done 5 times max for now)
+ */
+ for (iter = 0; iter < 5; iter++) {
+ pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) &&
+ (tdn->h1[0] < strip->prev->end));
+ nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) &&
+ (tdn->h2[0] > strip->next->start));
+
+ if ((pExceeded && nExceeded) || (iter == 4)) {
+ /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
+ * - simply crop strip to fit within the bounds of the strips bounding it
+ * - if there were no neighbors, clear the transforms (make it default to the strip's current values)
+ */
+ if (strip->prev && strip->next) {
+ tdn->h1[0] = strip->prev->end;
+ tdn->h2[0] = strip->next->start;
+ }
+ else {
+ tdn->h1[0] = strip->start;
+ tdn->h2[0] = strip->end;
+ }
+ }
+ else if (nExceeded) {
+ /* move backwards */
+ float offset = tdn->h2[0] - strip->next->start;
+
+ tdn->h1[0] -= offset;
+ tdn->h2[0] -= offset;
+ }
+ else if (pExceeded) {
+ /* more forwards */
+ float offset = strip->prev->end - tdn->h1[0];
+
+ tdn->h1[0] += offset;
+ tdn->h2[0] += offset;
+ }
+ else /* all is fine and well */
+ break;
+ }
+
+ /* handle auto-snapping
+ * NOTE: only do this when transform is still running, or we can't restore
+ */
+ if (t->state != TRANS_CANCEL) {
+ switch (snla->autosnap) {
+ case SACTSNAP_FRAME: /* snap to nearest frame */
+ case SACTSNAP_STEP: /* frame step - this is basically the same,
+ * since we don't have any remapping going on */
+ {
+ tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
+ tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
+ break;
+ }
+
+ case SACTSNAP_SECOND: /* snap to nearest second */
+ case SACTSNAP_TSTEP: /* second step - this is basically the same,
+ * since we don't have any remapping going on */
+ {
+ /* This case behaves differently from the rest, since lengths of strips
+ * may not be multiples of a second. If we just naively resize adjust
+ * the handles, things may not work correctly. Instead, we only snap
+ * the first handle, and move the other to fit.
+ *
+ * FIXME: we do run into problems here when user attempts to negatively
+ * scale the strip, as it then just compresses down and refuses
+ * to expand out the other end.
+ */
+ float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
+ float delta = h1_new - tdn->h1[0];
+
+ tdn->h1[0] = h1_new;
+ tdn->h2[0] += delta;
+ break;
+ }
+
+ case SACTSNAP_MARKER: /* snap to nearest marker */
+ {
+ tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
+ tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
+ break;
+ }
+ }
+ }
+
+ /* Use RNA to write the values to ensure that constraints on these are obeyed
+ * (e.g. for transition strips, the values are taken from the neighbors)
+ *
+ * NOTE: we write these twice to avoid truncation errors which can arise when
+ * moving the strips a large distance using numeric input [#33852]
+ */
+ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
+
+ RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
+ RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+
+ RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
+ RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+
+ /* flush transforms to child strips (since this should be a meta) */
+ BKE_nlameta_flush_transforms(strip);
+
+ /* now, check if we need to try and move track
+ * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
+ */
+ delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
+ delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
+
+ if (delta_y1 || delta_y2) {
+ NlaTrack *track;
+ int delta = (delta_y2) ? delta_y2 : delta_y1;
+ int n;
+
+ /* move in the requested direction, checking at each layer if there's space for strip to pass through,
+ * stopping on the last track available or that we're able to fit in
+ */
+ if (delta > 0) {
+ for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
+ /* check if space in this track for the strip */
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ /* move strip to this track */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BKE_nlatrack_add_strip(track, strip);
+
+ tdn->nlt = track;
+ tdn->trackIndex++;
+ }
+ else /* can't move any further */
+ break;
+ }
+ }
+ else {
+ /* make delta 'positive' before using it, since we now know to go backwards */
+ delta = -delta;
+
+ for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
+ /* check if space in this track for the strip */
+ if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
+ /* move strip to this track */
+ BLI_remlink(&tdn->nlt->strips, strip);
+ BKE_nlatrack_add_strip(track, strip);
+
+ tdn->nlt = track;
+ tdn->trackIndex--;
+ }
+ else /* can't move any further */
+ break;
+ }
+ }
+ }
+ }
}
static void recalcData_mask_common(TransInfo *t)
{
- Mask *mask = CTX_data_edit_mask(t->context);
+ Mask *mask = CTX_data_edit_mask(t->context);
- flushTransMasking(t);
+ flushTransMasking(t);
- DEG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
}
/* helper for recalcData() - for Image Editor transforms */
static void recalcData_image(TransInfo *t)
{
- if (t->options & CTX_MASK) {
- recalcData_mask_common(t);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- flushTransPaintCurve(t);
- }
- else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
- SpaceImage *sima = t->sa->spacedata.first;
-
- flushTransUVs(t);
- if (sima->flag & SI_LIVE_UNWRAP)
- ED_uvedit_live_unwrap_re_solve();
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0);
- }
- }
- }
+ if (t->options & CTX_MASK) {
+ recalcData_mask_common(t);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
+ else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
+ SpaceImage *sima = t->sa->spacedata.first;
+
+ flushTransUVs(t);
+ if (sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_re_solve();
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len) {
+ DEG_id_tag_update(tc->obedit->data, 0);
+ }
+ }
+ }
}
/* helper for recalcData() - for Movie Clip transforms */
static void recalcData_spaceclip(TransInfo *t)
{
- SpaceClip *sc = t->sa->spacedata.first;
-
- if (ED_space_clip_check_show_trackedit(sc)) {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- int framenr = ED_space_clip_get_clip_frame_number(sc);
-
- flushTransTracking(t);
-
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
-
- if (t->mode == TFM_TRANSLATION) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
- }
- else if (t->mode == TFM_RESIZE) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
- BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
- }
- else if (t->mode == TFM_ROTATION) {
- if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
- BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
- }
- }
-
- track = track->next;
- }
-
- DEG_id_tag_update(&clip->id, 0);
- }
- else if (t->options & CTX_MASK) {
- recalcData_mask_common(t);
- }
+ SpaceClip *sc = t->sa->spacedata.first;
+
+ if (ED_space_clip_check_show_trackedit(sc)) {
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ MovieTrackingTrack *track;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ flushTransTracking(t);
+
+ track = tracksbase->first;
+ while (track) {
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+
+ if (t->mode == TFM_TRANSLATION) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+ BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
+ }
+ else if (t->mode == TFM_RESIZE) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+ BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
+ }
+ else if (t->mode == TFM_ROTATION) {
+ if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+ BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
+ }
+ }
+
+ track = track->next;
+ }
+
+ DEG_id_tag_update(&clip->id, 0);
+ }
+ else if (t->options & CTX_MASK) {
+ recalcData_mask_common(t);
+ }
}
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
- Base *base = t->view_layer->basact;
-
- if (t->obedit_type != -1) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
-
- if (t->state != TRANS_CANCEL) {
- clipMirrorModifier(t);
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Curve *cu = tc->obedit->data;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- Nurb *nu = nurbs->first;
-
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
-
- if (t->state == TRANS_CANCEL) {
- while (nu) {
- /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
- BKE_nurb_handles_calc(nu);
- nu = nu->next;
- }
- }
- else {
- /* Normal updating */
- while (nu) {
- BKE_nurb_test_2d(nu);
- BKE_nurb_handles_calc(nu);
- nu = nu->next;
- }
- }
- }
- }
- else if (t->obedit_type == OB_LATTICE) {
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Lattice *la = tc->obedit->data;
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- if (la->editlatt->latt->flag & LT_OUTSIDE) {
- outside_lattice(la->editlatt->latt);
- }
- }
- }
- else if (t->obedit_type == OB_MESH) {
- /* mirror modifier clipping? */
- if (t->state != TRANS_CANCEL) {
- /* apply clipping after so we never project past the clip plane [#25423] */
- applyProject(t);
- clipMirrorModifier(t);
- }
- if ((t->flag & T_NO_MIRROR) == 0 &&
- (t->options & CTX_NO_MIRROR) == 0)
- {
- editbmesh_apply_to_mirror(t);
- }
-
- if (t->mode == TFM_EDGE_SLIDE) {
- projectEdgeSlideData(t, false);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- projectVertSlideData(t, false);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
- }
- }
- else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- bArmature *arm = tc->obedit->data;
- ListBase *edbo = arm->edbo;
- EditBone *ebo, *ebo_parent;
- TransData *td = tc->data;
- int i;
-
- /* Ensure all bones are correctly adjusted */
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
-
- if (ebo_parent) {
- /* If this bone has a parent tip that has been moved */
- if (ebo_parent->flag & BONE_TIPSEL) {
- copy_v3_v3(ebo->head, ebo_parent->tail);
- if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo_parent->rad_tail;
- }
- /* If this bone has a parent tip that has NOT been moved */
- else {
- copy_v3_v3(ebo_parent->tail, ebo->head);
- if (t->mode == TFM_BONE_ENVELOPE) ebo_parent->rad_tail = ebo->rad_head;
- }
- }
-
- /* on extrude bones, oldlength==0.0f, so we scale radius of points */
- ebo->length = len_v3v3(ebo->head, ebo->tail);
- if (ebo->oldlength == 0.0f) {
- ebo->rad_head = 0.25f * ebo->length;
- ebo->rad_tail = 0.10f * ebo->length;
- ebo->dist = 0.25f * ebo->length;
- if (ebo->parent) {
- if (ebo->rad_head > ebo->parent->rad_tail)
- ebo->rad_head = ebo->parent->rad_tail;
- }
- }
- else if (t->mode != TFM_BONE_ENVELOPE) {
- /* if bones change length, lets do that for the deform distance as well */
- ebo->dist *= ebo->length / ebo->oldlength;
- 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_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
- /* fix roll */
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->extra) {
- float vec[3], up_axis[3];
- float qrot[4];
- float roll;
-
- ebo = td->extra;
-
- if (t->state == TRANS_CANCEL) {
- /* restore roll */
- ebo->roll = td->ival;
- }
- else {
- copy_v3_v3(up_axis, td->axismtx[2]);
-
- sub_v3_v3v3(vec, ebo->tail, ebo->head);
- normalize_v3(vec);
- rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
- mul_qt_v3(qrot, up_axis);
-
- /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
- roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
- ebo->roll = angle_compat_rad(roll, td->ival);
- }
- }
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- if (t->state != TRANS_CANCEL) {
- ED_armature_edit_transform_mirror_update(tc->obedit);
- }
- else {
- restoreBones(tc);
- }
- }
- }
- }
- else {
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->data_len) {
- DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
- }
- }
- }
-
- }
- else if (t->flag & T_POSE) {
- GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- Object *ob = tc->poseobj;
- bArmature *arm = ob->data;
-
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. un-editable animation values)
- *
- * context is needed for keying set poll() functions.
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
- int targetless_ik = (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
-
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
- }
-
- if (motionpath_need_update_pose(t->scene, ob)) {
- BLI_gset_insert(motionpath_updates, ob);
- }
-
- /* old optimize trick... this enforces to bypass the depgraph */
- if (!(arm->flag & ARM_DELAYDEFORM)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
- /* transformation of pose may affect IK tree, make sure it is rebuilt */
- BIK_clear_data(ob->pose);
- }
- else {
- BKE_pose_where_is(t->depsgraph, t->scene, ob);
- }
- }
-
- /* Update motion paths once for all transformed bones in an object. */
- GSetIterator gs_iter;
- GSET_ITER (gs_iter, motionpath_updates) {
- Object *ob = BLI_gsetIterator_getKey(&gs_iter);
- ED_pose_recalculate_paths(t->context, t->scene, ob, true);
- }
- BLI_gset_free(motionpath_updates, NULL);
- }
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, base->object))
- {
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- flushTransParticles(t);
- }
- else {
- bool motionpath_update = false;
-
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
-
- for (int i = 0; i < tc->data_len; i++, td++) {
- Object *ob = td->ob;
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- /* if animtimer is running, and the object already has animation data,
- * check if the auto-record feature means that we should record 'samples'
- * (i.e. uneditable animation values)
- */
- // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
- animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
- }
-
- motionpath_update |= motionpath_need_update_object(t->scene, ob);
-
- /* sets recalc flags fully, instead of flushing existing ones
- * otherwise proxies don't function correctly
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
-
- if (t->flag & T_TEXTURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
-
- if (motionpath_update) {
- /* Update motion paths once for all transformed objects. */
- ED_objects_recalculate_paths(t->context, t->scene, true);
- }
- }
+ Base *base = t->view_layer->basact;
+
+ if (t->obedit_type != -1) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
+
+ if (t->state != TRANS_CANCEL) {
+ clipMirrorModifier(t);
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Curve *cu = tc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ Nurb *nu = nurbs->first;
+
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+
+ if (t->state == TRANS_CANCEL) {
+ while (nu) {
+ /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
+ BKE_nurb_handles_calc(nu);
+ nu = nu->next;
+ }
+ }
+ else {
+ /* Normal updating */
+ while (nu) {
+ BKE_nurb_test_2d(nu);
+ BKE_nurb_handles_calc(nu);
+ nu = nu->next;
+ }
+ }
+ }
+ }
+ else if (t->obedit_type == OB_LATTICE) {
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Lattice *la = tc->obedit->data;
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ if (la->editlatt->latt->flag & LT_OUTSIDE) {
+ outside_lattice(la->editlatt->latt);
+ }
+ }
+ }
+ else if (t->obedit_type == OB_MESH) {
+ /* mirror modifier clipping? */
+ if (t->state != TRANS_CANCEL) {
+ /* apply clipping after so we never project past the clip plane [#25423] */
+ applyProject(t);
+ clipMirrorModifier(t);
+ }
+ if ((t->flag & T_NO_MIRROR) == 0 && (t->options & CTX_NO_MIRROR) == 0) {
+ editbmesh_apply_to_mirror(t);
+ }
+
+ if (t->mode == TFM_EDGE_SLIDE) {
+ projectEdgeSlideData(t, false);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ projectVertSlideData(t, false);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+ }
+ }
+ else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ bArmature *arm = tc->obedit->data;
+ ListBase *edbo = arm->edbo;
+ EditBone *ebo, *ebo_parent;
+ TransData *td = tc->data;
+ int i;
+
+ /* Ensure all bones are correctly adjusted */
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
+
+ if (ebo_parent) {
+ /* If this bone has a parent tip that has been moved */
+ if (ebo_parent->flag & BONE_TIPSEL) {
+ copy_v3_v3(ebo->head, ebo_parent->tail);
+ if (t->mode == TFM_BONE_ENVELOPE)
+ ebo->rad_head = ebo_parent->rad_tail;
+ }
+ /* If this bone has a parent tip that has NOT been moved */
+ else {
+ copy_v3_v3(ebo_parent->tail, ebo->head);
+ if (t->mode == TFM_BONE_ENVELOPE)
+ ebo_parent->rad_tail = ebo->rad_head;
+ }
+ }
+
+ /* on extrude bones, oldlength==0.0f, so we scale radius of points */
+ ebo->length = len_v3v3(ebo->head, ebo->tail);
+ if (ebo->oldlength == 0.0f) {
+ ebo->rad_head = 0.25f * ebo->length;
+ ebo->rad_tail = 0.10f * ebo->length;
+ ebo->dist = 0.25f * ebo->length;
+ if (ebo->parent) {
+ if (ebo->rad_head > ebo->parent->rad_tail)
+ ebo->rad_head = ebo->parent->rad_tail;
+ }
+ }
+ else if (t->mode != TFM_BONE_ENVELOPE) {
+ /* if bones change length, lets do that for the deform distance as well */
+ ebo->dist *= ebo->length / ebo->oldlength;
+ 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_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
+ /* fix roll */
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->extra) {
+ float vec[3], up_axis[3];
+ float qrot[4];
+ float roll;
+
+ ebo = td->extra;
+
+ if (t->state == TRANS_CANCEL) {
+ /* restore roll */
+ ebo->roll = td->ival;
+ }
+ else {
+ copy_v3_v3(up_axis, td->axismtx[2]);
+
+ sub_v3_v3v3(vec, ebo->tail, ebo->head);
+ normalize_v3(vec);
+ rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
+ mul_qt_v3(qrot, up_axis);
+
+ /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
+ roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
+ ebo->roll = angle_compat_rad(roll, td->ival);
+ }
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ ED_armature_edit_transform_mirror_update(tc->obedit);
+ }
+ else {
+ restoreBones(tc);
+ }
+ }
+ }
+ }
+ else {
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->data_len) {
+ DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
+ }
+ }
+ }
+ }
+ else if (t->flag & T_POSE) {
+ GSet *motionpath_updates = BLI_gset_ptr_new("motionpath updates");
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ Object *ob = tc->poseobj;
+ bArmature *arm = ob->data;
+
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. un-editable animation values)
+ *
+ * context is needed for keying set poll() functions.
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
+ int targetless_ik =
+ (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
+
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_pose(t->context, t->scene, ob, t->mode, targetless_ik);
+ }
+
+ if (motionpath_need_update_pose(t->scene, ob)) {
+ BLI_gset_insert(motionpath_updates, ob);
+ }
+
+ /* old optimize trick... this enforces to bypass the depgraph */
+ if (!(arm->flag & ARM_DELAYDEFORM)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* sets recalc flags */
+ /* transformation of pose may affect IK tree, make sure it is rebuilt */
+ BIK_clear_data(ob->pose);
+ }
+ else {
+ BKE_pose_where_is(t->depsgraph, t->scene, ob);
+ }
+ }
+
+ /* Update motion paths once for all transformed bones in an object. */
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, motionpath_updates) {
+ Object *ob = BLI_gsetIterator_getKey(&gs_iter);
+ ED_pose_recalculate_paths(t->context, t->scene, ob, true);
+ }
+ BLI_gset_free(motionpath_updates, NULL);
+ }
+ else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
+ PE_get_current(t->scene, base->object)) {
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+ flushTransParticles(t);
+ }
+ else {
+ bool motionpath_update = false;
+
+ if (t->state != TRANS_CANCEL) {
+ applyProject(t);
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ Object *ob = td->ob;
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ /* if animtimer is running, and the object already has animation data,
+ * check if the auto-record feature means that we should record 'samples'
+ * (i.e. uneditable animation values)
+ */
+ // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
+ animrecord_check_state(t->scene, &ob->id, t->animtimer);
+ autokeyframe_object(t->context, t->scene, t->view_layer, ob, t->mode);
+ }
+
+ motionpath_update |= motionpath_need_update_object(t->scene, ob);
+
+ /* sets recalc flags fully, instead of flushing existing ones
+ * otherwise proxies don't function correctly
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ if (t->flag & T_TEXTURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ if (motionpath_update) {
+ /* Update motion paths once for all transformed objects. */
+ ED_objects_recalculate_paths(t->context, t->scene, true);
+ }
+ }
}
static void recalcData_cursor(TransInfo *t)
{
- DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&t->scene->id, ID_RECALC_COPY_ON_WRITE);
}
/* helper for recalcData() - for sequencer transforms */
static void recalcData_sequencer(TransInfo *t)
{
- TransData *td;
- int a;
- Sequence *seq_prev = NULL;
+ TransData *td;
+ int a;
+ Sequence *seq_prev = NULL;
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
- for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
- TransDataSeq *tdsq = (TransDataSeq *) td->extra;
- Sequence *seq = tdsq->seq;
+ for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
+ TransDataSeq *tdsq = (TransDataSeq *)td->extra;
+ Sequence *seq = tdsq->seq;
- if (seq != seq_prev) {
- if (BKE_sequence_tx_fullupdate_test(seq)) {
- /* A few effect strip types need a complete recache on transform. */
- BKE_sequence_invalidate_cache(t->scene, seq);
- }
- else {
- BKE_sequence_invalidate_dependent(t->scene, seq);
- }
- }
+ if (seq != seq_prev) {
+ if (BKE_sequence_tx_fullupdate_test(seq)) {
+ /* A few effect strip types need a complete recache on transform. */
+ BKE_sequence_invalidate_cache(t->scene, seq);
+ }
+ else {
+ BKE_sequence_invalidate_dependent(t->scene, seq);
+ }
+ }
- seq_prev = seq;
- }
+ seq_prev = seq;
+ }
- BKE_sequencer_preprocessed_cache_cleanup();
+ BKE_sequencer_preprocessed_cache_cleanup();
- flushTransSeq(t);
+ flushTransSeq(t);
}
/* force recalculation of triangles during transformation */
static void recalcData_gpencil_strokes(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- TransData *td = tc->data;
- for (int i = 0; i < tc->data_len; i++, td++) {
- bGPDstroke *gps = td->extra;
- if (gps != NULL) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- }
- }
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ TransData *td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ bGPDstroke *gps = td->extra;
+ if (gps != NULL) {
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ }
+ }
}
/* called for updating while transform acts, once per redraw */
void recalcData(TransInfo *t)
{
- /* if tests must match createTransData for correct updates */
- if (t->options & CTX_CURSOR) {
- recalcData_cursor(t);
- }
- else if (t->options & CTX_TEXTURE) {
- recalcData_objects(t);
- }
- else if (t->options & CTX_EDGE) {
- recalcData_objects(t);
- }
- else if (t->options & CTX_PAINT_CURVE) {
- flushTransPaintCurve(t);
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- /* set recalc triangle cache flag */
- recalcData_gpencil_strokes(t);
- }
- else if (t->spacetype == SPACE_IMAGE) {
- recalcData_image(t);
- }
- else if (t->spacetype == SPACE_ACTION) {
- recalcData_actedit(t);
- }
- else if (t->spacetype == SPACE_NLA) {
- recalcData_nla(t);
- }
- else if (t->spacetype == SPACE_SEQ) {
- recalcData_sequencer(t);
- }
- else if (t->spacetype == SPACE_GRAPH) {
- recalcData_graphedit(t);
- }
- else if (t->spacetype == SPACE_NODE) {
- flushTransNodes(t);
- }
- else if (t->spacetype == SPACE_CLIP) {
- recalcData_spaceclip(t);
- }
- else {
- recalcData_objects(t);
- }
+ /* if tests must match createTransData for correct updates */
+ if (t->options & CTX_CURSOR) {
+ recalcData_cursor(t);
+ }
+ else if (t->options & CTX_TEXTURE) {
+ recalcData_objects(t);
+ }
+ else if (t->options & CTX_EDGE) {
+ recalcData_objects(t);
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ /* set recalc triangle cache flag */
+ recalcData_gpencil_strokes(t);
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ recalcData_image(t);
+ }
+ else if (t->spacetype == SPACE_ACTION) {
+ recalcData_actedit(t);
+ }
+ else if (t->spacetype == SPACE_NLA) {
+ recalcData_nla(t);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ recalcData_sequencer(t);
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ recalcData_graphedit(t);
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ flushTransNodes(t);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ recalcData_spaceclip(t);
+ }
+ else {
+ recalcData_objects(t);
+ }
}
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
{
- float v1[3], v2[3], v3[3];
- unsigned char col[3], col2[3];
+ float v1[3], v2[3], v3[3];
+ unsigned char col[3], col2[3];
- if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = t->view;
+ if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = t->view;
- GPU_matrix_push();
+ GPU_matrix_push();
- copy_v3_v3(v3, dir);
- mul_v3_fl(v3, v3d->clip_end);
+ copy_v3_v3(v3, dir);
+ mul_v3_fl(v3, v3d->clip_end);
- sub_v3_v3v3(v2, center, v3);
- add_v3_v3v3(v1, center, v3);
+ sub_v3_v3v3(v2, center, v3);
+ add_v3_v3v3(v1, center, v3);
- if (options & DRAWLIGHT) {
- col[0] = col[1] = col[2] = 220;
- }
- else {
- UI_GetThemeColor3ubv(TH_GRID, col);
- }
- UI_make_axis_color(col, col2, axis);
+ if (options & DRAWLIGHT) {
+ col[0] = col[1] = col[2] = 220;
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ }
+ UI_make_axis_color(col, col2, axis);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3ubv(col2);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col2);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v2);
- immEnd();
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
- immUnbindProgram();
+ immUnbindProgram();
- GPU_matrix_pop();
- }
+ GPU_matrix_pop();
+ }
}
/**
@@ -1177,94 +1184,96 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
*/
void resetTransModal(TransInfo *t)
{
- freeTransCustomDataForMode(t);
+ freeTransCustomDataForMode(t);
}
void resetTransRestrictions(TransInfo *t)
{
- t->flag &= ~T_ALL_RESTRICTIONS;
+ t->flag &= ~T_ALL_RESTRICTIONS;
}
static int initTransInfo_edit_pet_to_flag(const int proportional)
{
- switch (proportional) {
- case PROP_EDIT_ON:
- return T_PROP_EDIT;
- case PROP_EDIT_CONNECTED:
- return T_PROP_EDIT | T_PROP_CONNECTED;
- case PROP_EDIT_PROJECTED:
- return T_PROP_EDIT | T_PROP_PROJECTED;
- default:
- return 0;
- }
+ switch (proportional) {
+ case PROP_EDIT_ON:
+ return T_PROP_EDIT;
+ case PROP_EDIT_CONNECTED:
+ return T_PROP_EDIT | T_PROP_CONNECTED;
+ case PROP_EDIT_PROJECTED:
+ return T_PROP_EDIT | T_PROP_PROJECTED;
+ default:
+ return 0;
+ }
}
-void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object **objects, uint objects_len)
+void initTransDataContainers_FromObjectData(TransInfo *t,
+ Object *obact,
+ Object **objects,
+ uint objects_len)
{
- const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
- const short object_type = obact ? obact->type : -1;
-
- if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) ||
- ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE)))
- {
- if (t->data_container) {
- MEM_freeN(t->data_container);
- }
-
- bool free_objects = false;
- if (objects == NULL) {
- objects = BKE_view_layer_array_from_objects_in_mode(
- t->view_layer,
- (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
- &objects_len, {
- .object_mode = object_mode,
- .no_dup_data = true,
- });
- free_objects = true;
- }
-
- t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
- t->data_container_len = objects_len;
-
- for (int i = 0; i < objects_len; i++) {
- TransDataContainer *tc = &t->data_container[i];
- /* TODO, multiple axes. */
- tc->mirror.axis_flag = (
- ((t->flag & T_NO_MIRROR) == 0) &&
- ((t->options & CTX_NO_MIRROR) == 0) &&
- (objects[i]->type == OB_MESH) &&
- (((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
-
- if (object_mode & OB_MODE_EDIT) {
- tc->obedit = objects[i];
- /* Check needed for UV's */
- if ((t->flag & T_2D_EDIT) == 0) {
- tc->use_local_mat = true;
- }
- }
- else if (object_mode & OB_MODE_POSE) {
- tc->poseobj = objects[i];
- tc->use_local_mat = true;
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- tc->use_local_mat = true;
- }
-
- if (tc->use_local_mat) {
- BLI_assert((t->flag & T_2D_EDIT) == 0);
- copy_m4_m4(tc->mat, objects[i]->obmat);
- copy_m3_m4(tc->mat3, tc->mat);
- invert_m4_m4(tc->imat, tc->mat);
- invert_m3_m3(tc->imat3, tc->mat3);
- normalize_m3_m3(tc->mat3_unit, tc->mat3);
- }
- /* Otherwise leave as zero. */
- }
-
- if (free_objects) {
- MEM_freeN(objects);
- }
- }
+ const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
+ const short object_type = obact ? obact->type : -1;
+
+ if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) ||
+ ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) {
+ if (t->data_container) {
+ MEM_freeN(t->data_container);
+ }
+
+ bool free_objects = false;
+ if (objects == NULL) {
+ objects = BKE_view_layer_array_from_objects_in_mode(
+ t->view_layer,
+ (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
+ &objects_len,
+ {
+ .object_mode = object_mode,
+ .no_dup_data = true,
+ });
+ free_objects = true;
+ }
+
+ t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
+ t->data_container_len = objects_len;
+
+ for (int i = 0; i < objects_len; i++) {
+ TransDataContainer *tc = &t->data_container[i];
+ /* TODO, multiple axes. */
+ tc->mirror.axis_flag = (((t->flag & T_NO_MIRROR) == 0) &&
+ ((t->options & CTX_NO_MIRROR) == 0) &&
+ (objects[i]->type == OB_MESH) &&
+ (((Mesh *)objects[i]->data)->editflag & ME_EDIT_MIRROR_X) != 0);
+
+ if (object_mode & OB_MODE_EDIT) {
+ tc->obedit = objects[i];
+ /* Check needed for UV's */
+ if ((t->flag & T_2D_EDIT) == 0) {
+ tc->use_local_mat = true;
+ }
+ }
+ else if (object_mode & OB_MODE_POSE) {
+ tc->poseobj = objects[i];
+ tc->use_local_mat = true;
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ tc->use_local_mat = true;
+ }
+
+ if (tc->use_local_mat) {
+ BLI_assert((t->flag & T_2D_EDIT) == 0);
+ copy_m4_m4(tc->mat, objects[i]->obmat);
+ copy_m3_m4(tc->mat3, tc->mat);
+ invert_m4_m4(tc->imat, tc->mat);
+ invert_m3_m3(tc->imat3, tc->mat3);
+ normalize_m3_m3(tc->mat3_unit, tc->mat3);
+ }
+ /* Otherwise leave as zero. */
+ }
+
+ if (free_objects) {
+ MEM_freeN(objects);
+ }
+ }
}
/**
@@ -1276,437 +1285,431 @@ void initTransDataContainers_FromObjectData(TransInfo *t, Object *obact, Object
*/
void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *sce = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const eObjectMode object_mode = OBACT(view_layer) ? OBACT(view_layer)->mode : OB_MODE_OBJECT;
- const short object_type = OBACT(view_layer) ? OBACT(view_layer)->type : -1;
- ToolSettings *ts = CTX_data_tool_settings(C);
- ARegion *ar = CTX_wm_region(C);
- ScrArea *sa = CTX_wm_area(C);
-
- bGPdata *gpd = CTX_data_gpencil_data(C);
- PropertyRNA *prop;
-
- t->depsgraph = depsgraph;
- t->scene = sce;
- t->view_layer = view_layer;
- t->sa = sa;
- t->ar = ar;
- t->settings = ts;
- t->reports = op ? op->reports : NULL;
-
- t->helpline = HLP_NONE;
-
- t->flag = 0;
-
- t->obedit_type = ((object_mode == OB_MODE_EDIT) || (object_mode == OB_MODE_EDIT_GPENCIL)) ? object_type : -1;
-
- /* Many kinds of transform only use a single handle. */
- if (t->data_container == NULL) {
- t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
- t->data_container_len = 1;
- }
-
- t->redraw = TREDRAW_HARD; /* redraw first time */
-
- if (event) {
- t->mouse.imval[0] = event->mval[0];
- t->mouse.imval[1] = event->mval[1];
- }
- else {
- t->mouse.imval[0] = 0;
- t->mouse.imval[1] = 0;
- }
-
- t->con.imval[0] = t->mouse.imval[0];
- t->con.imval[1] = t->mouse.imval[1];
-
- t->mval[0] = t->mouse.imval[0];
- t->mval[1] = t->mouse.imval[1];
-
- t->transform = NULL;
- t->handleEvent = NULL;
-
- t->data_len_all = 0;
-
- t->val = 0.0f;
-
- zero_v3(t->vec);
- zero_v3(t->center_global);
-
- unit_m3(t->mat);
-
- unit_m3(t->orient_matrix);
- negate_m3(t->orient_matrix);
- /* Leave 't->orient_matrix_is_set' to false,
- * so we overwrite it when we have a useful value. */
-
- /* Default to rotate on the Z axis. */
- t->orient_axis = 2;
- t->orient_axis_ortho = 1;
-
- /* if there's an event, we're modal */
- if (event) {
- t->flag |= T_MODAL;
- }
-
- /* Crease needs edge flag */
- if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
- t->options |= CTX_EDGE;
- }
-
- t->remove_on_cancel = false;
-
- if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) && RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->remove_on_cancel = true;
- }
- }
-
- /* GPencil editing context */
- if (GPENCIL_EDIT_MODE(gpd)) {
- t->options |= CTX_GPENCIL_STROKES;
- }
-
- /* Assign the space type, some exceptions for running in different mode */
- if (sa == NULL) {
- /* background mode */
- t->spacetype = SPACE_EMPTY;
- }
- else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
- /* running in the text editor */
- t->spacetype = SPACE_EMPTY;
- }
- else {
- /* normal operation */
- 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))) {
- SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
- }
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
-
- t->view = v3d;
- t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
-
- /* turn gizmo off during transform */
- if (t->flag & T_MODAL) {
- t->gizmo_flag = v3d->gizmo_flag;
- v3d->gizmo_flag = V3D_GIZMO_HIDE;
- }
-
- if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
- t->flag |= T_V3D_ALIGN;
- }
- t->around = t->scene->toolsettings->transform_pivot_point;
-
- /* bend always uses the cursor */
- if (t->mode == TFM_BEND) {
- t->around = V3D_AROUND_CURSOR;
- }
-
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
- t->orientation.unset = V3D_ORIENT_GLOBAL;
- t->orientation.user = orient_slot->type;
- t->orientation.custom = BKE_scene_transform_orientation_find(t->scene, orient_slot->index_custom);
-
- t->orientation.index = 0;
- ARRAY_SET_ITEMS(
- t->orientation.types,
- &t->orientation.user,
- NULL);
-
- /* Make second orientation local if both are global. */
- if (t->orientation.user == V3D_ORIENT_GLOBAL) {
- t->orientation.user_alt = V3D_ORIENT_LOCAL;
- t->orientation.types[0] = &t->orientation.user_alt;
- SWAP(short *, t->orientation.types[0], t->orientation.types[1]);
- }
-
- /* exceptional case */
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
- if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
- const bool use_island = transdata_check_local_islands(t, t->around);
-
- if ((t->obedit_type != -1) && !use_island) {
- t->options |= CTX_NO_PET;
- }
- }
- }
-
- if (object_mode & OB_MODE_ALL_PAINT) {
- Paint *p = BKE_paint_get_active_from_context(C);
- if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
- t->options |= CTX_PAINT_CURVE;
- }
- }
-
- /* initialize UV transform from */
- if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
- if (RNA_property_is_set(op->ptr, prop)) {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
- }
- else {
- t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
- }
- }
- else {
- RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
- }
- }
-
- }
- else if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- t->around = sima->around;
-
- if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
- /* UV transform */
- }
- else if (sima->mode == SI_MODE_MASK) {
- t->options |= CTX_MASK;
- }
- else if (sima->mode == SI_MODE_PAINT) {
- Paint *p = &sce->toolsettings->imapaint.paint;
- if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
- t->options |= CTX_PAINT_CURVE;
- }
- }
- /* image not in uv edit, nor in mask mode, can happen for some tools */
- }
- else if (t->spacetype == SPACE_NODE) {
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- t->around = V3D_AROUND_CENTER_BOUNDS;
- }
- else if (t->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = sa->spacedata.first;
- t->view = &ar->v2d;
- t->around = sipo->around;
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = sa->spacedata.first;
- t->view = &ar->v2d;
- t->around = sclip->around;
-
- if (ED_space_clip_check_show_trackedit(sclip))
- t->options |= CTX_MOVIECLIP;
- else if (ED_space_clip_check_show_maskedit(sclip))
- t->options |= CTX_MASK;
- }
- else {
- if (ar) {
- // XXX for now, get View2D from the active region
- t->view = &ar->v2d;
- // XXX for now, the center point is the midpoint of the data
- }
- else {
- t->view = NULL;
- }
- t->around = V3D_AROUND_CENTER_BOUNDS;
- }
-
- if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
- t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- }
- if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
- t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
- RNA_property_is_set(op->ptr, prop)) &&
- ((t->flag & T_MODAL) ||
- /* When using redo, don't use the the custom constraint matrix
- * if the user selects a different orientation. */
- (RNA_enum_get(op->ptr, "orient_type") ==
- RNA_enum_get(op->ptr, "orient_matrix_type"))))
- {
- RNA_property_float_get_array(op->ptr, prop, &t->spacemtx[0][0]);
- /* Some transform modes use this to operate on an axis. */
- t->orient_matrix_is_set = true;
- copy_m3_m3(t->orient_matrix, t->spacemtx);
- t->orient_matrix_is_set = true;
- t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX;
- t->orientation.custom = 0;
- if (t->flag & T_MODAL) {
- RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type"));
- }
- }
- else if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- short orientation = RNA_property_enum_get(op->ptr, prop);
- TransformOrientation *custom_orientation = NULL;
-
- if (orientation >= V3D_ORIENT_CUSTOM) {
- if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
- orientation = V3D_ORIENT_GLOBAL;
- }
- else {
- custom_orientation = BKE_scene_transform_orientation_find(
- t->scene, orientation - V3D_ORIENT_CUSTOM);
- orientation = V3D_ORIENT_CUSTOM;
- }
- }
-
- t->orientation.user = orientation;
- t->orientation.custom = custom_orientation;
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- if (RNA_property_boolean_get(op->ptr, prop)) {
- t->flag |= T_RELEASE_CONFIRM;
- }
- }
- else {
- if (U.flag & USER_RELEASECONFIRM) {
- t->flag |= T_RELEASE_CONFIRM;
- }
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- if (!RNA_property_boolean_get(op->ptr, prop)) {
- t->flag |= T_NO_MIRROR;
- }
- }
- else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
- /* pass */
- }
- else {
- /* Avoid mirroring for unsupported contexts. */
- t->options |= CTX_NO_MIRROR;
- }
-
- /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
- if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
- if (RNA_property_is_set(op->ptr, prop)) {
- t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
- }
- else {
- /* use settings from scene only if modal */
- if (t->flag & T_MODAL) {
- if ((t->options & CTX_NO_PET) == 0) {
- if (t->spacetype == SPACE_GRAPH) {
- 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_type != -1) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
- }
- else if (t->options & CTX_GPENCIL_STROKES) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
- }
- else if (t->options & CTX_MASK) {
- if (ts->proportional_mask) {
- t->flag |= T_PROP_EDIT;
-
- if (ts->proportional == PROP_EDIT_CONNECTED) {
- t->flag |= T_PROP_CONNECTED;
- }
- }
- }
- else if ((t->obedit_type == -1) && ts->proportional_objects) {
- t->flag |= T_PROP_EDIT;
- }
- }
- }
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->prop_size = RNA_property_float_get(op->ptr, prop);
- }
- else {
- t->prop_size = ts->proportional_size;
- }
-
-
- /* TRANSFORM_FIX_ME rna restrictions */
- if (t->prop_size <= 0.00001f) {
- printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
- t->prop_size = 1.0f;
- }
-
- if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->prop_mode = RNA_property_enum_get(op->ptr, prop);
- }
- else {
- t->prop_mode = ts->prop_mode;
- }
- }
- else { /* add not pet option to context when not available */
- t->options |= CTX_NO_PET;
- }
-
- // Mirror is not supported with PET, turn it off.
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *sce = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const eObjectMode object_mode = OBACT(view_layer) ? OBACT(view_layer)->mode : OB_MODE_OBJECT;
+ const short object_type = OBACT(view_layer) ? OBACT(view_layer)->type : -1;
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ ARegion *ar = CTX_wm_region(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ PropertyRNA *prop;
+
+ t->depsgraph = depsgraph;
+ t->scene = sce;
+ t->view_layer = view_layer;
+ t->sa = sa;
+ t->ar = ar;
+ t->settings = ts;
+ t->reports = op ? op->reports : NULL;
+
+ t->helpline = HLP_NONE;
+
+ t->flag = 0;
+
+ t->obedit_type = ((object_mode == OB_MODE_EDIT) || (object_mode == OB_MODE_EDIT_GPENCIL)) ?
+ object_type :
+ -1;
+
+ /* Many kinds of transform only use a single handle. */
+ if (t->data_container == NULL) {
+ t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
+ t->data_container_len = 1;
+ }
+
+ t->redraw = TREDRAW_HARD; /* redraw first time */
+
+ if (event) {
+ t->mouse.imval[0] = event->mval[0];
+ t->mouse.imval[1] = event->mval[1];
+ }
+ else {
+ t->mouse.imval[0] = 0;
+ t->mouse.imval[1] = 0;
+ }
+
+ t->con.imval[0] = t->mouse.imval[0];
+ t->con.imval[1] = t->mouse.imval[1];
+
+ t->mval[0] = t->mouse.imval[0];
+ t->mval[1] = t->mouse.imval[1];
+
+ t->transform = NULL;
+ t->handleEvent = NULL;
+
+ t->data_len_all = 0;
+
+ t->val = 0.0f;
+
+ zero_v3(t->vec);
+ zero_v3(t->center_global);
+
+ unit_m3(t->mat);
+
+ unit_m3(t->orient_matrix);
+ negate_m3(t->orient_matrix);
+ /* Leave 't->orient_matrix_is_set' to false,
+ * so we overwrite it when we have a useful value. */
+
+ /* Default to rotate on the Z axis. */
+ t->orient_axis = 2;
+ t->orient_axis_ortho = 1;
+
+ /* if there's an event, we're modal */
+ if (event) {
+ t->flag |= T_MODAL;
+ }
+
+ /* Crease needs edge flag */
+ if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
+ t->options |= CTX_EDGE;
+ }
+
+ t->remove_on_cancel = false;
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->remove_on_cancel = true;
+ }
+ }
+
+ /* GPencil editing context */
+ if (GPENCIL_EDIT_MODE(gpd)) {
+ t->options |= CTX_GPENCIL_STROKES;
+ }
+
+ /* Assign the space type, some exceptions for running in different mode */
+ if (sa == NULL) {
+ /* background mode */
+ t->spacetype = SPACE_EMPTY;
+ }
+ else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
+ /* running in the text editor */
+ t->spacetype = SPACE_EMPTY;
+ }
+ else {
+ /* normal operation */
+ 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))) {
+ SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
+ }
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = sa->spacedata.first;
+ bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
+
+ t->view = v3d;
+ t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
+
+ /* turn gizmo off during transform */
+ if (t->flag & T_MODAL) {
+ t->gizmo_flag = v3d->gizmo_flag;
+ v3d->gizmo_flag = V3D_GIZMO_HIDE;
+ }
+
+ if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
+ t->flag |= T_V3D_ALIGN;
+ }
+ t->around = t->scene->toolsettings->transform_pivot_point;
+
+ /* bend always uses the cursor */
+ if (t->mode == TFM_BEND) {
+ t->around = V3D_AROUND_CURSOR;
+ }
+
+ TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+ t->orientation.unset = V3D_ORIENT_GLOBAL;
+ t->orientation.user = orient_slot->type;
+ t->orientation.custom = BKE_scene_transform_orientation_find(t->scene,
+ orient_slot->index_custom);
+
+ t->orientation.index = 0;
+ ARRAY_SET_ITEMS(t->orientation.types, &t->orientation.user, NULL);
+
+ /* Make second orientation local if both are global. */
+ if (t->orientation.user == V3D_ORIENT_GLOBAL) {
+ t->orientation.user_alt = V3D_ORIENT_LOCAL;
+ t->orientation.types[0] = &t->orientation.user_alt;
+ SWAP(short *, t->orientation.types[0], t->orientation.types[1]);
+ }
+
+ /* exceptional case */
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ const bool use_island = transdata_check_local_islands(t, t->around);
+
+ if ((t->obedit_type != -1) && !use_island) {
+ t->options |= CTX_NO_PET;
+ }
+ }
+ }
+
+ if (object_mode & OB_MODE_ALL_PAINT) {
+ Paint *p = BKE_paint_get_active_from_context(C);
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+
+ /* initialize UV transform from */
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+ }
+ else {
+ t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
+ }
+ }
+ else {
+ RNA_property_boolean_set(
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ }
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ t->around = sima->around;
+
+ if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
+ /* UV transform */
+ }
+ else if (sima->mode == SI_MODE_MASK) {
+ t->options |= CTX_MASK;
+ }
+ else if (sima->mode == SI_MODE_PAINT) {
+ Paint *p = &sce->toolsettings->imapaint.paint;
+ if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+ /* image not in uv edit, nor in mask mode, can happen for some tools */
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ t->around = V3D_AROUND_CENTER_BOUNDS;
+ }
+ else if (t->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = sa->spacedata.first;
+ t->view = &ar->v2d;
+ t->around = sipo->around;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = sa->spacedata.first;
+ t->view = &ar->v2d;
+ t->around = sclip->around;
+
+ if (ED_space_clip_check_show_trackedit(sclip))
+ t->options |= CTX_MOVIECLIP;
+ else if (ED_space_clip_check_show_maskedit(sclip))
+ t->options |= CTX_MASK;
+ }
+ else {
+ if (ar) {
+ // XXX for now, get View2D from the active region
+ t->view = &ar->v2d;
+ // XXX for now, the center point is the midpoint of the data
+ }
+ else {
+ t->view = NULL;
+ }
+ t->around = V3D_AROUND_CENTER_BOUNDS;
+ }
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
+ t->orient_axis = RNA_property_enum_get(op->ptr, prop);
+ }
+ if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
+ t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop);
+ }
+
+ if (op &&
+ ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) &&
+ RNA_property_is_set(op->ptr, prop)) &&
+ ((t->flag & T_MODAL) ||
+ /* When using redo, don't use the the custom constraint matrix
+ * if the user selects a different orientation. */
+ (RNA_enum_get(op->ptr, "orient_type") == RNA_enum_get(op->ptr, "orient_matrix_type")))) {
+ RNA_property_float_get_array(op->ptr, prop, &t->spacemtx[0][0]);
+ /* Some transform modes use this to operate on an axis. */
+ t->orient_matrix_is_set = true;
+ copy_m3_m3(t->orient_matrix, t->spacemtx);
+ t->orient_matrix_is_set = true;
+ t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX;
+ t->orientation.custom = 0;
+ if (t->flag & T_MODAL) {
+ RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type"));
+ }
+ }
+ else if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ short orientation = RNA_property_enum_get(op->ptr, prop);
+ TransformOrientation *custom_orientation = NULL;
+
+ if (orientation >= V3D_ORIENT_CUSTOM) {
+ if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) {
+ orientation = V3D_ORIENT_GLOBAL;
+ }
+ else {
+ custom_orientation = BKE_scene_transform_orientation_find(t->scene,
+ orientation - V3D_ORIENT_CUSTOM);
+ orientation = V3D_ORIENT_CUSTOM;
+ }
+ }
+
+ t->orientation.user = orientation;
+ t->orientation.custom = custom_orientation;
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_RELEASE_CONFIRM;
+ }
+ }
+ else {
+ if (U.flag & USER_RELEASECONFIRM) {
+ t->flag |= T_RELEASE_CONFIRM;
+ }
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ if (!RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_NO_MIRROR;
+ }
+ }
+ else if ((t->spacetype == SPACE_VIEW3D) && (t->obedit_type == OB_MESH)) {
+ /* pass */
+ }
+ else {
+ /* Avoid mirroring for unsupported contexts. */
+ t->options |= CTX_NO_MIRROR;
+ }
+
+ /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
+ if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
+ if (RNA_property_is_set(op->ptr, prop)) {
+ t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
+ }
+ else {
+ /* use settings from scene only if modal */
+ if (t->flag & T_MODAL) {
+ if ((t->options & CTX_NO_PET) == 0) {
+ if (t->spacetype == SPACE_GRAPH) {
+ 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_type != -1) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
+ else if (t->options & CTX_GPENCIL_STROKES) {
+ t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
+ }
+ else if (t->options & CTX_MASK) {
+ if (ts->proportional_mask) {
+ t->flag |= T_PROP_EDIT;
+
+ if (ts->proportional == PROP_EDIT_CONNECTED) {
+ t->flag |= T_PROP_CONNECTED;
+ }
+ }
+ }
+ else if ((t->obedit_type == -1) && ts->proportional_objects) {
+ t->flag |= T_PROP_EDIT;
+ }
+ }
+ }
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ t->prop_size = RNA_property_float_get(op->ptr, prop);
+ }
+ else {
+ t->prop_size = ts->proportional_size;
+ }
+
+ /* TRANSFORM_FIX_ME rna restrictions */
+ if (t->prop_size <= 0.00001f) {
+ printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
+ t->prop_size = 1.0f;
+ }
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ RNA_property_is_set(op->ptr, prop))) {
+ t->prop_mode = RNA_property_enum_get(op->ptr, prop);
+ }
+ else {
+ t->prop_mode = ts->prop_mode;
+ }
+ }
+ else { /* add not pet option to context when not available */
+ t->options |= CTX_NO_PET;
+ }
+
+ // Mirror is not supported with PET, turn it off.
#if 0
- if (t->flag & T_PROP_EDIT) {
- t->flag &= ~T_MIRROR;
- }
+ if (t->flag & T_PROP_EDIT) {
+ t->flag &= ~T_MIRROR;
+ }
#endif
- setTransformViewAspect(t, t->aspect);
+ setTransformViewAspect(t, t->aspect);
- if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_get_array(op->ptr, prop, t->center_global);
- mul_v3_v3(t->center_global, t->aspect);
- t->flag |= T_OVERRIDE_CENTER;
- }
+ if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_get_array(op->ptr, prop, t->center_global);
+ mul_v3_v3(t->center_global, t->aspect);
+ t->flag |= T_OVERRIDE_CENTER;
+ }
- setTransformViewMatrices(t);
- initNumInput(&t->num);
+ setTransformViewMatrices(t);
+ initNumInput(&t->num);
}
-
-static void freeTransCustomData(
- TransInfo *t, TransDataContainer *tc,
- TransCustomData *custom_data)
+static void freeTransCustomData(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data)
{
- if (custom_data->free_cb) {
- /* Can take over freeing t->data and data_2d etc... */
- custom_data->free_cb(t, tc, custom_data);
- BLI_assert(custom_data->data == NULL);
- }
- else if ((custom_data->data != NULL) && custom_data->use_free) {
- MEM_freeN(custom_data->data);
- custom_data->data = NULL;
- }
- /* In case modes are switched in the same transform session. */
- custom_data->free_cb = false;
- custom_data->use_free = false;
+ if (custom_data->free_cb) {
+ /* Can take over freeing t->data and data_2d etc... */
+ custom_data->free_cb(t, tc, custom_data);
+ BLI_assert(custom_data->data == NULL);
+ }
+ else if ((custom_data->data != NULL) && custom_data->use_free) {
+ MEM_freeN(custom_data->data);
+ custom_data->data = NULL;
+ }
+ /* In case modes are switched in the same transform session. */
+ custom_data->free_cb = false;
+ custom_data->use_free = false;
}
-static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, TransCustomDataContainer *tcdc)
+static void freeTransCustomDataContainer(TransInfo *t,
+ TransDataContainer *tc,
+ TransCustomDataContainer *tcdc)
{
- TransCustomData *custom_data = &tcdc->first_elem;
- for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
- freeTransCustomData(t, tc, custom_data);
- }
+ TransCustomData *custom_data = &tcdc->first_elem;
+ for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
+ freeTransCustomData(t, tc, custom_data);
+ }
}
/**
@@ -1714,321 +1717,325 @@ static void freeTransCustomDataContainer(TransInfo *t, TransDataContainer *tc, T
*/
void freeTransCustomDataForMode(TransInfo *t)
{
- freeTransCustomData(t, NULL, &t->custom.mode);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- freeTransCustomData(t, tc, &tc->custom.mode);
- }
+ freeTransCustomData(t, NULL, &t->custom.mode);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ freeTransCustomData(t, tc, &tc->custom.mode);
+ }
}
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
void postTrans(bContext *C, TransInfo *t)
{
- if (t->draw_handle_view)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
- if (t->draw_handle_apply)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
- if (t->draw_handle_pixel)
- ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
- if (t->draw_handle_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
-
- if (t->flag & T_MODAL_CURSOR_SET) {
- WM_cursor_modal_restore(CTX_wm_window(C));
- }
-
- /* Free all custom-data */
- freeTransCustomDataContainer(t, NULL, &t->custom);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- freeTransCustomDataContainer(t, tc, &tc->custom);
- }
-
- /* postTrans can be called when nothing is selected, so data is NULL already */
- if (t->data_len_all != 0) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- /* free data malloced per trans-data */
- if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) ||
- (t->spacetype == SPACE_GRAPH))
- {
- TransData *td = tc->data;
- for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_BEZTRIPLE) {
- MEM_freeN(td->hdata);
- }
- }
- }
- MEM_freeN(tc->data);
-
- MEM_SAFE_FREE(tc->data_ext);
- MEM_SAFE_FREE(tc->data_2d);
- }
- }
-
- MEM_SAFE_FREE(t->data_container);
- t->data_container = NULL;
-
- BLI_freelistN(&t->tsnap.points);
-
- if (t->spacetype == SPACE_IMAGE) {
- if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
- /* pass */
- }
- else {
- SpaceImage *sima = t->sa->spacedata.first;
- if (sima->flag & SI_LIVE_UNWRAP)
- ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
- }
- }
- else if (t->spacetype == SPACE_VIEW3D) {
- View3D *v3d = t->sa->spacedata.first;
- /* restore gizmo */
- if (t->flag & T_MODAL) {
- v3d->gizmo_flag = t->gizmo_flag;
- }
- }
-
- if (t->mouse.data) {
- MEM_freeN(t->mouse.data);
- }
-
- if (t->rng != NULL) {
- BLI_rng_free(t->rng);
- }
-
- freeSnapping(t);
+ if (t->draw_handle_view)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
+ if (t->draw_handle_apply)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
+ if (t->draw_handle_pixel)
+ ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
+ if (t->draw_handle_cursor)
+ WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
+
+ if (t->flag & T_MODAL_CURSOR_SET) {
+ WM_cursor_modal_restore(CTX_wm_window(C));
+ }
+
+ /* Free all custom-data */
+ freeTransCustomDataContainer(t, NULL, &t->custom);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ freeTransCustomDataContainer(t, tc, &tc->custom);
+ }
+
+ /* postTrans can be called when nothing is selected, so data is NULL already */
+ if (t->data_len_all != 0) {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ /* free data malloced per trans-data */
+ if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) || (t->spacetype == SPACE_GRAPH)) {
+ TransData *td = tc->data;
+ for (int a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_BEZTRIPLE) {
+ MEM_freeN(td->hdata);
+ }
+ }
+ }
+ MEM_freeN(tc->data);
+
+ MEM_SAFE_FREE(tc->data_ext);
+ MEM_SAFE_FREE(tc->data_2d);
+ }
+ }
+
+ MEM_SAFE_FREE(t->data_container);
+ t->data_container = NULL;
+
+ BLI_freelistN(&t->tsnap.points);
+
+ if (t->spacetype == SPACE_IMAGE) {
+ if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
+ /* pass */
+ }
+ else {
+ SpaceImage *sima = t->sa->spacedata.first;
+ if (sima->flag & SI_LIVE_UNWRAP)
+ ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
+ }
+ }
+ else if (t->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = t->sa->spacedata.first;
+ /* restore gizmo */
+ if (t->flag & T_MODAL) {
+ v3d->gizmo_flag = t->gizmo_flag;
+ }
+ }
+
+ if (t->mouse.data) {
+ MEM_freeN(t->mouse.data);
+ }
+
+ if (t->rng != NULL) {
+ BLI_rng_free(t->rng);
+ }
+
+ freeSnapping(t);
}
void applyTransObjects(TransInfo *t)
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
-
- TransData *td;
-
- for (td = tc->data; td < tc->data + tc->data_len; td++) {
- copy_v3_v3(td->iloc, td->loc);
- if (td->ext->rot) {
- copy_v3_v3(td->ext->irot, td->ext->rot);
- }
- if (td->ext->size) {
- copy_v3_v3(td->ext->isize, td->ext->size);
- }
- }
- recalcData(t);
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+
+ TransData *td;
+
+ for (td = tc->data; td < tc->data + tc->data_len; td++) {
+ copy_v3_v3(td->iloc, td->loc);
+ if (td->ext->rot) {
+ copy_v3_v3(td->ext->irot, td->ext->rot);
+ }
+ if (td->ext->size) {
+ copy_v3_v3(td->ext->isize, td->ext->size);
+ }
+ }
+ recalcData(t);
}
static void restoreElement(TransData *td)
{
- /* TransData for crease has no loc */
- if (td->loc) {
- copy_v3_v3(td->loc, td->iloc);
- }
- if (td->val) {
- *td->val = td->ival;
- }
-
- if (td->ext && (td->flag & TD_NO_EXT) == 0) {
- if (td->ext->rot) {
- copy_v3_v3(td->ext->rot, td->ext->irot);
- }
- if (td->ext->rotAngle) {
- *td->ext->rotAngle = td->ext->irotAngle;
- }
- if (td->ext->rotAxis) {
- copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
- }
- /* XXX, drotAngle & drotAxis not used yet */
- if (td->ext->size) {
- copy_v3_v3(td->ext->size, td->ext->isize);
- }
- if (td->ext->quat) {
- copy_qt_qt(td->ext->quat, td->ext->iquat);
- }
- }
-
- if (td->flag & TD_BEZTRIPLE) {
- *(td->hdata->h1) = td->hdata->ih1;
- *(td->hdata->h2) = td->hdata->ih2;
- }
+ /* TransData for crease has no loc */
+ if (td->loc) {
+ copy_v3_v3(td->loc, td->iloc);
+ }
+ if (td->val) {
+ *td->val = td->ival;
+ }
+
+ if (td->ext && (td->flag & TD_NO_EXT) == 0) {
+ if (td->ext->rot) {
+ copy_v3_v3(td->ext->rot, td->ext->irot);
+ }
+ if (td->ext->rotAngle) {
+ *td->ext->rotAngle = td->ext->irotAngle;
+ }
+ if (td->ext->rotAxis) {
+ copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
+ }
+ /* XXX, drotAngle & drotAxis not used yet */
+ if (td->ext->size) {
+ copy_v3_v3(td->ext->size, td->ext->isize);
+ }
+ if (td->ext->quat) {
+ copy_qt_qt(td->ext->quat, td->ext->iquat);
+ }
+ }
+
+ if (td->flag & TD_BEZTRIPLE) {
+ *(td->hdata->h1) = td->hdata->ih1;
+ *(td->hdata->h2) = td->hdata->ih2;
+ }
}
void restoreTransObjects(TransInfo *t)
{
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
- TransData *td;
- TransData2D *td2d;
-
- for (td = tc->data; td < tc->data + tc->data_len; td++) {
- restoreElement(td);
- }
-
- for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
- if (td2d->h1) {
- td2d->h1[0] = td2d->ih1[0];
- td2d->h1[1] = td2d->ih1[1];
- }
- if (td2d->h2) {
- td2d->h2[0] = td2d->ih2[0];
- td2d->h2[1] = td2d->ih2[1];
- }
- }
-
- unit_m3(t->mat);
-
- }
-
- recalcData(t);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+
+ TransData *td;
+ TransData2D *td2d;
+
+ for (td = tc->data; td < tc->data + tc->data_len; td++) {
+ restoreElement(td);
+ }
+
+ for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
+ if (td2d->h1) {
+ td2d->h1[0] = td2d->ih1[0];
+ td2d->h1[1] = td2d->ih1[1];
+ }
+ if (td2d->h2) {
+ td2d->h2[0] = td2d->ih2[0];
+ td2d->h2[1] = td2d->ih2[1];
+ }
+ }
+
+ unit_m3(t->mat);
+ }
+
+ recalcData(t);
}
void calculateCenter2D(TransInfo *t)
{
- BLI_assert(!is_zero_v3(t->aspect));
- projectFloatView(t, t->center_global, t->center2d);
+ BLI_assert(!is_zero_v3(t->aspect));
+ projectFloatView(t, t->center_global, t->center2d);
}
-void calculateCenterLocal(
- TransInfo *t, const float center_global[3])
+void calculateCenterLocal(TransInfo *t, const float center_global[3])
{
- /* setting constraint center */
- /* note, init functions may over-ride t->center */
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- if (tc->use_local_mat) {
- mul_v3_m4v3(tc->center_local, tc->imat, center_global);
- }
- else {
- copy_v3_v3(tc->center_local, center_global);
- }
- }
+ /* setting constraint center */
+ /* note, init functions may over-ride t->center */
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(tc->center_local, tc->imat, center_global);
+ }
+ else {
+ copy_v3_v3(tc->center_local, center_global);
+ }
+ }
}
void calculateCenterCursor(TransInfo *t, float r_center[3])
{
- const float *cursor = t->scene->cursor.location;
- copy_v3_v3(r_center, cursor);
-
- /* If edit or pose mode, move cursor in local space */
- if (t->options & CTX_PAINT_CURVE) {
- if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
- r_center[0] = t->ar->winx / 2.0f;
- r_center[1] = t->ar->winy / 2.0f;
- }
- r_center[2] = 0.0f;
- }
+ const float *cursor = t->scene->cursor.location;
+ copy_v3_v3(r_center, cursor);
+
+ /* If edit or pose mode, move cursor in local space */
+ if (t->options & CTX_PAINT_CURVE) {
+ if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) !=
+ V3D_PROJ_RET_OK) {
+ r_center[0] = t->ar->winx / 2.0f;
+ r_center[1] = t->ar->winy / 2.0f;
+ }
+ r_center[2] = 0.0f;
+ }
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
{
- const float *cursor = NULL;
-
- if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- cursor = sima->cursor;
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
- cursor = space_clip->cursor;
- }
-
- if (cursor) {
- if (t->options & CTX_MASK) {
- float co[2];
-
- if (t->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
- }
- else if (t->spacetype == SPACE_CLIP) {
- SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
- BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
- }
- else {
- BLI_assert(!"Shall not happen");
- }
-
- 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) {
- r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
- r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
- }
- }
- else {
- r_center[0] = cursor[0] * t->aspect[0];
- r_center[1] = cursor[1] * t->aspect[1];
- }
- }
+ const float *cursor = NULL;
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ cursor = sima->cursor;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *)t->sa->spacedata.first;
+ cursor = space_clip->cursor;
+ }
+
+ if (cursor) {
+ if (t->options & CTX_MASK) {
+ float co[2];
+
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *)t->sa->spacedata.first;
+ BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
+ }
+ else {
+ BLI_assert(!"Shall not happen");
+ }
+
+ 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) {
+ r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
+ r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
+ }
+ }
+ else {
+ r_center[0] = cursor[0] * t->aspect[0];
+ r_center[1] = cursor[1] * t->aspect[1];
+ }
+ }
}
void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
{
- SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
- Scene *scene = t->scene;
-
- /* cursor is combination of current frame, and graph-editor cursor value */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- r_center[0] = sipo->cursorTime;
- r_center[1] = sipo->cursorVal;
- }
- else {
- r_center[0] = (float)(scene->r.cfra);
- r_center[1] = sipo->cursorVal;
- }
+ SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first;
+ Scene *scene = t->scene;
+
+ /* cursor is combination of current frame, and graph-editor cursor value */
+ if (sipo->mode == SIPO_MODE_DRIVERS) {
+ r_center[0] = sipo->cursorTime;
+ r_center[1] = sipo->cursorVal;
+ }
+ else {
+ r_center[0] = (float)(scene->r.cfra);
+ r_center[1] = sipo->cursorVal;
+ }
}
void calculateCenterMedian(TransInfo *t, float r_center[3])
{
- float partial[3] = {0.0f, 0.0f, 0.0f};
- int total = 0;
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- for (int i = 0; i < tc->data_len; i++) {
- if (tc->data[i].flag & TD_SELECTED) {
- if (!(tc->data[i].flag & TD_NOCENTER)) {
- if (tc->use_local_mat) {
- float v[3];
- mul_v3_m4v3(v, tc->mat, tc->data[i].center);
- add_v3_v3(partial, v);
- }
- else {
- add_v3_v3(partial, tc->data[i].center);
- }
- total++;
- }
- }
- }
- }
- if (total) {
- mul_v3_fl(partial, 1.0f / (float)total);
- }
- copy_v3_v3(r_center, partial);
+ float partial[3] = {0.0f, 0.0f, 0.0f};
+ int total = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ for (int i = 0; i < tc->data_len; i++) {
+ if (tc->data[i].flag & TD_SELECTED) {
+ if (!(tc->data[i].flag & TD_NOCENTER)) {
+ if (tc->use_local_mat) {
+ float v[3];
+ mul_v3_m4v3(v, tc->mat, tc->data[i].center);
+ add_v3_v3(partial, v);
+ }
+ else {
+ add_v3_v3(partial, tc->data[i].center);
+ }
+ total++;
+ }
+ }
+ }
+ }
+ if (total) {
+ mul_v3_fl(partial, 1.0f / (float)total);
+ }
+ copy_v3_v3(r_center, partial);
}
void calculateCenterBound(TransInfo *t, float r_center[3])
{
- float max[3], min[3];
- bool changed = false;
- INIT_MINMAX(min, max);
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- for (int i = 0; i < tc->data_len; i++) {
- if (tc->data[i].flag & TD_SELECTED) {
- if (!(tc->data[i].flag & TD_NOCENTER)) {
- if (tc->use_local_mat) {
- float v[3];
- mul_v3_m4v3(v, tc->mat, tc->data[i].center);
- minmax_v3v3_v3(min, max, v);
- }
- else {
- minmax_v3v3_v3(min, max, tc->data[i].center);
- }
- changed = true;
- }
- }
- }
- }
- if (changed) {
- mid_v3_v3v3(r_center, min, max);
- }
+ float max[3], min[3];
+ bool changed = false;
+ INIT_MINMAX(min, max);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ for (int i = 0; i < tc->data_len; i++) {
+ if (tc->data[i].flag & TD_SELECTED) {
+ if (!(tc->data[i].flag & TD_NOCENTER)) {
+ if (tc->use_local_mat) {
+ float v[3];
+ mul_v3_m4v3(v, tc->mat, tc->data[i].center);
+ minmax_v3v3_v3(min, max, v);
+ }
+ else {
+ minmax_v3v3_v3(min, max, tc->data[i].center);
+ }
+ changed = true;
+ }
+ }
+ }
+ }
+ if (changed) {
+ mid_v3_v3v3(r_center, min, max);
+ }
}
/**
@@ -2036,286 +2043,287 @@ void calculateCenterBound(TransInfo *t, float r_center[3])
*/
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
{
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
-
- if (t->spacetype != SPACE_VIEW3D) {
- return false;
- }
- else if (tc->obedit) {
- if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
- mul_m4_v3(tc->obedit->obmat, r_center);
- return true;
- }
- }
- else if (t->flag & T_POSE) {
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer) ;
- if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- }
- else if (t->options & CTX_PAINT_CURVE) {
- Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
- Brush *br = p->brush;
- PaintCurve *pc = br->paint_curve;
- copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
- r_center[2] = 0.0f;
- return true;
- }
- else {
- /* object mode */
- ViewLayer *view_layer = t->view_layer;
- Object *ob = OBACT(view_layer);
- Base *base = BASACT(view_layer);
- if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
- copy_v3_v3(r_center, ob->obmat[3]);
- return true;
- }
- }
-
- return false;
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+
+ if (t->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+ else if (tc->obedit) {
+ if (ED_object_calc_active_center_for_editmode(tc->obedit, select_only, r_center)) {
+ mul_m4_v3(tc->obedit->obmat, r_center);
+ return true;
+ }
+ }
+ else if (t->flag & T_POSE) {
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ }
+ else if (t->options & CTX_PAINT_CURVE) {
+ Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
+ r_center[2] = 0.0f;
+ return true;
+ }
+ else {
+ /* object mode */
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ Base *base = BASACT(view_layer);
+ if (ob && ((!select_only) || ((base->flag & BASE_SELECTED) != 0))) {
+ copy_v3_v3(r_center, ob->obmat[3]);
+ return true;
+ }
+ }
+
+ return false;
}
static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
{
- switch (around) {
- case V3D_AROUND_CENTER_BOUNDS:
- calculateCenterBound(t, r_center);
- break;
- case V3D_AROUND_CENTER_MEDIAN:
- calculateCenterMedian(t, r_center);
- break;
- case V3D_AROUND_CURSOR:
- if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
- calculateCenterCursor2D(t, r_center);
- else if (t->spacetype == SPACE_GRAPH)
- calculateCenterCursorGraph2D(t, r_center);
- else
- calculateCenterCursor(t, r_center);
- break;
- case V3D_AROUND_LOCAL_ORIGINS:
- /* Individual element center uses median center for helpline and such */
- calculateCenterMedian(t, r_center);
- break;
- case V3D_AROUND_ACTIVE:
- {
- if (calculateCenterActive(t, false, r_center)) {
- /* pass */
- }
- else {
- /* fallback */
- calculateCenterMedian(t, r_center);
- }
- break;
- }
- }
+ switch (around) {
+ case V3D_AROUND_CENTER_BOUNDS:
+ calculateCenterBound(t, r_center);
+ break;
+ case V3D_AROUND_CENTER_MEDIAN:
+ calculateCenterMedian(t, r_center);
+ break;
+ case V3D_AROUND_CURSOR:
+ if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
+ calculateCenterCursor2D(t, r_center);
+ else if (t->spacetype == SPACE_GRAPH)
+ calculateCenterCursorGraph2D(t, r_center);
+ else
+ calculateCenterCursor(t, r_center);
+ break;
+ case V3D_AROUND_LOCAL_ORIGINS:
+ /* Individual element center uses median center for helpline and such */
+ calculateCenterMedian(t, r_center);
+ break;
+ case V3D_AROUND_ACTIVE: {
+ if (calculateCenterActive(t, false, r_center)) {
+ /* pass */
+ }
+ else {
+ /* fallback */
+ calculateCenterMedian(t, r_center);
+ }
+ break;
+ }
+ }
}
void calculateCenter(TransInfo *t)
{
- if ((t->flag & T_OVERRIDE_CENTER) == 0) {
- calculateCenter_FromAround(t, t->around, t->center_global);
- }
- calculateCenterLocal(t, t->center_global);
-
- /* avoid calculating again */
- {
- TransCenterData *cd = &t->center_cache[t->around];
- copy_v3_v3(cd->global, t->center_global);
- cd->is_set = true;
- }
-
- calculateCenter2D(t);
-
- /* for panning from cameraview */
- if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
- if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
-
- if (t->flag & T_CAMERA) {
- float axis[3];
- /* persinv is nasty, use viewinv instead, always right */
- copy_v3_v3(axis, t->viewinv[2]);
- normalize_v3(axis);
-
- /* 6.0 = 6 grid units */
- axis[0] = t->center_global[0] - 6.0f * axis[0];
- axis[1] = t->center_global[1] - 6.0f * axis[1];
- axis[2] = t->center_global[2] - 6.0f * axis[2];
-
- projectFloatView(t, axis, t->center2d);
-
- /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
- if (t->mode == TFM_TRANSLATION) {
- copy_v3_v3(t->center_global, axis);
- }
- }
- }
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
-
- /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
- * and never used in other cases.
- *
- * We need special case here as well, since ED_view3d_calc_zfac will crash when called
- * for a region different from RGN_TYPE_WINDOW.
- */
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
- }
- else {
- t->zfac = 0.0f;
- }
- }
+ if ((t->flag & T_OVERRIDE_CENTER) == 0) {
+ calculateCenter_FromAround(t, t->around, t->center_global);
+ }
+ calculateCenterLocal(t, t->center_global);
+
+ /* avoid calculating again */
+ {
+ TransCenterData *cd = &t->center_cache[t->around];
+ copy_v3_v3(cd->global, t->center_global);
+ cd->is_set = true;
+ }
+
+ calculateCenter2D(t);
+
+ /* for panning from cameraview */
+ if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
+ if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
+
+ if (t->flag & T_CAMERA) {
+ float axis[3];
+ /* persinv is nasty, use viewinv instead, always right */
+ copy_v3_v3(axis, t->viewinv[2]);
+ normalize_v3(axis);
+
+ /* 6.0 = 6 grid units */
+ axis[0] = t->center_global[0] - 6.0f * axis[0];
+ axis[1] = t->center_global[1] - 6.0f * axis[1];
+ axis[2] = t->center_global[2] - 6.0f * axis[2];
+
+ projectFloatView(t, axis, t->center2d);
+
+ /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
+ if (t->mode == TFM_TRANSLATION) {
+ copy_v3_v3(t->center_global, axis);
+ }
+ }
+ }
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
+
+ /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
+ * and never used in other cases.
+ *
+ * We need special case here as well, since ED_view3d_calc_zfac will crash when called
+ * for a region different from RGN_TYPE_WINDOW.
+ */
+ if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
+ }
+ else {
+ t->zfac = 0.0f;
+ }
+ }
}
-BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), "test size");
+BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1),
+ "test size");
/**
* Lazy initialize transform center data, when we need to access center values from other types.
*/
const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
{
- BLI_assert(around <= V3D_AROUND_ACTIVE);
- TransCenterData *cd = &t->center_cache[around];
- if (cd->is_set == false) {
- calculateCenter_FromAround(t, around, cd->global);
- cd->is_set = true;
- }
- return cd;
+ BLI_assert(around <= V3D_AROUND_ACTIVE);
+ TransCenterData *cd = &t->center_cache[around];
+ if (cd->is_set == false) {
+ calculateCenter_FromAround(t, around, cd->global);
+ cd->is_set = true;
+ }
+ return cd;
}
void calculatePropRatio(TransInfo *t)
{
- int i;
- float dist;
- const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
-
- t->proptext[0] = '\0';
-
- if (t->flag & T_PROP_EDIT) {
- const char *pet_id = NULL;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SELECTED) {
- td->factor = 1.0f;
- }
- else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
- td->flag |= TD_SKIP;
- td->factor = 0.0f;
- restoreElement(td);
- }
- else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
- (connected == 0 && td->rdist > t->prop_size))
- {
- /*
- * The elements are sorted according to their dist member in the array,
- * that means we can stop when it finds one element outside of the propsize.
- * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
- */
-
- td->factor = 0.0f;
- restoreElement(td);
- }
- else {
- /* Use rdist for falloff calculations, it is the real distance */
- td->flag &= ~TD_NOACTION;
-
- if (connected)
- dist = (t->prop_size - td->dist) / t->prop_size;
- else
- dist = (t->prop_size - td->rdist) / t->prop_size;
-
- /*
- * Clamp to positive numbers.
- * Certain corner cases with connectivity and individual centers
- * can give values of rdist larger than propsize.
- */
- if (dist < 0.0f)
- dist = 0.0f;
-
- switch (t->prop_mode) {
- case PROP_SHARP:
- td->factor = dist * dist;
- break;
- case PROP_SMOOTH:
- td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
- break;
- case PROP_ROOT:
- td->factor = sqrtf(dist);
- break;
- case PROP_LIN:
- td->factor = dist;
- break;
- case PROP_CONST:
- td->factor = 1.0f;
- break;
- case PROP_SPHERE:
- td->factor = sqrtf(2 * dist - dist * dist);
- break;
- case PROP_RANDOM:
- if (t->rng == NULL) {
- /* Lazy initialization. */
- uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
- t->rng = BLI_rng_new(rng_seed);
- }
- td->factor = BLI_rng_get_float(t->rng) * dist;
- break;
- case PROP_INVSQUARE:
- td->factor = dist * (2.0f - dist);
- break;
- default:
- td->factor = 1;
- break;
- }
- }
- }
- }
-
- switch (t->prop_mode) {
- case PROP_SHARP:
- pet_id = N_("(Sharp)");
- break;
- case PROP_SMOOTH:
- pet_id = N_("(Smooth)");
- break;
- case PROP_ROOT:
- pet_id = N_("(Root)");
- break;
- case PROP_LIN:
- pet_id = N_("(Linear)");
- break;
- case PROP_CONST:
- pet_id = N_("(Constant)");
- break;
- case PROP_SPHERE:
- pet_id = N_("(Sphere)");
- break;
- case PROP_RANDOM:
- pet_id = N_("(Random)");
- break;
- case PROP_INVSQUARE:
- pet_id = N_("(InvSquare)");
- break;
- default:
- break;
- }
-
- if (pet_id) {
- BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- td->factor = 1.0;
- }
- }
- }
+ int i;
+ float dist;
+ const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
+
+ t->proptext[0] = '\0';
+
+ if (t->flag & T_PROP_EDIT) {
+ const char *pet_id = NULL;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ if (td->flag & TD_SELECTED) {
+ td->factor = 1.0f;
+ }
+ else if (tc->mirror.axis_flag && (td->loc[0] * tc->mirror.sign) < -0.00001f) {
+ td->flag |= TD_SKIP;
+ td->factor = 0.0f;
+ restoreElement(td);
+ }
+ else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
+ (connected == 0 && td->rdist > t->prop_size)) {
+ /*
+ * The elements are sorted according to their dist member in the array,
+ * that means we can stop when it finds one element outside of the propsize.
+ * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
+ */
+
+ td->factor = 0.0f;
+ restoreElement(td);
+ }
+ else {
+ /* Use rdist for falloff calculations, it is the real distance */
+ td->flag &= ~TD_NOACTION;
+
+ if (connected)
+ dist = (t->prop_size - td->dist) / t->prop_size;
+ else
+ dist = (t->prop_size - td->rdist) / t->prop_size;
+
+ /*
+ * Clamp to positive numbers.
+ * Certain corner cases with connectivity and individual centers
+ * can give values of rdist larger than propsize.
+ */
+ if (dist < 0.0f)
+ dist = 0.0f;
+
+ switch (t->prop_mode) {
+ case PROP_SHARP:
+ td->factor = dist * dist;
+ break;
+ case PROP_SMOOTH:
+ td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
+ break;
+ case PROP_ROOT:
+ td->factor = sqrtf(dist);
+ break;
+ case PROP_LIN:
+ td->factor = dist;
+ break;
+ case PROP_CONST:
+ td->factor = 1.0f;
+ break;
+ case PROP_SPHERE:
+ td->factor = sqrtf(2 * dist - dist * dist);
+ break;
+ case PROP_RANDOM:
+ if (t->rng == NULL) {
+ /* Lazy initialization. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ t->rng = BLI_rng_new(rng_seed);
+ }
+ td->factor = BLI_rng_get_float(t->rng) * dist;
+ break;
+ case PROP_INVSQUARE:
+ td->factor = dist * (2.0f - dist);
+ break;
+ default:
+ td->factor = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ switch (t->prop_mode) {
+ case PROP_SHARP:
+ pet_id = N_("(Sharp)");
+ break;
+ case PROP_SMOOTH:
+ pet_id = N_("(Smooth)");
+ break;
+ case PROP_ROOT:
+ pet_id = N_("(Root)");
+ break;
+ case PROP_LIN:
+ pet_id = N_("(Linear)");
+ break;
+ case PROP_CONST:
+ pet_id = N_("(Constant)");
+ break;
+ case PROP_SPHERE:
+ pet_id = N_("(Sphere)");
+ break;
+ case PROP_RANDOM:
+ pet_id = N_("(Random)");
+ break;
+ case PROP_INVSQUARE:
+ pet_id = N_("(InvSquare)");
+ break;
+ default:
+ break;
+ }
+
+ if (pet_id) {
+ BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ td->factor = 1.0;
+ }
+ }
+ }
}
/**
@@ -2325,101 +2333,100 @@ void calculatePropRatio(TransInfo *t)
*/
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
{
- float totmat[3][3];
- float smat[3][3];
- float fmat[3][3];
- float obmat[3][3];
-
- float dmat[3][3]; /* delta rotation */
- float dmat_inv[3][3];
-
- mul_m3_m3m3(totmat, mat, td->mtx);
- mul_m3_m3m3(smat, td->smtx, mat);
-
- /* logic from BKE_object_rot_to_mat3 */
- if (use_drot) {
- if (td->ext->rotOrder > 0) {
- eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ float totmat[3][3];
+ float smat[3][3];
+ float fmat[3][3];
+ float obmat[3][3];
+
+ float dmat[3][3]; /* delta rotation */
+ float dmat_inv[3][3];
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, mat);
+
+ /* logic from BKE_object_rot_to_mat3 */
+ if (use_drot) {
+ if (td->ext->rotOrder > 0) {
+ eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
#if 0
- axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
+ axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
#else
- unit_m3(dmat);
+ unit_m3(dmat);
#endif
- }
- else {
- float tquat[4];
- normalize_qt_qt(tquat, td->ext->dquat);
- quat_to_mat3(dmat, tquat);
- }
-
- invert_m3_m3(dmat_inv, dmat);
- }
-
-
- if (td->ext->rotOrder == ROT_MODE_QUAT) {
- float quat[4];
-
- /* calculate the total rotatation */
- quat_to_mat3(obmat, td->ext->iquat);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_quat(quat, fmat);
-
- /* apply */
- copy_qt_qt(td->ext->quat, quat);
- }
- else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
- float axis[3], angle;
-
- /* calculate the total rotatation */
- axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_axis_angle(axis, &angle, fmat);
-
- /* apply */
- copy_v3_v3(td->ext->rotAxis, axis);
- *td->ext->rotAngle = angle;
- }
- else {
- float eul[3];
-
- /* calculate the total rotatation */
- eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
- if (use_drot) {
- mul_m3_m3m3(obmat, dmat, obmat);
- }
-
- /* mat = transform, obmat = object rotation */
- mul_m3_m3m3(fmat, smat, obmat);
-
- if (use_drot) {
- mul_m3_m3m3(fmat, dmat_inv, fmat);
- }
-
- mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
-
- /* apply */
- copy_v3_v3(td->ext->rot, eul);
- }
+ }
+ else {
+ float tquat[4];
+ normalize_qt_qt(tquat, td->ext->dquat);
+ quat_to_mat3(dmat, tquat);
+ }
+
+ invert_m3_m3(dmat_inv, dmat);
+ }
+
+ if (td->ext->rotOrder == ROT_MODE_QUAT) {
+ float quat[4];
+
+ /* calculate the total rotatation */
+ quat_to_mat3(obmat, td->ext->iquat);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_quat(quat, fmat);
+
+ /* apply */
+ copy_qt_qt(td->ext->quat, quat);
+ }
+ else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
+ float axis[3], angle;
+
+ /* calculate the total rotatation */
+ axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_axis_angle(axis, &angle, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rotAxis, axis);
+ *td->ext->rotAngle = angle;
+ }
+ else {
+ float eul[3];
+
+ /* calculate the total rotatation */
+ eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
+ if (use_drot) {
+ mul_m3_m3m3(obmat, dmat, obmat);
+ }
+
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ if (use_drot) {
+ mul_m3_m3m3(fmat, dmat_inv, fmat);
+ }
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* apply */
+ copy_v3_v3(td->ext->rot, eul);
+ }
}
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index cbc72f99168..f5b8f19ed02 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -54,93 +54,92 @@
/* axes as index */
enum {
- MAN2D_AXIS_TRANS_X = 0,
- MAN2D_AXIS_TRANS_Y,
+ MAN2D_AXIS_TRANS_X = 0,
+ MAN2D_AXIS_TRANS_Y,
- MAN2D_AXIS_LAST,
+ MAN2D_AXIS_LAST,
};
typedef struct GizmoGroup2D {
- wmGizmo *translate_x,
- *translate_y;
+ wmGizmo *translate_x, *translate_y;
- wmGizmo *cage;
+ wmGizmo *cage;
- /* Current origin in view space, used to update widget origin for possible view changes */
- float origin[2];
- float min[2];
- float max[2];
+ /* Current origin in view space, used to update widget origin for possible view changes */
+ float origin[2];
+ float min[2];
+ float max[2];
} GizmoGroup2D;
-
/* **************** Utilities **************** */
/* loop over axes */
#define MAN2D_ITER_AXES_BEGIN(axis, axis_idx) \
- { \
- wmGizmo *axis; \
- int axis_idx; \
- for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \
- axis = gizmo2d_get_axis_from_index(ggd, axis_idx);
+ { \
+ wmGizmo *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \
+ axis = gizmo2d_get_axis_from_index(ggd, axis_idx);
#define MAN2D_ITER_AXES_END \
- } \
- } ((void)0)
+ } \
+ } \
+ ((void)0)
static wmGizmo *gizmo2d_get_axis_from_index(const GizmoGroup2D *ggd, const short axis_idx)
{
- BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y));
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y));
- switch (axis_idx) {
- case MAN2D_AXIS_TRANS_X:
- return ggd->translate_x;
- case MAN2D_AXIS_TRANS_Y:
- return ggd->translate_y;
- }
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ return ggd->translate_x;
+ case MAN2D_AXIS_TRANS_Y:
+ return ggd->translate_y;
+ }
- return NULL;
+ return NULL;
}
static void gizmo2d_get_axis_color(const int axis_idx, float *r_col, float *r_col_hi)
{
- const float alpha = 0.6f;
- const float alpha_hi = 1.0f;
- int col_id;
-
- switch (axis_idx) {
- case MAN2D_AXIS_TRANS_X:
- col_id = TH_AXIS_X;
- break;
- case MAN2D_AXIS_TRANS_Y:
- col_id = TH_AXIS_Y;
- break;
- }
-
- UI_GetThemeColor4fv(col_id, r_col);
-
- copy_v4_v4(r_col_hi, r_col);
- r_col[3] *= alpha;
- r_col_hi[3] *= alpha_hi;
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ int col_id;
+
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ col_id = TH_AXIS_X;
+ break;
+ case MAN2D_AXIS_TRANS_Y:
+ col_id = TH_AXIS_Y;
+ break;
+ }
+
+ UI_GetThemeColor4fv(col_id, r_col);
+
+ copy_v4_v4(r_col_hi, r_col);
+ r_col[3] *= alpha;
+ r_col_hi[3] *= alpha_hi;
}
static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
{
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true);
- const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_2d", true);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_2d", true);
- GizmoGroup2D *ggd = MEM_callocN(sizeof(GizmoGroup2D), __func__);
+ GizmoGroup2D *ggd = MEM_callocN(sizeof(GizmoGroup2D), __func__);
- ggd->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ ggd->translate_x = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->translate_y = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
- RNA_enum_set(ggd->cage->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE);
+ RNA_enum_set(ggd->cage->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
+ ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE);
- return ggd;
+ return ggd;
}
/**
@@ -148,33 +147,33 @@ static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
*/
static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max)
{
- float min_buf[2], max_buf[2];
- if (r_min == NULL) {
- r_min = min_buf;
- }
- if (r_max == NULL) {
- r_max = max_buf;
- }
-
- ScrArea *sa = CTX_wm_area(C);
- if (sa->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = sa->spacedata.first;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Image *ima = ED_space_image(sima);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- view_layer, NULL, &objects_len);
- if (!ED_uvedit_minmax_multi(CTX_data_scene(C), ima, objects, objects_len, r_min, r_max)) {
- zero_v2(r_min);
- zero_v2(r_max);
- }
- MEM_freeN(objects);
- }
- else {
- zero_v2(r_min);
- zero_v2(r_max);
- }
- mid_v2_v2v2(r_center, r_min, r_max);
+ float min_buf[2], max_buf[2];
+ if (r_min == NULL) {
+ r_min = min_buf;
+ }
+ if (r_max == NULL) {
+ r_max = max_buf;
+ }
+
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Image *ima = ED_space_image(sima);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, NULL, &objects_len);
+ if (!ED_uvedit_minmax_multi(CTX_data_scene(C), ima, objects, objects_len, r_min, r_max)) {
+ zero_v2(r_min);
+ zero_v2(r_max);
+ }
+ MEM_freeN(objects);
+ }
+ else {
+ zero_v2(r_min);
+ zero_v2(r_max);
+ }
+ mid_v2_v2v2(r_center, r_min, r_max);
}
/**
@@ -182,171 +181,183 @@ static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
*/
BLI_INLINE void gizmo2d_origin_to_region(ARegion *ar, float *r_origin)
{
- UI_view2d_view_to_region_fl(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
+ UI_view2d_view_to_region_fl(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
}
/**
* Custom handler for gizmo widgets
*/
-static int gizmo2d_modal(
- bContext *C, wmGizmo *widget, const wmEvent *UNUSED(event),
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo2d_modal(bContext *C,
+ wmGizmo *widget,
+ const wmEvent *UNUSED(event),
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- ARegion *ar = CTX_wm_region(C);
- float origin[3];
+ ARegion *ar = CTX_wm_region(C);
+ float origin[3];
- gizmo2d_calc_bounds(C, origin, NULL, NULL);
- gizmo2d_origin_to_region(ar, origin);
- WM_gizmo_set_matrix_location(widget, origin);
+ gizmo2d_calc_bounds(C, origin, NULL, NULL);
+ gizmo2d_origin_to_region(ar, origin);
+ WM_gizmo_set_matrix_location(widget, origin);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void ED_widgetgroup_gizmo2d_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
- GizmoGroup2D *ggd = gizmogroup2d_init(gzgroup);
- gzgroup->customdata = ggd;
-
- MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const float offset[3] = {0.0f, 0.2f};
-
- float color[4], color_hi[4];
- gizmo2d_get_axis_color(axis_idx, color, color_hi);
-
- /* custom handler! */
- WM_gizmo_set_fn_custom_modal(axis, gizmo2d_modal);
- /* set up widget data */
- RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx);
- RNA_float_set(axis->ptr, "length", 0.8f);
- WM_gizmo_set_matrix_offset_location(axis, offset);
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- WM_gizmo_set_scale(axis, U.gizmo_size);
- WM_gizmo_set_color(axis, color);
- WM_gizmo_set_color_highlight(axis, color_hi);
-
- /* assign operator */
- PointerRNA *ptr = WM_gizmo_operator_set(axis, 0, ot_translate, NULL);
- bool constraint[3] = {0};
- constraint[(axis_idx + 1) % 2] = 1;
- if (RNA_struct_find_property(ptr, "constraint_axis"))
- RNA_boolean_set_array(ptr, "constraint_axis", constraint);
- RNA_boolean_set(ptr, "release_confirm", 1);
- }
- MAN2D_ITER_AXES_END;
-
- {
- wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
- PointerRNA *ptr;
-
- /* assign operator */
- ptr = WM_gizmo_operator_set(ggd->cage, 0, ot_translate, NULL);
- RNA_boolean_set(ptr, "release_confirm", 1);
-
- bool constraint_x[3] = {1, 0, 0};
- bool constraint_y[3] = {0, 1, 0};
-
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
- PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
- PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
-
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE, ot_rotate, NULL);
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- }
+ wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
+ GizmoGroup2D *ggd = gizmogroup2d_init(gzgroup);
+ gzgroup->customdata = ggd;
+
+ MAN2D_ITER_AXES_BEGIN (axis, axis_idx) {
+ const float offset[3] = {0.0f, 0.2f};
+
+ float color[4], color_hi[4];
+ gizmo2d_get_axis_color(axis_idx, color, color_hi);
+
+ /* custom handler! */
+ WM_gizmo_set_fn_custom_modal(axis, gizmo2d_modal);
+ /* set up widget data */
+ RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx);
+ RNA_float_set(axis->ptr, "length", 0.8f);
+ WM_gizmo_set_matrix_offset_location(axis, offset);
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ WM_gizmo_set_scale(axis, U.gizmo_size);
+ WM_gizmo_set_color(axis, color);
+ WM_gizmo_set_color_highlight(axis, color_hi);
+
+ /* assign operator */
+ PointerRNA *ptr = WM_gizmo_operator_set(axis, 0, ot_translate, NULL);
+ bool constraint[3] = {0};
+ constraint[(axis_idx + 1) % 2] = 1;
+ if (RNA_struct_find_property(ptr, "constraint_axis"))
+ RNA_boolean_set_array(ptr, "constraint_axis", constraint);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ MAN2D_ITER_AXES_END;
+
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ ptr = WM_gizmo_operator_set(ggd->cage, 0, ot_translate, NULL);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+
+ bool constraint_x[3] = {1, 0, 0};
+ bool constraint_y[3] = {0, 1, 0};
+
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
+ PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(
+ ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE, ot_rotate, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ }
}
void ED_widgetgroup_gizmo2d_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup2D *ggd = gzgroup->customdata;
- float origin[3];
- gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
- copy_v2_v2(ggd->origin, origin);
- bool show_cage = !equals_v2v2(ggd->min, ggd->max);
-
- if (show_cage) {
- ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
- ggd->translate_x->flag |= WM_GIZMO_HIDDEN;
- ggd->translate_y->flag |= WM_GIZMO_HIDDEN;
- }
- else {
- ggd->cage->flag |= WM_GIZMO_HIDDEN;
- ggd->translate_x->flag &= ~WM_GIZMO_HIDDEN;
- ggd->translate_y->flag &= ~WM_GIZMO_HIDDEN;
- }
-
- if (show_cage) {
- wmGizmoOpElem *gzop;
- float mid[2];
- const float *min = ggd->min;
- const float *max = ggd->max;
- mid_v2_v2v2(mid, min, max);
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
- PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
- }
+ GizmoGroup2D *ggd = gzgroup->customdata;
+ float origin[3];
+ gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
+ copy_v2_v2(ggd->origin, origin);
+ bool show_cage = !equals_v2v2(ggd->min, ggd->max);
+
+ if (show_cage) {
+ ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
+ ggd->translate_x->flag |= WM_GIZMO_HIDDEN;
+ ggd->translate_y->flag |= WM_GIZMO_HIDDEN;
+ }
+ else {
+ ggd->cage->flag |= WM_GIZMO_HIDDEN;
+ ggd->translate_x->flag &= ~WM_GIZMO_HIDDEN;
+ ggd->translate_y->flag &= ~WM_GIZMO_HIDDEN;
+ }
+
+ if (show_cage) {
+ wmGizmoOpElem *gzop;
+ float mid[2];
+ const float *min = ggd->min;
+ const float *max = ggd->max;
+ mid_v2_v2v2(mid, min, max);
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
+ PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
+ RNA_property_float_set_array(
+ &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+ }
}
void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
- GizmoGroup2D *ggd = gzgroup->customdata;
- float origin[3] = {UNPACK2(ggd->origin), 0.0f};
- float origin_aa[3] = {UNPACK2(ggd->origin), 0.0f};
-
- gizmo2d_origin_to_region(ar, origin);
-
- MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
- {
- WM_gizmo_set_matrix_location(axis, origin);
- }
- MAN2D_ITER_AXES_END;
-
- UI_view2d_view_to_region_m4(&ar->v2d, ggd->cage->matrix_space);
- WM_gizmo_set_matrix_offset_location(ggd->cage, origin_aa);
- ggd->cage->matrix_offset[0][0] = (ggd->max[0] - ggd->min[0]);
- ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]);
+ ARegion *ar = CTX_wm_region(C);
+ GizmoGroup2D *ggd = gzgroup->customdata;
+ float origin[3] = {UNPACK2(ggd->origin), 0.0f};
+ float origin_aa[3] = {UNPACK2(ggd->origin), 0.0f};
+
+ gizmo2d_origin_to_region(ar, origin);
+
+ MAN2D_ITER_AXES_BEGIN (axis, axis_idx) {
+ WM_gizmo_set_matrix_location(axis, origin);
+ }
+ MAN2D_ITER_AXES_END;
+
+ UI_view2d_view_to_region_m4(&ar->v2d, ggd->cage->matrix_space);
+ WM_gizmo_set_matrix_offset_location(ggd->cage, origin_aa);
+ ggd->cage->matrix_offset[0][0] = (ggd->max[0] - ggd->min[0]);
+ ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]);
}
/* TODO (Julian)
@@ -355,35 +366,35 @@ void ED_widgetgroup_gizmo2d_draw_prepare(const bContext *C, wmGizmoGroup *gzgrou
*/
bool ED_widgetgroup_gizmo2d_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
{
- if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
- return false;
- }
-
- SpaceImage *sima = CTX_wm_space_image(C);
- Object *obedit = CTX_data_edit_object(C);
-
- if (ED_space_image_show_uvedit(sima, obedit)) {
- Image *ima = ED_space_image(sima);
- Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
- /* check if there's a selected poly */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!uvedit_face_visible_test(scene, obedit, ima, efa))
- continue;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- return true;
- }
- }
- }
- }
-
- return false;
+ if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
+ return false;
+ }
+
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ Image *ima = ED_space_image(sima);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* check if there's a selected poly */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, obedit, ima, efa))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 77480e1a8ce..1fde0006c2b 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -94,89 +94,89 @@
/* return codes for select, and drawing flags */
-#define MAN_TRANS_X (1 << 0)
-#define MAN_TRANS_Y (1 << 1)
-#define MAN_TRANS_Z (1 << 2)
-#define MAN_TRANS_C (MAN_TRANS_X | MAN_TRANS_Y | MAN_TRANS_Z)
+#define MAN_TRANS_X (1 << 0)
+#define MAN_TRANS_Y (1 << 1)
+#define MAN_TRANS_Z (1 << 2)
+#define MAN_TRANS_C (MAN_TRANS_X | MAN_TRANS_Y | MAN_TRANS_Z)
-#define MAN_ROT_X (1 << 3)
-#define MAN_ROT_Y (1 << 4)
-#define MAN_ROT_Z (1 << 5)
-#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
+#define MAN_ROT_X (1 << 3)
+#define MAN_ROT_Y (1 << 4)
+#define MAN_ROT_Z (1 << 5)
+#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
-#define MAN_SCALE_X (1 << 8)
-#define MAN_SCALE_Y (1 << 9)
-#define MAN_SCALE_Z (1 << 10)
-#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
+#define MAN_SCALE_X (1 << 8)
+#define MAN_SCALE_Y (1 << 9)
+#define MAN_SCALE_Z (1 << 10)
+#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
/* threshold for testing view aligned gizmo axis */
static struct {
- float min, max;
+ float min, max;
} g_tw_axis_range[2] = {
- /* Regular range */
- {0.02f, 0.1f},
- /* Use a different range because we flip the dot product,
- * also the view aligned planes are harder to see so hiding early is preferred. */
- {0.175f, 0.25f},
+ /* Regular range */
+ {0.02f, 0.1f},
+ /* Use a different range because we flip the dot product,
+ * also the view aligned planes are harder to see so hiding early is preferred. */
+ {0.175f, 0.25f},
};
/* axes as index */
enum {
- MAN_AXIS_TRANS_X = 0,
- MAN_AXIS_TRANS_Y,
- MAN_AXIS_TRANS_Z,
- MAN_AXIS_TRANS_C,
-
- MAN_AXIS_TRANS_XY,
- MAN_AXIS_TRANS_YZ,
- MAN_AXIS_TRANS_ZX,
+ MAN_AXIS_TRANS_X = 0,
+ MAN_AXIS_TRANS_Y,
+ MAN_AXIS_TRANS_Z,
+ MAN_AXIS_TRANS_C,
+
+ MAN_AXIS_TRANS_XY,
+ MAN_AXIS_TRANS_YZ,
+ MAN_AXIS_TRANS_ZX,
#define MAN_AXIS_RANGE_TRANS_START MAN_AXIS_TRANS_X
#define MAN_AXIS_RANGE_TRANS_END (MAN_AXIS_TRANS_ZX + 1)
- MAN_AXIS_ROT_X,
- MAN_AXIS_ROT_Y,
- MAN_AXIS_ROT_Z,
- MAN_AXIS_ROT_C,
- MAN_AXIS_ROT_T, /* trackball rotation */
+ MAN_AXIS_ROT_X,
+ MAN_AXIS_ROT_Y,
+ MAN_AXIS_ROT_Z,
+ MAN_AXIS_ROT_C,
+ MAN_AXIS_ROT_T, /* trackball rotation */
#define MAN_AXIS_RANGE_ROT_START MAN_AXIS_ROT_X
#define MAN_AXIS_RANGE_ROT_END (MAN_AXIS_ROT_T + 1)
- MAN_AXIS_SCALE_X,
- MAN_AXIS_SCALE_Y,
- MAN_AXIS_SCALE_Z,
- MAN_AXIS_SCALE_C,
- MAN_AXIS_SCALE_XY,
- MAN_AXIS_SCALE_YZ,
- MAN_AXIS_SCALE_ZX,
+ MAN_AXIS_SCALE_X,
+ MAN_AXIS_SCALE_Y,
+ MAN_AXIS_SCALE_Z,
+ MAN_AXIS_SCALE_C,
+ MAN_AXIS_SCALE_XY,
+ MAN_AXIS_SCALE_YZ,
+ MAN_AXIS_SCALE_ZX,
#define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X
#define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1)
- MAN_AXIS_LAST = MAN_AXIS_SCALE_ZX + 1,
+ MAN_AXIS_LAST = MAN_AXIS_SCALE_ZX + 1,
};
/* axis types */
enum {
- MAN_AXES_ALL = 0,
- MAN_AXES_TRANSLATE,
- MAN_AXES_ROTATE,
- MAN_AXES_SCALE,
+ MAN_AXES_ALL = 0,
+ MAN_AXES_TRANSLATE,
+ MAN_AXES_ROTATE,
+ MAN_AXES_SCALE,
};
typedef struct GizmoGroup {
- bool all_hidden;
- int twtype;
+ bool all_hidden;
+ int twtype;
- /* Users may change the twtype, detect changes to re-setup gizmo options. */
- int twtype_init;
- int twtype_prev;
- int use_twtype_refresh;
+ /* Users may change the twtype, detect changes to re-setup gizmo options. */
+ int twtype_init;
+ int twtype_prev;
+ int use_twtype_refresh;
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
- struct wmGizmo *gizmos[MAN_AXIS_LAST];
+ struct wmGizmo *gizmos[MAN_AXIS_LAST];
} GizmoGroup;
/* -------------------------------------------------------------------- */
@@ -185,991 +185,987 @@ typedef struct GizmoGroup {
/* loop over axes */
#define MAN_ITER_AXES_BEGIN(axis, axis_idx) \
- { \
- wmGizmo *axis; \
- int axis_idx; \
- for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
- axis = gizmo_get_axis_from_index(ggd, axis_idx);
+ { \
+ wmGizmo *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
+ axis = gizmo_get_axis_from_index(ggd, axis_idx);
#define MAN_ITER_AXES_END \
- } \
- } ((void)0)
+ } \
+ } \
+ ((void)0)
static wmGizmo *gizmo_get_axis_from_index(const GizmoGroup *ggd, const short axis_idx)
{
- BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
- return ggd->gizmos[axis_idx];
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
+ return ggd->gizmos[axis_idx];
}
static short gizmo_get_axis_type(const int axis_idx)
{
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- return MAN_AXES_TRANSLATE;
- }
- if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
- return MAN_AXES_ROTATE;
- }
- if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
- return MAN_AXES_SCALE;
- }
- BLI_assert(0);
- return -1;
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ return MAN_AXES_TRANSLATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
+ return MAN_AXES_ROTATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
+ return MAN_AXES_SCALE;
+ }
+ BLI_assert(0);
+ return -1;
}
static uint gizmo_orientation_axis(const int axis_idx, bool *r_is_plane)
{
- switch (axis_idx) {
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- return 0;
-
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- return 1;
-
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- if (r_is_plane) {
- *r_is_plane = true;
- }
- ATTR_FALLTHROUGH;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- return 2;
- }
- return 3;
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ return 0;
+
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ return 1;
+
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ return 2;
+ }
+ return 3;
}
-static bool gizmo_is_axis_visible(
- const RegionView3D *rv3d, const int twtype,
- const float idot[3], const int axis_type, const int axis_idx)
+static bool gizmo_is_axis_visible(const RegionView3D *rv3d,
+ const int twtype,
+ const float idot[3],
+ const int axis_type,
+ const int axis_idx)
{
- if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
- bool is_plane = false;
- const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
- /* don't draw axis perpendicular to the view */
- if (aidx_norm < 3) {
- float idot_axis = idot[aidx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- if (idot_axis < g_tw_axis_range[is_plane].min) {
- return false;
- }
- }
- }
-
- if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE)) ||
- (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE)) ||
- (axis_type == MAN_AXES_SCALE && !(twtype & V3D_GIZMO_SHOW_OBJECT_SCALE)))
- {
- return false;
- }
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- return (rv3d->twdrawflag & MAN_TRANS_X);
- case MAN_AXIS_TRANS_Y:
- return (rv3d->twdrawflag & MAN_TRANS_Y);
- case MAN_AXIS_TRANS_Z:
- return (rv3d->twdrawflag & MAN_TRANS_Z);
- case MAN_AXIS_TRANS_C:
- return (rv3d->twdrawflag & MAN_TRANS_C);
- case MAN_AXIS_ROT_X:
- return (rv3d->twdrawflag & MAN_ROT_X);
- case MAN_AXIS_ROT_Y:
- return (rv3d->twdrawflag & MAN_ROT_Y);
- case MAN_AXIS_ROT_Z:
- return (rv3d->twdrawflag & MAN_ROT_Z);
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_ROT_T:
- return (rv3d->twdrawflag & MAN_ROT_C);
- case MAN_AXIS_SCALE_X:
- return (rv3d->twdrawflag & MAN_SCALE_X);
- case MAN_AXIS_SCALE_Y:
- return (rv3d->twdrawflag & MAN_SCALE_Y);
- case MAN_AXIS_SCALE_Z:
- return (rv3d->twdrawflag & MAN_SCALE_Z);
- case MAN_AXIS_SCALE_C:
- return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0);
- case MAN_AXIS_TRANS_XY:
- return (rv3d->twdrawflag & MAN_TRANS_X &&
- rv3d->twdrawflag & MAN_TRANS_Y &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_TRANS_YZ:
- return (rv3d->twdrawflag & MAN_TRANS_Y &&
- rv3d->twdrawflag & MAN_TRANS_Z &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_TRANS_ZX:
- return (rv3d->twdrawflag & MAN_TRANS_Z &&
- rv3d->twdrawflag & MAN_TRANS_X &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_XY:
- return (rv3d->twdrawflag & MAN_SCALE_X &&
- rv3d->twdrawflag & MAN_SCALE_Y &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_YZ:
- return (rv3d->twdrawflag & MAN_SCALE_Y &&
- rv3d->twdrawflag & MAN_SCALE_Z &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- case MAN_AXIS_SCALE_ZX:
- return (rv3d->twdrawflag & MAN_SCALE_Z &&
- rv3d->twdrawflag & MAN_SCALE_X &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
- (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
- }
- return false;
+ if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
+ bool is_plane = false;
+ const uint aidx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
+ /* don't draw axis perpendicular to the view */
+ if (aidx_norm < 3) {
+ float idot_axis = idot[aidx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ if (idot_axis < g_tw_axis_range[is_plane].min) {
+ return false;
+ }
+ }
+ }
+
+ if ((axis_type == MAN_AXES_TRANSLATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE)) ||
+ (axis_type == MAN_AXES_ROTATE && !(twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE)) ||
+ (axis_type == MAN_AXES_SCALE && !(twtype & V3D_GIZMO_SHOW_OBJECT_SCALE))) {
+ return false;
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ return (rv3d->twdrawflag & MAN_TRANS_X);
+ case MAN_AXIS_TRANS_Y:
+ return (rv3d->twdrawflag & MAN_TRANS_Y);
+ case MAN_AXIS_TRANS_Z:
+ return (rv3d->twdrawflag & MAN_TRANS_Z);
+ case MAN_AXIS_TRANS_C:
+ return (rv3d->twdrawflag & MAN_TRANS_C);
+ case MAN_AXIS_ROT_X:
+ return (rv3d->twdrawflag & MAN_ROT_X);
+ case MAN_AXIS_ROT_Y:
+ return (rv3d->twdrawflag & MAN_ROT_Y);
+ case MAN_AXIS_ROT_Z:
+ return (rv3d->twdrawflag & MAN_ROT_Z);
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_ROT_T:
+ return (rv3d->twdrawflag & MAN_ROT_C);
+ case MAN_AXIS_SCALE_X:
+ return (rv3d->twdrawflag & MAN_SCALE_X);
+ case MAN_AXIS_SCALE_Y:
+ return (rv3d->twdrawflag & MAN_SCALE_Y);
+ case MAN_AXIS_SCALE_Z:
+ return (rv3d->twdrawflag & MAN_SCALE_Z);
+ case MAN_AXIS_SCALE_C:
+ return (rv3d->twdrawflag & MAN_SCALE_C && (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0);
+ case MAN_AXIS_TRANS_XY:
+ return (rv3d->twdrawflag & MAN_TRANS_X && rv3d->twdrawflag & MAN_TRANS_Y &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_TRANS_YZ:
+ return (rv3d->twdrawflag & MAN_TRANS_Y && rv3d->twdrawflag & MAN_TRANS_Z &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_TRANS_ZX:
+ return (rv3d->twdrawflag & MAN_TRANS_Z && rv3d->twdrawflag & MAN_TRANS_X &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_XY:
+ return (rv3d->twdrawflag & MAN_SCALE_X && rv3d->twdrawflag & MAN_SCALE_Y &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_YZ:
+ return (rv3d->twdrawflag & MAN_SCALE_Y && rv3d->twdrawflag & MAN_SCALE_Z &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ case MAN_AXIS_SCALE_ZX:
+ return (rv3d->twdrawflag & MAN_SCALE_Z && rv3d->twdrawflag & MAN_SCALE_X &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_TRANSLATE) == 0 &&
+ (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) == 0);
+ }
+ return false;
}
-static void gizmo_get_axis_color(
- const int axis_idx, const float idot[3],
- float r_col[4], float r_col_hi[4])
+static void gizmo_get_axis_color(const int axis_idx,
+ const float idot[3],
+ float r_col[4],
+ float r_col_hi[4])
{
- /* alpha values for normal/highlighted states */
- const float alpha = 0.6f;
- const float alpha_hi = 1.0f;
- float alpha_fac;
-
- if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
- /* Never fade rotation rings. */
- /* trackball rotation axis is a special case, we only draw a slight overlay */
- alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f;
- }
- else {
- bool is_plane = false;
- const int axis_idx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
- /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
- if (axis_idx_norm < 3) {
- const float idot_min = g_tw_axis_range[is_plane].min;
- const float idot_max = g_tw_axis_range[is_plane].max;
- float idot_axis = idot[axis_idx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- alpha_fac = (
- (idot_axis > idot_max) ?
- 1.0f : (idot_axis < idot_min) ?
- 0.0f : ((idot_axis - idot_min) / (idot_max - idot_min)));
- }
- else {
- alpha_fac = 1.0f;
- }
- }
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- UI_GetThemeColor4fv(TH_AXIS_X, r_col);
- break;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- UI_GetThemeColor4fv(TH_AXIS_Y, r_col);
- break;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- UI_GetThemeColor4fv(TH_AXIS_Z, r_col);
- break;
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- copy_v4_fl(r_col, 1.0f);
- break;
- }
-
- copy_v4_v4(r_col_hi, r_col);
-
- r_col[3] = alpha * alpha_fac;
- r_col_hi[3] = alpha_hi * alpha_fac;
+ /* alpha values for normal/highlighted states */
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ float alpha_fac;
+
+ if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
+ /* Never fade rotation rings. */
+ /* trackball rotation axis is a special case, we only draw a slight overlay */
+ alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f;
+ }
+ else {
+ bool is_plane = false;
+ const int axis_idx_norm = gizmo_orientation_axis(axis_idx, &is_plane);
+ /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
+ if (axis_idx_norm < 3) {
+ const float idot_min = g_tw_axis_range[is_plane].min;
+ const float idot_max = g_tw_axis_range[is_plane].max;
+ float idot_axis = idot[axis_idx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ alpha_fac = ((idot_axis > idot_max) ?
+ 1.0f :
+ (idot_axis < idot_min) ? 0.0f :
+ ((idot_axis - idot_min) / (idot_max - idot_min)));
+ }
+ else {
+ alpha_fac = 1.0f;
+ }
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ UI_GetThemeColor4fv(TH_AXIS_X, r_col);
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ UI_GetThemeColor4fv(TH_AXIS_Y, r_col);
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ UI_GetThemeColor4fv(TH_AXIS_Z, r_col);
+ break;
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ copy_v4_fl(r_col, 1.0f);
+ break;
+ }
+
+ copy_v4_v4(r_col_hi, r_col);
+
+ r_col[3] = alpha * alpha_fac;
+ r_col_hi[3] = alpha_hi * alpha_fac;
}
static void gizmo_get_axis_constraint(const int axis_idx, bool r_axis[3])
{
- ARRAY_SET_ITEMS(r_axis, 0, 0, 0);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_SCALE_X:
- r_axis[0] = 1;
- break;
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_SCALE_Y:
- r_axis[1] = 1;
- break;
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_ROT_Z:
- case MAN_AXIS_SCALE_Z:
- r_axis[2] = 1;
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_SCALE_XY:
- r_axis[0] = r_axis[1] = 1;
- break;
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_SCALE_YZ:
- r_axis[1] = r_axis[2] = 1;
- break;
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_ZX:
- r_axis[2] = r_axis[0] = 1;
- break;
- default:
- break;
- }
+ ARRAY_SET_ITEMS(r_axis, 0, 0, 0);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ r_axis[0] = 1;
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ r_axis[0] = r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ r_axis[1] = r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ r_axis[2] = r_axis[0] = 1;
+ break;
+ default:
+ break;
+ }
}
-
/* **************** Preparation Stuff **************** */
static void reset_tw_center(struct TransformBounds *tbounds)
{
- INIT_MINMAX(tbounds->min, tbounds->max);
- zero_v3(tbounds->center);
+ INIT_MINMAX(tbounds->min, tbounds->max);
+ zero_v3(tbounds->center);
- for (int i = 0; i < 3; i++) {
- tbounds->axis_min[i] = +FLT_MAX;
- tbounds->axis_max[i] = -FLT_MAX;
- }
+ for (int i = 0; i < 3; i++) {
+ tbounds->axis_min[i] = +FLT_MAX;
+ tbounds->axis_max[i] = -FLT_MAX;
+ }
}
/* transform widget center calc helper for below */
static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
{
- minmax_v3v3_v3(tbounds->min, tbounds->max, co);
- add_v3_v3(tbounds->center, co);
-
- for (int i = 0; i < 3; i++) {
- const float d = dot_v3v3(tbounds->axis[i], co);
- tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
- tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
- }
+ minmax_v3v3_v3(tbounds->min, tbounds->max, co);
+ add_v3_v3(tbounds->center, co);
+
+ for (int i = 0; i < 3; i++) {
+ const float d = dot_v3v3(tbounds->axis[i], co);
+ tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
+ tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
+ }
}
-static void calc_tw_center_with_matrix(
- struct TransformBounds *tbounds, const float co[3],
- const bool use_matrix, const float matrix[4][4])
+static void calc_tw_center_with_matrix(struct TransformBounds *tbounds,
+ const float co[3],
+ const bool use_matrix,
+ const float matrix[4][4])
{
- float co_world[3];
- if (use_matrix) {
- mul_v3_m4v3(co_world, matrix, co);
- co = co_world;
- }
- calc_tw_center(tbounds, co);
+ float co_world[3];
+ if (use_matrix) {
+ mul_v3_m4v3(co_world, matrix, co);
+ co = co_world;
+ }
+ calc_tw_center(tbounds, co);
}
static void protectflag_to_drawflags(short protectflag, short *drawflags)
{
- if (protectflag & OB_LOCK_LOCX)
- *drawflags &= ~MAN_TRANS_X;
- if (protectflag & OB_LOCK_LOCY)
- *drawflags &= ~MAN_TRANS_Y;
- if (protectflag & OB_LOCK_LOCZ)
- *drawflags &= ~MAN_TRANS_Z;
-
- if (protectflag & OB_LOCK_ROTX)
- *drawflags &= ~MAN_ROT_X;
- if (protectflag & OB_LOCK_ROTY)
- *drawflags &= ~MAN_ROT_Y;
- if (protectflag & OB_LOCK_ROTZ)
- *drawflags &= ~MAN_ROT_Z;
-
- if (protectflag & OB_LOCK_SCALEX)
- *drawflags &= ~MAN_SCALE_X;
- if (protectflag & OB_LOCK_SCALEY)
- *drawflags &= ~MAN_SCALE_Y;
- if (protectflag & OB_LOCK_SCALEZ)
- *drawflags &= ~MAN_SCALE_Z;
+ if (protectflag & OB_LOCK_LOCX)
+ *drawflags &= ~MAN_TRANS_X;
+ if (protectflag & OB_LOCK_LOCY)
+ *drawflags &= ~MAN_TRANS_Y;
+ if (protectflag & OB_LOCK_LOCZ)
+ *drawflags &= ~MAN_TRANS_Z;
+
+ if (protectflag & OB_LOCK_ROTX)
+ *drawflags &= ~MAN_ROT_X;
+ if (protectflag & OB_LOCK_ROTY)
+ *drawflags &= ~MAN_ROT_Y;
+ if (protectflag & OB_LOCK_ROTZ)
+ *drawflags &= ~MAN_ROT_Z;
+
+ if (protectflag & OB_LOCK_SCALEX)
+ *drawflags &= ~MAN_SCALE_X;
+ if (protectflag & OB_LOCK_SCALEY)
+ *drawflags &= ~MAN_SCALE_Y;
+ if (protectflag & OB_LOCK_SCALEZ)
+ *drawflags &= ~MAN_SCALE_Z;
}
/* for pose mode */
static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan)
{
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
}
/* for editmode*/
static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo)
{
- if (ebo->flag & BONE_EDITMODE_LOCKED) {
- protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
- }
+ if (ebo->flag & BONE_EDITMODE_LOCKED) {
+ protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
+ }
}
/* could move into BLI_math however this is only useful for display/editing purposes */
static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle)
{
- /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
+ /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */
- float cross_vec[3];
- float quat[4];
+ float cross_vec[3];
+ float quat[4];
- /* this is an un-scientific method to get a vector to cross with
- * XYZ intentionally YZX */
- cross_vec[0] = axis[1];
- cross_vec[1] = axis[2];
- cross_vec[2] = axis[0];
+ /* this is an un-scientific method to get a vector to cross with
+ * XYZ intentionally YZX */
+ cross_vec[0] = axis[1];
+ cross_vec[1] = axis[2];
+ cross_vec[2] = axis[0];
- /* X-axis */
- cross_v3_v3v3(gmat[0], cross_vec, axis);
- normalize_v3(gmat[0]);
- axis_angle_to_quat(quat, axis, angle);
- mul_qt_v3(quat, gmat[0]);
+ /* X-axis */
+ cross_v3_v3v3(gmat[0], cross_vec, axis);
+ normalize_v3(gmat[0]);
+ axis_angle_to_quat(quat, axis, angle);
+ mul_qt_v3(quat, gmat[0]);
- /* Y-axis */
- axis_angle_to_quat(quat, axis, M_PI_2);
- copy_v3_v3(gmat[1], gmat[0]);
- mul_qt_v3(quat, gmat[1]);
+ /* Y-axis */
+ axis_angle_to_quat(quat, axis, M_PI_2);
+ copy_v3_v3(gmat[1], gmat[0]);
+ mul_qt_v3(quat, gmat[1]);
- /* Z-axis */
- copy_v3_v3(gmat[2], axis);
+ /* Z-axis */
+ copy_v3_v3(gmat[2], axis);
- normalize_m3(gmat);
+ normalize_m3(gmat);
}
-
static bool test_rotmode_euler(short rotmode)
{
- return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
+ return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
}
bool gimbal_axis(Object *ob, float gmat[3][3])
{
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
-
- if (pchan) {
- float mat[3][3], tmat[3][3], obmat[3][3];
- if (test_rotmode_euler(pchan->rotmode)) {
- eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
- }
- else { /* quat */
- return 0;
- }
-
-
- /* apply bone transformation */
- mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
-
- if (pchan->parent) {
- float parent_mat[3][3];
-
- copy_m3_m4(parent_mat, pchan->parent->pose_mat);
- mul_m3_m3m3(mat, parent_mat, tmat);
-
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, mat);
- }
- else {
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, tmat);
- }
-
- normalize_m3(gmat);
- return 1;
- }
- }
- else {
- if (test_rotmode_euler(ob->rotmode)) {
- eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
- }
- else { /* quat */
- return 0;
- }
-
- if (ob->parent) {
- float parent_mat[3][3];
- copy_m3_m4(parent_mat, ob->parent->obmat);
- normalize_m3(parent_mat);
- mul_m3_m3m3(gmat, parent_mat, gmat);
- }
- return 1;
- }
-
- return 0;
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ if (pchan) {
+ float mat[3][3], tmat[3][3], obmat[3][3];
+ if (test_rotmode_euler(pchan->rotmode)) {
+ eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
+ }
+ else { /* quat */
+ return 0;
+ }
+
+ /* apply bone transformation */
+ mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
+
+ if (pchan->parent) {
+ float parent_mat[3][3];
+
+ copy_m3_m4(parent_mat, pchan->parent->pose_mat);
+ mul_m3_m3m3(mat, parent_mat, tmat);
+
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, mat);
+ }
+ else {
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, tmat);
+ }
+
+ normalize_m3(gmat);
+ return 1;
+ }
+ }
+ else {
+ if (test_rotmode_euler(ob->rotmode)) {
+ eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
+ }
+ else { /* quat */
+ return 0;
+ }
+
+ if (ob->parent) {
+ float parent_mat[3][3];
+ copy_m3_m4(parent_mat, ob->parent->obmat);
+ normalize_m3(parent_mat);
+ mul_m3_m3m3(gmat, parent_mat, gmat);
+ }
+ return 1;
+ }
+
+ return 0;
}
-void ED_transform_calc_orientation_from_type(
- const bContext *C, float r_mat[3][3])
+void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
{
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = ar->regiondata;
- Object *ob = OBACT(view_layer);
- const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- ED_transform_calc_orientation_from_type_ex(
- C, r_mat,
- scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Object *ob = OBACT(view_layer);
+ const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
+
+ ED_transform_calc_orientation_from_type_ex(
+ C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
}
-void ED_transform_calc_orientation_from_type_ex(
- const bContext *C, float r_mat[3][3],
- /* extra args (can be accessed from context) */
- Scene *scene, RegionView3D *rv3d, Object *ob, Object *obedit,
- const short orientation_type, int orientation_index_custom,
- const int pivot_point)
+void ED_transform_calc_orientation_from_type_ex(const bContext *C,
+ float r_mat[3][3],
+ /* extra args (can be accessed from context) */
+ Scene *scene,
+ RegionView3D *rv3d,
+ Object *ob,
+ Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point)
{
- bool ok = false;
-
- switch (orientation_type) {
- case V3D_ORIENT_GLOBAL:
- {
- break; /* nothing to do */
- }
- case V3D_ORIENT_GIMBAL:
- {
- if (gimbal_axis(ob, r_mat)) {
- ok = true;
- break;
- }
- /* if not gimbal, fall through to normal */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_NORMAL:
- {
- if (obedit || ob->mode & OB_MODE_POSE) {
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- /* no break we define 'normal' as 'local' in Object mode */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_LOCAL:
- {
- if (ob->mode & OB_MODE_POSE) {
- /* each bone moves on its own local axis, but to avoid confusion,
- * use the active pones axis for display [#33575], this works as expected on a single bone
- * and users who select many bones will understand what's going on and what local means
- * when they start transforming */
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- copy_m3_m4(r_mat, ob->obmat);
- normalize_m3(r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_VIEW:
- {
- if (rv3d != NULL) {
- copy_m3_m4(r_mat, rv3d->viewinv);
- normalize_m3(r_mat);
- ok = true;
- }
- break;
- }
- case V3D_ORIENT_CURSOR:
- {
- ED_view3d_cursor3d_calc_mat3(scene, r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_CUSTOM:
- {
- TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
- scene, orientation_index_custom);
- if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
- ok = true;
- }
- break;
- }
- }
-
- if (!ok) {
- unit_m3(r_mat);
- }
+ bool ok = false;
+
+ switch (orientation_type) {
+ case V3D_ORIENT_GLOBAL: {
+ break; /* nothing to do */
+ }
+ case V3D_ORIENT_GIMBAL: {
+ if (gimbal_axis(ob, r_mat)) {
+ ok = true;
+ break;
+ }
+ /* if not gimbal, fall through to normal */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_NORMAL: {
+ if (obedit || ob->mode & OB_MODE_POSE) {
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ ok = true;
+ break;
+ }
+ /* no break we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_LOCAL: {
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single bone
+ * and users who select many bones will understand what's going on and what local means
+ * when they start transforming */
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ ok = true;
+ break;
+ }
+ copy_m3_m4(r_mat, ob->obmat);
+ normalize_m3(r_mat);
+ ok = true;
+ break;
+ }
+ case V3D_ORIENT_VIEW: {
+ if (rv3d != NULL) {
+ copy_m3_m4(r_mat, rv3d->viewinv);
+ normalize_m3(r_mat);
+ ok = true;
+ }
+ break;
+ }
+ case V3D_ORIENT_CURSOR: {
+ ED_view3d_cursor3d_calc_mat3(scene, r_mat);
+ ok = true;
+ break;
+ }
+ case V3D_ORIENT_CUSTOM: {
+ TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
+ scene, orientation_index_custom);
+ if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
+ ok = true;
+ }
+ break;
+ }
+ }
+
+ if (!ok) {
+ unit_m3(r_mat);
+ }
}
/* centroid, boundbox, of selection */
/* returns total items selected */
-int ED_transform_calc_gizmo_stats(
- const bContext *C,
- const struct TransformCalcParams *params,
- struct TransformBounds *tbounds)
+int ED_transform_calc_gizmo_stats(const bContext *C,
+ const struct TransformCalcParams *params,
+ struct TransformBounds *tbounds)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = sa->spacedata.first;
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = ar->regiondata;
- Base *base;
- Object *ob = OBACT(view_layer);
- bGPdata *gpd = CTX_data_gpencil_data(C);
- const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
- int a, totsel = 0;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- /* transform widget matrix */
- unit_m4(rv3d->twmat);
-
- unit_m3(rv3d->tw_axis_matrix);
- zero_v3(rv3d->tw_axis_min);
- zero_v3(rv3d->tw_axis_max);
-
- rv3d->twdrawflag = 0xFFFF;
-
- /* global, local or normal orientation?
- * if we could check 'totsel' now, this should be skipped with no selection. */
- if (ob) {
- const short orientation_type = params->orientation_type ?
- (params->orientation_type - 1) : scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = params->orientation_type ?
- params->orientation_index_custom : scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- float mat[3][3];
- ED_transform_calc_orientation_from_type_ex(
- C, mat,
- scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
- copy_m4_m3(rv3d->twmat, mat);
- }
-
- /* transform widget centroid/center */
- reset_tw_center(tbounds);
-
- copy_m3_m4(tbounds->axis, rv3d->twmat);
- if (params->use_local_axis && (ob && ob->mode & OB_MODE_EDIT)) {
- float diff_mat[3][3];
- copy_m3_m4(diff_mat, ob->obmat);
- normalize_m3(diff_mat);
- invert_m3(diff_mat);
- mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
- normalize_m3(tbounds->axis);
- }
-
- if (is_gp_edit) {
- float diff_mat[4][4];
- const bool use_mat_local = true;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* only editable and visible layers are considered */
-
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
-
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
-
- for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
-
- /* we're only interested in selected points here... */
- if (gps->flag & GP_STROKE_SELECT) {
- bGPDspoint *pt;
- int i;
-
- /* Change selection status of all points, then make the stroke match */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
- totsel++;
- }
- }
- }
- }
- }
- }
-
-
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
- }
- }
- else if (obedit) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = sa->spacedata.first;
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Base *base;
+ Object *ob = OBACT(view_layer);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
+ int a, totsel = 0;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
+
+ /* transform widget matrix */
+ unit_m4(rv3d->twmat);
+
+ unit_m3(rv3d->tw_axis_matrix);
+ zero_v3(rv3d->tw_axis_min);
+ zero_v3(rv3d->tw_axis_max);
+
+ rv3d->twdrawflag = 0xFFFF;
+
+ /* global, local or normal orientation?
+ * if we could check 'totsel' now, this should be skipped with no selection. */
+ if (ob) {
+ const short orientation_type = params->orientation_type ?
+ (params->orientation_type - 1) :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom =
+ params->orientation_type ? params->orientation_index_custom :
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ float mat[3][3];
+ ED_transform_calc_orientation_from_type_ex(
+ C, mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+ copy_m4_m3(rv3d->twmat, mat);
+ }
+
+ /* transform widget centroid/center */
+ reset_tw_center(tbounds);
+
+ copy_m3_m4(tbounds->axis, rv3d->twmat);
+ if (params->use_local_axis && (ob && ob->mode & OB_MODE_EDIT)) {
+ float diff_mat[3][3];
+ copy_m3_m4(diff_mat, ob->obmat);
+ normalize_m3(diff_mat);
+ invert_m3(diff_mat);
+ mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
+ normalize_m3(tbounds->axis);
+ }
+
+ if (is_gp_edit) {
+ float diff_mat[4][4];
+ const bool use_mat_local = true;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* only editable and visible layers are considered */
+
+ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
+
+ for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+
+ /* we're only interested in selected points here... */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* Change selection status of all points, then make the stroke match */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
+ totsel++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
+ }
+ }
+ else if (obedit) {
#define FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) \
- { \
- invert_m4_m4(obedit->imat, obedit->obmat); \
- uint objects_len = 0; \
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(view_layer, CTX_wm_view3d(C), &objects_len); \
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \
- Object *ob_iter = objects[ob_index]; \
- const bool use_mat_local = (ob_iter != obedit);
+ { \
+ invert_m4_m4(obedit->imat, obedit->obmat); \
+ uint objects_len = 0; \
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( \
+ view_layer, CTX_wm_view3d(C), &objects_len); \
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { \
+ Object *ob_iter = objects[ob_index]; \
+ const bool use_mat_local = (ob_iter != obedit);
#define FOREACH_EDIT_OBJECT_END() \
- } \
- MEM_freeN(objects); \
- } ((void)0)
-
- ob = obedit;
- if (obedit->type == OB_MESH) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
- BMesh *bm = em_iter->bm;
-
- if (bm->totvertsel == 0) {
- continue;
- }
-
- BMVert *eve;
- BMIter iter;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
- totsel++;
- }
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- } /* end editmesh */
- else if (obedit->type == OB_ARMATURE) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- bArmature *arm = ob_iter->data;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
- for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if (EBONE_VISIBLE(arm, ebo)) {
- if (ebo->flag & BONE_TIPSEL) {
- calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
- totsel++;
- }
- if ((ebo->flag & BONE_ROOTSEL) &&
- /* don't include same point multiple times */
- ((ebo->flag & BONE_CONNECTED) &&
- (ebo->parent != NULL) &&
- (ebo->parent->flag & BONE_TIPSEL) &&
- EBONE_VISIBLE(arm, ebo->parent)) == 0)
- {
- calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
- totsel++;
- }
- if (ebo->flag & BONE_SELECTED) {
- protectflag_to_drawflags_ebone(rv3d, ebo);
- }
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- Curve *cu = ob_iter->data;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- nu = nurbs->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- /* exceptions
- * if handles are hidden then only check the center points.
- * If the center knot is selected then only use this as the center point.
- */
- if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- if (bezt->f2 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
- totsel++;
- }
- }
- else if (bezt->f2 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
- totsel++;
- }
- else {
- if (bezt->f1 & SELECT) {
- const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
- calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
- totsel++;
- }
- if (bezt->f3 & SELECT) {
- const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
- calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
- totsel++;
- }
- }
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
- totsel++;
- }
- bp++;
- }
- }
- nu = nu->next;
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (obedit->type == OB_MBALL) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- MetaBall *mb = (MetaBall *)ob_iter->data;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
- totsel++;
- }
- }
- } FOREACH_EDIT_OBJECT_END();
- }
- else if (obedit->type == OB_LATTICE) {
- FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
- Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
- BPoint *bp = lt->def;
- a = lt->pntsu * lt->pntsv * lt->pntsw;
-
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
- }
-
- while (a--) {
- if (bp->f1 & SELECT) {
- calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
- totsel++;
- }
- bp++;
- }
- } FOREACH_EDIT_OBJECT_END();
- }
+ } \
+ MEM_freeN(objects); \
+ } \
+ ((void)0)
+
+ ob = obedit;
+ if (obedit->type == OB_MESH) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+ BMesh *bm = em_iter->bm;
+
+ if (bm->totvertsel == 0) {
+ continue;
+ }
+
+ BMVert *eve;
+ BMIter iter;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ } /* end editmesh */
+ else if (obedit->type == OB_ARMATURE) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ bArmature *arm = ob_iter->data;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+ for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (EBONE_VISIBLE(arm, ebo)) {
+ if (ebo->flag & BONE_TIPSEL) {
+ calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
+ totsel++;
+ }
+ if ((ebo->flag & BONE_ROOTSEL) &&
+ /* don't include same point multiple times */
+ ((ebo->flag & BONE_CONNECTED) && (ebo->parent != NULL) &&
+ (ebo->parent->flag & BONE_TIPSEL) && EBONE_VISIBLE(arm, ebo->parent)) == 0) {
+ calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
+ totsel++;
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ protectflag_to_drawflags_ebone(rv3d, ebo);
+ }
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ Curve *cu = ob_iter->data;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ nu = nurbs->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ /* exceptions
+ * if handles are hidden then only check the center points.
+ * If the center knot is selected then only use this as the center point.
+ */
+ if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (bezt->f2 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ else if (bezt->f2 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
+ totsel++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
+ calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
+ totsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
+ calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (obedit->type == OB_MBALL) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ MetaBall *mb = (MetaBall *)ob_iter->data;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
+ totsel++;
+ }
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
+ else if (obedit->type == OB_LATTICE) {
+ FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) {
+ Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
+ BPoint *bp = lt->def;
+ a = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+ }
+
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+ totsel++;
+ }
+ bp++;
+ }
+ }
+ FOREACH_EDIT_OBJECT_END();
+ }
#undef FOREACH_EDIT_OBJECT_BEGIN
#undef FOREACH_EDIT_OBJECT_END
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(obedit->obmat, tbounds->center);
- mul_m4_v3(obedit->obmat, tbounds->min);
- mul_m4_v3(obedit->obmat, tbounds->max);
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- invert_m4_m4(ob->imat, ob->obmat);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode(
- view_layer, v3d, &objects_len, {.object_mode = OB_MODE_POSE});
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
- const bool use_mat_local = (ob_iter != ob);
- bPoseChannel *pchan;
-
- /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
- const int mode = TFM_ROTATION;
-
- const int totsel_iter = count_set_pose_transflags(ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
-
- if (totsel_iter) {
- float mat_local[4][4];
- if (use_mat_local) {
- mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
- }
-
- /* use channels to get stats */
- for (pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- if (bone && (bone->flag & BONE_TRANSFORM)) {
- calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
- protectflag_to_drawflags_pchan(rv3d, pchan);
- }
- }
- totsel += totsel_iter;
- }
- }
- MEM_freeN(objects);
-
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- mul_m4_v3(ob->obmat, tbounds->center);
- mul_m4_v3(ob->obmat, tbounds->min);
- mul_m4_v3(ob->obmat, tbounds->max);
- }
- }
- else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
- /* pass */
- }
- else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
- PTCacheEdit *edit = PE_get_current(scene, ob);
- PTCacheEditPoint *point;
- PTCacheEditKey *ek;
- int k;
-
- if (edit) {
- point = edit->points;
- for (a = 0; a < edit->totpoint; a++, point++) {
- if (point->flag & PEP_HIDE) continue;
-
- for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
- if (ek->flag & PEK_SELECT) {
- calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
- totsel++;
- }
- }
- }
-
- /* selection center */
- if (totsel)
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- }
- }
- else {
-
- /* we need the one selected object, if its not active */
- base = BASACT(view_layer);
- ob = OBACT(view_layer);
- if (base && ((base->flag & BASE_SELECTED) == 0)) ob = NULL;
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (!BASE_SELECTED_EDITABLE(v3d, base)) {
- continue;
- }
- if (ob == NULL) {
- ob = base->object;
- }
-
- /* Get the boundbox out of the evaluated object. */
- const BoundBox *bb = NULL;
- if (params->use_only_center == false) {
- bb = BKE_object_boundbox_get(base->object);
- }
-
- if (params->use_only_center || (bb == NULL)) {
- calc_tw_center(tbounds, base->object->obmat[3]);
- }
- else {
- for (uint j = 0; j < 8; j++) {
- float co[3];
- mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
- calc_tw_center(tbounds, co);
- }
- }
- protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
- totsel++;
- }
-
- /* selection center */
- if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
- }
- }
-
- if (totsel == 0) {
- unit_m4(rv3d->twmat);
- }
- else {
- copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
- copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
- copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
- }
-
- return totsel;
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ mul_m4_v3(obedit->obmat, tbounds->center);
+ mul_m4_v3(obedit->obmat, tbounds->min);
+ mul_m4_v3(obedit->obmat, tbounds->max);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ invert_m4_m4(ob->imat, ob->obmat);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode(
+ view_layer, v3d, &objects_len, {.object_mode = OB_MODE_POSE});
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+ const bool use_mat_local = (ob_iter != ob);
+ bPoseChannel *pchan;
+
+ /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
+ const int mode = TFM_ROTATION;
+
+ const int totsel_iter = count_set_pose_transflags(
+ ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
+
+ if (totsel_iter) {
+ float mat_local[4][4];
+ if (use_mat_local) {
+ mul_m4_m4m4(mat_local, ob->imat, ob_iter->obmat);
+ }
+
+ /* use channels to get stats */
+ for (pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ if (bone && (bone->flag & BONE_TRANSFORM)) {
+ calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
+ protectflag_to_drawflags_pchan(rv3d, pchan);
+ }
+ }
+ totsel += totsel_iter;
+ }
+ }
+ MEM_freeN(objects);
+
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ mul_m4_v3(ob->obmat, tbounds->center);
+ mul_m4_v3(ob->obmat, tbounds->min);
+ mul_m4_v3(ob->obmat, tbounds->max);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ /* pass */
+ }
+ else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEditPoint *point;
+ PTCacheEditKey *ek;
+ int k;
+
+ if (edit) {
+ point = edit->points;
+ for (a = 0; a < edit->totpoint; a++, point++) {
+ if (point->flag & PEP_HIDE)
+ continue;
+
+ for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
+ if (ek->flag & PEK_SELECT) {
+ calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
+ totsel++;
+ }
+ }
+ }
+
+ /* selection center */
+ if (totsel)
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ }
+ }
+ else {
+
+ /* we need the one selected object, if its not active */
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ if (base && ((base->flag & BASE_SELECTED) == 0))
+ ob = NULL;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (!BASE_SELECTED_EDITABLE(v3d, base)) {
+ continue;
+ }
+ if (ob == NULL) {
+ ob = base->object;
+ }
+
+ /* Get the boundbox out of the evaluated object. */
+ const BoundBox *bb = NULL;
+ if (params->use_only_center == false) {
+ bb = BKE_object_boundbox_get(base->object);
+ }
+
+ if (params->use_only_center || (bb == NULL)) {
+ calc_tw_center(tbounds, base->object->obmat[3]);
+ }
+ else {
+ for (uint j = 0; j < 8; j++) {
+ float co[3];
+ mul_v3_m4v3(co, base->object->obmat, bb->vec[j]);
+ calc_tw_center(tbounds, co);
+ }
+ }
+ protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
+ totsel++;
+ }
+
+ /* selection center */
+ if (totsel) {
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
+ }
+ }
+
+ if (totsel == 0) {
+ unit_m4(rv3d->twmat);
+ }
+ else {
+ copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
+ copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
+ copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
+ }
+
+ return totsel;
}
static void gizmo_get_idot(RegionView3D *rv3d, float r_idot[3])
{
- float view_vec[3], axis_vec[3];
- ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
- for (int i = 0; i < 3; i++) {
- normalize_v3_v3(axis_vec, rv3d->twmat[i]);
- r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
- }
+ float view_vec[3], axis_vec[3];
+ ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
+ for (int i = 0; i < 3; i++) {
+ normalize_v3_v3(axis_vec, rv3d->twmat[i]);
+ r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
+ }
}
-static void gizmo_prepare_mat(
- const bContext *C, RegionView3D *rv3d, const struct TransformBounds *tbounds)
+static void gizmo_prepare_mat(const bContext *C,
+ RegionView3D *rv3d,
+ const struct TransformBounds *tbounds)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- switch (scene->toolsettings->transform_pivot_point) {
- case V3D_AROUND_CENTER_BOUNDS:
- case V3D_AROUND_ACTIVE:
- {
- mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Object *ob = OBACT(view_layer);
- if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
- /* pass */
- }
- else if (ob != NULL) {
- ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
- }
- }
- break;
- }
- case V3D_AROUND_LOCAL_ORIGINS:
- case V3D_AROUND_CENTER_MEDIAN:
- copy_v3_v3(rv3d->twmat[3], tbounds->center);
- break;
- case V3D_AROUND_CURSOR:
- copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
- break;
- }
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ switch (scene->toolsettings->transform_pivot_point) {
+ case V3D_AROUND_CENTER_BOUNDS:
+ case V3D_AROUND_ACTIVE: {
+ mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
+
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = OBACT(view_layer);
+ if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
+ /* pass */
+ }
+ else if (ob != NULL) {
+ ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
+ }
+ }
+ break;
+ }
+ case V3D_AROUND_LOCAL_ORIGINS:
+ case V3D_AROUND_CENTER_MEDIAN:
+ copy_v3_v3(rv3d->twmat[3], tbounds->center);
+ break;
+ case V3D_AROUND_CURSOR:
+ copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
+ break;
+ }
}
/**
@@ -1178,771 +1174,779 @@ static void gizmo_prepare_mat(
*/
static void gizmo_line_range(const int twtype, const short axis_type, float *r_start, float *r_len)
{
- const float ofs = 0.2f;
-
- *r_start = 0.2f;
- *r_len = 1.0f;
-
- switch (axis_type) {
- case MAN_AXES_TRANSLATE:
- if (twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) {
- *r_start = *r_len - ofs + 0.075f;
- }
- if (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
- *r_len += ofs;
- }
- break;
- case MAN_AXES_SCALE:
- if (twtype & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE)) {
- *r_len -= ofs + 0.025f;
- }
- break;
- }
-
- *r_len -= *r_start;
+ const float ofs = 0.2f;
+
+ *r_start = 0.2f;
+ *r_len = 1.0f;
+
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) {
+ *r_start = *r_len - ofs + 0.075f;
+ }
+ if (twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ *r_len += ofs;
+ }
+ break;
+ case MAN_AXES_SCALE:
+ if (twtype & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE)) {
+ *r_len -= ofs + 0.025f;
+ }
+ break;
+ }
+
+ *r_len -= *r_start;
}
-static void gizmo_xform_message_subscribe(
- wmGizmoGroup *gzgroup, struct wmMsgBus *mbus,
- Scene *scene, bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn)
+static void gizmo_xform_message_subscribe(wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus,
+ Scene *scene,
+ bScreen *screen,
+ ScrArea *sa,
+ ARegion *ar,
+ const void *type_fn)
{
- /* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- int orient_flag = 0;
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- GizmoGroup *ggd = gzgroup->customdata;
- orient_flag = ggd->twtype_init;
- }
- else if (type_fn == VIEW3D_GGT_xform_cage) {
- orient_flag = V3D_GIZMO_SHOW_OBJECT_SCALE;
- /* pass */
- }
- else if (type_fn == VIEW3D_GGT_xform_shear) {
- orient_flag = V3D_GIZMO_SHOW_OBJECT_ROTATE;
- }
- TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, orient_flag);
- PointerRNA orient_ref_ptr;
- RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
- const ToolSettings *ts = scene->toolsettings;
-
- PointerRNA scene_ptr;
- RNA_id_pointer_create(&scene->id, &scene_ptr);
- {
- extern PropertyRNA rna_Scene_transform_orientation_slots;
- const PropertyRNA *props[] = {
- &rna_Scene_transform_orientation_slots,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
-
- if ((ts->transform_pivot_point == V3D_AROUND_CURSOR) ||
- (orient_slot->type == V3D_ORIENT_CURSOR))
- {
- /* We could be more specific here, for now subscribe to any cursor change. */
- PointerRNA cursor_ptr;
- RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
- WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
- }
-
- {
- extern PropertyRNA rna_TransformOrientationSlot_type;
- extern PropertyRNA rna_TransformOrientationSlot_use;
- const PropertyRNA *props[] = {
- &rna_TransformOrientationSlot_type,
- &rna_TransformOrientationSlot_use,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- if (props[i]) {
- WM_msg_subscribe_rna(mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
- }
-
- PointerRNA toolsettings_ptr;
- RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
-
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- extern PropertyRNA rna_ToolSettings_transform_pivot_point;
- const PropertyRNA *props[] = {
- &rna_ToolSettings_transform_pivot_point,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
-
- PointerRNA view3d_ptr;
- RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &view3d_ptr);
-
- if (type_fn == VIEW3D_GGT_xform_gizmo) {
- GizmoGroup *ggd = gzgroup->customdata;
- if (ggd->use_twtype_refresh) {
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_translate;
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_rotate;
- extern PropertyRNA rna_SpaceView3D_show_gizmo_object_scale;
- const PropertyRNA *props[] = {
- &rna_SpaceView3D_show_gizmo_object_translate,
- &rna_SpaceView3D_show_gizmo_object_rotate,
- &rna_SpaceView3D_show_gizmo_object_scale,
- };
- for (int i = 0; i < ARRAY_SIZE(props); i++) {
- WM_msg_subscribe_rna(mbus, &view3d_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
- }
- }
- }
- else if (type_fn == VIEW3D_GGT_xform_cage) {
- /* pass */
- }
- else if (type_fn == VIEW3D_GGT_xform_shear) {
- /* pass */
- }
- else {
- BLI_assert(0);
- }
-
- WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
+ .owner = ar,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ int orient_flag = 0;
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ GizmoGroup *ggd = gzgroup->customdata;
+ orient_flag = ggd->twtype_init;
+ }
+ else if (type_fn == VIEW3D_GGT_xform_cage) {
+ orient_flag = V3D_GIZMO_SHOW_OBJECT_SCALE;
+ /* pass */
+ }
+ else if (type_fn == VIEW3D_GGT_xform_shear) {
+ orient_flag = V3D_GIZMO_SHOW_OBJECT_ROTATE;
+ }
+ TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene,
+ orient_flag);
+ PointerRNA orient_ref_ptr;
+ RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
+ const ToolSettings *ts = scene->toolsettings;
+
+ PointerRNA scene_ptr;
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ {
+ extern PropertyRNA rna_Scene_transform_orientation_slots;
+ const PropertyRNA *props[] = {
+ &rna_Scene_transform_orientation_slots,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &scene_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+
+ if ((ts->transform_pivot_point == V3D_AROUND_CURSOR) ||
+ (orient_slot->type == V3D_ORIENT_CURSOR)) {
+ /* We could be more specific here, for now subscribe to any cursor change. */
+ PointerRNA cursor_ptr;
+ RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &cursor_ptr);
+ WM_msg_subscribe_rna(mbus, &cursor_ptr, NULL, &msg_sub_value_gz_tag_refresh, __func__);
+ }
+
+ {
+ extern PropertyRNA rna_TransformOrientationSlot_type;
+ extern PropertyRNA rna_TransformOrientationSlot_use;
+ const PropertyRNA *props[] = {
+ &rna_TransformOrientationSlot_type,
+ &rna_TransformOrientationSlot_use,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ if (props[i]) {
+ WM_msg_subscribe_rna(
+ mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+ }
+
+ PointerRNA toolsettings_ptr;
+ RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
+
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ extern PropertyRNA rna_ToolSettings_transform_pivot_point;
+ const PropertyRNA *props[] = {
+ &rna_ToolSettings_transform_pivot_point,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(
+ mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+
+ PointerRNA view3d_ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &view3d_ptr);
+
+ if (type_fn == VIEW3D_GGT_xform_gizmo) {
+ GizmoGroup *ggd = gzgroup->customdata;
+ if (ggd->use_twtype_refresh) {
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_translate;
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_rotate;
+ extern PropertyRNA rna_SpaceView3D_show_gizmo_object_scale;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_show_gizmo_object_translate,
+ &rna_SpaceView3D_show_gizmo_object_rotate,
+ &rna_SpaceView3D_show_gizmo_object_scale,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &view3d_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+ }
+ }
+ }
+ else if (type_fn == VIEW3D_GGT_xform_cage) {
+ /* pass */
+ }
+ else if (type_fn == VIEW3D_GGT_xform_shear) {
+ /* pass */
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_gz_tag_refresh);
}
-
void drawDial3d(const TransInfo *t)
{
- if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
- wmGizmo *gz = wm_gizmomap_modal_get(t->ar->gizmo_map);
- if (gz == NULL) {
- /* We only draw Dial3d if the operator has been called by a gizmo. */
- return;
- }
-
- float mat_basis[4][4];
- float mat_final[4][4];
- float color[4];
- float increment;
- float line_with = GIZMO_AXIS_LINE_WIDTH + 1.0f;
- float scale = UI_DPI_FAC * U.gizmo_size;
-
- int axis_idx;
-
- const TransCon *tc = &(t->con);
- if (tc->mode & CON_APPLY) {
- if (tc->mode & CON_AXIS0) {
- axis_idx = MAN_AXIS_ROT_X;
- negate_v3_v3(mat_basis[2], tc->mtx[0]);
- }
- else if (tc->mode & CON_AXIS1) {
- axis_idx = MAN_AXIS_ROT_Y;
- negate_v3_v3(mat_basis[2], tc->mtx[1]);
- }
- else {
- BLI_assert((tc->mode & CON_AXIS2) != 0);
- axis_idx = MAN_AXIS_ROT_Z;
- negate_v3_v3(mat_basis[2], tc->mtx[2]);
- }
- }
- else {
- axis_idx = MAN_AXIS_ROT_C;
- negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]);
- scale *= 1.2f;
- line_with -= 1.0f;
- }
-
- copy_v3_v3(mat_basis[3], t->center_global);
- mat_basis[2][3] = -dot_v3v3(mat_basis[2], mat_basis[3]);
-
- if (ED_view3d_win_to_3d_on_plane(
- t->ar, mat_basis[2], (float[2]){UNPACK2(t->mouse.imval)},
- false, mat_basis[1]))
- {
- sub_v3_v3(mat_basis[1], mat_basis[3]);
- normalize_v3(mat_basis[1]);
- cross_v3_v3v3(mat_basis[0], mat_basis[1], mat_basis[2]);
- }
- else {
- /* The plane and the mouse direction are parallel.
- * Calculate a matrix orthogonal to the axis. */
- ortho_basis_v3v3_v3(mat_basis[0], mat_basis[1], mat_basis[2]);
- }
-
- mat_basis[0][3] = 0.0f;
- mat_basis[1][3] = 0.0f;
- mat_basis[2][3] = 0.0f;
- mat_basis[3][3] = 1.0f;
-
- copy_m4_m4(mat_final, mat_basis);
- scale *= ED_view3d_pixel_size_no_ui_scale(t->ar->regiondata, mat_final[3]);
- mul_mat3_m4_fl(mat_final, scale);
-
- if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) &&
- activeSnap(t))
- {
- increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1];
- }
- else {
- increment = t->snap[0];
- }
-
- BLI_assert(axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END);
- gizmo_get_axis_color(axis_idx, NULL, color, color);
-
- GPU_depth_test(false);
- GPU_blend(true);
- GPU_line_smooth(true);
-
- ED_gizmotypes_dial_3d_draw_util(
- mat_basis, mat_final, line_with, color, false,
- &(struct Dial3dParams){
- .draw_options = ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE,
- .angle_delta = t->values[0],
- .angle_increment = increment,
- });
-
- GPU_line_smooth(false);
- GPU_depth_test(true);
- GPU_blend(false);
- }
+ if (t->mode == TFM_ROTATION && t->spacetype == SPACE_VIEW3D) {
+ wmGizmo *gz = wm_gizmomap_modal_get(t->ar->gizmo_map);
+ if (gz == NULL) {
+ /* We only draw Dial3d if the operator has been called by a gizmo. */
+ return;
+ }
+
+ float mat_basis[4][4];
+ float mat_final[4][4];
+ float color[4];
+ float increment;
+ float line_with = GIZMO_AXIS_LINE_WIDTH + 1.0f;
+ float scale = UI_DPI_FAC * U.gizmo_size;
+
+ int axis_idx;
+
+ const TransCon *tc = &(t->con);
+ if (tc->mode & CON_APPLY) {
+ if (tc->mode & CON_AXIS0) {
+ axis_idx = MAN_AXIS_ROT_X;
+ negate_v3_v3(mat_basis[2], tc->mtx[0]);
+ }
+ else if (tc->mode & CON_AXIS1) {
+ axis_idx = MAN_AXIS_ROT_Y;
+ negate_v3_v3(mat_basis[2], tc->mtx[1]);
+ }
+ else {
+ BLI_assert((tc->mode & CON_AXIS2) != 0);
+ axis_idx = MAN_AXIS_ROT_Z;
+ negate_v3_v3(mat_basis[2], tc->mtx[2]);
+ }
+ }
+ else {
+ axis_idx = MAN_AXIS_ROT_C;
+ negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]);
+ scale *= 1.2f;
+ line_with -= 1.0f;
+ }
+
+ copy_v3_v3(mat_basis[3], t->center_global);
+ mat_basis[2][3] = -dot_v3v3(mat_basis[2], mat_basis[3]);
+
+ if (ED_view3d_win_to_3d_on_plane(
+ t->ar, mat_basis[2], (float[2]){UNPACK2(t->mouse.imval)}, false, mat_basis[1])) {
+ sub_v3_v3(mat_basis[1], mat_basis[3]);
+ normalize_v3(mat_basis[1]);
+ cross_v3_v3v3(mat_basis[0], mat_basis[1], mat_basis[2]);
+ }
+ else {
+ /* The plane and the mouse direction are parallel.
+ * Calculate a matrix orthogonal to the axis. */
+ ortho_basis_v3v3_v3(mat_basis[0], mat_basis[1], mat_basis[2]);
+ }
+
+ mat_basis[0][3] = 0.0f;
+ mat_basis[1][3] = 0.0f;
+ mat_basis[2][3] = 0.0f;
+ mat_basis[3][3] = 1.0f;
+
+ copy_m4_m4(mat_final, mat_basis);
+ scale *= ED_view3d_pixel_size_no_ui_scale(t->ar->regiondata, mat_final[3]);
+ mul_mat3_m4_fl(mat_final, scale);
+
+ if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) && activeSnap(t)) {
+ increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1];
+ }
+ else {
+ increment = t->snap[0];
+ }
+
+ BLI_assert(axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END);
+ gizmo_get_axis_color(axis_idx, NULL, color, color);
+
+ GPU_depth_test(false);
+ GPU_blend(true);
+ GPU_line_smooth(true);
+
+ ED_gizmotypes_dial_3d_draw_util(mat_basis,
+ mat_final,
+ line_with,
+ color,
+ false,
+ &(struct Dial3dParams){
+ .draw_options = ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE,
+ .angle_delta = t->values[0],
+ .angle_increment = increment,
+ });
+
+ GPU_line_smooth(false);
+ GPU_depth_test(true);
+ GPU_blend(false);
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Transform Gizmo
* \{ */
static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd;
-
- ggd = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
- const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
-
-#define GIZMO_NEW_ARROW(v, draw_style) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
-} ((void)0)
-#define GIZMO_NEW_DIAL(v, draw_options) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_options", draw_options); \
-} ((void)0)
-#define GIZMO_NEW_PRIM(v, draw_style) { \
- ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
- RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
-} ((void)0)
-
- /* add/init widgets - order matters! */
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_T, ED_GIZMO_DIAL_DRAW_FLAG_FILL);
-
- GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
-
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X, ED_GIZMO_ARROW_STYLE_BOX);
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_GIZMO_ARROW_STYLE_BOX);
- GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_GIZMO_ARROW_STYLE_BOX);
-
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
-
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_X, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_Z, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
-
- /* init screen aligned widget last here, looks better, behaves better */
- GIZMO_NEW_DIAL(MAN_AXIS_ROT_C, ED_GIZMO_DIAL_DRAW_FLAG_NOP);
-
- GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
-
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X, ED_GIZMO_ARROW_STYLE_NORMAL);
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_GIZMO_ARROW_STYLE_NORMAL);
- GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_GIZMO_ARROW_STYLE_NORMAL);
-
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
- GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
-
- ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
-
- return ggd;
+ GizmoGroup *ggd;
+
+ ggd = MEM_callocN(sizeof(GizmoGroup), "gizmo_data");
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+ const wmGizmoType *gzt_prim = WM_gizmotype_find("GIZMO_GT_primitive_3d", true);
+
+#define GIZMO_NEW_ARROW(v, draw_style) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
+ } \
+ ((void)0)
+#define GIZMO_NEW_DIAL(v, draw_options) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_options", draw_options); \
+ } \
+ ((void)0)
+#define GIZMO_NEW_PRIM(v, draw_style) \
+ { \
+ ggd->gizmos[v] = WM_gizmo_new_ptr(gzt_prim, gzgroup, NULL); \
+ RNA_enum_set(ggd->gizmos[v]->ptr, "draw_style", draw_style); \
+ } \
+ ((void)0)
+
+ /* add/init widgets - order matters! */
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_T, ED_GIZMO_DIAL_DRAW_FLAG_FILL);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
+
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X, ED_GIZMO_ARROW_STYLE_BOX);
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_GIZMO_ARROW_STYLE_BOX);
+ GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_GIZMO_ARROW_STYLE_BOX);
+
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_X, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_Z, ED_GIZMO_DIAL_DRAW_FLAG_CLIP);
+
+ /* init screen aligned widget last here, looks better, behaves better */
+ GIZMO_NEW_DIAL(MAN_AXIS_ROT_C, ED_GIZMO_DIAL_DRAW_FLAG_NOP);
+
+ GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C, ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT);
+
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X, ED_GIZMO_ARROW_STYLE_NORMAL);
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_GIZMO_ARROW_STYLE_NORMAL);
+ GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_GIZMO_ARROW_STYLE_NORMAL);
+
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+ GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_GIZMO_PRIMITIVE_STYLE_PLANE);
+
+ ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
+
+ return ggd;
}
/**
* Custom handler for gizmo widgets
*/
-static int gizmo_modal(
- bContext *C, wmGizmo *widget, const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+static int gizmo_modal(bContext *C,
+ wmGizmo *widget,
+ const wmEvent *event,
+ eWM_GizmoFlagTweak UNUSED(tweak_flag))
{
- /* Avoid unnecessary updates, partially address: T55458. */
- if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
- return OPERATOR_RUNNING_MODAL;
- }
-
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- struct TransformBounds tbounds;
-
-
- if (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .use_only_center = true,
- }, &tbounds))
- {
- gizmo_prepare_mat(C, rv3d, &tbounds);
- WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
- }
-
- ED_region_tag_redraw(ar);
-
- return OPERATOR_RUNNING_MODAL;
+ /* Avoid unnecessary updates, partially address: T55458. */
+ if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ struct TransformBounds tbounds;
+
+ if (ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_only_center = true,
+ },
+ &tbounds)) {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+ WM_gizmo_set_matrix_location(widget, rv3d->twmat[3]);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
{
- struct {
- wmOperatorType *translate, *rotate, *trackball, *resize;
- } ot_store = {NULL};
- GizmoGroup *ggd = gzgroup->customdata;
-
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- bool constraint_axis[3] = {1, 0, 0};
- PointerRNA *ptr = NULL;
-
- gizmo_get_axis_constraint(axis_idx, constraint_axis);
-
- /* custom handler! */
- WM_gizmo_set_fn_custom_modal(axis, gizmo_modal);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- int draw_options = 0;
- if ((ggd->twtype & (V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
- draw_options |= ED_GIZMO_ARROW_DRAW_FLAG_STEM;
- }
- RNA_enum_set(axis->ptr, "draw_options", draw_options);
- }
-
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- break;
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_ROT_Z:
- /* increased line width for better display */
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_XY:
- case MAN_AXIS_SCALE_YZ:
- case MAN_AXIS_SCALE_ZX:
- {
- const float ofs_ax = 7.0f;
- const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
- WM_gizmo_set_scale(axis, 0.07f);
- WM_gizmo_set_matrix_offset_location(axis, ofs);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
- break;
- }
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
- if (axis_idx == MAN_AXIS_ROT_T) {
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_HOVER, true);
- }
- else if (axis_idx == MAN_AXIS_ROT_C) {
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
- WM_gizmo_set_scale(axis, 1.2f);
- }
- else {
- WM_gizmo_set_scale(axis, 0.2f);
- }
- break;
- }
-
- switch (axis_type) {
- case MAN_AXES_TRANSLATE:
- if (ot_store.translate == NULL) {
- ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_store.translate, NULL);
- break;
- case MAN_AXES_ROTATE:
- {
- wmOperatorType *ot_rotate;
- if (axis_idx == MAN_AXIS_ROT_T) {
- if (ot_store.trackball == NULL) {
- ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
- }
- ot_rotate = ot_store.trackball;
- }
- else {
- if (ot_store.rotate == NULL) {
- ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
- }
- ot_rotate = ot_store.rotate;
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_rotate, NULL);
- break;
- }
- case MAN_AXES_SCALE:
- {
- if (ot_store.resize == NULL) {
- ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- }
- ptr = WM_gizmo_operator_set(axis, 0, ot_store.resize, NULL);
- break;
- }
- }
-
- if (ptr) {
- PropertyRNA *prop;
- if (ELEM(true, UNPACK3(constraint_axis))) {
- if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
- RNA_property_boolean_set_array(ptr, prop, constraint_axis);
- }
- }
-
- RNA_boolean_set(ptr, "release_confirm", 1);
- }
- }
- MAN_ITER_AXES_END;
+ struct {
+ wmOperatorType *translate, *rotate, *trackball, *resize;
+ } ot_store = {NULL};
+ GizmoGroup *ggd = gzgroup->customdata;
+
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ bool constraint_axis[3] = {1, 0, 0};
+ PointerRNA *ptr = NULL;
+
+ gizmo_get_axis_constraint(axis_idx, constraint_axis);
+
+ /* custom handler! */
+ WM_gizmo_set_fn_custom_modal(axis, gizmo_modal);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ int draw_options = 0;
+ if ((ggd->twtype & (V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
+ draw_options |= ED_GIZMO_ARROW_DRAW_FLAG_STEM;
+ }
+ RNA_enum_set(axis->ptr, "draw_options", draw_options);
+ }
+
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ break;
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ /* increased line width for better display */
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX: {
+ const float ofs_ax = 7.0f;
+ const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
+ WM_gizmo_set_scale(axis, 0.07f);
+ WM_gizmo_set_matrix_offset_location(axis, ofs);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ break;
+ }
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH);
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_HOVER, true);
+ }
+ else if (axis_idx == MAN_AXIS_ROT_C) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
+ WM_gizmo_set_scale(axis, 1.2f);
+ }
+ else {
+ WM_gizmo_set_scale(axis, 0.2f);
+ }
+ break;
+ }
+
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (ot_store.translate == NULL) {
+ ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_store.translate, NULL);
+ break;
+ case MAN_AXES_ROTATE: {
+ wmOperatorType *ot_rotate;
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ if (ot_store.trackball == NULL) {
+ ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
+ }
+ ot_rotate = ot_store.trackball;
+ }
+ else {
+ if (ot_store.rotate == NULL) {
+ ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ }
+ ot_rotate = ot_store.rotate;
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_rotate, NULL);
+ break;
+ }
+ case MAN_AXES_SCALE: {
+ if (ot_store.resize == NULL) {
+ ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ }
+ ptr = WM_gizmo_operator_set(axis, 0, ot_store.resize, NULL);
+ break;
+ }
+ }
+
+ if (ptr) {
+ PropertyRNA *prop;
+ if (ELEM(true, UNPACK3(constraint_axis))) {
+ if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
+ RNA_property_boolean_set_array(ptr, prop, constraint_axis);
+ }
+ }
+
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ }
+ MAN_ITER_AXES_END;
}
static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd = gizmogroup_init(gzgroup);
-
- gzgroup->customdata = ggd;
-
- {
- ScrArea *sa = CTX_wm_area(C);
- const bToolRef *tref = sa->runtime.tool;
-
- ggd->twtype = 0;
- if (tref && STREQ(tref->idname, "builtin.move")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_TRANSLATE;
- }
- else if (tref && STREQ(tref->idname, "builtin.rotate")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_ROTATE;
- }
- else if (tref && STREQ(tref->idname, "builtin.scale")) {
- ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE;
- }
- else {
- /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
- ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE;
- ggd->use_twtype_refresh = true;
- }
- BLI_assert(ggd->twtype != 0);
- ggd->twtype_init = ggd->twtype;
- }
-
- /* *** set properties for axes *** */
- gizmogroup_init_properties_from_twtype(gzgroup);
+ GizmoGroup *ggd = gizmogroup_init(gzgroup);
+
+ gzgroup->customdata = ggd;
+
+ {
+ ScrArea *sa = CTX_wm_area(C);
+ const bToolRef *tref = sa->runtime.tool;
+
+ ggd->twtype = 0;
+ if (tref && STREQ(tref->idname, "builtin.move")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_TRANSLATE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.rotate")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_ROTATE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.scale")) {
+ ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE;
+ }
+ else {
+ /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
+ ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
+ V3D_GIZMO_SHOW_OBJECT_SCALE;
+ ggd->use_twtype_refresh = true;
+ }
+ BLI_assert(ggd->twtype != 0);
+ ggd->twtype_init = ggd->twtype;
+ }
+
+ /* *** set properties for axes *** */
+ gizmogroup_init_properties_from_twtype(gzgroup);
}
static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd = gzgroup->customdata;
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- struct TransformBounds tbounds;
-
- if (ggd->use_twtype_refresh) {
- ggd->twtype = v3d->gizmo_show_object & ggd->twtype_init;
- if (ggd->twtype != ggd->twtype_prev) {
- ggd->twtype_prev = ggd->twtype;
- gizmogroup_init_properties_from_twtype(gzgroup);
- }
- }
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
-
- /* skip, we don't draw anything anyway */
- if ((ggd->all_hidden =
- (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .use_only_center = true,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0)))
- {
- return;
- }
-
- gizmo_prepare_mat(C, rv3d, &tbounds);
-
- /* *** set properties for axes *** */
-
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
-
- WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- {
- float start_co[3] = {0.0f, 0.0f, 0.0f};
- float len;
-
- gizmo_line_range(ggd->twtype, axis_type, &start_co[2], &len);
-
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
- RNA_float_set(axis->ptr, "length", len);
-
- if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
- if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
- /* Avoid rotate and translate arrows overlap. */
- start_co[2] += 0.215f;
- }
- }
- WM_gizmo_set_matrix_offset_location(axis, start_co);
- WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
- break;
- }
- case MAN_AXIS_ROT_X:
- case MAN_AXIS_ROT_Y:
- case MAN_AXIS_ROT_Z:
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
- break;
- case MAN_AXIS_TRANS_XY:
- case MAN_AXIS_TRANS_YZ:
- case MAN_AXIS_TRANS_ZX:
- case MAN_AXIS_SCALE_XY:
- case MAN_AXIS_SCALE_YZ:
- case MAN_AXIS_SCALE_ZX:
- {
- const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1];
- const float *z_axis = rv3d->twmat[aidx_norm];
- WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
- break;
- }
- }
- }
- MAN_ITER_AXES_END;
+ GizmoGroup *ggd = gzgroup->customdata;
+ Scene *scene = CTX_data_scene(C);
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ struct TransformBounds tbounds;
+
+ if (ggd->use_twtype_refresh) {
+ ggd->twtype = v3d->gizmo_show_object & ggd->twtype_init;
+ if (ggd->twtype != ggd->twtype_prev) {
+ ggd->twtype_prev = ggd->twtype;
+ gizmogroup_init_properties_from_twtype(gzgroup);
+ }
+ }
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+
+ /* skip, we don't draw anything anyway */
+ if ((ggd->all_hidden = (ED_transform_calc_gizmo_stats(
+ C,
+ &(struct TransformCalcParams){
+ .use_only_center = true,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0))) {
+ return;
+ }
+
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+
+ /* *** set properties for axes *** */
+
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ const int aidx_norm = gizmo_orientation_axis(axis_idx, NULL);
+
+ WM_gizmo_set_matrix_location(axis, rv3d->twmat[3]);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z: {
+ float start_co[3] = {0.0f, 0.0f, 0.0f};
+ float len;
+
+ gizmo_line_range(ggd->twtype, axis_type, &start_co[2], &len);
+
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
+ RNA_float_set(axis->ptr, "length", len);
+
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ /* Avoid rotate and translate arrows overlap. */
+ start_co[2] += 0.215f;
+ }
+ }
+ WM_gizmo_set_matrix_offset_location(axis, start_co);
+ WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
+ break;
+ }
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX: {
+ const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1];
+ const float *z_axis = rv3d->twmat[aidx_norm];
+ WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
+ break;
+ }
+ }
+ }
+ MAN_ITER_AXES_END;
}
-static void WIDGETGROUP_gizmo_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- Scene *scene = CTX_data_scene(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_gizmo);
+ Scene *scene = CTX_data_scene(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_gizmo);
}
static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoGroup *ggd = gzgroup->customdata;
- // ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- // View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
- float idot[3];
-
- /* when looking through a selected camera, the gizmo can be at the
- * exact same position as the view, skip so we don't break selection */
- if (ggd->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) {
- MAN_ITER_AXES_BEGIN(axis, axis_idx)
- {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
- }
- MAN_ITER_AXES_END;
- return;
- }
- gizmo_get_idot(rv3d, idot);
-
- /* *** set properties for axes *** */
- MAN_ITER_AXES_BEGIN(axis, axis_idx) {
- const short axis_type = gizmo_get_axis_type(axis_idx);
- /* XXX maybe unset _HIDDEN flag on redraw? */
-
- if (gizmo_is_axis_visible(rv3d, ggd->twtype, idot, axis_type, axis_idx)) {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
- }
- else {
- WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
- continue;
- }
-
- float color[4], color_hi[4];
- gizmo_get_axis_color(axis_idx, idot, color, color_hi);
- WM_gizmo_set_color(axis, color);
- WM_gizmo_set_color_highlight(axis, color_hi);
-
- switch (axis_idx) {
- case MAN_AXIS_TRANS_C:
- case MAN_AXIS_ROT_C:
- case MAN_AXIS_SCALE_C:
- case MAN_AXIS_ROT_T:
- WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
- break;
- }
- } MAN_ITER_AXES_END;
-
- /* Refresh handled above when using view orientation. */
- if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
- {
- Scene *scene = CTX_data_scene(C);
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- WIDGETGROUP_gizmo_refresh(C, gzgroup);
- break;
- }
- }
- }
- copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
- }
-
+ GizmoGroup *ggd = gzgroup->customdata;
+ // ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ // View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+ float idot[3];
+
+ /* when looking through a selected camera, the gizmo can be at the
+ * exact same position as the view, skip so we don't break selection */
+ if (ggd->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) {
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
+ }
+ MAN_ITER_AXES_END;
+ return;
+ }
+ gizmo_get_idot(rv3d, idot);
+
+ /* *** set properties for axes *** */
+ MAN_ITER_AXES_BEGIN (axis, axis_idx) {
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ /* XXX maybe unset _HIDDEN flag on redraw? */
+
+ if (gizmo_is_axis_visible(rv3d, ggd->twtype, idot, axis_type, axis_idx)) {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false);
+ }
+ else {
+ WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true);
+ continue;
+ }
+
+ float color[4], color_hi[4];
+ gizmo_get_axis_color(axis_idx, idot, color, color_hi);
+ WM_gizmo_set_color(axis, color);
+ WM_gizmo_set_color_highlight(axis, color_hi);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
+ break;
+ }
+ }
+ MAN_ITER_AXES_END;
+
+ /* Refresh handled above when using view orientation. */
+ if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
+ {
+ Scene *scene = CTX_data_scene(C);
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ WIDGETGROUP_gizmo_refresh(C, gzgroup);
+ break;
+ }
+ }
+ }
+ copy_m3_m4(ggd->prev.viewinv_m3, rv3d->viewinv);
+ }
}
-static void WIDGETGROUP_gizmo_invoke_prepare(
- const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
{
- GizmoGroup *ggd = gzgroup->customdata;
-
- /* Support gizmo spesific orientation. */
- if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
- Scene *scene = CTX_data_scene(C);
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA *ptr = &gzop->ptr;
- PropertyRNA *prop_orient_type = RNA_struct_find_property(ptr, "orient_type");
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(scene, ggd->twtype_init);
- if (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
- RNA_property_unset(ptr, prop_orient_type);
- }
- else {
- /* TODO: APIfunction */
- int index = BKE_scene_orientation_slot_get_index(orient_slot);
- RNA_property_enum_set(ptr, prop_orient_type, index);
- }
- }
-
- /* Support shift click to constrain axis. */
- const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
- int axis = -1;
- switch (axis_idx) {
- case MAN_AXIS_TRANS_X:
- case MAN_AXIS_TRANS_Y:
- case MAN_AXIS_TRANS_Z:
- axis = axis_idx - MAN_AXIS_TRANS_X; break;
- case MAN_AXIS_SCALE_X:
- case MAN_AXIS_SCALE_Y:
- case MAN_AXIS_SCALE_Z:
- axis = axis_idx - MAN_AXIS_SCALE_X; break;
- }
-
- if (axis != -1) {
- wmWindow *win = CTX_wm_window(C);
- /* Swap single axis for two-axis constraint. */
- bool flip = win->eventstate->shift;
- BLI_assert(axis_idx != -1);
- const short axis_type = gizmo_get_axis_type(axis_idx);
- if (axis_type != MAN_AXES_ROTATE) {
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA *ptr = &gzop->ptr;
- PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- if (prop_constraint_axis) {
- bool constraint[3] = {false};
- constraint[axis] = true;
- if (flip) {
- for (int i = 0; i < ARRAY_SIZE(constraint); i++) {
- constraint[i] = !constraint[i];
- }
- }
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
- }
- }
- }
+ GizmoGroup *ggd = gzgroup->customdata;
+
+ /* Support gizmo spesific orientation. */
+ if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
+ Scene *scene = CTX_data_scene(C);
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA *ptr = &gzop->ptr;
+ PropertyRNA *prop_orient_type = RNA_struct_find_property(ptr, "orient_type");
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get_from_flag(
+ scene, ggd->twtype_init);
+ if (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
+ RNA_property_unset(ptr, prop_orient_type);
+ }
+ else {
+ /* TODO: APIfunction */
+ int index = BKE_scene_orientation_slot_get_index(orient_slot);
+ RNA_property_enum_set(ptr, prop_orient_type, index);
+ }
+ }
+
+ /* Support shift click to constrain axis. */
+ const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
+ int axis = -1;
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ axis = axis_idx - MAN_AXIS_TRANS_X;
+ break;
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
+ axis = axis_idx - MAN_AXIS_SCALE_X;
+ break;
+ }
+
+ if (axis != -1) {
+ wmWindow *win = CTX_wm_window(C);
+ /* Swap single axis for two-axis constraint. */
+ bool flip = win->eventstate->shift;
+ BLI_assert(axis_idx != -1);
+ const short axis_type = gizmo_get_axis_type(axis_idx);
+ if (axis_type != MAN_AXES_ROTATE) {
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA *ptr = &gzop->ptr;
+ PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ if (prop_constraint_axis) {
+ bool constraint[3] = {false};
+ constraint[axis] = true;
+ if (flip) {
+ for (int i = 0; i < ARRAY_SIZE(constraint); i++) {
+ constraint[i] = !constraint[i];
+ }
+ }
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
+ }
+ }
+ }
}
static bool WIDGETGROUP_gizmo_poll_generic(View3D *v3d)
{
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE) {
- return false;
- }
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
- return false;
- }
- return true;
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE) {
+ return false;
+ }
+ if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
+ return false;
+ }
+ return true;
}
-static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C, struct wmGizmoGroupType *UNUSED(gzgt))
+static bool WIDGETGROUP_gizmo_poll_context(const struct bContext *C,
+ struct wmGizmoGroupType *UNUSED(gzgt))
{
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
- return false;
- }
-
- const bToolRef *tref = sa->runtime.tool;
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
- return false;
- }
- if ((v3d->gizmo_show_object & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
- return false;
- }
-
- /* Don't show if the tool has a gizmo. */
- if (tref && tref->runtime && tref->runtime->gizmo_group[0]) {
- return false;
- }
- return true;
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
+ return false;
+ }
+
+ const bToolRef *tref = sa->runtime.tool;
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE_CONTEXT) {
+ return false;
+ }
+ if ((v3d->gizmo_show_object & (V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
+ V3D_GIZMO_SHOW_OBJECT_SCALE)) == 0) {
+ return false;
+ }
+
+ /* Don't show if the tool has a gizmo. */
+ if (tref && tref->runtime && tref->runtime->gizmo_group[0]) {
+ return false;
+ }
+ return true;
}
static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
-
- return true;
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
- return false;
- }
-
- if (v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) {
- return false;
- }
-
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+
+ return true;
+ ScrArea *sa = CTX_wm_area(C);
+ View3D *v3d = sa->spacedata.first;
+ if (!WIDGETGROUP_gizmo_poll_generic(v3d)) {
+ return false;
+ }
+
+ if (v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) {
+ return false;
+ }
+
+ return true;
}
/* Expose as multiple gizmos so tools use one, persistant context another.
@@ -1950,236 +1954,238 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo
void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo";
- gzgt->idname = "VIEW3D_GGT_xform_gizmo";
+ gzgt->name = "Transform Gizmo";
+ gzgt->idname = "VIEW3D_GGT_xform_gizmo";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_gizmo_poll_tool;
- gzgt->setup = WIDGETGROUP_gizmo_setup;
- gzgt->refresh = WIDGETGROUP_gizmo_refresh;
- gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
- gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
+ gzgt->poll = WIDGETGROUP_gizmo_poll_tool;
+ gzgt->setup = WIDGETGROUP_gizmo_setup;
+ gzgt->refresh = WIDGETGROUP_gizmo_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
+ gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
}
/** Only poll, flag & gzmap_params differ. */
void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo Context";
- gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
+ gzgt->name = "Transform Gizmo Context";
+ gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
- gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT;
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT;
- gzgt->poll = WIDGETGROUP_gizmo_poll_context;
- gzgt->setup = WIDGETGROUP_gizmo_setup;
- gzgt->refresh = WIDGETGROUP_gizmo_refresh;
- gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
- gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
+ gzgt->poll = WIDGETGROUP_gizmo_poll_context;
+ gzgt->setup = WIDGETGROUP_gizmo_setup;
+ gzgt->refresh = WIDGETGROUP_gizmo_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
+ gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Scale Cage Gizmo
* \{ */
struct XFormCageWidgetGroup {
- wmGizmo *gizmo;
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ wmGizmo *gizmo;
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
};
static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
- return false;
- }
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
- return false;
- }
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
+ return false;
+ }
+ if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
+ return false;
+ }
+ return true;
}
static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__);
- const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
- xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
- wmGizmo *gz = xgzgroup->gizmo;
-
- RNA_enum_set(gz->ptr, "transform",
- ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
- ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
-
- gz->color[0] = 1;
- gz->color_hi[0] = 1;
-
- gzgroup->customdata = xgzgroup;
-
- {
- wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
- PointerRNA *ptr;
-
- /* assign operator */
- PropertyRNA *prop_release_confirm = NULL;
- PropertyRNA *prop_constraint_axis = NULL;
-
- int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- for (int z = 0; z < 3; z++) {
- bool constraint[3] = {x != 1, y != 1, z != 1};
- ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
- if (prop_release_confirm == NULL) {
- prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
- prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- }
- RNA_property_boolean_set(ptr, prop_release_confirm, true);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
- i++;
- }
- }
- }
- }
+ struct XFormCageWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup),
+ __func__);
+ const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
+ xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
+ wmGizmo *gz = xgzgroup->gizmo;
+
+ RNA_enum_set(gz->ptr,
+ "transform",
+ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
+
+ gz->color[0] = 1;
+ gz->color_hi[0] = 1;
+
+ gzgroup->customdata = xgzgroup;
+
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ PropertyRNA *prop_release_confirm = NULL;
+ PropertyRNA *prop_constraint_axis = NULL;
+
+ int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int z = 0; z < 3; z++) {
+ bool constraint[3] = {x != 1, y != 1, z != 1};
+ ptr = WM_gizmo_operator_set(gz, i, ot_resize, NULL);
+ if (prop_release_confirm == NULL) {
+ prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ }
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
+ i++;
+ }
+ }
+ }
+ }
}
static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
- Scene *scene = CTX_data_scene(C);
-
- struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
- wmGizmo *gz = xgzgroup->gizmo;
-
- struct TransformBounds tbounds;
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_SCALE);
-
- if ((ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams) {
- .use_local_axis = true,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0) ||
- equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max))
- {
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
- else {
- gizmo_prepare_mat(C, rv3d, &tbounds);
-
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
-
- float dims[3];
- sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
- RNA_float_set_array(gz->ptr, "dimensions", dims);
- mul_v3_fl(dims, 0.5f);
-
- copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
- mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
- mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
-
- float matrix_offset_global[4][4];
- mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
-
- PropertyRNA *prop_center_override = NULL;
- float center[3];
- float center_global[3];
- int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
- for (int x = 0; x < 3; x++) {
- center[0] = (float)(1 - x) * dims[0];
- for (int y = 0; y < 3; y++) {
- center[1] = (float)(1 - y) * dims[1];
- for (int z = 0; z < 3; z++) {
- center[2] = (float)(1 - z) * dims[2];
- struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
- if (prop_center_override == NULL) {
- prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
- }
- mul_v3_m4v3(center_global, matrix_offset_global, center);
- RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
- i++;
- }
- }
- }
- }
-
- /* Needed to test view orientation changes. */
- copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = CTX_data_scene(C);
+
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
+
+ struct TransformBounds tbounds;
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_SCALE);
+
+ if ((ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_local_axis = true,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0) ||
+ equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+ else {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
+
+ float dims[3];
+ sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
+ RNA_float_set_array(gz->ptr, "dimensions", dims);
+ mul_v3_fl(dims, 0.5f);
+
+ copy_m4_m3(gz->matrix_offset, rv3d->tw_axis_matrix);
+ mid_v3_v3v3(gz->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
+ mul_m3_v3(rv3d->tw_axis_matrix, gz->matrix_offset[3]);
+
+ float matrix_offset_global[4][4];
+ mul_m4_m4m4(matrix_offset_global, gz->matrix_space, gz->matrix_offset);
+
+ PropertyRNA *prop_center_override = NULL;
+ float center[3];
+ float center_global[3];
+ int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ center[0] = (float)(1 - x) * dims[0];
+ for (int y = 0; y < 3; y++) {
+ center[1] = (float)(1 - y) * dims[1];
+ for (int z = 0; z < 3; z++) {
+ center[2] = (float)(1 - z) * dims[2];
+ struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, i);
+ if (prop_center_override == NULL) {
+ prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+ }
+ mul_v3_m4v3(center_global, matrix_offset_global, center);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, center_global);
+ i++;
+ }
+ }
+ }
+ }
+
+ /* Needed to test view orientation changes. */
+ copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
-static void WIDGETGROUP_xform_cage_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_xform_cage_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- Scene *scene = CTX_data_scene(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_cage);
+ Scene *scene = CTX_data_scene(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_cage);
}
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
- wmGizmo *gz = xgzgroup->gizmo;
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- if (ob && ob->mode & OB_MODE_EDIT) {
- copy_m4_m4(gz->matrix_space, ob->obmat);
- }
- else {
- unit_m4(gz->matrix_space);
- }
-
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- {
- Scene *scene = CTX_data_scene(C);
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_SCALE);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
- if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
- /* Take care calling refresh from draw_prepare,
- * this should be OK because it's only adjusting the cage orientation. */
- WIDGETGROUP_xform_cage_refresh(C, gzgroup);
- }
- break;
- }
- }
- }
+ struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
+ wmGizmo *gz = xgzgroup->gizmo;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->mode & OB_MODE_EDIT) {
+ copy_m4_m4(gz->matrix_space, ob->obmat);
+ }
+ else {
+ unit_m4(gz->matrix_space);
+ }
+
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ {
+ Scene *scene = CTX_data_scene(C);
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_SCALE);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+ if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
+ /* Take care calling refresh from draw_prepare,
+ * this should be OK because it's only adjusting the cage orientation. */
+ WIDGETGROUP_xform_cage_refresh(C, gzgroup);
+ }
+ break;
+ }
+ }
+ }
}
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Cage";
- gzgt->idname = "VIEW3D_GGT_xform_cage";
+ gzgt->name = "Transform Cage";
+ gzgt->idname = "VIEW3D_GGT_xform_cage";
- gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_xform_cage_poll;
- gzgt->setup = WIDGETGROUP_xform_cage_setup;
- gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
- gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
+ gzgt->poll = WIDGETGROUP_xform_cage_poll;
+ gzgt->setup = WIDGETGROUP_xform_cage_setup;
+ gzgt->refresh = WIDGETGROUP_xform_cage_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
/** \} */
@@ -2189,177 +2195,180 @@ void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt)
* \{ */
struct XFormShearWidgetGroup {
- wmGizmo *gizmo[3][2];
- /* Only for view orientation. */
- struct {
- float viewinv_m3[3][3];
- } prev;
+ wmGizmo *gizmo[3][2];
+ /* Only for view orientation. */
+ struct {
+ float viewinv_m3[3][3];
+ } prev;
};
static bool WIDGETGROUP_xform_shear_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
- return false;
- }
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
- return false;
- }
- return true;
+ if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+ return false;
+ }
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) {
+ return false;
+ }
+ return true;
}
static void WIDGETGROUP_xform_shear_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- struct XFormShearWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormShearWidgetGroup), __func__);
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
-
- float axis_color[3][3];
- for (int i = 0; i < 3; i++) {
- UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
- }
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
- const int i_ortho_a = (i + j + 1) % 3;
- const int i_ortho_b = (i + (1 - j) + 1) % 3;
- interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
- gz->color[3] = 0.5f;
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
- RNA_enum_set(ptr, "shear_axis", 0);
- RNA_boolean_set(ptr, "release_confirm", 1);
- xgzgroup->gizmo[i][j] = gz;
- }
- }
-
- gzgroup->customdata = xgzgroup;
+ struct XFormShearWidgetGroup *xgzgroup = MEM_mallocN(sizeof(struct XFormShearWidgetGroup),
+ __func__);
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ wmOperatorType *ot_shear = WM_operatortype_find("TRANSFORM_OT_shear", true);
+
+ float axis_color[3][3];
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, axis_color[i]);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
+ const int i_ortho_a = (i + j + 1) % 3;
+ const int i_ortho_b = (i + (1 - j) + 1) % 3;
+ interp_v3_v3v3(gz->color, axis_color[i_ortho_a], axis_color[i_ortho_b], 0.75f);
+ gz->color[3] = 0.5f;
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_shear, NULL);
+ RNA_enum_set(ptr, "shear_axis", 0);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ xgzgroup->gizmo[i][j] = gz;
+ }
+ }
+
+ gzgroup->customdata = xgzgroup;
}
static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ar->regiondata;
-
- struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
- struct TransformBounds tbounds;
-
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_ROTATE);
-
- if (ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams) {
- .use_local_axis = false,
- .orientation_type = orient_slot->type + 1,
- .orientation_index_custom = orient_slot->index_custom,
- }, &tbounds) == 0)
- {
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = xgzgroup->gizmo[i][j];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
- }
- }
- }
- else {
- gizmo_prepare_mat(C, rv3d, &tbounds);
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- wmGizmo *gz = xgzgroup->gizmo[i][j];
- WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
- WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
-
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- const int i_ortho_a = (i + j + 1) % 3;
- const int i_ortho_b = (i + (1 - j) + 1) % 3;
- WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
- WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
-
- RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
- RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
-
- RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
- RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
-
- mul_v3_fl(gz->matrix_basis[0], 0.5f);
- mul_v3_fl(gz->matrix_basis[1], 6.0f);
- }
- }
- }
-
- /* Needed to test view orientation changes. */
- copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
+ struct TransformBounds tbounds;
+
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene,
+ SCE_ORIENT_ROTATE);
+
+ if (ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .use_local_axis = false,
+ .orientation_type = orient_slot->type + 1,
+ .orientation_index_custom = orient_slot->index_custom,
+ },
+ &tbounds) == 0) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = xgzgroup->gizmo[i][j];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
+ }
+ }
+ }
+ else {
+ gizmo_prepare_mat(C, rv3d, &tbounds);
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ wmGizmo *gz = xgzgroup->gizmo[i][j];
+ WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
+ WM_gizmo_set_flag(gz, WM_GIZMO_MOVE_CURSOR, true);
+
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ const int i_ortho_a = (i + j + 1) % 3;
+ const int i_ortho_b = (i + (1 - j) + 1) % 3;
+ WM_gizmo_set_matrix_rotation_from_yz_axis(gz, rv3d->twmat[i_ortho_a], rv3d->twmat[i]);
+ WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
+
+ RNA_float_set_array(&gzop->ptr, "orient_matrix", &tbounds.axis[0][0]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_slot->type);
+
+ RNA_enum_set(&gzop->ptr, "orient_axis", i_ortho_b);
+ RNA_enum_set(&gzop->ptr, "orient_axis_ortho", i_ortho_a);
+
+ mul_v3_fl(gz->matrix_basis[0], 0.5f);
+ mul_v3_fl(gz->matrix_basis[1], 6.0f);
+ }
+ }
+ }
+
+ /* Needed to test view orientation changes. */
+ copy_m3_m4(xgzgroup->prev.viewinv_m3, rv3d->viewinv);
}
-static void WIDGETGROUP_xform_shear_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void WIDGETGROUP_xform_shear_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- Scene *scene = CTX_data_scene(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_shear);
+ Scene *scene = CTX_data_scene(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ gizmo_xform_message_subscribe(gzgroup, mbus, scene, screen, sa, ar, VIEW3D_GGT_xform_shear);
}
static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- {
- Scene *scene = CTX_data_scene(C);
- /* Shear is like rotate, use the rotate setting. */
- const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_ORIENT_ROTATE);
- switch (orient_slot->type) {
- case V3D_ORIENT_VIEW:
- {
- float viewinv_m3[3][3];
- copy_m3_m4(viewinv_m3, rv3d->viewinv);
- if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
- /* Take care calling refresh from draw_prepare,
- * this should be OK because it's only adjusting the cage orientation. */
- WIDGETGROUP_xform_shear_refresh(C, gzgroup);
- }
- break;
- }
- }
- }
-
- /* Basic ordering for drawing only. */
- {
- LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
- /* Since we have two pairs of each axis,
- * bias the values so gizmos that are orthogonal to the view get priority.
- * This means we never default to shearing along
- * the view axis in the case of an overlap. */
- float axis_order[3], axis_bias[3];
- copy_v3_v3(axis_order, gz->matrix_basis[2]);
- copy_v3_v3(axis_bias, gz->matrix_basis[1]);
- if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
- negate_v3(axis_bias);
- }
- madd_v3_v3fl(axis_order, axis_bias, 0.01f);
- gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
- }
- BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
- }
+ struct XFormShearWidgetGroup *xgzgroup = gzgroup->customdata;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ {
+ Scene *scene = CTX_data_scene(C);
+ /* Shear is like rotate, use the rotate setting. */
+ const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(
+ scene, SCE_ORIENT_ROTATE);
+ switch (orient_slot->type) {
+ case V3D_ORIENT_VIEW: {
+ float viewinv_m3[3][3];
+ copy_m3_m4(viewinv_m3, rv3d->viewinv);
+ if (!equals_m3m3(viewinv_m3, xgzgroup->prev.viewinv_m3)) {
+ /* Take care calling refresh from draw_prepare,
+ * this should be OK because it's only adjusting the cage orientation. */
+ WIDGETGROUP_xform_shear_refresh(C, gzgroup);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Basic ordering for drawing only. */
+ {
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
+ /* Since we have two pairs of each axis,
+ * bias the values so gizmos that are orthogonal to the view get priority.
+ * This means we never default to shearing along
+ * the view axis in the case of an overlap. */
+ float axis_order[3], axis_bias[3];
+ copy_v3_v3(axis_order, gz->matrix_basis[2]);
+ copy_v3_v3(axis_bias, gz->matrix_basis[1]);
+ if (dot_v3v3(axis_bias, rv3d->viewinv[2]) < 0.0f) {
+ negate_v3(axis_bias);
+ }
+ madd_v3_v3fl(axis_order, axis_bias, 0.01f);
+ gz->temp.f = dot_v3v3(rv3d->viewinv[2], axis_order);
+ }
+ BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
+ }
}
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Shear";
- gzgt->idname = "VIEW3D_GGT_xform_shear";
+ gzgt->name = "Transform Shear";
+ gzgt->idname = "VIEW3D_GGT_xform_shear";
- gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D;
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
- gzgt->poll = WIDGETGROUP_xform_shear_poll;
- gzgt->setup = WIDGETGROUP_xform_shear_setup;
- gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
- gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
- gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
+ gzgt->poll = WIDGETGROUP_xform_shear_poll;
+ gzgt->setup = WIDGETGROUP_xform_shear_setup;
+ gzgt->refresh = WIDGETGROUP_xform_shear_refresh;
+ gzgt->message_subscribe = WIDGETGROUP_xform_shear_message_subscribe;
+ gzgt->draw_prepare = WIDGETGROUP_xform_shear_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
index 3d2e7c89f2b..47a584561f9 100644
--- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
@@ -49,8 +49,8 @@
* \{ */
enum {
- EXTRUDE_AXIS_NORMAL = 0,
- EXTRUDE_AXIS_XYZ = 1,
+ EXTRUDE_AXIS_NORMAL = 0,
+ EXTRUDE_AXIS_XYZ = 1,
};
static const float extrude_button_scale = 0.15f;
@@ -61,415 +61,418 @@ static const float extrude_arrow_normal_axis_scale = 1.0f;
static const float extrude_dial_scale = 0.2;
static const uchar shape_plus[] = {
- 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11,
- 0x40, 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25,
- 0xee, 0x40, 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee,
- 0xa0, 0xfb, 0x80, 0xff, 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d,
- 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27, 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e,
- 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
+ 0x5f, 0xfb, 0x40, 0xee, 0x25, 0xda, 0x11, 0xbf, 0x4, 0xa0, 0x0, 0x80, 0x4, 0x5f, 0x11, 0x40,
+ 0x25, 0x25, 0x40, 0x11, 0x5f, 0x4, 0x7f, 0x0, 0xa0, 0x4, 0xbf, 0x11, 0xda, 0x25, 0xee, 0x40,
+ 0xfb, 0x5f, 0xff, 0x7f, 0xfb, 0xa0, 0xee, 0xbf, 0xda, 0xda, 0xbf, 0xee, 0xa0, 0xfb, 0x80, 0xff,
+ 0x6e, 0xd7, 0x92, 0xd7, 0x92, 0x90, 0xd8, 0x90, 0xd8, 0x6d, 0x92, 0x6d, 0x92, 0x27, 0x6e, 0x27,
+ 0x6e, 0x6d, 0x28, 0x6d, 0x28, 0x90, 0x6e, 0x90, 0x6e, 0xd7, 0x80, 0xff, 0x5f, 0xfb, 0x5f, 0xfb,
};
typedef struct GizmoExtrudeGroup {
- /* XYZ & normal. */
- wmGizmo *invoke_xyz_no[4];
- /* Constrained & unconstrained (arrow & circle). */
- wmGizmo *adjust[2];
- int adjust_axis;
-
- /* Copied from the transform operator,
- * use to redo with the same settings. */
- struct {
- float orient_matrix[3][3];
- bool constraint_axis[3];
- float value[4];
- } redo_xform;
-
- /* Depends on object type. */
- int normal_axis;
-
- struct {
- float normal_mat3[3][3]; /* use Z axis for normal. */
- int orientation_type;
- } data;
-
- wmOperatorType *ot_extrude;
- PropertyRNA *gzgt_axis_type_prop;
+ /* XYZ & normal. */
+ wmGizmo *invoke_xyz_no[4];
+ /* Constrained & unconstrained (arrow & circle). */
+ wmGizmo *adjust[2];
+ int adjust_axis;
+
+ /* Copied from the transform operator,
+ * use to redo with the same settings. */
+ struct {
+ float orient_matrix[3][3];
+ bool constraint_axis[3];
+ float value[4];
+ } redo_xform;
+
+ /* Depends on object type. */
+ int normal_axis;
+
+ struct {
+ float normal_mat3[3][3]; /* use Z axis for normal. */
+ int orientation_type;
+ } data;
+
+ wmOperatorType *ot_extrude;
+ PropertyRNA *gzgt_axis_type_prop;
} GizmoExtrudeGroup;
-static void gizmo_mesh_extrude_orientation_matrix_set(
- struct GizmoExtrudeGroup *ggd, const float mat[3][3])
+static void gizmo_mesh_extrude_orientation_matrix_set(struct GizmoExtrudeGroup *ggd,
+ const float mat[3][3])
{
- for (int i = 0; i < 3; i++) {
- mul_v3_v3fl(
- ggd->invoke_xyz_no[i]->matrix_offset[3],
- mat[i],
- (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
- }
+ for (int i = 0; i < 3; i++) {
+ mul_v3_v3fl(ggd->invoke_xyz_no[i]->matrix_offset[3],
+ mat[i],
+ (extrude_arrow_xyz_axis_scale * extrude_button_offset_scale) /
+ extrude_button_scale);
+ }
}
-static void gizmo_mesh_extrude_orientation_matrix_set_for_adjust(
- struct GizmoExtrudeGroup *ggd, const float mat[3][3])
+static void gizmo_mesh_extrude_orientation_matrix_set_for_adjust(struct GizmoExtrudeGroup *ggd,
+ const float mat[3][3])
{
- /* Set orientation without location. */
- for (int j = 0; j < 3; j++) {
- copy_v3_v3(ggd->adjust[0]->matrix_basis[j], mat[j]);
- }
- /* nop when (i == 2). */
- swap_v3_v3(ggd->adjust[0]->matrix_basis[ggd->adjust_axis], ggd->adjust[0]->matrix_basis[2]);
+ /* Set orientation without location. */
+ for (int j = 0; j < 3; j++) {
+ copy_v3_v3(ggd->adjust[0]->matrix_basis[j], mat[j]);
+ }
+ /* nop when (i == 2). */
+ swap_v3_v3(ggd->adjust[0]->matrix_basis[ggd->adjust_axis], ggd->adjust[0]->matrix_basis[2]);
}
static void gizmo_mesh_extrude_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
- struct GizmoExtrudeGroup *ggd = MEM_callocN(sizeof(GizmoExtrudeGroup), __func__);
- gzgroup->customdata = ggd;
-
- const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
- const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_button_2d", true);
- const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
-
- ggd->adjust[0] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
- ggd->adjust[1] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
- for (int i = 0; i < 4; i++) {
- ggd->invoke_xyz_no[i] = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
- ggd->invoke_xyz_no[i]->flag |= WM_GIZMO_DRAW_OFFSET_SCALE;
- }
-
- {
- PropertyRNA *prop = RNA_struct_find_property(ggd->invoke_xyz_no[3]->ptr, "shape");
- for (int i = 0; i < 4; i++) {
- RNA_property_string_set_bytes(
- ggd->invoke_xyz_no[i]->ptr, prop,
- (const char *)shape_plus, ARRAY_SIZE(shape_plus));
- }
- }
-
- {
- const char *op_idname = NULL;
- /* grease pencil does not use obedit */
- /* GPXX: Remove if OB_MODE_EDIT_GPENCIL is merged with OB_MODE_EDIT */
- const Object *obact = CTX_data_active_object(C);
- if (obact->type == OB_GPENCIL) {
- op_idname = "GPENCIL_OT_extrude_move";
- }
- else if (obact->type == OB_MESH) {
- op_idname = "MESH_OT_extrude_context_move";
- ggd->normal_axis = 2;
- }
- else if (obact->type == OB_ARMATURE) {
- op_idname = "ARMATURE_OT_extrude_move";
- ggd->normal_axis = 1;
- }
- else if (obact->type == OB_CURVE) {
- op_idname = "CURVE_OT_extrude_move";
- ggd->normal_axis = 2;
- }
- else {
- BLI_assert(0);
- }
- ggd->ot_extrude = WM_operatortype_find(op_idname, true);
- ggd->gzgt_axis_type_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis_type");
- }
-
- for (int i = 0; i < 3; i++) {
- UI_GetThemeColor3fv(TH_AXIS_X + i, ggd->invoke_xyz_no[i]->color);
- }
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->invoke_xyz_no[3]->color);
- for (int i = 0; i < 2; i++) {
- UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->adjust[i]->color);
- }
-
- for (int i = 0; i < 4; i++) {
- WM_gizmo_set_scale(ggd->invoke_xyz_no[i], extrude_button_scale);
- }
- WM_gizmo_set_scale(ggd->adjust[0], extrude_arrow_scale);
- WM_gizmo_set_scale(ggd->adjust[1], extrude_dial_scale);
- ggd->adjust[1]->line_width = 2.0f;
-
- /* XYZ & normal axis extrude. */
- for (int i = 0; i < 4; i++) {
- PointerRNA *ptr = WM_gizmo_operator_set(ggd->invoke_xyz_no[i], 0, ggd->ot_extrude, NULL);
- {
- bool constraint[3] = {0, 0, 0};
- constraint[(i < 3) ? i : ggd->normal_axis] = true;
- PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
- RNA_boolean_set(&macroptr, "release_confirm", true);
- RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
- }
- }
-
- /* Adjust extrude. */
- for (int i = 0; i < 2; i++) {
- wmGizmo *gz = ggd->adjust[i];
- PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->ot_extrude, NULL);
- PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
- RNA_boolean_set(&macroptr, "release_confirm", true);
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- gzop->is_redo = true;
- }
+ struct GizmoExtrudeGroup *ggd = MEM_callocN(sizeof(GizmoExtrudeGroup), __func__);
+ gzgroup->customdata = ggd;
+
+ const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true);
+ const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_button_2d", true);
+ const wmGizmoType *gzt_dial = WM_gizmotype_find("GIZMO_GT_dial_3d", true);
+
+ ggd->adjust[0] = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL);
+ ggd->adjust[1] = WM_gizmo_new_ptr(gzt_dial, gzgroup, NULL);
+ for (int i = 0; i < 4; i++) {
+ ggd->invoke_xyz_no[i] = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL);
+ ggd->invoke_xyz_no[i]->flag |= WM_GIZMO_DRAW_OFFSET_SCALE;
+ }
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(ggd->invoke_xyz_no[3]->ptr, "shape");
+ for (int i = 0; i < 4; i++) {
+ RNA_property_string_set_bytes(
+ ggd->invoke_xyz_no[i]->ptr, prop, (const char *)shape_plus, ARRAY_SIZE(shape_plus));
+ }
+ }
+
+ {
+ const char *op_idname = NULL;
+ /* grease pencil does not use obedit */
+ /* GPXX: Remove if OB_MODE_EDIT_GPENCIL is merged with OB_MODE_EDIT */
+ const Object *obact = CTX_data_active_object(C);
+ if (obact->type == OB_GPENCIL) {
+ op_idname = "GPENCIL_OT_extrude_move";
+ }
+ else if (obact->type == OB_MESH) {
+ op_idname = "MESH_OT_extrude_context_move";
+ ggd->normal_axis = 2;
+ }
+ else if (obact->type == OB_ARMATURE) {
+ op_idname = "ARMATURE_OT_extrude_move";
+ ggd->normal_axis = 1;
+ }
+ else if (obact->type == OB_CURVE) {
+ op_idname = "CURVE_OT_extrude_move";
+ ggd->normal_axis = 2;
+ }
+ else {
+ BLI_assert(0);
+ }
+ ggd->ot_extrude = WM_operatortype_find(op_idname, true);
+ ggd->gzgt_axis_type_prop = RNA_struct_type_find_property(gzgroup->type->srna, "axis_type");
+ }
+
+ for (int i = 0; i < 3; i++) {
+ UI_GetThemeColor3fv(TH_AXIS_X + i, ggd->invoke_xyz_no[i]->color);
+ }
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->invoke_xyz_no[3]->color);
+ for (int i = 0; i < 2; i++) {
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, ggd->adjust[i]->color);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ WM_gizmo_set_scale(ggd->invoke_xyz_no[i], extrude_button_scale);
+ }
+ WM_gizmo_set_scale(ggd->adjust[0], extrude_arrow_scale);
+ WM_gizmo_set_scale(ggd->adjust[1], extrude_dial_scale);
+ ggd->adjust[1]->line_width = 2.0f;
+
+ /* XYZ & normal axis extrude. */
+ for (int i = 0; i < 4; i++) {
+ PointerRNA *ptr = WM_gizmo_operator_set(ggd->invoke_xyz_no[i], 0, ggd->ot_extrude, NULL);
+ {
+ bool constraint[3] = {0, 0, 0};
+ constraint[(i < 3) ? i : ggd->normal_axis] = true;
+ PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
+ RNA_boolean_set(&macroptr, "release_confirm", true);
+ RNA_boolean_set_array(&macroptr, "constraint_axis", constraint);
+ }
+ }
+
+ /* Adjust extrude. */
+ for (int i = 0; i < 2; i++) {
+ wmGizmo *gz = ggd->adjust[i];
+ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ggd->ot_extrude, NULL);
+ PointerRNA macroptr = RNA_pointer_get(ptr, "TRANSFORM_OT_translate");
+ RNA_boolean_set(&macroptr, "release_confirm", true);
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ gzop->is_redo = true;
+ }
}
static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
-
- for (int i = 0; i < 4; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
- }
- for (int i = 0; i < 2; i++) {
- WM_gizmo_set_flag(ggd->adjust[i], WM_GIZMO_HIDDEN, true);
- }
-
- if (G.moving) {
- return;
- }
-
- Scene *scene = CTX_data_scene(C);
-
- int axis_type;
- {
- PointerRNA ptr;
- bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
- WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
- axis_type = RNA_property_enum_get(&ptr, ggd->gzgt_axis_type_prop);
- }
-
- ggd->data.orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const bool use_normal = (
- (ggd->data.orientation_type != V3D_ORIENT_NORMAL) ||
- (axis_type == EXTRUDE_AXIS_NORMAL));
- const int axis_len_used = use_normal ? 4 : 3;
-
- struct TransformBounds tbounds;
-
- if (use_normal) {
- struct TransformBounds tbounds_normal;
- if (!ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .orientation_type = V3D_ORIENT_NORMAL + 1,
- }, &tbounds_normal))
- {
- unit_m3(tbounds_normal.axis);
- }
- copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis);
- }
-
- /* TODO(campbell): run second since this modifies the 3D view, it should not. */
- if (!ED_transform_calc_gizmo_stats(
- C, &(struct TransformCalcParams){
- .orientation_type = ggd->data.orientation_type + 1,
- }, &tbounds))
- {
- return;
- }
-
- /* Main axis is normal. */
- if (!use_normal) {
- copy_m3_m3(ggd->data.normal_mat3, tbounds.axis);
- }
-
- /* Offset the add icon. */
- mul_v3_v3fl(
- ggd->invoke_xyz_no[3]->matrix_offset[3],
- ggd->data.normal_mat3[ggd->normal_axis],
- (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) / extrude_button_scale);
-
- /* Adjust current operator. */
- /* Don't use 'WM_operator_last_redo' because selection actions will be ignored. */
- wmOperator *op = CTX_wm_manager(C)->operators.last;
- bool has_redo = (op && op->type == ggd->ot_extrude);
- wmOperator *op_xform = has_redo ? op->macro.last : NULL;
-
- bool adjust_is_flip = false;
- wmGizmo *gz_adjust = NULL;
-
- if (has_redo) {
- gz_adjust = ggd->adjust[1];
- /* We can't access this from 'ot->last_properties'
- * because some properties use skip-save. */
- RNA_float_get_array(op_xform->ptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
- RNA_boolean_get_array(op_xform->ptr, "constraint_axis", ggd->redo_xform.constraint_axis);
- RNA_float_get_array(op_xform->ptr, "value", ggd->redo_xform.value);
-
- /* Set properties for redo. */
- for (int i = 0; i < 3; i++) {
- if (ggd->redo_xform.constraint_axis[i]) {
- adjust_is_flip = ggd->redo_xform.value[i] < 0.0f;
- ggd->adjust_axis = i;
- gz_adjust = ggd->adjust[0];
- break;
- }
- }
- }
-
- /* Needed for normal orientation. */
- gizmo_mesh_extrude_orientation_matrix_set(ggd, tbounds.axis);
-
- /* Location. */
- for (int i = 0; i < axis_len_used; i++) {
- WM_gizmo_set_matrix_location(ggd->invoke_xyz_no[i], tbounds.center);
- }
- /* Un-hide. */
- for (int i = 0; i < axis_len_used; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, false);
- }
-
- if (has_redo) {
- if (gz_adjust == ggd->adjust[0]) {
- gizmo_mesh_extrude_orientation_matrix_set_for_adjust(ggd, ggd->redo_xform.orient_matrix);
- if (adjust_is_flip) {
- negate_v3(ggd->adjust[0]->matrix_basis[2]);
- }
- }
- WM_gizmo_set_matrix_location(gz_adjust, tbounds.center);
- WM_gizmo_set_flag(gz_adjust, WM_GIZMO_HIDDEN, false);
- }
-
- /* Redo with current settings. */
- if (has_redo) {
- for (int i = 0; i < 4; i++) {
- RNA_enum_set(
- ggd->invoke_xyz_no[i]->ptr,
- "draw_options",
- ((gz_adjust == ggd->adjust[0]) &&
- dot_v3v3(ggd->adjust[0]->matrix_basis[2],
- ggd->invoke_xyz_no[i]->matrix_offset[3]) > 0.98f) ? 0 : ED_GIZMO_BUTTON_SHOW_HELPLINE);
- }
- }
- else {
- for (int i = 0; i < 4; i++) {
- RNA_enum_set(ggd->invoke_xyz_no[i]->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_HELPLINE);
- }
- }
-
- /* TODO: skip calculating axis which wont be used (above). */
- switch (axis_type) {
- case EXTRUDE_AXIS_NORMAL:
- for (int i = 0; i < 3; i++) {
- WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
- }
- break;
- case EXTRUDE_AXIS_XYZ:
- WM_gizmo_set_flag(ggd->invoke_xyz_no[3], WM_GIZMO_HIDDEN, true);
- break;
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+
+ for (int i = 0; i < 4; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
+ }
+ for (int i = 0; i < 2; i++) {
+ WM_gizmo_set_flag(ggd->adjust[i], WM_GIZMO_HIDDEN, true);
+ }
+
+ if (G.moving) {
+ return;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+
+ int axis_type;
+ {
+ PointerRNA ptr;
+ bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
+ WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &ptr);
+ axis_type = RNA_property_enum_get(&ptr, ggd->gzgt_axis_type_prop);
+ }
+
+ ggd->data.orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const bool use_normal = ((ggd->data.orientation_type != V3D_ORIENT_NORMAL) ||
+ (axis_type == EXTRUDE_AXIS_NORMAL));
+ const int axis_len_used = use_normal ? 4 : 3;
+
+ struct TransformBounds tbounds;
+
+ if (use_normal) {
+ struct TransformBounds tbounds_normal;
+ if (!ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .orientation_type = V3D_ORIENT_NORMAL + 1,
+ },
+ &tbounds_normal)) {
+ unit_m3(tbounds_normal.axis);
+ }
+ copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis);
+ }
+
+ /* TODO(campbell): run second since this modifies the 3D view, it should not. */
+ if (!ED_transform_calc_gizmo_stats(C,
+ &(struct TransformCalcParams){
+ .orientation_type = ggd->data.orientation_type + 1,
+ },
+ &tbounds)) {
+ return;
+ }
+
+ /* Main axis is normal. */
+ if (!use_normal) {
+ copy_m3_m3(ggd->data.normal_mat3, tbounds.axis);
+ }
+
+ /* Offset the add icon. */
+ mul_v3_v3fl(ggd->invoke_xyz_no[3]->matrix_offset[3],
+ ggd->data.normal_mat3[ggd->normal_axis],
+ (extrude_arrow_normal_axis_scale * extrude_button_offset_scale) /
+ extrude_button_scale);
+
+ /* Adjust current operator. */
+ /* Don't use 'WM_operator_last_redo' because selection actions will be ignored. */
+ wmOperator *op = CTX_wm_manager(C)->operators.last;
+ bool has_redo = (op && op->type == ggd->ot_extrude);
+ wmOperator *op_xform = has_redo ? op->macro.last : NULL;
+
+ bool adjust_is_flip = false;
+ wmGizmo *gz_adjust = NULL;
+
+ if (has_redo) {
+ gz_adjust = ggd->adjust[1];
+ /* We can't access this from 'ot->last_properties'
+ * because some properties use skip-save. */
+ RNA_float_get_array(op_xform->ptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
+ RNA_boolean_get_array(op_xform->ptr, "constraint_axis", ggd->redo_xform.constraint_axis);
+ RNA_float_get_array(op_xform->ptr, "value", ggd->redo_xform.value);
+
+ /* Set properties for redo. */
+ for (int i = 0; i < 3; i++) {
+ if (ggd->redo_xform.constraint_axis[i]) {
+ adjust_is_flip = ggd->redo_xform.value[i] < 0.0f;
+ ggd->adjust_axis = i;
+ gz_adjust = ggd->adjust[0];
+ break;
+ }
+ }
+ }
+
+ /* Needed for normal orientation. */
+ gizmo_mesh_extrude_orientation_matrix_set(ggd, tbounds.axis);
+
+ /* Location. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_gizmo_set_matrix_location(ggd->invoke_xyz_no[i], tbounds.center);
+ }
+ /* Un-hide. */
+ for (int i = 0; i < axis_len_used; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, false);
+ }
+
+ if (has_redo) {
+ if (gz_adjust == ggd->adjust[0]) {
+ gizmo_mesh_extrude_orientation_matrix_set_for_adjust(ggd, ggd->redo_xform.orient_matrix);
+ if (adjust_is_flip) {
+ negate_v3(ggd->adjust[0]->matrix_basis[2]);
+ }
+ }
+ WM_gizmo_set_matrix_location(gz_adjust, tbounds.center);
+ WM_gizmo_set_flag(gz_adjust, WM_GIZMO_HIDDEN, false);
+ }
+
+ /* Redo with current settings. */
+ if (has_redo) {
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(ggd->invoke_xyz_no[i]->ptr,
+ "draw_options",
+ ((gz_adjust == ggd->adjust[0]) &&
+ dot_v3v3(ggd->adjust[0]->matrix_basis[2],
+ ggd->invoke_xyz_no[i]->matrix_offset[3]) > 0.98f) ?
+ 0 :
+ ED_GIZMO_BUTTON_SHOW_HELPLINE);
+ }
+ }
+ else {
+ for (int i = 0; i < 4; i++) {
+ RNA_enum_set(ggd->invoke_xyz_no[i]->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_HELPLINE);
+ }
+ }
+
+ /* TODO: skip calculating axis which wont be used (above). */
+ switch (axis_type) {
+ case EXTRUDE_AXIS_NORMAL:
+ for (int i = 0; i < 3; i++) {
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[i], WM_GIZMO_HIDDEN, true);
+ }
+ break;
+ case EXTRUDE_AXIS_XYZ:
+ WM_gizmo_set_flag(ggd->invoke_xyz_no[3], WM_GIZMO_HIDDEN, true);
+ break;
+ }
}
static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- switch (ggd->data.orientation_type) {
- case V3D_ORIENT_VIEW:
- {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float mat[3][3];
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
- gizmo_mesh_extrude_orientation_matrix_set(ggd, mat);
- break;
- }
- }
-
- /* Basic ordering for drawing only. */
- {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
- gz->temp.f = dot_v3v3(rv3d->viewinv[2], gz->matrix_offset[3]);
- }
- BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
-
- if ((ggd->adjust[1]->flag & WM_GIZMO_HIDDEN) == 0) {
- copy_v3_v3(ggd->adjust[1]->matrix_basis[0], rv3d->viewinv[0]);
- copy_v3_v3(ggd->adjust[1]->matrix_basis[1], rv3d->viewinv[1]);
- copy_v3_v3(ggd->adjust[1]->matrix_basis[2], rv3d->viewinv[2]);
- }
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ switch (ggd->data.orientation_type) {
+ case V3D_ORIENT_VIEW: {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ gizmo_mesh_extrude_orientation_matrix_set(ggd, mat);
+ break;
+ }
+ }
+
+ /* Basic ordering for drawing only. */
+ {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
+ gz->temp.f = dot_v3v3(rv3d->viewinv[2], gz->matrix_offset[3]);
+ }
+ BLI_listbase_sort(&gzgroup->gizmos, WM_gizmo_cmp_temp_fl_reverse);
+
+ if ((ggd->adjust[1]->flag & WM_GIZMO_HIDDEN) == 0) {
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[0], rv3d->viewinv[0]);
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[1], rv3d->viewinv[1]);
+ copy_v3_v3(ggd->adjust[1]->matrix_basis[2], rv3d->viewinv[2]);
+ }
+ }
}
-static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C),
+ wmGizmoGroup *gzgroup,
+ wmGizmo *gz)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) {
- /* Set properties for redo. */
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
- if (gz == ggd->adjust[0]) {
- RNA_boolean_set_array(&macroptr, "constraint_axis", ggd->redo_xform.constraint_axis);
- RNA_float_set_array(&macroptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
- RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
- }
- RNA_float_set_array(&macroptr, "value", ggd->redo_xform.value);
- }
- else {
- /* Workaround for extrude action modifying normals. */
- const int i = BLI_array_findindex(ggd->invoke_xyz_no, ARRAY_SIZE(ggd->invoke_xyz_no), &gz);
- BLI_assert(i != -1);
- bool use_normal_matrix = false;
- if (i == 3) {
- use_normal_matrix = true;
- }
- else if (ggd->data.orientation_type == V3D_ORIENT_NORMAL) {
- use_normal_matrix = true;
- }
- if (use_normal_matrix) {
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
- PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
- RNA_float_set_array(&macroptr, "orient_matrix", &ggd->data.normal_mat3[0][0]);
- RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
- }
- }
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) {
+ /* Set properties for redo. */
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
+ if (gz == ggd->adjust[0]) {
+ RNA_boolean_set_array(&macroptr, "constraint_axis", ggd->redo_xform.constraint_axis);
+ RNA_float_set_array(&macroptr, "orient_matrix", &ggd->redo_xform.orient_matrix[0][0]);
+ RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
+ }
+ RNA_float_set_array(&macroptr, "value", ggd->redo_xform.value);
+ }
+ else {
+ /* Workaround for extrude action modifying normals. */
+ const int i = BLI_array_findindex(ggd->invoke_xyz_no, ARRAY_SIZE(ggd->invoke_xyz_no), &gz);
+ BLI_assert(i != -1);
+ bool use_normal_matrix = false;
+ if (i == 3) {
+ use_normal_matrix = true;
+ }
+ else if (ggd->data.orientation_type == V3D_ORIENT_NORMAL) {
+ use_normal_matrix = true;
+ }
+ if (use_normal_matrix) {
+ wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+ PointerRNA macroptr = RNA_pointer_get(&gzop->ptr, "TRANSFORM_OT_translate");
+ RNA_float_set_array(&macroptr, "orient_matrix", &ggd->data.normal_mat3[0][0]);
+ RNA_enum_set(&macroptr, "orient_type", V3D_ORIENT_NORMAL);
+ }
+ }
}
-static void gizmo_mesh_extrude_message_subscribe(
- const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus)
+static void gizmo_mesh_extrude_message_subscribe(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
{
- GizmoExtrudeGroup *ggd = gzgroup->customdata;
- ARegion *ar = CTX_wm_region(C);
-
- /* Subscribe to view properties */
- wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
- .owner = ar,
- .user_data = gzgroup->parent_gzmap,
- .notify = WM_gizmo_do_msg_notify_tag_refresh,
- };
-
- {
- WM_msg_subscribe_rna_anon_prop(mbus, TransformOrientationSlot, type, &msg_sub_value_gz_tag_refresh);
- }
-
-
- WM_msg_subscribe_rna_params(
- mbus,
- &(const wmMsgParams_RNA){
- .ptr = (PointerRNA){ .type = gzgroup->type->srna, },
- .prop = ggd->gzgt_axis_type_prop,
- },
- &msg_sub_value_gz_tag_refresh, __func__);
+ GizmoExtrudeGroup *ggd = gzgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
+ .owner = ar,
+ .user_data = gzgroup->parent_gzmap,
+ .notify = WM_gizmo_do_msg_notify_tag_refresh,
+ };
+
+ {
+ WM_msg_subscribe_rna_anon_prop(
+ mbus, TransformOrientationSlot, type, &msg_sub_value_gz_tag_refresh);
+ }
+
+ WM_msg_subscribe_rna_params(mbus,
+ &(const wmMsgParams_RNA){
+ .ptr =
+ (PointerRNA){
+ .type = gzgroup->type->srna,
+ },
+ .prop = ggd->gzgt_axis_type_prop,
+ },
+ &msg_sub_value_gz_tag_refresh,
+ __func__);
}
void VIEW3D_GGT_xform_extrude(struct wmGizmoGroupType *gzgt)
{
- gzgt->name = "3D View Extrude";
- gzgt->idname = "VIEW3D_GGT_xform_extrude";
-
- gzgt->flag = WM_GIZMOGROUPTYPE_3D;
-
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
-
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = gizmo_mesh_extrude_setup;
- gzgt->refresh = gizmo_mesh_extrude_refresh;
- gzgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
- gzgt->invoke_prepare = gizmo_mesh_extrude_invoke_prepare;
- gzgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
-
- static const EnumPropertyItem axis_type_items[] = {
- {EXTRUDE_AXIS_NORMAL, "NORMAL", 0, "Regular", "Only show normal axis"},
- {EXTRUDE_AXIS_XYZ, "XYZ", 0, "XYZ", "Follow scene orientation"},
- {0, NULL, 0, NULL, NULL},
- };
- RNA_def_enum(gzgt->srna, "axis_type", axis_type_items, 0, "Axis Type", "");
+ gzgt->name = "3D View Extrude";
+ gzgt->idname = "VIEW3D_GGT_xform_extrude";
+
+ gzgt->flag = WM_GIZMOGROUPTYPE_3D;
+
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = gizmo_mesh_extrude_setup;
+ gzgt->refresh = gizmo_mesh_extrude_refresh;
+ gzgt->draw_prepare = gizmo_mesh_extrude_draw_prepare;
+ gzgt->invoke_prepare = gizmo_mesh_extrude_invoke_prepare;
+ gzgt->message_subscribe = gizmo_mesh_extrude_message_subscribe;
+
+ static const EnumPropertyItem axis_type_items[] = {
+ {EXTRUDE_AXIS_NORMAL, "NORMAL", 0, "Regular", "Only show normal axis"},
+ {EXTRUDE_AXIS_XYZ, "XYZ", 0, "XYZ", "Follow scene orientation"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ RNA_def_enum(gzgt->srna, "axis_type", axis_type_items, 0, "Axis Type", "");
}
/** \} */
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index b03d50e11e7..46f6e576cf4 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -18,7 +18,6 @@
* \ingroup edtransform
*/
-
#include <stdlib.h>
#include <math.h>
@@ -40,426 +39,454 @@
static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
+ convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]);
}
-static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputSpring(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- double dx, dy;
- float ratio;
+ double dx, dy;
+ float ratio;
- dx = ((double)mi->center[0] - mval[0]);
- dy = ((double)mi->center[1] - mval[1]);
- ratio = hypot(dx, dy) / (double)mi->factor;
+ dx = ((double)mi->center[0] - mval[0]);
+ dy = ((double)mi->center[1] - mval[1]);
+ ratio = hypot(dx, dy) / (double)mi->factor;
- output[0] = ratio;
+ output[0] = ratio;
}
static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputSpring(t, mi, mval, output);
-
- /* flip scale */
- /* values can become really big when zoomed in so use longs [#26598] */
- if ((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) +
- (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1]) < 0)
- {
- output[0] *= -1.0f;
- }
+ InputSpring(t, mi, mval, output);
+
+ /* flip scale */
+ /* values can become really big when zoomed in so use longs [#26598] */
+ if ((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) +
+ (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1]) <
+ 0) {
+ output[0] *= -1.0f;
+ }
}
static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputSpring(t, mi, mval, output);
- output[0] -= 1.0f;
+ InputSpring(t, mi, mval, output);
+ output[0] -= 1.0f;
}
-static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputTrackBall(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- output[0] = (float)(mi->imval[1] - mval[1]);
- output[1] = (float)(mval[0] - mi->imval[0]);
+ output[0] = (float)(mi->imval[1] - mval[1]);
+ output[1] = (float)(mval[0] - mi->imval[0]);
- output[0] *= mi->factor;
- output[1] *= mi->factor;
+ output[0] *= mi->factor;
+ output[1] *= mi->factor;
}
-static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+static void InputHorizontalRatio(TransInfo *t,
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- const int winx = t->ar ? t->ar->winx : 1;
+ const int winx = t->ar ? t->ar->winx : 1;
- output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
+ output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
}
-static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+static void InputHorizontalAbsolute(TransInfo *t,
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- float vec[3];
+ float vec[3];
- InputVector(t, mi, mval, vec);
- project_v3_v3v3(vec, vec, t->viewinv[0]);
+ InputVector(t, mi, mval, vec);
+ project_v3_v3v3(vec, vec, t->viewinv[0]);
- output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
+ output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
}
static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- const int winy = t->ar ? t->ar->winy : 1;
+ const int winy = t->ar ? t->ar->winy : 1;
- output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
+ output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
}
-static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
+static void InputVerticalAbsolute(TransInfo *t,
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- float vec[3];
+ float vec[3];
- InputVector(t, mi, mval, vec);
- project_v3_v3v3(vec, vec, t->viewinv[1]);
+ InputVector(t, mi, mval, vec);
+ project_v3_v3v3(vec, vec, t->viewinv[1]);
- output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f;
+ output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f;
}
-void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int mval_start[2], const int mval_end[2])
+void setCustomPoints(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const int mval_start[2],
+ const int mval_end[2])
{
- int *data;
+ int *data;
- mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
+ mi->data = MEM_reallocN(mi->data, sizeof(int) * 4);
- data = mi->data;
+ data = mi->data;
- data[0] = mval_start[0];
- data[1] = mval_start[1];
- data[2] = mval_end[0];
- data[3] = mval_end[1];
+ data[0] = mval_start[0];
+ data[1] = mval_start[1];
+ data[2] = mval_end[0];
+ data[3] = mval_end[1];
}
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2])
{
- BLI_ASSERT_UNIT_V2(dir);
- const int win_axis = t->ar ? ((abs((int)(t->ar->winx * dir[0])) + abs((int)(t->ar->winy * dir[1]))) / 2) : 1;
- const int mval_start[2] = {
- mi->imval[0] + dir[0] * win_axis,
- mi->imval[1] + dir[1] * win_axis,
- };
- const int mval_end[2] = {mi->imval[0], mi->imval[1]};
- setCustomPoints(t, mi, mval_start, mval_end);
+ BLI_ASSERT_UNIT_V2(dir);
+ const int win_axis = t->ar ?
+ ((abs((int)(t->ar->winx * dir[0])) + abs((int)(t->ar->winy * dir[1]))) /
+ 2) :
+ 1;
+ const int mval_start[2] = {
+ mi->imval[0] + dir[0] * win_axis,
+ mi->imval[1] + dir[1] * win_axis,
+ };
+ const int mval_end[2] = {mi->imval[0], mi->imval[1]};
+ setCustomPoints(t, mi, mval_start, mval_end);
}
-static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
+static void InputCustomRatioFlip(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const double mval[2],
+ float output[3])
{
- double length;
- double distance;
- double dx, dy;
- const int *data = mi->data;
+ double length;
+ double distance;
+ double dx, dy;
+ const int *data = mi->data;
- if (data) {
- int mdx, mdy;
- dx = data[2] - data[0];
- dy = data[3] - data[1];
+ if (data) {
+ int mdx, mdy;
+ dx = data[2] - data[0];
+ dy = data[3] - data[1];
- length = hypot(dx, dy);
+ length = hypot(dx, dy);
- mdx = mval[0] - data[2];
- mdy = mval[1] - data[3];
+ mdx = mval[0] - data[2];
+ mdy = mval[1] - data[3];
- distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
+ distance = (length != 0.0) ? (mdx * dx + mdy * dy) / length : 0.0;
- output[0] = (length != 0.0) ? (double)(distance / length) : 0.0;
- }
+ output[0] = (length != 0.0) ? (double)(distance / length) : 0.0;
+ }
}
static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- InputCustomRatioFlip(t, mi, mval, output);
- output[0] = -output[0];
+ InputCustomRatioFlip(t, mi, mval, output);
+ output[0] = -output[0];
}
struct InputAngle_Data {
- double angle;
- double mval_prev[2];
+ double angle;
+ double mval_prev[2];
};
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3])
{
- struct InputAngle_Data *data = mi->data;
- double dx2 = mval[0] - (double)mi->center[0];
- double dy2 = mval[1] - (double)mi->center[1];
- double B = sqrt(dx2 * dx2 + dy2 * dy2);
+ struct InputAngle_Data *data = mi->data;
+ double dx2 = mval[0] - (double)mi->center[0];
+ double dy2 = mval[1] - (double)mi->center[1];
+ double B = sqrt(dx2 * dx2 + dy2 * dy2);
- double dx1 = data->mval_prev[0] - (double)mi->center[0];
- double dy1 = data->mval_prev[1] - (double)mi->center[1];
- double A = sqrt(dx1 * dx1 + dy1 * dy1);
+ double dx1 = data->mval_prev[0] - (double)mi->center[0];
+ double dy1 = data->mval_prev[1] - (double)mi->center[1];
+ double A = sqrt(dx1 * dx1 + dy1 * dy1);
- double dx3 = mval[0] - data->mval_prev[0];
- double dy3 = mval[1] - data->mval_prev[1];
+ double dx3 = mval[0] - data->mval_prev[0];
+ double dy3 = mval[1] - data->mval_prev[1];
- /* use doubles here, to make sure a "1.0" (no rotation)
- * doesn't become 9.999999e-01, which gives 0.02 for acos */
- double deler = (((dx1 * dx1 + dy1 * dy1) +
- (dx2 * dx2 + dy2 * dy2) -
- (dx3 * dx3 + dy3 * dy3)) / (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0)));
- /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
+ /* use doubles here, to make sure a "1.0" (no rotation)
+ * doesn't become 9.999999e-01, which gives 0.02 for acos */
+ double deler = (((dx1 * dx1 + dy1 * dy1) + (dx2 * dx2 + dy2 * dy2) - (dx3 * dx3 + dy3 * dy3)) /
+ (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0)));
+ /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
- float dphi;
+ float dphi;
- dphi = saacos((float)deler);
- if ((dx1 * dy2 - dx2 * dy1) > 0.0) dphi = -dphi;
+ dphi = saacos((float)deler);
+ if ((dx1 * dy2 - dx2 * dy1) > 0.0)
+ dphi = -dphi;
- /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
- * approximate the angle with the opposite side of the normalized triangle
- * This is a good approximation here since the smallest acos value seems to be around
- * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
- */
- if (dphi == 0) {
- double dx, dy;
+ /* If the angle is zero, because of lack of precision close to the 1.0 value in acos
+ * approximate the angle with the opposite side of the normalized triangle
+ * This is a good approximation here since the smallest acos value seems to be around
+ * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation
+ */
+ if (dphi == 0) {
+ double dx, dy;
- dx2 /= A;
- dy2 /= A;
+ dx2 /= A;
+ dy2 /= A;
- dx1 /= B;
- dy1 /= B;
+ dx1 /= B;
+ dy1 /= B;
- dx = dx1 - dx2;
- dy = dy1 - dy2;
+ dx = dx1 - dx2;
+ dy = dy1 - dy2;
- dphi = sqrt(dx * dx + dy * dy);
- if ((dx1 * dy2 - dx2 * dy1) > 0.0) dphi = -dphi;
- }
+ dphi = sqrt(dx * dx + dy * dy);
+ if ((dx1 * dy2 - dx2 * dy1) > 0.0)
+ dphi = -dphi;
+ }
- data->angle += ((double)dphi) * (mi->precision ? (double)mi->precision_factor : 1.0);
+ data->angle += ((double)dphi) * (mi->precision ? (double)mi->precision_factor : 1.0);
- data->mval_prev[0] = mval[0];
- data->mval_prev[1] = mval[1];
+ data->mval_prev[0] = mval[0];
+ data->mval_prev[1] = mval[1];
- output[0] = data->angle;
+ output[0] = data->angle;
}
static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
- float toutput[3];
+ float toutput[3];
- InputAngle(t, mi, mval, output);
- InputSpring(t, mi, mval, toutput);
+ InputAngle(t, mi, mval, output);
+ InputSpring(t, mi, mval, toutput);
- output[1] = toutput[0];
+ output[1] = toutput[0];
}
-void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2], const bool precision)
+void initMouseInput(TransInfo *UNUSED(t),
+ MouseInput *mi,
+ const float center[2],
+ const int mval[2],
+ const bool precision)
{
- mi->factor = 0;
- mi->precision = precision;
+ mi->factor = 0;
+ mi->precision = precision;
- mi->center[0] = center[0];
- mi->center[1] = center[1];
+ mi->center[0] = center[0];
+ mi->center[1] = center[1];
- mi->imval[0] = mval[0];
- mi->imval[1] = mval[1];
+ mi->imval[0] = mval[0];
+ mi->imval[1] = mval[1];
- mi->post = NULL;
+ mi->post = NULL;
}
static void calcSpringFactor(MouseInput *mi)
{
- mi->factor = sqrtf(((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) +
- ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0])));
+ mi->factor = sqrtf(
+ ((float)(mi->center[1] - mi->imval[1])) * ((float)(mi->center[1] - mi->imval[1])) +
+ ((float)(mi->center[0] - mi->imval[0])) * ((float)(mi->center[0] - mi->imval[0])));
- if (mi->factor == 0.0f) {
- mi->factor = 1.0f; /* prevent Inf */
- }
+ if (mi->factor == 0.0f) {
+ mi->factor = 1.0f; /* prevent Inf */
+ }
}
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
{
- /* incase we allocate a new value */
- void *mi_data_prev = mi->data;
-
- mi->use_virtual_mval = true;
- mi->precision_factor = 1.0f / 10.0f;
-
- switch (mode) {
- case INPUT_VECTOR:
- mi->apply = InputVector;
- t->helpline = HLP_NONE;
- break;
- case INPUT_SPRING:
- calcSpringFactor(mi);
- mi->apply = InputSpring;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_SPRING_FLIP:
- calcSpringFactor(mi);
- mi->apply = InputSpringFlip;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_SPRING_DELTA:
- calcSpringFactor(mi);
- mi->apply = InputSpringDelta;
- t->helpline = HLP_SPRING;
- break;
- case INPUT_ANGLE:
- case INPUT_ANGLE_SPRING:
- {
- struct InputAngle_Data *data;
- mi->use_virtual_mval = false;
- mi->precision_factor = 1.0f / 30.0f;
- data = MEM_callocN(sizeof(struct InputAngle_Data), "angle accumulator");
- data->mval_prev[0] = mi->imval[0];
- data->mval_prev[1] = mi->imval[1];
- mi->data = data;
- if (mode == INPUT_ANGLE) {
- mi->apply = InputAngle;
- }
- else {
- calcSpringFactor(mi);
- mi->apply = InputAngleSpring;
- }
- t->helpline = HLP_ANGLE;
- break;
- }
- case INPUT_TRACKBALL:
- mi->precision_factor = 1.0f / 30.0f;
- /* factor has to become setting or so */
- mi->factor = 0.01f;
- mi->apply = InputTrackBall;
- t->helpline = HLP_TRACKBALL;
- break;
- case INPUT_HORIZONTAL_RATIO:
- mi->apply = InputHorizontalRatio;
- t->helpline = HLP_HARROW;
- break;
- case INPUT_HORIZONTAL_ABSOLUTE:
- mi->apply = InputHorizontalAbsolute;
- t->helpline = HLP_HARROW;
- break;
- case INPUT_VERTICAL_RATIO:
- mi->apply = InputVerticalRatio;
- t->helpline = HLP_VARROW;
- break;
- case INPUT_VERTICAL_ABSOLUTE:
- mi->apply = InputVerticalAbsolute;
- t->helpline = HLP_VARROW;
- break;
- case INPUT_CUSTOM_RATIO:
- mi->apply = InputCustomRatio;
- t->helpline = HLP_CARROW;
- break;
- case INPUT_CUSTOM_RATIO_FLIP:
- mi->apply = InputCustomRatioFlip;
- t->helpline = HLP_CARROW;
- break;
- case INPUT_NONE:
- default:
- mi->apply = NULL;
- break;
- }
-
- /* setup for the mouse cursor: either set a custom one,
- * or hide it if it will be drawn with the helpline */
- wmWindow *win = CTX_wm_window(t->context);
- switch (t->helpline) {
- case HLP_NONE:
- /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */
- if (t->flag & T_MODAL) {
- t->flag |= T_MODAL_CURSOR_SET;
- WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
- }
- break;
- case HLP_SPRING:
- case HLP_ANGLE:
- case HLP_TRACKBALL:
- case HLP_HARROW:
- case HLP_VARROW:
- case HLP_CARROW:
- if (t->flag & T_MODAL) {
- t->flag |= T_MODAL_CURSOR_SET;
- WM_cursor_modal_set(win, CURSOR_NONE);
- }
- break;
- default:
- break;
- }
-
- /* if we've allocated new data, free the old data
- * less hassle then checking before every alloc above */
- if (mi_data_prev && (mi_data_prev != mi->data)) {
- MEM_freeN(mi_data_prev);
- }
+ /* incase we allocate a new value */
+ void *mi_data_prev = mi->data;
+
+ mi->use_virtual_mval = true;
+ mi->precision_factor = 1.0f / 10.0f;
+
+ switch (mode) {
+ case INPUT_VECTOR:
+ mi->apply = InputVector;
+ t->helpline = HLP_NONE;
+ break;
+ case INPUT_SPRING:
+ calcSpringFactor(mi);
+ mi->apply = InputSpring;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_SPRING_FLIP:
+ calcSpringFactor(mi);
+ mi->apply = InputSpringFlip;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_SPRING_DELTA:
+ calcSpringFactor(mi);
+ mi->apply = InputSpringDelta;
+ t->helpline = HLP_SPRING;
+ break;
+ case INPUT_ANGLE:
+ case INPUT_ANGLE_SPRING: {
+ struct InputAngle_Data *data;
+ mi->use_virtual_mval = false;
+ mi->precision_factor = 1.0f / 30.0f;
+ data = MEM_callocN(sizeof(struct InputAngle_Data), "angle accumulator");
+ data->mval_prev[0] = mi->imval[0];
+ data->mval_prev[1] = mi->imval[1];
+ mi->data = data;
+ if (mode == INPUT_ANGLE) {
+ mi->apply = InputAngle;
+ }
+ else {
+ calcSpringFactor(mi);
+ mi->apply = InputAngleSpring;
+ }
+ t->helpline = HLP_ANGLE;
+ break;
+ }
+ case INPUT_TRACKBALL:
+ mi->precision_factor = 1.0f / 30.0f;
+ /* factor has to become setting or so */
+ mi->factor = 0.01f;
+ mi->apply = InputTrackBall;
+ t->helpline = HLP_TRACKBALL;
+ break;
+ case INPUT_HORIZONTAL_RATIO:
+ mi->apply = InputHorizontalRatio;
+ t->helpline = HLP_HARROW;
+ break;
+ case INPUT_HORIZONTAL_ABSOLUTE:
+ mi->apply = InputHorizontalAbsolute;
+ t->helpline = HLP_HARROW;
+ break;
+ case INPUT_VERTICAL_RATIO:
+ mi->apply = InputVerticalRatio;
+ t->helpline = HLP_VARROW;
+ break;
+ case INPUT_VERTICAL_ABSOLUTE:
+ mi->apply = InputVerticalAbsolute;
+ t->helpline = HLP_VARROW;
+ break;
+ case INPUT_CUSTOM_RATIO:
+ mi->apply = InputCustomRatio;
+ t->helpline = HLP_CARROW;
+ break;
+ case INPUT_CUSTOM_RATIO_FLIP:
+ mi->apply = InputCustomRatioFlip;
+ t->helpline = HLP_CARROW;
+ break;
+ case INPUT_NONE:
+ default:
+ mi->apply = NULL;
+ break;
+ }
+
+ /* setup for the mouse cursor: either set a custom one,
+ * or hide it if it will be drawn with the helpline */
+ wmWindow *win = CTX_wm_window(t->context);
+ switch (t->helpline) {
+ case HLP_NONE:
+ /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */
+ if (t->flag & T_MODAL) {
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR);
+ }
+ break;
+ case HLP_SPRING:
+ case HLP_ANGLE:
+ case HLP_TRACKBALL:
+ case HLP_HARROW:
+ case HLP_VARROW:
+ case HLP_CARROW:
+ if (t->flag & T_MODAL) {
+ t->flag |= T_MODAL_CURSOR_SET;
+ WM_cursor_modal_set(win, CURSOR_NONE);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* if we've allocated new data, free the old data
+ * less hassle then checking before every alloc above */
+ if (mi_data_prev && (mi_data_prev != mi->data)) {
+ MEM_freeN(mi_data_prev);
+ }
}
void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]))
{
- mi->post = post;
+ mi->post = post;
}
void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
{
- double mval_db[2];
-
- if (mi->use_virtual_mval) {
- /* update accumulator */
- double mval_delta[2];
-
- mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
- mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
-
- mi->virtual_mval.prev[0] += mval_delta[0];
- mi->virtual_mval.prev[1] += mval_delta[1];
-
- if (mi->precision) {
- mval_delta[0] *= (double)mi->precision_factor;
- mval_delta[1] *= (double)mi->precision_factor;
- }
-
- mi->virtual_mval.accum[0] += mval_delta[0];
- mi->virtual_mval.accum[1] += mval_delta[1];
-
- mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
- mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
- }
- else {
- mval_db[0] = mval[0];
- mval_db[1] = mval[1];
- }
-
-
- if (mi->apply != NULL) {
- mi->apply(t, mi, mval_db, output);
- }
-
- if (!is_zero_v3(t->values_modal_offset)) {
- float values_ofs[3];
- if (t->con.mode & CON_APPLY) {
- mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset);
- }
- else {
- copy_v3_v3(values_ofs, t->values_modal_offset);
- }
- add_v3_v3(t->values, values_ofs);
- }
-
- if (mi->post) {
- mi->post(t, output);
- }
+ double mval_db[2];
+
+ if (mi->use_virtual_mval) {
+ /* update accumulator */
+ double mval_delta[2];
+
+ mval_delta[0] = (mval[0] - mi->imval[0]) - mi->virtual_mval.prev[0];
+ mval_delta[1] = (mval[1] - mi->imval[1]) - mi->virtual_mval.prev[1];
+
+ mi->virtual_mval.prev[0] += mval_delta[0];
+ mi->virtual_mval.prev[1] += mval_delta[1];
+
+ if (mi->precision) {
+ mval_delta[0] *= (double)mi->precision_factor;
+ mval_delta[1] *= (double)mi->precision_factor;
+ }
+
+ mi->virtual_mval.accum[0] += mval_delta[0];
+ mi->virtual_mval.accum[1] += mval_delta[1];
+
+ mval_db[0] = mi->imval[0] + mi->virtual_mval.accum[0];
+ mval_db[1] = mi->imval[1] + mi->virtual_mval.accum[1];
+ }
+ else {
+ mval_db[0] = mval[0];
+ mval_db[1] = mval[1];
+ }
+
+ if (mi->apply != NULL) {
+ mi->apply(t, mi, mval_db, output);
+ }
+
+ if (!is_zero_v3(t->values_modal_offset)) {
+ float values_ofs[3];
+ if (t->con.mode & CON_APPLY) {
+ mul_v3_m3v3(values_ofs, t->spacemtx, t->values_modal_offset);
+ }
+ else {
+ copy_v3_v3(values_ofs, t->values_modal_offset);
+ }
+ add_v3_v3(t->values, values_ofs);
+ }
+
+ if (mi->post) {
+ mi->post(t, output);
+ }
}
eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
{
- eRedrawFlag redraw = TREDRAW_NOTHING;
-
- switch (event->type) {
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- if (event->val == KM_PRESS) {
- t->modifiers |= MOD_PRECISION;
- /* shift is modifier for higher precision transforn */
- mi->precision = 1;
- redraw = TREDRAW_HARD;
- }
- else if (event->val == KM_RELEASE) {
- t->modifiers &= ~MOD_PRECISION;
- mi->precision = 0;
- redraw = TREDRAW_HARD;
- }
- break;
- }
-
- return redraw;
+ eRedrawFlag redraw = TREDRAW_NOTHING;
+
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (event->val == KM_PRESS) {
+ t->modifiers |= MOD_PRECISION;
+ /* shift is modifier for higher precision transforn */
+ mi->precision = 1;
+ redraw = TREDRAW_HARD;
+ }
+ else if (event->val == KM_RELEASE) {
+ t->modifiers &= ~MOD_PRECISION;
+ mi->precision = 0;
+ redraw = TREDRAW_HARD;
+ }
+ break;
+ }
+
+ return redraw;
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 7140938c99a..14d904fdc6d 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -54,9 +54,9 @@
#include "transform.h"
typedef struct TransformModeItem {
- const char *idname;
- int mode;
- void (*opfunc)(wmOperatorType *);
+ const char *idname;
+ int mode;
+ void (*opfunc)(wmOperatorType *);
} TransformModeItem;
static const float VecOne[3] = {1, 1, 1};
@@ -99,1079 +99,1141 @@ static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot);
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot);
-static TransformModeItem transform_modes[] =
-{
- {OP_TRANSLATION, TFM_TRANSLATION, TRANSFORM_OT_translate},
- {OP_ROTATION, TFM_ROTATION, TRANSFORM_OT_rotate},
- {OP_TOSPHERE, TFM_TOSPHERE, TRANSFORM_OT_tosphere},
- {OP_RESIZE, TFM_RESIZE, TRANSFORM_OT_resize},
- {OP_SKIN_RESIZE, TFM_SKIN_RESIZE, TRANSFORM_OT_skin_resize},
- {OP_SHEAR, TFM_SHEAR, TRANSFORM_OT_shear},
- {OP_BEND, TFM_BEND, TRANSFORM_OT_bend},
- {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN, TRANSFORM_OT_shrink_fatten},
- {OP_PUSH_PULL, TFM_PUSHPULL, TRANSFORM_OT_push_pull},
- {OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
- {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
- {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
- {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide},
- {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide},
- {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
- {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
- {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
- {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal},
- {NULL, 0},
+static TransformModeItem transform_modes[] = {
+ {OP_TRANSLATION, TFM_TRANSLATION, TRANSFORM_OT_translate},
+ {OP_ROTATION, TFM_ROTATION, TRANSFORM_OT_rotate},
+ {OP_TOSPHERE, TFM_TOSPHERE, TRANSFORM_OT_tosphere},
+ {OP_RESIZE, TFM_RESIZE, TRANSFORM_OT_resize},
+ {OP_SKIN_RESIZE, TFM_SKIN_RESIZE, TRANSFORM_OT_skin_resize},
+ {OP_SHEAR, TFM_SHEAR, TRANSFORM_OT_shear},
+ {OP_BEND, TFM_BEND, TRANSFORM_OT_bend},
+ {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN, TRANSFORM_OT_shrink_fatten},
+ {OP_PUSH_PULL, TFM_PUSHPULL, TRANSFORM_OT_push_pull},
+ {OP_TILT, TFM_TILT, TRANSFORM_OT_tilt},
+ {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
+ {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
+ {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide},
+ {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide},
+ {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
+ {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
+ {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
+ {OP_NORMAL_ROTATION, TFM_NORMAL_ROTATION, TRANSFORM_OT_rotate_normal},
+ {NULL, 0},
};
-const EnumPropertyItem rna_enum_transform_mode_types[] =
-{
- {TFM_INIT, "INIT", 0, "Init", ""},
- {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
- {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
- {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
- {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
- {TFM_SKIN_RESIZE, "SKIN_RESIZE", 0, "Skin Resize", ""},
- {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
- {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
- {TFM_BEND, "BEND", 0, "Bend", ""},
- {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
- {TFM_TILT, "TILT", 0, "Tilt", ""},
- {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
- {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
- {TFM_CREASE, "CREASE", 0, "Crease", ""},
- {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", ""},
- {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
- {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
- {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
- {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
- {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
- {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
- {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
- {TFM_ALIGN, "ALIGN", 0, "Align", ""},
- {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
- {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
- {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""},
- {0, NULL, 0, NULL, NULL},
+const EnumPropertyItem rna_enum_transform_mode_types[] = {
+ {TFM_INIT, "INIT", 0, "Init", ""},
+ {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
+ {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
+ {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
+ {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
+ {TFM_SKIN_RESIZE, "SKIN_RESIZE", 0, "Skin Resize", ""},
+ {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
+ {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
+ {TFM_BEND, "BEND", 0, "Bend", ""},
+ {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
+ {TFM_TILT, "TILT", 0, "Tilt", ""},
+ {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
+ {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
+ {TFM_CREASE, "CREASE", 0, "Crease", ""},
+ {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", ""},
+ {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
+ {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
+ {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
+ {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
+ {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
+ {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
+ {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
+ {TFM_ALIGN, "ALIGN", 0, "Align", ""},
+ {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
+ {TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
+ {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int select_orientation_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
- int orientation = RNA_enum_get(op->ptr, "orientation");
+ int orientation = RNA_enum_get(op->ptr, "orientation");
- BKE_scene_orientation_slot_set_index(&scene->orientation_slots[SCE_ORIENT_DEFAULT], orientation);
+ BKE_scene_orientation_slot_set_index(&scene->orientation_slots[SCE_ORIENT_DEFAULT], orientation);
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- WM_msg_publish_rna_prop(mbus, &scene->id, scene, TransformOrientationSlot, type);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, TransformOrientationSlot, type);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int select_orientation_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
- UI_popup_menu_end(C, pup);
+ pup = UI_popup_menu_begin(C, IFACE_("Orientation"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Select Orientation";
- ot->description = "Select transformation orientation";
- ot->idname = "TRANSFORM_OT_select_orientation";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = select_orientation_invoke;
- ot->exec = select_orientation_exec;
- ot->poll = ED_operator_view3d_active;
-
- prop = RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Orientation";
+ ot->description = "Select transformation orientation";
+ ot->idname = "TRANSFORM_OT_select_orientation";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = select_orientation_invoke;
+ ot->exec = select_orientation_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ prop = RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
}
-
static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- BIF_removeTransformOrientationIndex(C, scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom);
+ Scene *scene = CTX_data_scene(C);
+ BIF_removeTransformOrientationIndex(C,
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return delete_orientation_exec(C, op);
+ return delete_orientation_exec(C, op);
}
static bool delete_orientation_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (ED_operator_areaactive(C) == 0)
- return 0;
+ if (ED_operator_areaactive(C) == 0)
+ return 0;
- return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_ORIENT_CUSTOM) &&
- (scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
+ return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_ORIENT_CUSTOM) &&
+ (scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
}
static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Orientation";
- ot->description = "Delete transformation orientation";
- ot->idname = "TRANSFORM_OT_delete_orientation";
- ot->flag = OPTYPE_UNDO;
-
- /* api callbacks */
- ot->invoke = delete_orientation_invoke;
- ot->exec = delete_orientation_exec;
- ot->poll = delete_orientation_poll;
+ /* identifiers */
+ ot->name = "Delete Orientation";
+ ot->description = "Delete transformation orientation";
+ ot->idname = "TRANSFORM_OT_delete_orientation";
+ ot->flag = OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->invoke = delete_orientation_invoke;
+ ot->exec = delete_orientation_exec;
+ ot->poll = delete_orientation_poll;
}
static int create_orientation_exec(bContext *C, wmOperator *op)
{
- char name[MAX_NAME];
- const bool use = RNA_boolean_get(op->ptr, "use");
- const bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
- const bool use_view = RNA_boolean_get(op->ptr, "use_view");
- View3D *v3d = CTX_wm_view3d(C);
+ char name[MAX_NAME];
+ const bool use = RNA_boolean_get(op->ptr, "use");
+ const bool overwrite = RNA_boolean_get(op->ptr, "overwrite");
+ const bool use_view = RNA_boolean_get(op->ptr, "use_view");
+ View3D *v3d = CTX_wm_view3d(C);
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- if (use && !v3d) {
- BKE_report(op->reports, RPT_ERROR, "Create Orientation's 'use' parameter only valid in a 3DView context");
- return OPERATOR_CANCELLED;
- }
+ if (use && !v3d) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Create Orientation's 'use' parameter only valid in a 3DView context");
+ return OPERATOR_CANCELLED;
+ }
- BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
+ BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static void TRANSFORM_OT_create_orientation(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create Orientation";
- ot->description = "Create transformation orientation from selection";
- ot->idname = "TRANSFORM_OT_create_orientation";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* api callbacks */
- ot->exec = create_orientation_exec;
- ot->poll = ED_operator_areaactive;
-
- RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
- RNA_def_boolean(ot->srna, "use_view", false, "Use View",
- "Use the current view instead of the active object to create the new orientation");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
- RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite previous",
- "Overwrite previously created orientation with same name");
+ /* identifiers */
+ ot->name = "Create Orientation";
+ ot->description = "Create transformation orientation from selection";
+ ot->idname = "TRANSFORM_OT_create_orientation";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* api callbacks */
+ ot->exec = create_orientation_exec;
+ ot->poll = ED_operator_areaactive;
+
+ RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
+ RNA_def_boolean(
+ ot->srna,
+ "use_view",
+ false,
+ "Use View",
+ "Use the current view instead of the active object to create the new orientation");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(
+ ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
+ RNA_def_boolean(ot->srna,
+ "overwrite",
+ false,
+ "Overwrite previous",
+ "Overwrite previously created orientation with same name");
}
-
#ifdef USE_LOOPSLIDE_HACK
/**
* Special hack for MESH_OT_loopcut_slide so we get back to the selection mode
*/
static void transformops_loopsel_hack(bContext *C, wmOperator *op)
{
- if (op->type->idname == OP_EDGE_SLIDE) {
- if (op->opm && op->opm->opm && op->opm->opm->prev) {
- wmOperator *op_prev = op->opm->opm->prev;
- Scene *scene = CTX_data_scene(C);
- bool mesh_select_mode[3];
- PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
-
- if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
- ToolSettings *ts = scene->toolsettings;
- short selectmode_orig;
-
- RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
- selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
- (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) |
- (mesh_select_mode[2] ? SCE_SELECT_FACE : 0));
-
- /* still switch if we were originally in face select mode */
- if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- em->selectmode = ts->selectmode = selectmode_orig;
- EDBM_selectmode_set(em);
- }
- }
- }
- }
+ if (op->type->idname == OP_EDGE_SLIDE) {
+ if (op->opm && op->opm->opm && op->opm->opm->prev) {
+ wmOperator *op_prev = op->opm->opm->prev;
+ Scene *scene = CTX_data_scene(C);
+ bool mesh_select_mode[3];
+ PropertyRNA *prop = RNA_struct_find_property(op_prev->ptr, "mesh_select_mode_init");
+
+ if (prop && RNA_property_is_set(op_prev->ptr, prop)) {
+ ToolSettings *ts = scene->toolsettings;
+ short selectmode_orig;
+
+ RNA_property_boolean_get_array(op_prev->ptr, prop, mesh_select_mode);
+ selectmode_orig = ((mesh_select_mode[0] ? SCE_SELECT_VERTEX : 0) |
+ (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) |
+ (mesh_select_mode[2] ? SCE_SELECT_FACE : 0));
+
+ /* still switch if we were originally in face select mode */
+ if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ em->selectmode = ts->selectmode = selectmode_orig;
+ EDBM_selectmode_set(em);
+ }
+ }
+ }
+ }
}
#else
/* prevent removal by cleanup */
# error "loopslide hack removed!"
-#endif /* USE_LOOPSLIDE_HACK */
-
+#endif /* USE_LOOPSLIDE_HACK */
static void transformops_exit(bContext *C, wmOperator *op)
{
#ifdef USE_LOOPSLIDE_HACK
- transformops_loopsel_hack(C, op);
+ transformops_loopsel_hack(C, op);
#endif
- saveTransform(C, op->customdata, op);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- G.moving = 0;
+ saveTransform(C, op->customdata, op);
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+ G.moving = 0;
}
static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event)
{
- int retval = 1;
- if (op->customdata == NULL) {
- TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
- TransformModeItem *tmode;
- int mode = -1;
-
- for (tmode = transform_modes; tmode->idname; tmode++) {
- if (op->type->idname == tmode->idname) {
- mode = tmode->mode;
- break;
- }
- }
-
- if (mode == -1) {
- mode = RNA_enum_get(op->ptr, "mode");
- }
-
- retval = initTransform(C, t, op, event, mode);
-
- /* store data */
- if (retval) {
- G.moving = special_transform_moving(t);
- op->customdata = t;
- }
- else {
- MEM_freeN(t);
- }
- }
-
- return retval; /* return 0 on error */
+ int retval = 1;
+ if (op->customdata == NULL) {
+ TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data2");
+ TransformModeItem *tmode;
+ int mode = -1;
+
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ if (op->type->idname == tmode->idname) {
+ mode = tmode->mode;
+ break;
+ }
+ }
+
+ if (mode == -1) {
+ mode = RNA_enum_get(op->ptr, "mode");
+ }
+
+ retval = initTransform(C, t, op, event, mode);
+
+ /* store data */
+ if (retval) {
+ G.moving = special_transform_moving(t);
+ op->customdata = t;
+ }
+ else {
+ MEM_freeN(t);
+ }
+ }
+
+ return retval; /* return 0 on error */
}
static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- int exit_code;
+ int exit_code;
- TransInfo *t = op->customdata;
- const enum TfmMode mode_prev = t->mode;
+ TransInfo *t = op->customdata;
+ const enum TfmMode mode_prev = t->mode;
#if defined(WITH_INPUT_NDOF) && 0
- // stable 2D mouse coords map to different 3D coords while the 3D mouse is active
- // in other words, 2D deltas are no longer good enough!
- // disable until individual 'transformers' behave better
+ // stable 2D mouse coords map to different 3D coords while the 3D mouse is active
+ // in other words, 2D deltas are no longer good enough!
+ // disable until individual 'transformers' behave better
- if (event->type == NDOF_MOTION)
- return OPERATOR_PASS_THROUGH;
+ if (event->type == NDOF_MOTION)
+ return OPERATOR_PASS_THROUGH;
#endif
- /* XXX insert keys are called here, and require context */
- t->context = C;
- exit_code = transformEvent(t, event);
- t->context = NULL;
-
- /* XXX, workaround: active needs to be calculated before transforming,
- * since we're not reading from 'td->center' in this case. see: T40241 */
- if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) {
- /* In camera view, tsnap callback is not set
- * (see initSnappingMode() in transfrom_snap.c, and T40348). */
- if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) {
- t->tsnap.targetSnap(t);
- }
- }
-
- transformApply(C, t);
-
- exit_code |= transformEnd(C, t);
-
- if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
- transformops_exit(C, op);
- exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */
- }
- else {
- if (mode_prev != t->mode) {
- /* WARNING: this is not normal to switch operator types
- * normally it would not be supported but transform happens
- * to share callbacks between different operators. */
- wmOperatorType *ot_new = NULL;
- TransformModeItem *item = transform_modes;
- while (item->idname) {
- if (item->mode == t->mode) {
- ot_new = WM_operatortype_find(item->idname, false);
- break;
- }
- item++;
- }
-
- BLI_assert(ot_new != NULL);
- if (ot_new) {
- WM_operator_type_set(op, ot_new);
- }
- /* end suspicious code */
- }
- }
-
- return exit_code;
+ /* XXX insert keys are called here, and require context */
+ t->context = C;
+ exit_code = transformEvent(t, event);
+ t->context = NULL;
+
+ /* XXX, workaround: active needs to be calculated before transforming,
+ * since we're not reading from 'td->center' in this case. see: T40241 */
+ if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) {
+ /* In camera view, tsnap callback is not set
+ * (see initSnappingMode() in transfrom_snap.c, and T40348). */
+ if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) {
+ t->tsnap.targetSnap(t);
+ }
+ }
+
+ transformApply(C, t);
+
+ exit_code |= transformEnd(C, t);
+
+ if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) {
+ transformops_exit(C, op);
+ exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */
+ }
+ else {
+ if (mode_prev != t->mode) {
+ /* WARNING: this is not normal to switch operator types
+ * normally it would not be supported but transform happens
+ * to share callbacks between different operators. */
+ wmOperatorType *ot_new = NULL;
+ TransformModeItem *item = transform_modes;
+ while (item->idname) {
+ if (item->mode == t->mode) {
+ ot_new = WM_operatortype_find(item->idname, false);
+ break;
+ }
+ item++;
+ }
+
+ BLI_assert(ot_new != NULL);
+ if (ot_new) {
+ WM_operator_type_set(op, ot_new);
+ }
+ /* end suspicious code */
+ }
+ }
+
+ return exit_code;
}
static void transform_cancel(bContext *C, wmOperator *op)
{
- TransInfo *t = op->customdata;
+ TransInfo *t = op->customdata;
- t->state = TRANS_CANCEL;
- transformEnd(C, t);
- transformops_exit(C, op);
+ t->state = TRANS_CANCEL;
+ transformEnd(C, t);
+ transformops_exit(C, op);
}
static int transform_exec(bContext *C, wmOperator *op)
{
- TransInfo *t;
+ TransInfo *t;
- if (!transformops_data(C, op, NULL)) {
- G.moving = 0;
- return OPERATOR_CANCELLED;
- }
+ if (!transformops_data(C, op, NULL)) {
+ G.moving = 0;
+ return OPERATOR_CANCELLED;
+ }
- t = op->customdata;
+ t = op->customdata;
- t->options |= CTX_AUTOCONFIRM;
+ t->options |= CTX_AUTOCONFIRM;
- transformApply(C, t);
+ transformApply(C, t);
- transformEnd(C, t);
+ transformEnd(C, t);
- transformops_exit(C, op);
+ transformops_exit(C, op);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (!transformops_data(C, op, event)) {
- G.moving = 0;
- return OPERATOR_CANCELLED;
- }
-
- /* When modal, allow 'value' to set initial offset. */
- if ((event == NULL) &&
- RNA_struct_property_is_set(op->ptr, "value"))
- {
- return transform_exec(C, op);
- }
- else {
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the gizmo only?
-
- /* Use when modal input has some transformation to begin with. */
- {
- TransInfo *t = op->customdata;
- if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) {
- transformApply(C, t);
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
- }
+ if (!transformops_data(C, op, event)) {
+ G.moving = 0;
+ return OPERATOR_CANCELLED;
+ }
+
+ /* When modal, allow 'value' to set initial offset. */
+ if ((event == NULL) && RNA_struct_property_is_set(op->ptr, "value")) {
+ return transform_exec(C, op);
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the gizmo only?
+
+ /* Use when modal input has some transformation to begin with. */
+ {
+ TransInfo *t = op->customdata;
+ if (UNLIKELY(!is_zero_v4(t->values_modal_offset))) {
+ transformApply(C, t);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+ }
}
-static bool transform_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool transform_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
-
- /* Orientation/Constraints. */
- {
- /* Hide orientation axis if no constraints are set, since it wont be used. */
- PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "orient_type");
- if (prop_con != NULL && (prop_con != prop)) {
- if (STRPREFIX(prop_id, "constraint")) {
-
- /* Special case: show constraint axis if we don't have values,
- * needed for mirror operator. */
- if (STREQ(prop_id, "constraint_axis") &&
- (RNA_struct_find_property(op->ptr, "value") == NULL))
- {
- return true;
- }
-
- return false;
- }
- }
- }
-
- /* Proportional Editing. */
- {
- PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional");
- if (prop_pet && (prop_pet != prop) &&
- (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF))
- {
- if (STRPREFIX(prop_id, "proportional")) {
- return false;
- }
- }
- }
-
- return true;
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Orientation/Constraints. */
+ {
+ /* Hide orientation axis if no constraints are set, since it wont be used. */
+ PropertyRNA *prop_con = RNA_struct_find_property(op->ptr, "orient_type");
+ if (prop_con != NULL && (prop_con != prop)) {
+ if (STRPREFIX(prop_id, "constraint")) {
+
+ /* Special case: show constraint axis if we don't have values,
+ * needed for mirror operator. */
+ if (STREQ(prop_id, "constraint_axis") &&
+ (RNA_struct_find_property(op->ptr, "value") == NULL)) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+
+ /* Proportional Editing. */
+ {
+ PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "proportional");
+ if (prop_pet && (prop_pet != prop) &&
+ (RNA_property_enum_get(op->ptr, prop_pet) == PROP_EDIT_OFF)) {
+ if (STRPREFIX(prop_id, "proportional")) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
void Transform_Properties(struct wmOperatorType *ot, int flags)
{
- PropertyRNA *prop;
-
- if (flags & P_ORIENT_AXIS) {
- prop = RNA_def_property(ot->srna, "orient_axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Axis", "");
- RNA_def_property_enum_default(prop, 2);
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
- if (flags & P_ORIENT_AXIS_ORTHO) {
- prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Axis Ortho", "");
- RNA_def_property_enum_default(prop, 1);
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- }
-
- if (flags & P_ORIENT_MATRIX) {
- prop = RNA_def_property(ot->srna, "orient_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
-
- /* Set by 'orient_type' or gizmo which acts on non-standard orientation. */
- prop = RNA_def_float_matrix(ot->srna, "orient_matrix", 3, 3, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- /* Only use 'orient_matrix' when 'orient_matrix_type == orient_type',
- * this allows us to reuse the orientation set by a gizmo for eg, without disabling the ability
- * to switch over to other orientations. */
- prop = RNA_def_property(ot->srna, "orient_matrix_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_ui_text(prop, "Matrix Orientation", "");
- RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
-
- if (flags & P_CONSTRAINT) {
- RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
- }
-
- if (flags & P_MIRROR) {
- prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
- if (flags & P_MIRROR_DUMMY) {
- /* only used so macros can disable this option */
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- }
-
-
- if (flags & P_PROPORTIONAL) {
- RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", "");
- prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0,
- "Proportional Falloff", "Falloff type for proportional editing mode");
- /* Abusing id_curve :/ */
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
- RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
- "Proportional Size", "", 0.001f, 100.0f);
- }
-
- if (flags & P_SNAP) {
- prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- if (flags & P_GEO_SNAP) {
- prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- if (flags & P_ALIGN_SNAP) {
- prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_float_vector(ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
- }
- }
-
- if (flags & P_GPENCIL_EDIT) {
- prop = RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if (flags & P_CURSOR_EDIT) {
- prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
- prop = RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- if (flags & P_CORRECT_UV) {
- RNA_def_boolean(ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
- }
-
- if (flags & P_CENTER) {
- /* For gizmos that define their own center. */
- prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
- RNA_def_property_array(prop, 3);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
- }
-
- if ((flags & P_NO_DEFAULTS) == 0) {
- prop = RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- }
+ PropertyRNA *prop;
+
+ if (flags & P_ORIENT_AXIS) {
+ prop = RNA_def_property(ot->srna, "orient_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Axis", "");
+ RNA_def_property_enum_default(prop, 2);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+ if (flags & P_ORIENT_AXIS_ORTHO) {
+ prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Axis Ortho", "");
+ RNA_def_property_enum_default(prop, 1);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_ORIENT_MATRIX) {
+ prop = RNA_def_property(ot->srna, "orient_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+
+ /* Set by 'orient_type' or gizmo which acts on non-standard orientation. */
+ prop = RNA_def_float_matrix(
+ ot->srna, "orient_matrix", 3, 3, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* Only use 'orient_matrix' when 'orient_matrix_type == orient_type',
+ * this allows us to reuse the orientation set by a gizmo for eg, without disabling the ability
+ * to switch over to other orientations. */
+ prop = RNA_def_property(ot->srna, "orient_matrix_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Matrix Orientation", "");
+ RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+
+ if (flags & P_CONSTRAINT) {
+ RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
+ }
+
+ if (flags & P_MIRROR) {
+ prop = RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
+ if (flags & P_MIRROR_DUMMY) {
+ /* only used so macros can disable this option */
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+
+ if (flags & P_PROPORTIONAL) {
+ RNA_def_enum(ot->srna,
+ "proportional",
+ rna_enum_proportional_editing_items,
+ 0,
+ "Proportional Editing",
+ "");
+ prop = RNA_def_enum(ot->srna,
+ "proportional_edit_falloff",
+ rna_enum_proportional_falloff_items,
+ 0,
+ "Proportional Falloff",
+ "Falloff type for proportional editing mode");
+ /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
+ RNA_def_float(ot->srna,
+ "proportional_size",
+ 1,
+ T_PROP_SIZE_MIN,
+ T_PROP_SIZE_MAX,
+ "Proportional Size",
+ "",
+ 0.001f,
+ 100.0f);
+ }
+
+ if (flags & P_SNAP) {
+ prop = RNA_def_boolean(ot->srna, "snap", 0, "Use Snapping Options", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flags & P_GEO_SNAP) {
+ prop = RNA_def_enum(ot->srna, "snap_target", rna_enum_snap_target_items, 0, "Target", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float_vector(
+ ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flags & P_ALIGN_SNAP) {
+ prop = RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_float_vector(
+ ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
+ }
+ }
+
+ if (flags & P_GPENCIL_EDIT) {
+ prop = RNA_def_boolean(ot->srna,
+ "gpencil_strokes",
+ 0,
+ "Edit Grease Pencil",
+ "Edit selected Grease Pencil strokes");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_CURSOR_EDIT) {
+ prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
+ prop = RNA_def_boolean(
+ ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ if (flags & P_CORRECT_UV) {
+ RNA_def_boolean(
+ ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming");
+ }
+
+ if (flags & P_CENTER) {
+ /* For gizmos that define their own center. */
+ prop = RNA_def_property(ot->srna, "center_override", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_property_ui_text(prop, "Center Override", "Force using this center value (when set)");
+ }
+
+ if ((flags & P_NO_DEFAULTS) == 0) {
+ prop = RNA_def_boolean(ot->srna,
+ "release_confirm",
+ 0,
+ "Confirm on Release",
+ "Always confirm operation when releasing button");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
}
static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move";
- ot->description = "Move selected items";
- ot->idname = OP_TRANSLATION;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot,
- P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS |
- P_GPENCIL_EDIT | P_CURSOR_EDIT);
+ /* identifiers */
+ ot->name = "Move";
+ ot->description = "Move selected items";
+ ot->idname = OP_TRANSLATION;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector_xyz(
+ ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Move", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
+ P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Resize";
- ot->description = "Scale (resize) selected items";
- ot->idname = OP_RESIZE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Resize";
+ ot->description = "Scale (resize) selected items";
+ ot->idname = OP_RESIZE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector(
+ ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
+ P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
static bool skin_resize_poll(bContext *C)
{
- struct Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
- }
- return 0;
+ struct Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
+ }
+ return 0;
}
static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Skin Resize";
- ot->description = "Scale selected vertices' skin radii";
- ot->idname = OP_SKIN_RESIZE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = skin_resize_poll;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_NO_TEXSPACE);
+ /* identifiers */
+ ot->name = "Skin Resize";
+ ot->description = "Scale selected vertices' skin radii";
+ ot->idname = OP_SKIN_RESIZE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = skin_resize_poll;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_vector(
+ ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP |
+ P_OPTIONS | P_NO_TEXSPACE);
}
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Trackball";
- ot->description = "Trackball style rotation of selected items";
- ot->idname = OP_TRACKBALL;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- /* Maybe we could use float_vector_xyz here too? */
- RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Trackball";
+ ot->description = "Trackball style rotation of selected items";
+ ot->idname = OP_TRACKBALL;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ /* Maybe we could use float_vector_xyz here too? */
+ RNA_def_float_rotation(
+ ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Rotate";
- ot->description = "Rotate selected items";
- ot->idname = OP_ROTATION;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Rotate";
+ ot->description = "Rotate selected items";
+ ot->idname = OP_ROTATION;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
+ P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Tilt";
- /* optional -
- * "Tilt selected vertices"
- * "Specify an extra axis rotation for selected vertices of 3D curve" */
- ot->description = "Tilt selected control vertices of 3D curve";
- ot->idname = OP_TILT;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editcurve_3d;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ /* identifiers */
+ ot->name = "Tilt";
+ /* optional -
+ * "Tilt selected vertices"
+ * "Specify an extra axis rotation for selected vertices of 3D curve" */
+ ot->description = "Tilt selected control vertices of 3D curve";
+ ot->idname = OP_TILT;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editcurve_3d;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bend";
- ot->description = "Bend selected items between the 3D cursor and the mouse";
- ot->idname = OP_BEND;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- // ot->exec = transform_exec; // unsupported
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_region_view3d_active;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Bend";
+ ot->description = "Bend selected items between the 3D cursor and the mouse";
+ ot->idname = OP_BEND;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ // ot->exec = transform_exec; // unsupported
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_region_view3d_active;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shear";
- ot->description = "Shear selected items along the horizontal screen axis";
- ot->idname = OP_SHEAR;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- RNA_def_enum(ot->srna, "shear_axis", rna_enum_axis_xy_items, 0, "Shear Axis", "");
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_AXIS_ORTHO | P_ORIENT_MATRIX | P_PROPORTIONAL | P_MIRROR |
- P_SNAP | P_GPENCIL_EDIT);
+ /* identifiers */
+ ot->name = "Shear";
+ ot->description = "Shear selected items along the horizontal screen axis";
+ ot->idname = OP_SHEAR;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_enum(ot->srna, "shear_axis", rna_enum_axis_xy_items, 0, "Shear Axis", "");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_AXIS_ORTHO | P_ORIENT_MATRIX | P_PROPORTIONAL |
+ P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Push/Pull";
- ot->description = "Push/Pull selected items";
- ot->idname = OP_PUSH_PULL;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Push/Pull";
+ ot->description = "Push/Pull selected items";
+ ot->idname = OP_PUSH_PULL;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
- RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
}
static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shrink/Fatten";
- ot->description = "Shrink/fatten selected vertices along normals";
- ot->idname = OP_SHRINK_FATTEN;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_distance(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
-
- RNA_def_boolean(ot->srna, "use_even_offset", false, "Offset Even", "Scale the offset to give more even thickness");
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
+ /* identifiers */
+ ot->name = "Shrink/Fatten";
+ ot->description = "Shrink/fatten selected vertices along normals";
+ ot->idname = OP_SHRINK_FATTEN;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_distance(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+
+ RNA_def_boolean(ot->srna,
+ "use_even_offset",
+ false,
+ "Offset Even",
+ "Scale the offset to give more even thickness");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "To Sphere";
- //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
- ot->description = "Move selected vertices outward in a spherical shape around mesh center";
- ot->idname = OP_TOSPHERE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "To Sphere";
+ //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()"
+ ot->description = "Move selected vertices outward in a spherical shape around mesh center";
+ ot->idname = OP_TOSPHERE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror";
- ot->description = "Mirror selected items around one or more axes";
- ot->idname = OP_MIRROR;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
+ /* identifiers */
+ ot->name = "Mirror";
+ ot->description = "Mirror selected items around one or more axes";
+ ot->idname = OP_MIRROR;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ Transform_Properties(
+ ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
}
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";
- ot->idname = OP_EDGE_SLIDE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh_region_view3d;
- ot->poll_property = transform_poll_property;
-
- 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);
- RNA_def_boolean(ot->srna, "use_even", false, "Even",
- "Make the edge loop match the shape of the adjacent edge loop");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
- "When Even mode is active, flips between the two adjacent edge loops");
- RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
- "Clamp within the edge extents");
-
- Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Edge Slide";
+ ot->description = "Slide an edge loop along a mesh";
+ ot->idname = OP_EDGE_SLIDE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
+
+ 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);
+ RNA_def_boolean(ot->srna,
+ "use_even",
+ false,
+ "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
+
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Slide";
- ot->description = "Slide a vertex along a mesh";
- ot->idname = OP_VERT_SLIDE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh_region_view3d;
- ot->poll_property = transform_poll_property;
-
- RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
- RNA_def_boolean(ot->srna, "use_even", false, "Even",
- "Make the edge loop match the shape of the adjacent edge loop");
-
- WM_operatortype_props_advanced_begin(ot);
-
- RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
- "When Even mode is active, flips between the two adjacent edge loops");
- RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
- "Clamp within the edge extents");
-
- Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
+ /* identifiers */
+ ot->name = "Vertex Slide";
+ ot->description = "Slide a vertex along a mesh";
+ ot->idname = OP_VERT_SLIDE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh_region_view3d;
+ ot->poll_property = transform_poll_property;
+
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_boolean(ot->srna,
+ "use_even",
+ false,
+ "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ RNA_def_boolean(ot->srna,
+ "flipped",
+ false,
+ "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", "Clamp within the edge extents");
+
+ Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Crease";
- ot->description = "Change the crease of edges";
- ot->idname = OP_EDGE_CREASE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Edge Crease";
+ ot->description = "Change the crease of edges";
+ ot->idname = OP_EDGE_CREASE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
- ot->poll_property = transform_poll_property;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
+ ot->poll_property = transform_poll_property;
- 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, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Edge Bevel Weight";
- ot->description = "Change the bevel weight of edges";
- ot->idname = OP_EDGE_BWEIGHT;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Edge Bevel Weight";
+ ot->description = "Change the bevel weight of edges";
+ ot->idname = OP_EDGE_BWEIGHT;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
- 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, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Sequence Slide";
- ot->description = "Slide a sequence strip in time";
- ot->idname = OP_SEQ_SLIDE;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Sequence Slide";
+ ot->description = "Slide a sequence strip in time";
+ ot->idname = OP_SEQ_SLIDE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_sequencer_active;
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_sequencer_active;
- RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector_xyz(
+ ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
- WM_operatortype_props_advanced_begin(ot);
+ WM_operatortype_props_advanced_begin(ot);
- Transform_Properties(ot, P_SNAP);
+ Transform_Properties(ot, P_SNAP);
}
static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normal Rotate";
- ot->description = "Rotate split normal of selected items";
- ot->idname = OP_NORMAL_ROTATION;
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh_auto_smooth;
-
- RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
-
- Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
+ /* identifiers */
+ ot->name = "Normal Rotate";
+ ot->description = "Rotate split normal of selected items";
+ ot->idname = OP_NORMAL_ROTATION;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh_auto_smooth;
+
+ RNA_def_float_rotation(
+ ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+
+ Transform_Properties(ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_MIRROR);
}
-
static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Transform";
- ot->description = "Transform selected items by mode type";
- ot->idname = "TRANSFORM_OT_transform";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- /* api callbacks */
- ot->invoke = transform_invoke;
- ot->exec = transform_exec;
- ot->modal = transform_modal;
- ot->cancel = transform_cancel;
- ot->poll = ED_operator_screenactive;
- ot->poll_property = transform_poll_property;
-
- prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
-
- WM_operatortype_props_advanced_begin(ot);
-
- Transform_Properties(
- ot, P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
- P_GPENCIL_EDIT | P_CENTER);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Transform";
+ ot->description = "Transform selected items by mode type";
+ ot->idname = "TRANSFORM_OT_transform";
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_screenactive;
+ ot->poll_property = transform_poll_property;
+
+ prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ RNA_def_float_vector(
+ ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
+
+ WM_operatortype_props_advanced_begin(ot);
+
+ Transform_Properties(ot,
+ P_ORIENT_AXIS | P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR |
+ P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
void transform_operatortypes(void)
{
- TransformModeItem *tmode;
+ TransformModeItem *tmode;
- for (tmode = transform_modes; tmode->idname; tmode++) {
- WM_operatortype_append(tmode->opfunc);
- }
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ WM_operatortype_append(tmode->opfunc);
+ }
- WM_operatortype_append(TRANSFORM_OT_transform);
+ WM_operatortype_append(TRANSFORM_OT_transform);
- WM_operatortype_append(TRANSFORM_OT_select_orientation);
- WM_operatortype_append(TRANSFORM_OT_create_orientation);
- WM_operatortype_append(TRANSFORM_OT_delete_orientation);
+ WM_operatortype_append(TRANSFORM_OT_select_orientation);
+ WM_operatortype_append(TRANSFORM_OT_create_orientation);
+ WM_operatortype_append(TRANSFORM_OT_delete_orientation);
}
void ED_keymap_transform(wmKeyConfig *keyconf)
{
- wmKeyMap *modalmap = transform_modal_keymap(keyconf);
+ wmKeyMap *modalmap = transform_modal_keymap(keyconf);
- TransformModeItem *tmode;
+ TransformModeItem *tmode;
- for (tmode = transform_modes; tmode->idname; tmode++) {
- WM_modalkeymap_assign(modalmap, tmode->idname);
- }
- WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
+ for (tmode = transform_modes; tmode->idname; tmode++) {
+ WM_modalkeymap_assign(modalmap, tmode->idname);
+ }
+ WM_modalkeymap_assign(modalmap, "TRANSFORM_OT_transform");
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index b486976bfad..18b19d903c4 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -58,194 +58,207 @@
void BIF_clearTransformOrientation(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
-
- BLI_freelistN(transform_orientations);
-
- for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
- TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
- if (orient_slot->type == V3D_ORIENT_CUSTOM) {
- orient_slot->type = V3D_ORIENT_GLOBAL; /* fallback to global */
- orient_slot->index_custom = -1;
- }
- }
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+
+ BLI_freelistN(transform_orientations);
+
+ for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+ TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
+ if (orient_slot->type == V3D_ORIENT_CUSTOM) {
+ orient_slot->type = V3D_ORIENT_GLOBAL; /* fallback to global */
+ orient_slot->index_custom = -1;
+ }
+ }
}
static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
{
- return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
+ return BLI_findstring(lb, name, offsetof(TransformOrientation, name));
}
static bool uniqueOrientationNameCheck(void *arg, const char *name)
{
- return findOrientationName((ListBase *)arg, name) != NULL;
+ return findOrientationName((ListBase *)arg, name) != NULL;
}
static void uniqueOrientationName(ListBase *lb, char *name)
{
- BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"), '.', name,
- sizeof(((TransformOrientation *)NULL)->name));
+ BLI_uniquename_cb(uniqueOrientationNameCheck,
+ lb,
+ CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"),
+ '.',
+ name,
+ sizeof(((TransformOrientation *)NULL)->name));
}
-static TransformOrientation *createViewSpace(bContext *C, ReportList *UNUSED(reports),
- const char *name, const bool overwrite)
+static TransformOrientation *createViewSpace(bContext *C,
+ ReportList *UNUSED(reports),
+ const char *name,
+ const bool overwrite)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float mat[3][3];
-
- if (!rv3d)
- return NULL;
-
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
-
- if (name[0] == 0) {
- View3D *v3d = CTX_wm_view3d(C);
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /* If an object is used as camera, then this space is the same as object space! */
- name = v3d->camera->id.name + 2;
- }
- else {
- name = "Custom View";
- }
- }
-
- return addMatrixSpace(C, mat, name, overwrite);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float mat[3][3];
+
+ if (!rv3d)
+ return NULL;
+
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+
+ if (name[0] == 0) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ /* If an object is used as camera, then this space is the same as object space! */
+ name = v3d->camera->id.name + 2;
+ }
+ else {
+ name = "Custom View";
+ }
+ }
+
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports),
- const char *name, const bool overwrite)
+static TransformOrientation *createObjectSpace(bContext *C,
+ ReportList *UNUSED(reports),
+ const char *name,
+ const bool overwrite)
{
- Base *base = CTX_data_active_base(C);
- Object *ob;
- float mat[3][3];
+ Base *base = CTX_data_active_base(C);
+ Object *ob;
+ float mat[3][3];
- if (base == NULL)
- return NULL;
+ if (base == NULL)
+ return NULL;
- ob = base->object;
+ ob = base->object;
- copy_m3_m4(mat, ob->obmat);
- normalize_m3(mat);
+ copy_m3_m4(mat, ob->obmat);
+ normalize_m3(mat);
- /* use object name if no name is given */
- if (name[0] == 0) {
- name = ob->id.name + 2;
- }
+ /* use object name if no name is given */
+ if (name[0] == 0) {
+ name = ob->id.name + 2;
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createBoneSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
+ float mat[3][3];
+ float normal[3], plane[3];
- getTransformOrientation(C, normal, plane);
+ getTransformOrientation(C, normal, plane);
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length bone");
- return NULL;
- }
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length bone");
+ return NULL;
+ }
- if (name[0] == 0) {
- name = "Bone";
- }
+ if (name[0] == 0) {
+ name = "Bone";
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createCurveSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
+ float mat[3][3];
+ float normal[3], plane[3];
- getTransformOrientation(C, normal, plane);
+ getTransformOrientation(C, normal, plane);
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length curve");
- return NULL;
- }
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length curve");
+ return NULL;
+ }
- if (name[0] == 0) {
- name = "Curve";
- }
+ if (name[0] == 0) {
+ name = "Curve";
+ }
- return addMatrixSpace(C, mat, name, overwrite);
+ return addMatrixSpace(C, mat, name, overwrite);
}
-
-static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
- const char *name, const bool overwrite)
+static TransformOrientation *createMeshSpace(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool overwrite)
{
- float mat[3][3];
- float normal[3], plane[3];
- int type;
-
- type = getTransformOrientation(C, normal, plane);
-
- switch (type) {
- case ORIENTATION_VERT:
- if (createSpaceNormal(mat, normal) == 0) {
- BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Vertex";
- }
- break;
- case ORIENTATION_EDGE:
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-length edge");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Edge";
- }
- break;
- case ORIENTATION_FACE:
- if (createSpaceNormalTangent(mat, normal, plane) == 0) {
- BKE_reports_prepend(reports, "Cannot use zero-area face");
- return NULL;
- }
-
- if (name[0] == 0) {
- name = "Face";
- }
- break;
- default:
- return NULL;
- }
-
- return addMatrixSpace(C, mat, name, overwrite);
+ float mat[3][3];
+ float normal[3], plane[3];
+ int type;
+
+ type = getTransformOrientation(C, normal, plane);
+
+ switch (type) {
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(mat, normal) == 0) {
+ BKE_reports_prepend(reports, "Cannot use vertex with zero-length normal");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Vertex";
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-length edge");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Edge";
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(mat, normal, plane) == 0) {
+ BKE_reports_prepend(reports, "Cannot use zero-area face");
+ return NULL;
+ }
+
+ if (name[0] == 0) {
+ name = "Face";
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ return addMatrixSpace(C, mat, name, overwrite);
}
bool createSpaceNormal(float mat[3][3], const float normal[3])
{
- float tangent[3] = {0.0f, 0.0f, 1.0f};
+ float tangent[3] = {0.0f, 0.0f, 1.0f};
- copy_v3_v3(mat[2], normal);
- if (normalize_v3(mat[2]) == 0.0f) {
- return false; /* error return */
- }
+ copy_v3_v3(mat[2], normal);
+ if (normalize_v3(mat[2]) == 0.0f) {
+ return false; /* error return */
+ }
- cross_v3_v3v3(mat[0], mat[2], tangent);
- if (is_zero_v3(mat[0])) {
- tangent[0] = 1.0f;
- tangent[1] = tangent[2] = 0.0f;
- cross_v3_v3v3(mat[0], tangent, mat[2]);
- }
+ cross_v3_v3v3(mat[0], mat[2], tangent);
+ if (is_zero_v3(mat[0])) {
+ tangent[0] = 1.0f;
+ tangent[1] = tangent[2] = 0.0f;
+ cross_v3_v3v3(mat[0], tangent, mat[2]);
+ }
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
+ cross_v3_v3v3(mat[1], mat[2], mat[0]);
- normalize_m3(mat);
+ normalize_m3(mat);
- return true;
+ return true;
}
/**
@@ -255,902 +268,909 @@ bool createSpaceNormal(float mat[3][3], const float normal[3])
*/
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3])
{
- if (normalize_v3_v3(mat[2], normal) == 0.0f) {
- return false; /* error return */
- }
+ if (normalize_v3_v3(mat[2], normal) == 0.0f) {
+ return false; /* error return */
+ }
- /* negate so we can use values from the matrix as input */
- negate_v3_v3(mat[1], tangent);
- /* preempt zero length tangent from causing trouble */
- if (is_zero_v3(mat[1])) {
- mat[1][2] = 1.0f;
- }
+ /* negate so we can use values from the matrix as input */
+ negate_v3_v3(mat[1], tangent);
+ /* preempt zero length tangent from causing trouble */
+ if (is_zero_v3(mat[1])) {
+ mat[1][2] = 1.0f;
+ }
- cross_v3_v3v3(mat[0], mat[2], mat[1]);
- if (normalize_v3(mat[0]) == 0.0f) {
- return false; /* error return */
- }
+ cross_v3_v3v3(mat[0], mat[2], mat[1]);
+ if (normalize_v3(mat[0]) == 0.0f) {
+ return false; /* error return */
+ }
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
- normalize_v3(mat[1]);
+ cross_v3_v3v3(mat[1], mat[2], mat[0]);
+ normalize_v3(mat[1]);
- /* final matrix must be normalized, do inline */
- // normalize_m3(mat);
+ /* final matrix must be normalized, do inline */
+ // normalize_m3(mat);
- return true;
+ return true;
}
-void BIF_createTransformOrientation(bContext *C, ReportList *reports,
- const char *name, const bool use_view,
- const bool activate, const bool overwrite)
+void BIF_createTransformOrientation(bContext *C,
+ ReportList *reports,
+ const char *name,
+ const bool use_view,
+ const bool activate,
+ const bool overwrite)
{
- TransformOrientation *ts = NULL;
-
- if (use_view) {
- ts = createViewSpace(C, reports, name, overwrite);
- }
- else {
- Object *obedit = CTX_data_edit_object(C);
- Object *ob = CTX_data_active_object(C);
- if (obedit) {
- if (obedit->type == OB_MESH)
- ts = createMeshSpace(C, reports, name, overwrite);
- else if (obedit->type == OB_ARMATURE)
- ts = createBoneSpace(C, reports, name, overwrite);
- else if (obedit->type == OB_CURVE)
- ts = createCurveSpace(C, reports, name, overwrite);
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- ts = createBoneSpace(C, reports, name, overwrite);
- }
- else {
- ts = createObjectSpace(C, reports, name, overwrite);
- }
- }
-
- if (activate && ts != NULL) {
- BIF_selectTransformOrientation(C, ts);
- }
+ TransformOrientation *ts = NULL;
+
+ if (use_view) {
+ ts = createViewSpace(C, reports, name, overwrite);
+ }
+ else {
+ Object *obedit = CTX_data_edit_object(C);
+ Object *ob = CTX_data_active_object(C);
+ if (obedit) {
+ if (obedit->type == OB_MESH)
+ ts = createMeshSpace(C, reports, name, overwrite);
+ else if (obedit->type == OB_ARMATURE)
+ ts = createBoneSpace(C, reports, name, overwrite);
+ else if (obedit->type == OB_CURVE)
+ ts = createCurveSpace(C, reports, name, overwrite);
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ ts = createBoneSpace(C, reports, name, overwrite);
+ }
+ else {
+ ts = createObjectSpace(C, reports, name, overwrite);
+ }
+ }
+
+ if (activate && ts != NULL) {
+ BIF_selectTransformOrientation(C, ts);
+ }
}
-TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
- const char *name, const bool overwrite)
+TransformOrientation *addMatrixSpace(bContext *C,
+ float mat[3][3],
+ const char *name,
+ const bool overwrite)
{
- TransformOrientation *ts = NULL;
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
- char name_unique[sizeof(ts->name)];
-
- if (overwrite) {
- ts = findOrientationName(transform_orientations, name);
- }
- else {
- BLI_strncpy(name_unique, name, sizeof(name_unique));
- uniqueOrientationName(transform_orientations, name_unique);
- name = name_unique;
- }
-
- /* if not, create a new one */
- if (ts == NULL) {
- ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
- BLI_addtail(transform_orientations, ts);
- BLI_strncpy(ts->name, name, sizeof(ts->name));
- }
-
- /* copy matrix into transform space */
- copy_m3_m3(ts->mat, mat);
-
- return ts;
+ TransformOrientation *ts = NULL;
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+ char name_unique[sizeof(ts->name)];
+
+ if (overwrite) {
+ ts = findOrientationName(transform_orientations, name);
+ }
+ else {
+ BLI_strncpy(name_unique, name, sizeof(name_unique));
+ uniqueOrientationName(transform_orientations, name_unique);
+ name = name_unique;
+ }
+
+ /* if not, create a new one */
+ if (ts == NULL) {
+ ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
+ BLI_addtail(transform_orientations, ts);
+ BLI_strncpy(ts->name, name, sizeof(ts->name));
+ }
+
+ /* copy matrix into transform space */
+ copy_m3_m3(ts->mat, mat);
+
+ return ts;
}
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
{
- BKE_scene_transform_orientation_remove(CTX_data_scene(C), target);
+ BKE_scene_transform_orientation_remove(CTX_data_scene(C), target);
}
void BIF_removeTransformOrientationIndex(bContext *C, int index)
{
- TransformOrientation *target = BKE_scene_transform_orientation_find(CTX_data_scene(C), index);
- BIF_removeTransformOrientation(C, target);
+ TransformOrientation *target = BKE_scene_transform_orientation_find(CTX_data_scene(C), index);
+ BIF_removeTransformOrientation(C, target);
}
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
{
- Scene *scene = CTX_data_scene(C);
- int index = BKE_scene_transform_orientation_get_index(scene, target);
+ Scene *scene = CTX_data_scene(C);
+ int index = BKE_scene_transform_orientation_get_index(scene, target);
- BLI_assert(index != -1);
+ BLI_assert(index != -1);
- scene->orientation_slots[SCE_ORIENT_DEFAULT].type = V3D_ORIENT_CUSTOM;
- scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom = index;
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].type = V3D_ORIENT_CUSTOM;
+ scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom = index;
}
int BIF_countTransformOrientation(const bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_orientations = &scene->transform_spaces;
- return BLI_listbase_count(transform_orientations);
+ Scene *scene = CTX_data_scene(C);
+ ListBase *transform_orientations = &scene->transform_spaces;
+ return BLI_listbase_count(transform_orientations);
}
bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
{
- if (r_name) {
- BLI_strncpy(r_name, ts->name, MAX_NAME);
- }
- copy_m3_m3(r_mat, ts->mat);
+ if (r_name) {
+ BLI_strncpy(r_name, ts->name, MAX_NAME);
+ }
+ copy_m3_m3(r_mat, ts->mat);
- return true;
+ return true;
}
static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
{
- Bone *bone;
- bool do_next;
- int total = 0;
-
- for (bone = lb->first; bone; bone = bone->next) {
- bone->flag &= ~BONE_TRANSFORM;
- do_next = do_it;
- if (do_it) {
- if (bone->layer & arm->layer) {
- if (bone->flag & BONE_SELECTED) {
- bone->flag |= BONE_TRANSFORM;
- total++;
-
- /* no transform on children if one parent bone is selected */
- do_next = false;
- }
- }
- }
- total += count_bone_select(arm, &bone->childbase, do_next);
- }
-
- return total;
+ Bone *bone;
+ bool do_next;
+ int total = 0;
+
+ for (bone = lb->first; bone; bone = bone->next) {
+ bone->flag &= ~BONE_TRANSFORM;
+ do_next = do_it;
+ if (do_it) {
+ if (bone->layer & arm->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_TRANSFORM;
+ total++;
+
+ /* no transform on children if one parent bone is selected */
+ do_next = false;
+ }
+ }
+ }
+ total += count_bone_select(arm, &bone->childbase, do_next);
+ }
+
+ return total;
}
void initTransformOrientation(bContext *C, TransInfo *t)
{
- Object *ob = CTX_data_active_object(C);
- Object *obedit = CTX_data_active_object(C);
-
- switch (t->orientation.user) {
- case V3D_ORIENT_GLOBAL:
- unit_m3(t->spacemtx);
- BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
- break;
-
- case V3D_ORIENT_GIMBAL:
- unit_m3(t->spacemtx);
- if (ob && gimbal_axis(ob, t->spacemtx)) {
- BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
- break;
- }
- ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
- case V3D_ORIENT_NORMAL:
- if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
- ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
- break;
- }
- ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
- case V3D_ORIENT_LOCAL:
- BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
-
- if (ob) {
- copy_m3_m4(t->spacemtx, ob->obmat);
- normalize_m3(t->spacemtx);
- }
- else {
- unit_m3(t->spacemtx);
- }
-
- break;
-
- case V3D_ORIENT_VIEW:
- if ((t->spacetype == SPACE_VIEW3D) &&
- (t->ar->regiontype == RGN_TYPE_WINDOW))
- {
- RegionView3D *rv3d = t->ar->regiondata;
- float mat[3][3];
-
- BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
- copy_m3_m3(t->spacemtx, mat);
- }
- else {
- unit_m3(t->spacemtx);
- }
- break;
- case V3D_ORIENT_CURSOR:
- {
- BLI_strncpy(t->spacename, IFACE_("cursor"), sizeof(t->spacename));
- ED_view3d_cursor3d_calc_mat3(t->scene, t->spacemtx);
- break;
- }
- case V3D_ORIENT_CUSTOM_MATRIX:
- /* Already set. */
- BLI_strncpy(t->spacename, IFACE_("custom"), sizeof(t->spacename));
- break;
- case V3D_ORIENT_CUSTOM:
- BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
-
- if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
- /* pass */
- }
- else {
- unit_m3(t->spacemtx);
- }
- break;
- }
-
- if (t->orient_matrix_is_set == false) {
- t->orient_matrix_is_set = true;
- if (t->flag & T_MODAL) {
- /* Rotate for example defaults to operating on the view plane. */
- t->orientation.unset = V3D_ORIENT_VIEW;
- copy_m3_m4(t->orient_matrix, t->viewinv);
- normalize_m3(t->orient_matrix);
- }
- else {
- copy_m3_m3(t->orient_matrix, t->spacemtx);
- }
- negate_m3(t->orient_matrix);
- }
+ Object *ob = CTX_data_active_object(C);
+ Object *obedit = CTX_data_active_object(C);
+
+ switch (t->orientation.user) {
+ case V3D_ORIENT_GLOBAL:
+ unit_m3(t->spacemtx);
+ BLI_strncpy(t->spacename, IFACE_("global"), sizeof(t->spacename));
+ break;
+
+ case V3D_ORIENT_GIMBAL:
+ unit_m3(t->spacemtx);
+ if (ob && gimbal_axis(ob, t->spacemtx)) {
+ BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
+ break;
+ }
+ ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
+ case V3D_ORIENT_NORMAL:
+ if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
+ BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
+ ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
+ break;
+ }
+ ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
+ case V3D_ORIENT_LOCAL:
+ BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
+
+ if (ob) {
+ copy_m3_m4(t->spacemtx, ob->obmat);
+ normalize_m3(t->spacemtx);
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+
+ break;
+
+ case V3D_ORIENT_VIEW:
+ if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
+ RegionView3D *rv3d = t->ar->regiondata;
+ float mat[3][3];
+
+ BLI_strncpy(t->spacename, IFACE_("view"), sizeof(t->spacename));
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ copy_m3_m3(t->spacemtx, mat);
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+ break;
+ case V3D_ORIENT_CURSOR: {
+ BLI_strncpy(t->spacename, IFACE_("cursor"), sizeof(t->spacename));
+ ED_view3d_cursor3d_calc_mat3(t->scene, t->spacemtx);
+ break;
+ }
+ case V3D_ORIENT_CUSTOM_MATRIX:
+ /* Already set. */
+ BLI_strncpy(t->spacename, IFACE_("custom"), sizeof(t->spacename));
+ break;
+ case V3D_ORIENT_CUSTOM:
+ BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename));
+
+ if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) {
+ /* pass */
+ }
+ else {
+ unit_m3(t->spacemtx);
+ }
+ break;
+ }
+
+ if (t->orient_matrix_is_set == false) {
+ t->orient_matrix_is_set = true;
+ if (t->flag & T_MODAL) {
+ /* Rotate for example defaults to operating on the view plane. */
+ t->orientation.unset = V3D_ORIENT_VIEW;
+ copy_m3_m4(t->orient_matrix, t->viewinv);
+ normalize_m3(t->orient_matrix);
+ }
+ else {
+ copy_m3_m3(t->orient_matrix, t->spacemtx);
+ }
+ negate_m3(t->orient_matrix);
+ }
}
/**
* utility function - get first n, selected vert/edge/faces
*/
static unsigned int bm_mesh_elems_select_get_n__internal(
- BMesh *bm, BMElem **elems, const unsigned int n,
- const BMIterType itype, const char htype)
+ BMesh *bm, BMElem **elems, const unsigned int n, const BMIterType itype, const char htype)
{
- BMIter iter;
- BMElem *ele;
- unsigned int i;
-
- BLI_assert(ELEM(htype, BM_VERT, BM_EDGE, BM_FACE));
- BLI_assert(ELEM(itype, BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH));
-
- if (!BLI_listbase_is_empty(&bm->selected)) {
- /* quick check */
- BMEditSelection *ese;
- i = 0;
- for (ese = bm->selected.last; ese; ese = ese->prev) {
- /* shouldn't need this check */
- if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
-
- /* only use contiguous selection */
- if (ese->htype != htype) {
- i = 0;
- break;
- }
-
- elems[i++] = ese->ele;
- if (n == i) {
- break;
- }
- }
- else {
- BLI_assert(0);
- }
- }
-
- if (i == 0) {
- /* pass */
- }
- else if (i == n) {
- return i;
- }
- }
-
- i = 0;
- BM_ITER_MESH (ele, &iter, bm, itype) {
- BLI_assert(ele->head.htype == htype);
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- elems[i++] = ele;
- if (n == i) {
- break;
- }
- }
- }
-
- return i;
+ BMIter iter;
+ BMElem *ele;
+ unsigned int i;
+
+ BLI_assert(ELEM(htype, BM_VERT, BM_EDGE, BM_FACE));
+ BLI_assert(ELEM(itype, BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH));
+
+ if (!BLI_listbase_is_empty(&bm->selected)) {
+ /* quick check */
+ BMEditSelection *ese;
+ i = 0;
+ for (ese = bm->selected.last; ese; ese = ese->prev) {
+ /* shouldn't need this check */
+ if (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
+
+ /* only use contiguous selection */
+ if (ese->htype != htype) {
+ i = 0;
+ break;
+ }
+
+ elems[i++] = ese->ele;
+ if (n == i) {
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ if (i == 0) {
+ /* pass */
+ }
+ else if (i == n) {
+ return i;
+ }
+ }
+
+ i = 0;
+ BM_ITER_MESH (ele, &iter, bm, itype) {
+ BLI_assert(ele->head.htype == htype);
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ elems[i++] = ele;
+ if (n == i) {
+ break;
+ }
+ }
+ }
+
+ return i;
}
static unsigned int bm_mesh_verts_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totvertsel),
- BM_VERTS_OF_MESH, BM_VERT);
+ return bm_mesh_elems_select_get_n__internal(
+ bm, (BMElem **)elems, min_ii(n, bm->totvertsel), BM_VERTS_OF_MESH, BM_VERT);
}
static unsigned int bm_mesh_edges_select_get_n(BMesh *bm, BMEdge **elems, const unsigned int n)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totedgesel),
- BM_EDGES_OF_MESH, BM_EDGE);
+ return bm_mesh_elems_select_get_n__internal(
+ bm, (BMElem **)elems, min_ii(n, bm->totedgesel), BM_EDGES_OF_MESH, BM_EDGE);
}
#if 0
static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const unsigned int n)
{
- return bm_mesh_elems_select_get_n__internal(
- bm, (BMElem **)elems, min_ii(n, bm->totfacesel),
- BM_FACES_OF_MESH, BM_FACE);
+ return bm_mesh_elems_select_get_n__internal(
+ bm, (BMElem **)elems, min_ii(n, bm->totfacesel),
+ BM_FACES_OF_MESH, BM_FACE);
}
#endif
-int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
+int getTransformOrientation_ex(const bContext *C,
+ float normal[3],
+ float plane[3],
+ const short around)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
- Base *base;
- Object *ob = OBACT(view_layer);
- int result = ORIENTATION_NONE;
- const bool activeOnly = (around == V3D_AROUND_ACTIVE);
-
- zero_v3(normal);
- zero_v3(plane);
-
- if (obedit) {
- float imat[3][3], mat[3][3];
-
- /* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
-
- invert_m3_m3(mat, imat);
- transpose_m3(mat);
-
- ob = obedit;
-
- if (ob->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMEditSelection ese;
- float vec[3] = {0, 0, 0};
-
- /* USE LAST SELECTED WITH ACTIVE */
- if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_normal(&ese, normal);
- BM_editselection_plane(&ese, plane);
-
- switch (ese.htype) {
- case BM_VERT:
- result = ORIENTATION_VERT;
- break;
- case BM_EDGE:
- result = ORIENTATION_EDGE;
- break;
- case BM_FACE:
- result = ORIENTATION_FACE;
- break;
- }
- }
- else {
- if (em->bm->totfacesel >= 1) {
- BMFace *efa;
- BMIter iter;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_tangent_auto(efa, vec);
- add_v3_v3(normal, efa->no);
- add_v3_v3(plane, vec);
- }
- }
-
- result = ORIENTATION_FACE;
- }
- else if (em->bm->totvertsel == 3) {
- BMVert *v_tri[3];
-
- if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
- BMEdge *e = NULL;
- float no_test[3];
-
- normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
-
- /* check if the normal is pointing opposite to vert normals */
- no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
- no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
- no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
- if (dot_v3v3(no_test, normal) < 0.0f) {
- negate_v3(normal);
- }
-
- if (em->bm->totedgesel >= 1) {
- /* find an edge that's apart of v_tri (no need to search all edges) */
- float e_length;
- int j;
-
- for (j = 0; j < 3; j++) {
- BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
- if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
- const float e_test_length = BM_edge_calc_length_squared(e_test);
- if ((e == NULL) || (e_length < e_test_length)) {
- e = e_test;
- e_length = e_test_length;
- }
- }
- }
- }
-
- if (e) {
- BMVert *v_pair[2];
- if (BM_edge_is_boundary(e)) {
- BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
- }
- else {
- v_pair[0] = e->v1;
- v_pair[1] = e->v2;
- }
- sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
- }
- else {
- BM_vert_tri_calc_tangent_edge(v_tri, plane);
- }
- }
- else {
- BLI_assert(0);
- }
-
- result = ORIENTATION_FACE;
- }
- else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
- BMVert *v_pair[2] = {NULL, NULL};
- BMEdge *eed = NULL;
-
- if (em->bm->totedgesel == 1) {
- if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
- v_pair[0] = eed->v1;
- v_pair[1] = eed->v2;
- }
- }
- else {
- BLI_assert(em->bm->totvertsel == 2);
- bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
- }
-
- /* should never fail */
- if (LIKELY(v_pair[0] && v_pair[1])) {
- bool v_pair_swap = false;
- /**
- * Logic explained:
- *
- * - Edges and vert-pairs treated the same way.
- * - Point the Y axis along the edge vector (towards the active vertex).
- * - Point the Z axis outwards (the same direction as the normals).
- *
- * \note Z points outwards - along the normal.
- * take care making changes here, see: T38592, T43708
- */
-
- /* be deterministic where possible and ensure v_pair[0] is active */
- if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
- v_pair_swap = true;
- }
- else if (eed && BM_edge_is_boundary(eed)) {
- /* predictable direction for boundary edges */
- if (eed->l->v != v_pair[0]) {
- v_pair_swap = true;
- }
- }
-
- if (v_pair_swap) {
- SWAP(BMVert *, v_pair[0], v_pair[1]);
- }
-
- add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
- sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
-
- if (normalize_v3(plane) != 0.0f) {
- /* For edges it'd important the resulting matrix can rotate around the edge,
- * project onto the plane so we can use a fallback value. */
- project_plane_normalized_v3_v3v3(normal, normal, plane);
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- /* in the case the normal and plane are aligned,
- * use a fallback normal which is orthogonal to the plane. */
- ortho_v3_v3(normal, plane);
- }
- }
- }
-
- result = ORIENTATION_EDGE;
- }
- else if (em->bm->totvertsel == 1) {
- BMVert *v = NULL;
-
- if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
- copy_v3_v3(normal, v->no);
- BMEdge *e_pair[2];
-
- if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
- bool v_pair_swap = false;
- BMVert *v_pair[2] = {BM_edge_other_vert(e_pair[0], v), BM_edge_other_vert(e_pair[1], v)};
- float dir_pair[2][3];
-
- if (BM_edge_is_boundary(e_pair[0])) {
- if (e_pair[0]->l->v != v) {
- v_pair_swap = true;
- }
- }
- else {
- if (BM_edge_calc_length_squared(e_pair[0]) < BM_edge_calc_length_squared(e_pair[1])) {
- v_pair_swap = true;
- }
- }
-
- if (v_pair_swap) {
- SWAP(BMVert *, v_pair[0], v_pair[1]);
- }
-
- sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
- sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
- normalize_v3(dir_pair[0]);
- normalize_v3(dir_pair[1]);
-
- add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
- }
- }
-
- result = is_zero_v3(plane) ? ORIENTATION_VERT : ORIENTATION_EDGE;
- }
- else if (em->bm->totvertsel > 3) {
- BMIter iter;
- BMVert *v;
-
- zero_v3(normal);
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- add_v3_v3(normal, v->no);
- }
- }
- normalize_v3(normal);
- result = ORIENTATION_VERT;
- }
- }
-
- /* not needed but this matches 2.68 and older behavior */
- negate_v3(plane);
-
- } /* end editmesh */
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- Curve *cu = obedit->data;
- Nurb *nu = NULL;
- int a;
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
- void *vert_act = NULL;
- if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt = vert_act;
- BKE_nurb_bezt_calc_normal(nu, bezt, normal);
- BKE_nurb_bezt_calc_plane(nu, bezt, plane);
- }
- else {
- BPoint *bp = vert_act;
- BKE_nurb_bpoint_calc_normal(nu, bp, normal);
- BKE_nurb_bpoint_calc_plane(nu, bp, plane);
- }
- }
- else {
- const bool use_handle = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
-
- for (nu = nurbs->first; nu; nu = nu->next) {
- /* only bezier has a normal */
- if (nu->type == CU_BEZIER) {
- BezTriple *bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- short flag = 0;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Base *base;
+ Object *ob = OBACT(view_layer);
+ int result = ORIENTATION_NONE;
+ const bool activeOnly = (around == V3D_AROUND_ACTIVE);
+
+ zero_v3(normal);
+ zero_v3(plane);
+
+ if (obedit) {
+ float imat[3][3], mat[3][3];
+
+ /* we need the transpose of the inverse for a normal... */
+ copy_m3_m4(imat, ob->obmat);
+
+ invert_m3_m3(mat, imat);
+ transpose_m3(mat);
+
+ ob = obedit;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMEditSelection ese;
+ float vec[3] = {0, 0, 0};
+
+ /* USE LAST SELECTED WITH ACTIVE */
+ if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_normal(&ese, normal);
+ BM_editselection_plane(&ese, plane);
+
+ switch (ese.htype) {
+ case BM_VERT:
+ result = ORIENTATION_VERT;
+ break;
+ case BM_EDGE:
+ result = ORIENTATION_EDGE;
+ break;
+ case BM_FACE:
+ result = ORIENTATION_FACE;
+ break;
+ }
+ }
+ else {
+ if (em->bm->totfacesel >= 1) {
+ BMFace *efa;
+ BMIter iter;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_calc_tangent_auto(efa, vec);
+ add_v3_v3(normal, efa->no);
+ add_v3_v3(plane, vec);
+ }
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->bm->totvertsel == 3) {
+ BMVert *v_tri[3];
+
+ if (bm_mesh_verts_select_get_n(em->bm, v_tri, 3) == 3) {
+ BMEdge *e = NULL;
+ float no_test[3];
+
+ normal_tri_v3(normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
+
+ /* check if the normal is pointing opposite to vert normals */
+ no_test[0] = v_tri[0]->no[0] + v_tri[1]->no[0] + v_tri[2]->no[0];
+ no_test[1] = v_tri[0]->no[1] + v_tri[1]->no[1] + v_tri[2]->no[1];
+ no_test[2] = v_tri[0]->no[2] + v_tri[1]->no[2] + v_tri[2]->no[2];
+ if (dot_v3v3(no_test, normal) < 0.0f) {
+ negate_v3(normal);
+ }
+
+ if (em->bm->totedgesel >= 1) {
+ /* find an edge that's apart of v_tri (no need to search all edges) */
+ float e_length;
+ int j;
+
+ for (j = 0; j < 3; j++) {
+ BMEdge *e_test = BM_edge_exists(v_tri[j], v_tri[(j + 1) % 3]);
+ if (e_test && BM_elem_flag_test(e_test, BM_ELEM_SELECT)) {
+ const float e_test_length = BM_edge_calc_length_squared(e_test);
+ if ((e == NULL) || (e_length < e_test_length)) {
+ e = e_test;
+ e_length = e_test_length;
+ }
+ }
+ }
+ }
+
+ if (e) {
+ BMVert *v_pair[2];
+ if (BM_edge_is_boundary(e)) {
+ BM_edge_ordered_verts(e, &v_pair[0], &v_pair[1]);
+ }
+ else {
+ v_pair[0] = e->v1;
+ v_pair[1] = e->v2;
+ }
+ sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
+ }
+ else {
+ BM_vert_tri_calc_tangent_edge(v_tri, plane);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ result = ORIENTATION_FACE;
+ }
+ else if (em->bm->totedgesel == 1 || em->bm->totvertsel == 2) {
+ BMVert *v_pair[2] = {NULL, NULL};
+ BMEdge *eed = NULL;
+
+ if (em->bm->totedgesel == 1) {
+ if (bm_mesh_edges_select_get_n(em->bm, &eed, 1) == 1) {
+ v_pair[0] = eed->v1;
+ v_pair[1] = eed->v2;
+ }
+ }
+ else {
+ BLI_assert(em->bm->totvertsel == 2);
+ bm_mesh_verts_select_get_n(em->bm, v_pair, 2);
+ }
+
+ /* should never fail */
+ if (LIKELY(v_pair[0] && v_pair[1])) {
+ bool v_pair_swap = false;
+ /**
+ * Logic explained:
+ *
+ * - Edges and vert-pairs treated the same way.
+ * - Point the Y axis along the edge vector (towards the active vertex).
+ * - Point the Z axis outwards (the same direction as the normals).
+ *
+ * \note Z points outwards - along the normal.
+ * take care making changes here, see: T38592, T43708
+ */
+
+ /* be deterministic where possible and ensure v_pair[0] is active */
+ if (BM_mesh_active_vert_get(em->bm) == v_pair[1]) {
+ v_pair_swap = true;
+ }
+ else if (eed && BM_edge_is_boundary(eed)) {
+ /* predictable direction for boundary edges */
+ if (eed->l->v != v_pair[0]) {
+ v_pair_swap = true;
+ }
+ }
+
+ if (v_pair_swap) {
+ SWAP(BMVert *, v_pair[0], v_pair[1]);
+ }
+
+ add_v3_v3v3(normal, v_pair[1]->no, v_pair[0]->no);
+ sub_v3_v3v3(plane, v_pair[1]->co, v_pair[0]->co);
+
+ if (normalize_v3(plane) != 0.0f) {
+ /* For edges it'd important the resulting matrix can rotate around the edge,
+ * project onto the plane so we can use a fallback value. */
+ project_plane_normalized_v3_v3v3(normal, normal, plane);
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ /* in the case the normal and plane are aligned,
+ * use a fallback normal which is orthogonal to the plane. */
+ ortho_v3_v3(normal, plane);
+ }
+ }
+ }
+
+ result = ORIENTATION_EDGE;
+ }
+ else if (em->bm->totvertsel == 1) {
+ BMVert *v = NULL;
+
+ if (bm_mesh_verts_select_get_n(em->bm, &v, 1) == 1) {
+ copy_v3_v3(normal, v->no);
+ BMEdge *e_pair[2];
+
+ if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
+ bool v_pair_swap = false;
+ BMVert *v_pair[2] = {BM_edge_other_vert(e_pair[0], v),
+ BM_edge_other_vert(e_pair[1], v)};
+ float dir_pair[2][3];
+
+ if (BM_edge_is_boundary(e_pair[0])) {
+ if (e_pair[0]->l->v != v) {
+ v_pair_swap = true;
+ }
+ }
+ else {
+ if (BM_edge_calc_length_squared(e_pair[0]) <
+ BM_edge_calc_length_squared(e_pair[1])) {
+ v_pair_swap = true;
+ }
+ }
+
+ if (v_pair_swap) {
+ SWAP(BMVert *, v_pair[0], v_pair[1]);
+ }
+
+ sub_v3_v3v3(dir_pair[0], v->co, v_pair[0]->co);
+ sub_v3_v3v3(dir_pair[1], v_pair[1]->co, v->co);
+ normalize_v3(dir_pair[0]);
+ normalize_v3(dir_pair[1]);
+
+ add_v3_v3v3(plane, dir_pair[0], dir_pair[1]);
+ }
+ }
+
+ result = is_zero_v3(plane) ? ORIENTATION_VERT : ORIENTATION_EDGE;
+ }
+ else if (em->bm->totvertsel > 3) {
+ BMIter iter;
+ BMVert *v;
+
+ zero_v3(normal);
+
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ add_v3_v3(normal, v->no);
+ }
+ }
+ normalize_v3(normal);
+ result = ORIENTATION_VERT;
+ }
+ }
+
+ /* not needed but this matches 2.68 and older behavior */
+ negate_v3(plane);
+
+ } /* end editmesh */
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = obedit->data;
+ Nurb *nu = NULL;
+ int a;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ void *vert_act = NULL;
+ if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = vert_act;
+ BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+ BKE_nurb_bezt_calc_plane(nu, bezt, plane);
+ }
+ else {
+ BPoint *bp = vert_act;
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+ }
+ }
+ else {
+ const bool use_handle = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
+
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ /* only bezier has a normal */
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ short flag = 0;
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
- if (use_handle) {
- if (bezt->f1 & SELECT) flag |= SEL_F1;
- if (bezt->f2 & SELECT) flag |= SEL_F2;
- if (bezt->f3 & SELECT) flag |= SEL_F3;
- }
- else {
- flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
- }
-
- /* exception */
- if (flag) {
- float tvec[3];
- if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
- ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
- {
- BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
- add_v3_v3(normal, tvec);
- }
- else {
- /* ignore bezt->f2 in this case */
- if (flag & SEL_F1) {
- sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- if (flag & SEL_F3) {
- sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- }
-
- BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
- add_v3_v3(plane, tvec);
- }
+ if (use_handle) {
+ if (bezt->f1 & SELECT)
+ flag |= SEL_F1;
+ if (bezt->f2 & SELECT)
+ flag |= SEL_F2;
+ if (bezt->f3 & SELECT)
+ flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
+
+ /* exception */
+ if (flag) {
+ float tvec[3];
+ if ((around == V3D_AROUND_LOCAL_ORIGINS) ||
+ ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) {
+ BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else {
+ /* ignore bezt->f2 in this case */
+ if (flag & SEL_F1) {
+ sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+ if (flag & SEL_F3) {
+ sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+ }
+
+ BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
+ add_v3_v3(plane, tvec);
+ }
#undef SEL_F1
#undef SEL_F2
#undef SEL_F3
- bezt++;
- }
- }
- else if (nu->bp && (nu->pntsv == 1)) {
- BPoint *bp = nu->bp;
- a = nu->pntsu;
- while (a--) {
- if (bp->f1 & SELECT) {
- float tvec[3];
-
- BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
- BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
-
- const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
- const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
- if (is_prev_sel == false && is_next_sel == false) {
- /* Isolated, add based on surrounding */
- BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
- add_v3_v3(normal, tvec);
- }
- else if (is_next_sel) {
- /* A segment, add the edge normal */
- sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
-
- BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
- add_v3_v3(plane, tvec);
- }
- bp++;
- }
- }
- }
- }
-
- if (!is_zero_v3(normal)) {
- result = ORIENTATION_FACE;
- }
- }
- else if (obedit->type == OB_MBALL) {
- MetaBall *mb = obedit->data;
- MetaElem *ml;
- bool ok = false;
- float tmat[3][3];
-
- if (activeOnly && (ml = mb->lastelem)) {
- quat_to_mat3(tmat, ml->quat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else {
- for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (ml->flag & SELECT) {
- quat_to_mat3(tmat, ml->quat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- }
- }
-
- if (ok) {
- if (!is_zero_v3(plane)) {
- result = ORIENTATION_FACE;
- }
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- bArmature *arm = obedit->data;
- EditBone *ebone;
- bool ok = false;
- float tmat[3][3];
-
- if (activeOnly && (ebone = arm->act_edbone)) {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else {
- /* When we only have the root/tip are selected. */
- bool fallback_ok = false;
- float fallback_normal[3];
- float fallback_plane[3];
-
- zero_v3(fallback_normal);
- zero_v3(fallback_plane);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_SELECTED) {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(normal, tmat[2]);
- add_v3_v3(plane, tmat[1]);
- ok = true;
- }
- else if ((ok == false) &&
- ((ebone->flag & BONE_TIPSEL) ||
- ((ebone->flag & BONE_ROOTSEL) &&
- (ebone->parent && ebone->flag & BONE_CONNECTED) == false)))
- {
- ED_armature_ebone_to_mat3(ebone, tmat);
- add_v3_v3(fallback_normal, tmat[2]);
- add_v3_v3(fallback_plane, tmat[1]);
- fallback_ok = true;
- }
- }
- }
- if ((ok == false) && fallback_ok) {
- ok = true;
- copy_v3_v3(normal, fallback_normal);
- copy_v3_v3(plane, fallback_plane);
- }
- }
-
- if (ok) {
- if (!is_zero_v3(plane)) {
- result = ORIENTATION_EDGE;
- }
- }
- }
-
- /* Vectors from edges don't need the special transpose inverse multiplication */
- if (result == ORIENTATION_EDGE) {
- float tvec[3];
-
- mul_mat3_m4_v3(ob->obmat, normal);
- mul_mat3_m4_v3(ob->obmat, plane);
-
- /* align normal to edge direction (so normal is perpendicular to the plane).
- * 'ORIENTATION_EDGE' will do the other way around.
- * This has to be done **after** applying obmat, see T45775! */
- project_v3_v3v3(tvec, normal, plane);
- sub_v3_v3(normal, tvec);
- }
- else {
- mul_m3_v3(mat, normal);
- mul_m3_v3(mat, plane);
- }
- }
- else if (ob && (ob->mode & OB_MODE_POSE)) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- float imat[3][3], mat[3][3];
- bool ok = false;
-
- if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
- add_v3_v3(normal, pchan->pose_mat[2]);
- add_v3_v3(plane, pchan->pose_mat[1]);
- ok = true;
- }
- else {
- int totsel;
-
- totsel = count_bone_select(arm, &arm->bonebase, true);
- if (totsel) {
- /* use channels to get stats */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
- add_v3_v3(normal, pchan->pose_mat[2]);
- add_v3_v3(plane, pchan->pose_mat[1]);
- }
- }
- ok = true;
- }
- }
-
- /* use for both active & all */
- if (ok) {
- /* we need the transpose of the inverse for a normal... */
- copy_m3_m4(imat, ob->obmat);
-
- invert_m3_m3(mat, imat);
- transpose_m3(mat);
- mul_m3_v3(mat, normal);
- mul_m3_v3(mat, plane);
-
- result = ORIENTATION_EDGE;
- }
- }
- else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
- /* pass */
- }
- else {
- /* we need the one selected object, if its not active */
- base = BASACT(view_layer);
- ob = OBACT(view_layer);
- if (base && ((base->flag & BASE_SELECTED) != 0)) {
- /* pass */
- }
- else {
- /* first selected */
- ob = NULL;
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- ob = base->object;
- break;
- }
- }
- }
-
- if (ob) {
- copy_v3_v3(normal, ob->obmat[2]);
- copy_v3_v3(plane, ob->obmat[1]);
- }
- result = ORIENTATION_NORMAL;
- }
-
- return result;
+ bezt++;
+ }
+ }
+ else if (nu->bp && (nu->pntsv == 1)) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ float tvec[3];
+
+ BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp);
+ BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp);
+
+ const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT);
+ const bool is_next_sel = bp_next && (bp_next->f1 & SELECT);
+ if (is_prev_sel == false && is_next_sel == false) {
+ /* Isolated, add based on surrounding */
+ BKE_nurb_bpoint_calc_normal(nu, bp, tvec);
+ add_v3_v3(normal, tvec);
+ }
+ else if (is_next_sel) {
+ /* A segment, add the edge normal */
+ sub_v3_v3v3(tvec, bp->vec, bp_next->vec);
+ normalize_v3(tvec);
+ add_v3_v3(normal, tvec);
+ }
+
+ BKE_nurb_bpoint_calc_plane(nu, bp, tvec);
+ add_v3_v3(plane, tvec);
+ }
+ bp++;
+ }
+ }
+ }
+ }
+
+ if (!is_zero_v3(normal)) {
+ result = ORIENTATION_FACE;
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ MetaBall *mb = obedit->data;
+ MetaElem *ml;
+ bool ok = false;
+ float tmat[3][3];
+
+ if (activeOnly && (ml = mb->lastelem)) {
+ quat_to_mat3(tmat, ml->quat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else {
+ for (ml = mb->editelems->first; ml; ml = ml->next) {
+ if (ml->flag & SELECT) {
+ quat_to_mat3(tmat, ml->quat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ }
+ }
+
+ if (ok) {
+ if (!is_zero_v3(plane)) {
+ result = ORIENTATION_FACE;
+ }
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+ bool ok = false;
+ float tmat[3][3];
+
+ if (activeOnly && (ebone = arm->act_edbone)) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else {
+ /* When we only have the root/tip are selected. */
+ bool fallback_ok = false;
+ float fallback_normal[3];
+ float fallback_plane[3];
+
+ zero_v3(fallback_normal);
+ zero_v3(fallback_plane);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(normal, tmat[2]);
+ add_v3_v3(plane, tmat[1]);
+ ok = true;
+ }
+ else if ((ok == false) &&
+ ((ebone->flag & BONE_TIPSEL) ||
+ ((ebone->flag & BONE_ROOTSEL) &&
+ (ebone->parent && ebone->flag & BONE_CONNECTED) == false))) {
+ ED_armature_ebone_to_mat3(ebone, tmat);
+ add_v3_v3(fallback_normal, tmat[2]);
+ add_v3_v3(fallback_plane, tmat[1]);
+ fallback_ok = true;
+ }
+ }
+ }
+ if ((ok == false) && fallback_ok) {
+ ok = true;
+ copy_v3_v3(normal, fallback_normal);
+ copy_v3_v3(plane, fallback_plane);
+ }
+ }
+
+ if (ok) {
+ if (!is_zero_v3(plane)) {
+ result = ORIENTATION_EDGE;
+ }
+ }
+ }
+
+ /* Vectors from edges don't need the special transpose inverse multiplication */
+ if (result == ORIENTATION_EDGE) {
+ float tvec[3];
+
+ mul_mat3_m4_v3(ob->obmat, normal);
+ mul_mat3_m4_v3(ob->obmat, plane);
+
+ /* align normal to edge direction (so normal is perpendicular to the plane).
+ * 'ORIENTATION_EDGE' will do the other way around.
+ * This has to be done **after** applying obmat, see T45775! */
+ project_v3_v3v3(tvec, normal, plane);
+ sub_v3_v3(normal, tvec);
+ }
+ else {
+ mul_m3_v3(mat, normal);
+ mul_m3_v3(mat, plane);
+ }
+ }
+ else if (ob && (ob->mode & OB_MODE_POSE)) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ float imat[3][3], mat[3][3];
+ bool ok = false;
+
+ if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ ok = true;
+ }
+ else {
+ int totsel;
+
+ totsel = count_bone_select(arm, &arm->bonebase, true);
+ if (totsel) {
+ /* use channels to get stats */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ }
+ }
+ ok = true;
+ }
+ }
+
+ /* use for both active & all */
+ if (ok) {
+ /* we need the transpose of the inverse for a normal... */
+ copy_m3_m4(imat, ob->obmat);
+
+ invert_m3_m3(mat, imat);
+ transpose_m3(mat);
+ mul_m3_v3(mat, normal);
+ mul_m3_v3(mat, plane);
+
+ result = ORIENTATION_EDGE;
+ }
+ }
+ else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
+ /* pass */
+ }
+ else {
+ /* we need the one selected object, if its not active */
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ if (base && ((base->flag & BASE_SELECTED) != 0)) {
+ /* pass */
+ }
+ else {
+ /* first selected */
+ ob = NULL;
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTED_EDITABLE(v3d, base)) {
+ ob = base->object;
+ break;
+ }
+ }
+ }
+
+ if (ob) {
+ copy_v3_v3(normal, ob->obmat[2]);
+ copy_v3_v3(plane, ob->obmat[1]);
+ }
+ result = ORIENTATION_NORMAL;
+ }
+
+ return result;
}
int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
{
- /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
- short around = V3D_AROUND_CENTER_BOUNDS;
+ /* dummy value, not V3D_AROUND_ACTIVE and not V3D_AROUND_LOCAL_ORIGINS */
+ short around = V3D_AROUND_CENTER_BOUNDS;
- return getTransformOrientation_ex(C, normal, plane, around);
+ return getTransformOrientation_ex(C, normal, plane, around);
}
-void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around)
+void ED_getTransformOrientationMatrix(const bContext *C,
+ float orientation_mat[3][3],
+ const short around)
{
- float normal[3] = {0.0, 0.0, 0.0};
- float plane[3] = {0.0, 0.0, 0.0};
-
- int type;
-
- type = getTransformOrientation_ex(C, normal, plane, around);
-
- /* Fallback, when the plane can't be calculated. */
- if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
- type = ORIENTATION_VERT;
- }
-
- switch (type) {
- case ORIENTATION_NORMAL:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_VERT:
- if (createSpaceNormal(orientation_mat, normal) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_EDGE:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- case ORIENTATION_FACE:
- if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
- type = ORIENTATION_NONE;
- }
- break;
- default:
- BLI_assert(type == ORIENTATION_NONE);
- break;
- }
-
- if (type == ORIENTATION_NONE) {
- unit_m3(orientation_mat);
- }
+ float normal[3] = {0.0, 0.0, 0.0};
+ float plane[3] = {0.0, 0.0, 0.0};
+
+ int type;
+
+ type = getTransformOrientation_ex(C, normal, plane, around);
+
+ /* Fallback, when the plane can't be calculated. */
+ if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {
+ type = ORIENTATION_VERT;
+ }
+
+ switch (type) {
+ case ORIENTATION_NORMAL:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_VERT:
+ if (createSpaceNormal(orientation_mat, normal) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_EDGE:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ case ORIENTATION_FACE:
+ if (createSpaceNormalTangent(orientation_mat, normal, plane) == 0) {
+ type = ORIENTATION_NONE;
+ }
+ break;
+ default:
+ BLI_assert(type == ORIENTATION_NONE);
+ break;
+ }
+
+ if (type == ORIENTATION_NONE) {
+ unit_m3(orientation_mat);
+ }
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 305b17949c8..d9cc9e3fcee 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -30,7 +30,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
+#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */
#include "DNA_node_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
@@ -46,7 +46,7 @@
#include "BKE_layer.h"
#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_sequencer.h"
@@ -96,7 +96,6 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
static float TranslationBetween(TransInfo *t, const float p1[3], const float p2[3]);
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]);
-
/****************** IMPLEMENTATIONS *********************/
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select);
@@ -105,1506 +104,1534 @@ static NodeBorder snapNodeBorder(int snap_node_mode);
#if 0
int BIF_snappingSupported(Object *obedit)
{
- int status = 0;
+ int status = 0;
- /* only support object mesh, armature, curves */
- if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
- status = 1;
- }
+ /* only support object mesh, armature, curves */
+ if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
+ status = 1;
+ }
- return status;
+ return status;
}
#endif
bool validSnap(const TransInfo *t)
{
- return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
- (t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
+ return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) ||
+ (t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT);
}
bool activeSnap(const TransInfo *t)
{
- return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
- ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
+ return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
+ ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
}
bool transformModeUseSnap(const TransInfo *t)
{
- ToolSettings *ts = t->settings;
- if (t->mode == TFM_TRANSLATION) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
- }
- if (t->mode == TFM_ROTATION) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_ROTATE) != 0;
- }
- if (t->mode == TFM_RESIZE) {
- return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
- }
-
- return false;
+ ToolSettings *ts = t->settings;
+ if (t->mode == TFM_TRANSLATION) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
+ }
+ if (t->mode == TFM_ROTATION) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_ROTATE) != 0;
+ }
+ if (t->mode == TFM_RESIZE) {
+ return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
+ }
+
+ return false;
}
static bool doForceIncrementSnap(const TransInfo *t)
{
- return !transformModeUseSnap(t);
+ return !transformModeUseSnap(t);
}
void drawSnapping(const struct bContext *C, TransInfo *t)
{
- unsigned char col[4], selectedCol[4], activeCol[4];
+ unsigned char col[4], selectedCol[4], activeCol[4];
- if (!activeSnap(t))
- return;
+ if (!activeSnap(t))
+ return;
- UI_GetThemeColor3ubv(TH_TRANSFORM, col);
- col[3] = 128;
+ UI_GetThemeColor3ubv(TH_TRANSFORM, col);
+ col[3] = 128;
- UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
- selectedCol[3] = 128;
+ UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
+ selectedCol[3] = 128;
- UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
- activeCol[3] = 192;
+ UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
+ activeCol[3] = 192;
- if (t->spacetype == SPACE_VIEW3D) {
- if (validSnap(t)) {
- TransSnapPoint *p;
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float imat[4][4];
- float size;
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (validSnap(t)) {
+ TransSnapPoint *p;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float imat[4][4];
+ float size;
- GPU_depth_test(false);
+ GPU_depth_test(false);
- size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- invert_m4_m4(imat, rv3d->viewmat);
+ invert_m4_m4(imat, rv3d->viewmat);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- for (p = t->tsnap.points.first; p; p = p->next) {
- if (p == t->tsnap.selectedPoint) {
- immUniformColor4ubv(selectedCol);
- }
- else {
- immUniformColor4ubv(col);
- }
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ if (p == t->tsnap.selectedPoint) {
+ immUniformColor4ubv(selectedCol);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
- imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
- }
+ imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
+ }
- if (t->tsnap.status & POINT_INIT) {
- immUniformColor4ubv(activeCol);
+ if (t->tsnap.status & POINT_INIT) {
+ immUniformColor4ubv(activeCol);
- imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
- }
+ imm_drawcircball(
+ t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
+ }
- /* draw normal if needed */
- if (usingSnappingNormal(t) && validSnappingNormal(t)) {
- immUniformColor4ubv(activeCol);
+ /* draw normal if needed */
+ if (usingSnappingNormal(t) && validSnappingNormal(t)) {
+ immUniformColor4ubv(activeCol);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
- immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
- t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
- t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
- immEnd();
- }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
+ immVertex3f(pos,
+ t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
+ t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
+ t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
+ immEnd();
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_depth_test(true);
- }
- }
- else if (t->spacetype == SPACE_IMAGE) {
- if (validSnap(t)) {
- /* This will not draw, and Im nor sure why - campbell */
- /* TODO: see 2.7x for non-working code */
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- if (validSnap(t)) {
- ARegion *ar = CTX_wm_region(C);
- TransSnapPoint *p;
- float size;
+ GPU_depth_test(true);
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ if (validSnap(t)) {
+ /* This will not draw, and Im nor sure why - campbell */
+ /* TODO: see 2.7x for non-working code */
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ if (validSnap(t)) {
+ ARegion *ar = CTX_wm_region(C);
+ TransSnapPoint *p;
+ float size;
- size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- GPU_blend(true);
+ GPU_blend(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- for (p = t->tsnap.points.first; p; p = p->next) {
- if (p == t->tsnap.selectedPoint) {
- immUniformColor4ubv(selectedCol);
- }
- else {
- immUniformColor4ubv(col);
- }
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ if (p == t->tsnap.selectedPoint) {
+ immUniformColor4ubv(selectedCol);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
- ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
- }
+ ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
+ }
- if (t->tsnap.status & POINT_INIT) {
- immUniformColor4ubv(activeCol);
+ if (t->tsnap.status & POINT_INIT) {
+ immUniformColor4ubv(activeCol);
- ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
- }
+ ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
+ }
- immUnbindProgram();
+ immUnbindProgram();
- GPU_blend(false);
- }
- }
+ GPU_blend(false);
+ }
+ }
}
eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event)
{
- eRedrawFlag status = TREDRAW_NOTHING;
-
-#if 0 // XXX need a proper selector for all snap mode
- if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
- /* toggle snap and reinit */
- t->settings->snap_flag ^= SCE_SNAP;
- initSnapping(t, NULL);
- status = TREDRAW_HARD;
- }
+ eRedrawFlag status = TREDRAW_NOTHING;
+
+#if 0 // XXX need a proper selector for all snap mode
+ if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) {
+ /* toggle snap and reinit */
+ t->settings->snap_flag ^= SCE_SNAP;
+ initSnapping(t, NULL);
+ status = TREDRAW_HARD;
+ }
#endif
- if (event->type == MOUSEMOVE) {
- status |= updateSelectedSnapPoint(t);
- }
+ if (event->type == MOUSEMOVE) {
+ status |= updateSelectedSnapPoint(t);
+ }
- return status;
+ return status;
}
void applyProject(TransInfo *t)
{
- /* XXX FLICKER IN OBJECT MODE */
- if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
- float tvec[3];
- int i;
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- for (i = 0; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], no[3];
- float mval_fl[2];
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
- continue;
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->flag & T_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- if (ED_transform_snap_object_project_view3d(
- t->tsnap.object_context,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- .use_occlusion_test = false,
- },
- mval_fl, 0, loc, no))
- {
+ /* XXX FLICKER IN OBJECT MODE */
+ if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
+ float tvec[3];
+ int i;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (i = 0; i < tc->data_len; i++, td++) {
+ float iloc[3], loc[3], no[3];
+ float mval_fl[2];
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
+ continue;
+
+ copy_v3_v3(iloc, td->loc);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, iloc);
+ }
+ else if (t->flag & T_OBJECT) {
+ BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
+ copy_v3_v3(iloc, td->ob->obmat[3]);
+ }
+
+ if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) ==
+ V3D_PROJ_RET_OK) {
+ if (ED_transform_snap_object_project_view3d(
+ t->tsnap.object_context,
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .use_occlusion_test = false,
+ },
+ mval_fl,
+ 0,
+ loc,
+ no)) {
#if 0
- if (tc->use_local_mat) {
- mul_m4_v3(tc->imat, loc);
- }
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->imat, loc);
+ }
#endif
- sub_v3_v3v3(tvec, loc, iloc);
+ sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
+ mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
+ add_v3_v3(td->loc, tvec);
- if (t->tsnap.align && (t->flag & T_OBJECT)) {
- /* handle alignment as well */
- const float *original_normal;
- float mat[3][3];
+ if (t->tsnap.align && (t->flag & T_OBJECT)) {
+ /* handle alignment as well */
+ const float *original_normal;
+ float mat[3][3];
- /* In pose mode, we want to align normals with Y axis of bones... */
- original_normal = td->axismtx[2];
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ original_normal = td->axismtx[2];
- rotation_between_vecs_to_mat3(mat, original_normal, no);
+ rotation_between_vecs_to_mat3(mat, original_normal, no);
- transform_data_ext_rotate(td, mat, true);
+ transform_data_ext_rotate(td, mat, true);
- /* TODO support constraints for rotation too? see ElementRotation */
- }
- }
- }
+ /* TODO support constraints for rotation too? see ElementRotation */
+ }
+ }
+ }
- //XXX constraintTransLim(t, td);
- }
- }
- }
+ //XXX constraintTransLim(t, td);
+ }
+ }
+ }
}
void applyGridAbsolute(TransInfo *t)
{
- float grid_size = 0.0f;
- GearsType grid_action;
- int i;
-
- if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
- return;
-
- grid_action = BIG_GEARS;
- if (t->modifiers & MOD_PRECISION)
- grid_action = SMALL_GEARS;
-
- switch (grid_action) {
- case NO_GEARS: grid_size = t->snap_spatial[0]; break;
- case BIG_GEARS: grid_size = t->snap_spatial[1]; break;
- case SMALL_GEARS: grid_size = t->snap_spatial[2]; break;
- }
- /* early exit on unusable grid size */
- if (grid_size == 0.0f)
- return;
-
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td;
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], tvec[3];
-
- if (td->flag & TD_NOACTION)
- break;
-
- if (td->flag & TD_SKIP)
- continue;
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
- continue;
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->flag & T_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
- loc[0] = roundf(loc[0]);
- loc[1] = roundf(loc[1]);
- loc[2] = roundf(loc[2]);
- mul_v3_fl(loc, grid_size);
-
- sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
- }
- }
+ float grid_size = 0.0f;
+ GearsType grid_action;
+ int i;
+
+ if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID))))
+ return;
+
+ grid_action = BIG_GEARS;
+ if (t->modifiers & MOD_PRECISION)
+ grid_action = SMALL_GEARS;
+
+ switch (grid_action) {
+ case NO_GEARS:
+ grid_size = t->snap_spatial[0];
+ break;
+ case BIG_GEARS:
+ grid_size = t->snap_spatial[1];
+ break;
+ case SMALL_GEARS:
+ grid_size = t->snap_spatial[2];
+ break;
+ }
+ /* early exit on unusable grid size */
+ if (grid_size == 0.0f)
+ return;
+
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td;
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ float iloc[3], loc[3], tvec[3];
+
+ if (td->flag & TD_NOACTION)
+ break;
+
+ if (td->flag & TD_SKIP)
+ continue;
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
+ continue;
+
+ copy_v3_v3(iloc, td->loc);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, iloc);
+ }
+ else if (t->flag & T_OBJECT) {
+ BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
+ copy_v3_v3(iloc, td->ob->obmat[3]);
+ }
+
+ mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
+ loc[0] = roundf(loc[0]);
+ loc[1] = roundf(loc[1]);
+ loc[2] = roundf(loc[2]);
+ mul_v3_fl(loc, grid_size);
+
+ sub_v3_v3v3(tvec, loc, iloc);
+ mul_m3_v3(td->smtx, tvec);
+ add_v3_v3(td->loc, tvec);
+ }
+ }
}
void applySnapping(TransInfo *t, float *vec)
{
- /* Each Trans Data already makes the snap to face */
- if (doForceIncrementSnap(t) ||
- (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE))
- {
- return;
- }
-
- if (t->tsnap.status & SNAP_FORCED) {
- t->tsnap.targetSnap(t);
-
- t->tsnap.applySnap(t, vec);
- }
- else if (((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) != 0) &&
- activeSnap(t))
- {
- double current = PIL_check_seconds_timer();
-
- // Time base quirky code to go around findnearest slowness
- /* !TODO! add exception for object mode, no need to slow it down then */
- if (current - t->tsnap.last >= 0.01) {
- t->tsnap.calcSnap(t, vec);
- t->tsnap.targetSnap(t);
-
- t->tsnap.last = current;
- }
- if (validSnap(t)) {
- t->tsnap.applySnap(t, vec);
- }
- }
+ /* Each Trans Data already makes the snap to face */
+ if (doForceIncrementSnap(t) || (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE)) {
+ return;
+ }
+
+ if (t->tsnap.status & SNAP_FORCED) {
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.applySnap(t, vec);
+ }
+ else if (((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) != 0) &&
+ activeSnap(t)) {
+ double current = PIL_check_seconds_timer();
+
+ // Time base quirky code to go around findnearest slowness
+ /* !TODO! add exception for object mode, no need to slow it down then */
+ if (current - t->tsnap.last >= 0.01) {
+ t->tsnap.calcSnap(t, vec);
+ t->tsnap.targetSnap(t);
+
+ t->tsnap.last = current;
+ }
+ if (validSnap(t)) {
+ t->tsnap.applySnap(t, vec);
+ }
+ }
}
void resetSnapping(TransInfo *t)
{
- t->tsnap.status = 0;
- t->tsnap.align = false;
- t->tsnap.project = 0;
- t->tsnap.mode = 0;
- t->tsnap.modeSelect = 0;
- t->tsnap.target = 0;
- t->tsnap.last = 0;
- t->tsnap.applySnap = NULL;
-
- t->tsnap.snapNormal[0] = 0;
- t->tsnap.snapNormal[1] = 0;
- t->tsnap.snapNormal[2] = 0;
-
- t->tsnap.snapNodeBorder = 0;
+ t->tsnap.status = 0;
+ t->tsnap.align = false;
+ t->tsnap.project = 0;
+ t->tsnap.mode = 0;
+ t->tsnap.modeSelect = 0;
+ t->tsnap.target = 0;
+ t->tsnap.last = 0;
+ t->tsnap.applySnap = NULL;
+
+ t->tsnap.snapNormal[0] = 0;
+ t->tsnap.snapNormal[1] = 0;
+ t->tsnap.snapNormal[2] = 0;
+
+ t->tsnap.snapNodeBorder = 0;
}
bool usingSnappingNormal(const TransInfo *t)
{
- return t->tsnap.align;
+ return t->tsnap.align;
}
bool validSnappingNormal(const TransInfo *t)
{
- if (validSnap(t)) {
- if (!is_zero_v3(t->tsnap.snapNormal)) {
- return true;
- }
- }
+ if (validSnap(t)) {
+ if (!is_zero_v3(t->tsnap.snapNormal)) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
static bool bm_edge_is_snap_target(BMEdge *e, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ||
- BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
- {
- return false;
- }
-
- return true;
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ||
+ BM_elem_flag_test(e->v1, BM_ELEM_SELECT) || BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) {
+ return false;
+ }
+
+ return true;
}
static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
{
- if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
- return false;
- }
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- return true;
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
+ return false;
+ }
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ return false;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return true;
}
static void initSnappingMode(TransInfo *t)
{
- Main *bmain = CTX_data_main(t->context);
- ToolSettings *ts = t->settings;
- /* All obedit types will match. */
- const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
- ViewLayer *view_layer = t->view_layer;
- Base *base_act = view_layer->basact;
-
- if (t->spacetype == SPACE_NODE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_node_mode;
- }
- else if (t->spacetype == SPACE_IMAGE) {
- /* force project off when not supported */
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_uv_mode;
- }
- else {
- /* force project off when not supported */
- if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
- t->tsnap.project = 0;
-
- t->tsnap.mode = ts->snap_mode;
- }
-
- if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */
- (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */
- {
- setSnappingCallback(t);
-
- /* Edit mode */
- if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- ((obedit_type != -1) && ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, metaballs
- {
- /* Exclude editmesh if using proportional edit */
- if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
- t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
- }
- else {
- t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
- }
- }
- /* Particles edit mode*/
- else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- ((obedit_type == -1) && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
- {
- t->tsnap.modeSelect = SNAP_ALL;
- }
- /* Object mode */
- else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit_type == -1) ) // Object Mode
- {
- /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
- * TODO: perform self snap in gpencil_strokes */
- t->tsnap.modeSelect = (
- ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
- SNAP_ALL : SNAP_NOT_SELECTED);
- }
- else {
- /* Grid if snap is not possible */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- setSnappingCallback(t);
-
- if (t->tsnap.applySnap != NULL) {
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
- }
- else {
- /* Grid if snap is not possible */
- t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
- }
- }
- else 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;
- }
-
- if (t->spacetype == SPACE_VIEW3D) {
- if (t->tsnap.object_context == NULL) {
- t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- bmain, t->scene, t->depsgraph, 0, t->ar, t->view);
-
- ED_transform_snap_object_context_set_editmesh_callbacks(
- t->tsnap.object_context,
- (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
- bm_edge_is_snap_target,
- bm_face_is_snap_target,
- POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
- }
- }
+ Main *bmain = CTX_data_main(t->context);
+ ToolSettings *ts = t->settings;
+ /* All obedit types will match. */
+ const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base_act = view_layer->basact;
+
+ if (t->spacetype == SPACE_NODE) {
+ /* force project off when not supported */
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_node_mode;
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ /* force project off when not supported */
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_uv_mode;
+ }
+ else {
+ /* force project off when not supported */
+ if ((ts->snap_mode & SCE_SNAP_MODE_FACE) == 0)
+ t->tsnap.project = 0;
+
+ t->tsnap.mode = ts->snap_mode;
+ }
+
+ if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */
+ (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */
+ {
+ setSnappingCallback(t);
+
+ /* Edit mode */
+ if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ ((obedit_type != -1) &&
+ ELEM(obedit_type,
+ OB_MESH,
+ OB_ARMATURE,
+ OB_CURVE,
+ OB_LATTICE,
+ OB_MBALL))) // Temporary limited to edit mode meshes, armature, curves, metaballs
+ {
+ /* Exclude editmesh if using proportional edit */
+ if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
+ t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
+ }
+ else {
+ t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
+ }
+ }
+ /* Particles edit mode*/
+ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ ((obedit_type == -1) && base_act && base_act->object &&
+ base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
+ t->tsnap.modeSelect = SNAP_ALL;
+ }
+ /* Object mode */
+ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
+ (obedit_type == -1)) // Object Mode
+ {
+ /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes */
+ t->tsnap.modeSelect = (((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
+ SNAP_ALL :
+ SNAP_NOT_SELECTED);
+ }
+ else {
+ /* Grid if snap is not possible */
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ setSnappingCallback(t);
+
+ if (t->tsnap.applySnap != NULL) {
+ t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ }
+ else {
+ /* Grid if snap is not possible */
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+ }
+ else 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;
+ }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->tsnap.object_context == NULL) {
+ t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
+ bmain, t->scene, t->depsgraph, 0, t->ar, t->view);
+
+ ED_transform_snap_object_context_set_editmesh_callbacks(
+ t->tsnap.object_context,
+ (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
+ bm_edge_is_snap_target,
+ bm_face_is_snap_target,
+ POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
+ }
+ }
}
void initSnapping(TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = t->settings;
- short snap_target = t->settings->snap_target;
-
- resetSnapping(t);
-
- /* if snap property exists */
- if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_struct_property_is_set(op->ptr, "snap")) {
- if (RNA_boolean_get(op->ptr, "snap")) {
- t->modifiers |= MOD_SNAP;
-
- if (RNA_struct_property_is_set(op->ptr, "snap_target")) {
- snap_target = RNA_enum_get(op->ptr, "snap_target");
- }
-
- if (RNA_struct_property_is_set(op->ptr, "snap_point")) {
- RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
- t->tsnap.status |= SNAP_FORCED | POINT_INIT;
- }
-
- /* snap align only defined in specific cases */
- if (RNA_struct_find_property(op->ptr, "snap_align")) {
- t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
- RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
- normalize_v3(t->tsnap.snapNormal);
- }
-
- if (RNA_struct_find_property(op->ptr, "use_snap_project")) {
- t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project");
- }
-
- if (RNA_struct_find_property(op->ptr, "use_snap_self")) {
- t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self");
- }
- }
- }
- /* use scene defaults only when transform is modal */
- else if (t->flag & T_MODAL) {
- if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
- if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) {
- t->modifiers |= MOD_SNAP;
- }
-
- t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0);
- t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
- t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- }
-
- /* for now only 3d view (others can be added if we want) */
- if (t->spacetype == SPACE_VIEW3D) {
- t->tsnap.snap_spatial_grid = ((t->settings->snap_flag & SCE_SNAP_ABS_GRID) != 0);
- }
- }
-
- t->tsnap.target = snap_target;
-
- initSnappingMode(t);
+ ToolSettings *ts = t->settings;
+ short snap_target = t->settings->snap_target;
+
+ resetSnapping(t);
+
+ /* if snap property exists */
+ if (op && RNA_struct_find_property(op->ptr, "snap") &&
+ RNA_struct_property_is_set(op->ptr, "snap")) {
+ if (RNA_boolean_get(op->ptr, "snap")) {
+ t->modifiers |= MOD_SNAP;
+
+ if (RNA_struct_property_is_set(op->ptr, "snap_target")) {
+ snap_target = RNA_enum_get(op->ptr, "snap_target");
+ }
+
+ if (RNA_struct_property_is_set(op->ptr, "snap_point")) {
+ RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
+ t->tsnap.status |= SNAP_FORCED | POINT_INIT;
+ }
+
+ /* snap align only defined in specific cases */
+ if (RNA_struct_find_property(op->ptr, "snap_align")) {
+ t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
+ RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
+ normalize_v3(t->tsnap.snapNormal);
+ }
+
+ if (RNA_struct_find_property(op->ptr, "use_snap_project")) {
+ t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project");
+ }
+
+ if (RNA_struct_find_property(op->ptr, "use_snap_self")) {
+ t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self");
+ }
+ }
+ }
+ /* use scene defaults only when transform is modal */
+ else if (t->flag & T_MODAL) {
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
+ if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) {
+ t->modifiers |= MOD_SNAP;
+ }
+
+ t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0);
+ t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
+ t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
+ t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
+ }
+
+ /* for now only 3d view (others can be added if we want) */
+ if (t->spacetype == SPACE_VIEW3D) {
+ t->tsnap.snap_spatial_grid = ((t->settings->snap_flag & SCE_SNAP_ABS_GRID) != 0);
+ }
+ }
+
+ t->tsnap.target = snap_target;
+
+ initSnappingMode(t);
}
void freeSnapping(TransInfo *t)
{
- if (t->tsnap.object_context) {
- ED_transform_snap_object_context_destroy(t->tsnap.object_context);
- t->tsnap.object_context = NULL;
- }
+ if (t->tsnap.object_context) {
+ ED_transform_snap_object_context_destroy(t->tsnap.object_context);
+ t->tsnap.object_context = NULL;
+ }
}
static void setSnappingCallback(TransInfo *t)
{
- t->tsnap.calcSnap = CalcSnapGeometry;
-
- switch (t->tsnap.target) {
- case SCE_SNAP_TARGET_CLOSEST:
- t->tsnap.targetSnap = TargetSnapClosest;
- break;
- case SCE_SNAP_TARGET_CENTER:
- t->tsnap.targetSnap = TargetSnapCenter;
- break;
- case SCE_SNAP_TARGET_MEDIAN:
- t->tsnap.targetSnap = TargetSnapMedian;
- break;
- case SCE_SNAP_TARGET_ACTIVE:
- t->tsnap.targetSnap = TargetSnapActive;
- break;
-
- }
-
- switch (t->mode) {
- case TFM_TRANSLATION:
- t->tsnap.applySnap = ApplySnapTranslation;
- t->tsnap.distance = TranslationBetween;
- break;
- case TFM_ROTATION:
- t->tsnap.applySnap = ApplySnapRotation;
- t->tsnap.distance = RotationBetween;
-
- // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
- if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- }
- break;
- case TFM_RESIZE:
- t->tsnap.applySnap = ApplySnapResize;
- t->tsnap.distance = ResizeBetween;
-
- // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
- if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- }
- break;
- default:
- t->tsnap.applySnap = NULL;
- break;
- }
+ t->tsnap.calcSnap = CalcSnapGeometry;
+
+ switch (t->tsnap.target) {
+ case SCE_SNAP_TARGET_CLOSEST:
+ t->tsnap.targetSnap = TargetSnapClosest;
+ break;
+ case SCE_SNAP_TARGET_CENTER:
+ t->tsnap.targetSnap = TargetSnapCenter;
+ break;
+ case SCE_SNAP_TARGET_MEDIAN:
+ t->tsnap.targetSnap = TargetSnapMedian;
+ break;
+ case SCE_SNAP_TARGET_ACTIVE:
+ t->tsnap.targetSnap = TargetSnapActive;
+ break;
+ }
+
+ switch (t->mode) {
+ case TFM_TRANSLATION:
+ t->tsnap.applySnap = ApplySnapTranslation;
+ t->tsnap.distance = TranslationBetween;
+ break;
+ case TFM_ROTATION:
+ t->tsnap.applySnap = ApplySnapRotation;
+ t->tsnap.distance = RotationBetween;
+
+ // Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ case TFM_RESIZE:
+ t->tsnap.applySnap = ApplySnapResize;
+ t->tsnap.distance = ResizeBetween;
+
+ // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ default:
+ t->tsnap.applySnap = NULL;
+ break;
+ }
}
void addSnapPoint(TransInfo *t)
{
- /* Currently only 3D viewport works for snapping points. */
- if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
- TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
+ /* Currently only 3D viewport works for snapping points. */
+ if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
+ TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
- t->tsnap.selectedPoint = p;
+ t->tsnap.selectedPoint = p;
- copy_v3_v3(p->co, t->tsnap.snapPoint);
+ copy_v3_v3(p->co, t->tsnap.snapPoint);
- BLI_addtail(&t->tsnap.points, p);
+ BLI_addtail(&t->tsnap.points, p);
- t->tsnap.status |= MULTI_POINTS;
- }
+ t->tsnap.status |= MULTI_POINTS;
+ }
}
eRedrawFlag updateSelectedSnapPoint(TransInfo *t)
{
- eRedrawFlag status = TREDRAW_NOTHING;
+ eRedrawFlag status = TREDRAW_NOTHING;
- if (t->tsnap.status & MULTI_POINTS) {
- TransSnapPoint *p, *closest_p = NULL;
- float dist_min_sq = TRANSFORM_SNAP_MAX_PX;
- const float mval_fl[2] = {t->mval[0], t->mval[1]};
- float screen_loc[2];
+ if (t->tsnap.status & MULTI_POINTS) {
+ TransSnapPoint *p, *closest_p = NULL;
+ float dist_min_sq = TRANSFORM_SNAP_MAX_PX;
+ const float mval_fl[2] = {t->mval[0], t->mval[1]};
+ float screen_loc[2];
- for (p = t->tsnap.points.first; p; p = p->next) {
- float dist_sq;
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ float dist_sq;
- if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
- continue;
- }
+ if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) !=
+ V3D_PROJ_RET_OK) {
+ continue;
+ }
- dist_sq = len_squared_v2v2(mval_fl, screen_loc);
+ dist_sq = len_squared_v2v2(mval_fl, screen_loc);
- if (dist_sq < dist_min_sq) {
- closest_p = p;
- dist_min_sq = dist_sq;
- }
- }
+ if (dist_sq < dist_min_sq) {
+ closest_p = p;
+ dist_min_sq = dist_sq;
+ }
+ }
- if (closest_p) {
- if (t->tsnap.selectedPoint != closest_p) {
- status = TREDRAW_HARD;
- }
+ if (closest_p) {
+ if (t->tsnap.selectedPoint != closest_p) {
+ status = TREDRAW_HARD;
+ }
- t->tsnap.selectedPoint = closest_p;
- }
- }
+ t->tsnap.selectedPoint = closest_p;
+ }
+ }
- return status;
+ return status;
}
void removeSnapPoint(TransInfo *t)
{
- if (t->tsnap.status & MULTI_POINTS) {
- updateSelectedSnapPoint(t);
-
- if (t->tsnap.selectedPoint) {
- BLI_freelinkN(&t->tsnap.points, t->tsnap.selectedPoint);
+ if (t->tsnap.status & MULTI_POINTS) {
+ updateSelectedSnapPoint(t);
- if (BLI_listbase_is_empty(&t->tsnap.points)) {
- t->tsnap.status &= ~MULTI_POINTS;
- }
+ if (t->tsnap.selectedPoint) {
+ BLI_freelinkN(&t->tsnap.points, t->tsnap.selectedPoint);
- t->tsnap.selectedPoint = NULL;
- }
+ if (BLI_listbase_is_empty(&t->tsnap.points)) {
+ t->tsnap.status &= ~MULTI_POINTS;
+ }
- }
+ t->tsnap.selectedPoint = NULL;
+ }
+ }
}
void getSnapPoint(const TransInfo *t, float vec[3])
{
- if (t->tsnap.points.first) {
- TransSnapPoint *p;
- int total = 0;
-
- vec[0] = vec[1] = vec[2] = 0;
-
- for (p = t->tsnap.points.first; p; p = p->next, total++) {
- add_v3_v3(vec, p->co);
- }
-
- if (t->tsnap.status & POINT_INIT) {
- add_v3_v3(vec, t->tsnap.snapPoint);
- total++;
- }
-
- mul_v3_fl(vec, 1.0f / total);
- }
- else {
- copy_v3_v3(vec, t->tsnap.snapPoint);
- }
+ if (t->tsnap.points.first) {
+ TransSnapPoint *p;
+ int total = 0;
+
+ vec[0] = vec[1] = vec[2] = 0;
+
+ for (p = t->tsnap.points.first; p; p = p->next, total++) {
+ add_v3_v3(vec, p->co);
+ }
+
+ if (t->tsnap.status & POINT_INIT) {
+ add_v3_v3(vec, t->tsnap.snapPoint);
+ total++;
+ }
+
+ mul_v3_fl(vec, 1.0f / total);
+ }
+ else {
+ copy_v3_v3(vec, t->tsnap.snapPoint);
+ }
}
/********************** APPLY **************************/
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
- float point[3];
- getSnapPoint(t, point);
-
- if (t->spacetype == SPACE_NODE) {
- char border = t->tsnap.snapNodeBorder;
- if (border & (NODE_LEFT | NODE_RIGHT))
- vec[0] = point[0] - t->tsnap.snapTarget[0];
- if (border & (NODE_BOTTOM | NODE_TOP))
- vec[1] = point[1] - t->tsnap.snapTarget[1];
- }
- else {
- if (t->spacetype == SPACE_VIEW3D) {
- if (t->options & CTX_PAINT_CURVE) {
- if (ED_view3d_project_float_global(t->ar, point, point, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
- zero_v3(point); /* no good answer here... */
- }
- }
- }
-
- sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
- }
+ float point[3];
+ getSnapPoint(t, point);
+
+ if (t->spacetype == SPACE_NODE) {
+ char border = t->tsnap.snapNodeBorder;
+ if (border & (NODE_LEFT | NODE_RIGHT))
+ vec[0] = point[0] - t->tsnap.snapTarget[0];
+ if (border & (NODE_BOTTOM | NODE_TOP))
+ vec[1] = point[1] - t->tsnap.snapTarget[1];
+ }
+ else {
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & CTX_PAINT_CURVE) {
+ if (ED_view3d_project_float_global(t->ar, point, point, V3D_PROJ_TEST_NOP) !=
+ V3D_PROJ_RET_OK) {
+ zero_v3(point); /* no good answer here... */
+ }
+ }
+ }
+
+ sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
+ }
}
static void ApplySnapRotation(TransInfo *t, float *value)
{
- float point[3];
- getSnapPoint(t, point);
+ float point[3];
+ getSnapPoint(t, point);
- float dist = RotationBetween(t, t->tsnap.snapTarget, point);
- *value = dist;
+ float dist = RotationBetween(t, t->tsnap.snapTarget, point);
+ *value = dist;
}
static void ApplySnapResize(TransInfo *t, float vec[3])
{
- float point[3];
- getSnapPoint(t, point);
+ float point[3];
+ getSnapPoint(t, point);
- float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
- if (dist != TRANSFORM_DIST_INVALID) {
- copy_v3_fl(vec, dist);
- }
+ float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
+ if (dist != TRANSFORM_DIST_INVALID) {
+ copy_v3_fl(vec, dist);
+ }
}
/********************** DISTANCE **************************/
static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3])
{
- return len_squared_v3v3(p1, p2);
+ return len_squared_v3v3(p1, p2);
}
-static float RotationBetween(
- TransInfo *t, const float p1[3], const float p2[3])
+static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float angle, start[3], end[3];
+ float angle, start[3], end[3];
- sub_v3_v3v3(start, p1, t->center_global);
- sub_v3_v3v3(end, p2, t->center_global);
+ 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)) {
- float axis[3], tmp[3];
+ // Angle around a constraint axis (error prone, will need debug)
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ float axis[3], tmp[3];
- t->con.applyRot(t, NULL, NULL, axis, NULL);
+ t->con.applyRot(t, NULL, NULL, axis, NULL);
- project_v3_v3v3(tmp, end, axis);
- sub_v3_v3v3(end, end, tmp);
+ project_v3_v3v3(tmp, end, axis);
+ sub_v3_v3v3(end, end, tmp);
- project_v3_v3v3(tmp, start, axis);
- sub_v3_v3v3(start, start, tmp);
+ project_v3_v3v3(tmp, start, axis);
+ sub_v3_v3v3(start, start, tmp);
- normalize_v3(end);
- normalize_v3(start);
+ normalize_v3(end);
+ normalize_v3(start);
- cross_v3_v3v3(tmp, start, end);
+ cross_v3_v3v3(tmp, start, end);
- if (dot_v3v3(tmp, axis) < 0.0f)
- angle = -acosf(dot_v3v3(start, end));
- else
- angle = acosf(dot_v3v3(start, end));
- }
- else {
- float mtx[3][3];
+ if (dot_v3v3(tmp, axis) < 0.0f)
+ angle = -acosf(dot_v3v3(start, end));
+ else
+ angle = acosf(dot_v3v3(start, end));
+ }
+ else {
+ float mtx[3][3];
- copy_m3_m4(mtx, t->viewmat);
+ copy_m3_m4(mtx, t->viewmat);
- mul_m3_v3(mtx, end);
- mul_m3_v3(mtx, start);
+ mul_m3_v3(mtx, end);
+ mul_m3_v3(mtx, start);
- angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
- }
+ angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
+ }
- if (angle > (float)M_PI) {
- angle = angle - 2 * (float)M_PI;
- }
- else if (angle < -((float)M_PI)) {
- angle = 2.0f * (float)M_PI + angle;
- }
+ if (angle > (float)M_PI) {
+ angle = angle - 2 * (float)M_PI;
+ }
+ else if (angle < -((float)M_PI)) {
+ angle = 2.0f * (float)M_PI + angle;
+ }
- return angle;
+ return angle;
}
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
- float d1[3], d2[3], len_d1;
+ float d1[3], d2[3], len_d1;
- sub_v3_v3v3(d1, p1, t->center_global);
- sub_v3_v3v3(d2, p2, t->center_global);
+ 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);
- mul_m3_v3(t->con.pmtx, d2);
- }
+ if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
+ mul_m3_v3(t->con.pmtx, d1);
+ mul_m3_v3(t->con.pmtx, d2);
+ }
- project_v3_v3v3(d1, d1, d2);
+ project_v3_v3v3(d1, d1, d2);
- len_d1 = len_v3(d1);
+ len_d1 = len_v3(d1);
- /* Use 'invalid' dist when `center == p1` (after projecting),
- * in this case scale will _never_ move the point in relation to the center,
- * so it makes no sense to take it into account when scaling. see: T46503 */
- return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
+ /* Use 'invalid' dist when `center == p1` (after projecting),
+ * in this case scale will _never_ move the point in relation to the center,
+ * so it makes no sense to take it into account when scaling. see: T46503 */
+ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
/********************** CALC **************************/
-static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec))
+static void UNUSED_FUNCTION(CalcSnapGrid)(TransInfo *t, float *UNUSED(vec))
{
- snapGridIncrementAction(t, t->tsnap.snapPoint, BIG_GEARS);
+ snapGridIncrementAction(t, t->tsnap.snapPoint, BIG_GEARS);
}
static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
{
- if (t->spacetype == SPACE_VIEW3D) {
- float loc[3];
- float no[3];
- float mval[2];
- bool found = false;
- float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
-
- mval[0] = t->mval[0];
- mval[1] = t->mval[1];
-
- if (t->tsnap.mode &
- (SCE_SNAP_MODE_VERTEX |
- SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE))
- {
- zero_v3(no); /* objects won't set this */
- found = snapObjectsTransform(
- t, mval, &dist_px,
- loc, no);
- }
- if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
- found = peelObjectsTransform(
- t, mval,
- (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
- loc, no, NULL);
- }
-
- if (found == true) {
- copy_v3_v3(t->tsnap.snapPoint, loc);
- copy_v3_v3(t->tsnap.snapNormal, no);
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- }
- else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
- if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
- Image *ima = ED_space_image(t->sa->spacedata.first);
- float co[2];
-
- UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
- t->view_layer, NULL, &objects_len);
-
- float dist_sq = FLT_MAX;
- if (ED_uvedit_nearest_uv_multi(t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
- t->tsnap.snapPoint[0] *= t->aspect[0];
- t->tsnap.snapPoint[1] *= t->aspect[1];
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- MEM_freeN(objects);
- }
- }
- else if (t->spacetype == SPACE_NODE) {
- if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
- float loc[2];
- float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
- char node_border;
-
- if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
- copy_v2_v2(t->tsnap.snapPoint, loc);
- t->tsnap.snapNodeBorder = node_border;
-
- t->tsnap.status |= POINT_INIT;
- }
- else {
- t->tsnap.status &= ~POINT_INIT;
- }
- }
- }
+ if (t->spacetype == SPACE_VIEW3D) {
+ float loc[3];
+ float no[3];
+ float mval[2];
+ bool found = false;
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
+
+ mval[0] = t->mval[0];
+ mval[1] = t->mval[1];
+
+ if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
+ zero_v3(no); /* objects won't set this */
+ found = snapObjectsTransform(t, mval, &dist_px, loc, no);
+ }
+ if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
+ found = peelObjectsTransform(
+ t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL);
+ }
+
+ if (found == true) {
+ copy_v3_v3(t->tsnap.snapPoint, loc);
+ copy_v3_v3(t->tsnap.snapNormal, no);
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+ else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
+ if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
+ Image *ima = ED_space_image(t->sa->spacedata.first);
+ float co[2];
+
+ UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ t->view_layer, NULL, &objects_len);
+
+ float dist_sq = FLT_MAX;
+ if (ED_uvedit_nearest_uv_multi(
+ t->scene, ima, objects, objects_len, co, &dist_sq, t->tsnap.snapPoint)) {
+ t->tsnap.snapPoint[0] *= t->aspect[0];
+ t->tsnap.snapPoint[1] *= t->aspect[1];
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ MEM_freeN(objects);
+ }
+ }
+ else if (t->spacetype == SPACE_NODE) {
+ if (t->tsnap.mode & (SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y)) {
+ float loc[2];
+ float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
+ char node_border;
+
+ if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
+ copy_v2_v2(t->tsnap.snapPoint, loc);
+ t->tsnap.snapNodeBorder = node_border;
+
+ t->tsnap.status |= POINT_INIT;
+ }
+ else {
+ t->tsnap.status &= ~POINT_INIT;
+ }
+ }
+ }
}
/********************** TARGET **************************/
static void TargetSnapOffset(TransInfo *t, TransData *td)
{
- if (t->spacetype == SPACE_NODE && td != NULL) {
- bNode *node = td->extra;
- char border = t->tsnap.snapNodeBorder;
- float width = BLI_rctf_size_x(&node->totr);
- float height = BLI_rctf_size_y(&node->totr);
+ if (t->spacetype == SPACE_NODE && td != NULL) {
+ bNode *node = td->extra;
+ char border = t->tsnap.snapNodeBorder;
+ float width = BLI_rctf_size_x(&node->totr);
+ float height = BLI_rctf_size_y(&node->totr);
#ifdef USE_NODE_CENTER
- if (border & NODE_LEFT)
- t->tsnap.snapTarget[0] -= 0.5f * width;
- if (border & NODE_RIGHT)
- t->tsnap.snapTarget[0] += 0.5f * width;
- if (border & NODE_BOTTOM)
- t->tsnap.snapTarget[1] -= 0.5f * height;
- if (border & NODE_TOP)
- t->tsnap.snapTarget[1] += 0.5f * height;
+ if (border & NODE_LEFT)
+ t->tsnap.snapTarget[0] -= 0.5f * width;
+ if (border & NODE_RIGHT)
+ t->tsnap.snapTarget[0] += 0.5f * width;
+ if (border & NODE_BOTTOM)
+ t->tsnap.snapTarget[1] -= 0.5f * height;
+ if (border & NODE_TOP)
+ t->tsnap.snapTarget[1] += 0.5f * height;
#else
- if (border & NODE_LEFT)
- t->tsnap.snapTarget[0] -= 0.0f;
- if (border & NODE_RIGHT)
- t->tsnap.snapTarget[0] += width;
- if (border & NODE_BOTTOM)
- t->tsnap.snapTarget[1] -= height;
- if (border & NODE_TOP)
- t->tsnap.snapTarget[1] += 0.0f;
+ if (border & NODE_LEFT)
+ t->tsnap.snapTarget[0] -= 0.0f;
+ if (border & NODE_RIGHT)
+ t->tsnap.snapTarget[0] += width;
+ if (border & NODE_BOTTOM)
+ t->tsnap.snapTarget[1] -= height;
+ if (border & NODE_TOP)
+ t->tsnap.snapTarget[1] += 0.0f;
#endif
- }
+ }
}
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_global);
- TargetSnapOffset(t, NULL);
+ /* Only need to calculate once */
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ copy_v3_v3(t->tsnap.snapTarget, t->center_global);
+ TargetSnapOffset(t, NULL);
- t->tsnap.status |= TARGET_INIT;
- }
+ t->tsnap.status |= TARGET_INIT;
+ }
}
static void TargetSnapActive(TransInfo *t)
{
- /* Only need to calculate once */
- if ((t->tsnap.status & TARGET_INIT) == 0) {
- if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
- TargetSnapOffset(t, NULL);
-
- t->tsnap.status |= TARGET_INIT;
- }
- /* No active, default to median */
- else {
- t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
- t->tsnap.targetSnap = TargetSnapMedian;
- TargetSnapMedian(t);
- }
- }
+ /* Only need to calculate once */
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
+ TargetSnapOffset(t, NULL);
+
+ t->tsnap.status |= TARGET_INIT;
+ }
+ /* No active, default to median */
+ else {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ TargetSnapMedian(t);
+ }
+ }
}
static void TargetSnapMedian(TransInfo *t)
{
- // Only need to calculate once
- if ((t->tsnap.status & TARGET_INIT) == 0) {
- int i_accum = 0;
+ // Only need to calculate once
+ if ((t->tsnap.status & TARGET_INIT) == 0) {
+ int i_accum = 0;
- t->tsnap.snapTarget[0] = 0;
- t->tsnap.snapTarget[1] = 0;
- t->tsnap.snapTarget[2] = 0;
+ t->tsnap.snapTarget[0] = 0;
+ t->tsnap.snapTarget[1] = 0;
+ t->tsnap.snapTarget[2] = 0;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td = tc->data;
- int i;
- float v[3];
- zero_v3(v);
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ int i;
+ float v[3];
+ zero_v3(v);
- for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- add_v3_v3(v, td->center);
- }
+ for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ add_v3_v3(v, td->center);
+ }
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, v);
- }
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, v);
+ }
- add_v3_v3(t->tsnap.snapTarget, v);
- i_accum += i;
- }
+ add_v3_v3(t->tsnap.snapTarget, v);
+ i_accum += i;
+ }
- mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
+ mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
- TargetSnapOffset(t, NULL);
+ TargetSnapOffset(t, NULL);
- t->tsnap.status |= TARGET_INIT;
- }
+ t->tsnap.status |= TARGET_INIT;
+ }
}
static void TargetSnapClosest(TransInfo *t)
{
- // Only valid if a snap point has been selected
- if (t->tsnap.status & POINT_INIT) {
- float dist_closest = 0.0f;
- TransData *closest = NULL;
-
- /* Object mode */
- if (t->flag & T_OBJECT) {
- int i;
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
-
- /* use boundbox if possible */
- if (bb) {
- int j;
-
- for (j = 0; j < 8; j++) {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, bb->vec[j]);
- mul_m4_v3(td->ext->obmat, loc);
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- dist_closest = dist;
- }
- }
- }
- /* use element center otherwise */
- else {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, td->center);
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- }
- }
- }
- }
- }
- else {
- FOREACH_TRANS_DATA_CONTAINER(t, tc) {
- TransData *td = tc->data;
- int i;
- for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- float loc[3];
- float dist;
-
- copy_v3_v3(loc, td->center);
-
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, loc);
- }
-
- dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if ((dist != TRANSFORM_DIST_INVALID) &&
- (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
- {
- copy_v3_v3(t->tsnap.snapTarget, loc);
- closest = td;
- dist_closest = dist;
- }
- }
- }
- }
-
- TargetSnapOffset(t, closest);
-
- t->tsnap.status |= TARGET_INIT;
- }
+ // Only valid if a snap point has been selected
+ if (t->tsnap.status & POINT_INIT) {
+ float dist_closest = 0.0f;
+ TransData *closest = NULL;
+
+ /* Object mode */
+ if (t->flag & T_OBJECT) {
+ int i;
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
+
+ /* use boundbox if possible */
+ if (bb) {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, bb->vec[j]);
+ mul_m4_v3(td->ext->obmat, loc);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ dist_closest = dist;
+ }
+ }
+ }
+ /* use element center otherwise */
+ else {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, td->center);
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ }
+ }
+ }
+ }
+ }
+ else {
+ FOREACH_TRANS_DATA_CONTAINER(t, tc)
+ {
+ TransData *td = tc->data;
+ int i;
+ for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
+ float loc[3];
+ float dist;
+
+ copy_v3_v3(loc, td->center);
+
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, loc);
+ }
+
+ dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(dist_closest))) {
+ copy_v3_v3(t->tsnap.snapTarget, loc);
+ closest = td;
+ dist_closest = dist;
+ }
+ }
+ }
+ }
+
+ TargetSnapOffset(t, closest);
+
+ t->tsnap.status |= TARGET_INIT;
+ }
}
bool snapObjectsTransform(
- TransInfo *t, const float mval[2],
- float *dist_px,
- float r_loc[3], float r_no[3])
+ TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
{
- return ED_transform_snap_object_project_view3d(
- t->tsnap.object_context,
- t->scene->toolsettings->snap_mode,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
- },
- mval, dist_px, r_loc, r_no);
+ return ED_transform_snap_object_project_view3d(
+ t->tsnap.object_context,
+ t->scene->toolsettings->snap_mode,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
+ },
+ mval,
+ dist_px,
+ r_loc,
+ r_no);
}
-
/******************** PEELING *********************************/
-bool peelObjectsSnapContext(
- SnapObjectContext *sctx,
- const float mval[2],
- const struct SnapObjectParams *params,
- const bool use_peel_object,
- /* return args */
- float r_loc[3], float r_no[3], float *r_thickness)
+bool peelObjectsSnapContext(SnapObjectContext *sctx,
+ const float mval[2],
+ const struct SnapObjectParams *params,
+ const bool use_peel_object,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ float *r_thickness)
{
- ListBase depths_peel = {0};
- ED_transform_snap_object_project_all_view3d_ex(
- sctx,
- params,
- mval, -1.0f, false,
- &depths_peel);
-
- if (!BLI_listbase_is_empty(&depths_peel)) {
- /* At the moment we only use the hits of the first object */
- struct SnapObjectHitDepth *hit_min = depths_peel.first;
- for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
- if (iter->depth < hit_min->depth) {
- hit_min = iter;
- }
- }
- struct SnapObjectHitDepth *hit_max = NULL;
-
- if (use_peel_object) {
- /* if peeling objects, take the first and last from each object */
- hit_max = hit_min;
- for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
- if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
- hit_max = iter;
- }
- }
- }
- else {
- /* otherwise, pair first with second and so on */
- for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
- if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
- if (hit_max == NULL) {
- hit_max = iter;
- }
- else if (iter->depth < hit_max->depth) {
- hit_max = iter;
- }
- }
- }
- /* in this case has only one hit. treat as raycast */
- if (hit_max == NULL) {
- hit_max = hit_min;
- }
- }
-
- mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
-
- if (r_thickness) {
- *r_thickness = hit_max->depth - hit_min->depth;
- }
-
- /* XXX, is there a correct normal in this case ???, for now just z up */
- r_no[0] = 0.0;
- r_no[1] = 0.0;
- r_no[2] = 1.0;
-
- BLI_freelistN(&depths_peel);
- return true;
- }
- return false;
+ ListBase depths_peel = {0};
+ ED_transform_snap_object_project_all_view3d_ex(sctx, params, mval, -1.0f, false, &depths_peel);
+
+ if (!BLI_listbase_is_empty(&depths_peel)) {
+ /* At the moment we only use the hits of the first object */
+ struct SnapObjectHitDepth *hit_min = depths_peel.first;
+ for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
+ if (iter->depth < hit_min->depth) {
+ hit_min = iter;
+ }
+ }
+ struct SnapObjectHitDepth *hit_max = NULL;
+
+ if (use_peel_object) {
+ /* if peeling objects, take the first and last from each object */
+ hit_max = hit_min;
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ hit_max = iter;
+ }
+ }
+ }
+ else {
+ /* otherwise, pair first with second and so on */
+ for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
+ if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
+ if (hit_max == NULL) {
+ hit_max = iter;
+ }
+ else if (iter->depth < hit_max->depth) {
+ hit_max = iter;
+ }
+ }
+ }
+ /* in this case has only one hit. treat as raycast */
+ if (hit_max == NULL) {
+ hit_max = hit_min;
+ }
+ }
+
+ mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
+
+ if (r_thickness) {
+ *r_thickness = hit_max->depth - hit_min->depth;
+ }
+
+ /* XXX, is there a correct normal in this case ???, for now just z up */
+ r_no[0] = 0.0;
+ r_no[1] = 0.0;
+ r_no[2] = 1.0;
+
+ BLI_freelistN(&depths_peel);
+ return true;
+ }
+ return false;
}
-bool peelObjectsTransform(
- TransInfo *t,
- const float mval[2],
- const bool use_peel_object,
- /* return args */
- float r_loc[3], float r_no[3], float *r_thickness)
+bool peelObjectsTransform(TransInfo *t,
+ const float mval[2],
+ const bool use_peel_object,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ float *r_thickness)
{
- return peelObjectsSnapContext(
- t->tsnap.object_context,
- mval,
- &(const struct SnapObjectParams){
- .snap_select = t->tsnap.modeSelect,
- .use_object_edit_cage = (t->flag & T_EDIT) != 0,
- },
- use_peel_object,
- r_loc, r_no, r_thickness);
+ return peelObjectsSnapContext(t->tsnap.object_context,
+ mval,
+ &(const struct SnapObjectParams){
+ .snap_select = t->tsnap.modeSelect,
+ .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ },
+ use_peel_object,
+ r_loc,
+ r_no,
+ r_thickness);
}
/******************** NODES ***********************************/
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapSelect snap_select)
{
- /* node is use for snapping only if a) snap mode matches and b) node is inside the view */
- return ((snap_select == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
- (snap_select == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
- (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
- node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
+ /* node is use for snapping only if a) snap mode matches and b) node is inside the view */
+ return ((snap_select == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
+ (snap_select == SNAP_ALL && !(node->flag & NODE_ACTIVE))) &&
+ (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin &&
+ node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin);
}
static NodeBorder snapNodeBorder(int snap_node_mode)
{
- NodeBorder flag = 0;
- if (snap_node_mode & SCE_SNAP_MODE_NODE_X) {
- flag |= NODE_LEFT | NODE_RIGHT;
- }
- if (snap_node_mode & SCE_SNAP_MODE_NODE_Y) {
- flag |= NODE_TOP | NODE_BOTTOM;
- }
- return flag;
+ NodeBorder flag = 0;
+ if (snap_node_mode & SCE_SNAP_MODE_NODE_X) {
+ flag |= NODE_LEFT | NODE_RIGHT;
+ }
+ if (snap_node_mode & SCE_SNAP_MODE_NODE_Y) {
+ flag |= NODE_TOP | NODE_BOTTOM;
+ }
+ return flag;
}
-static bool snapNode(
- ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
- float r_loc[2], float *r_dist_px, char *r_node_border)
+static bool snapNode(ToolSettings *ts,
+ SpaceNode *UNUSED(snode),
+ ARegion *ar,
+ bNode *node,
+ const int mval[2],
+ float r_loc[2],
+ float *r_dist_px,
+ char *r_node_border)
{
- View2D *v2d = &ar->v2d;
- NodeBorder border = snapNodeBorder(ts->snap_node_mode);
- bool retval = false;
- rcti totr;
- int new_dist;
-
- UI_view2d_view_to_region_rcti(v2d, &node->totr, &totr);
-
- if (border & NODE_LEFT) {
- new_dist = abs(totr.xmin - mval[0]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_LEFT;
- retval = true;
- }
- }
-
- if (border & NODE_RIGHT) {
- new_dist = abs(totr.xmax - mval[0]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_RIGHT;
- retval = true;
- }
- }
-
- if (border & NODE_BOTTOM) {
- new_dist = abs(totr.ymin - mval[1]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_BOTTOM;
- retval = true;
- }
- }
-
- if (border & NODE_TOP) {
- new_dist = abs(totr.ymax - mval[1]);
- if (new_dist < *r_dist_px) {
- UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
- *r_dist_px = new_dist;
- *r_node_border = NODE_TOP;
- retval = true;
- }
- }
-
- return retval;
+ View2D *v2d = &ar->v2d;
+ NodeBorder border = snapNodeBorder(ts->snap_node_mode);
+ bool retval = false;
+ rcti totr;
+ int new_dist;
+
+ UI_view2d_view_to_region_rcti(v2d, &node->totr, &totr);
+
+ if (border & NODE_LEFT) {
+ new_dist = abs(totr.xmin - mval[0]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_LEFT;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_RIGHT) {
+ new_dist = abs(totr.xmax - mval[0]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_RIGHT;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_BOTTOM) {
+ new_dist = abs(totr.ymin - mval[1]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_BOTTOM;
+ retval = true;
+ }
+ }
+
+ if (border & NODE_TOP) {
+ new_dist = abs(totr.ymax - mval[1]);
+ if (new_dist < *r_dist_px) {
+ UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
+ *r_dist_px = new_dist;
+ *r_node_border = NODE_TOP;
+ retval = true;
+ }
+ }
+
+ return retval;
}
-static bool snapNodes(
- ToolSettings *ts, SpaceNode *snode, ARegion *ar,
- const int mval[2], eSnapSelect snap_select,
- float r_loc[2], float *r_dist_px, char *r_node_border)
+static bool snapNodes(ToolSettings *ts,
+ SpaceNode *snode,
+ ARegion *ar,
+ const int mval[2],
+ eSnapSelect snap_select,
+ float r_loc[2],
+ float *r_dist_px,
+ char *r_node_border)
{
- bNodeTree *ntree = snode->edittree;
- bNode *node;
- bool retval = false;
+ bNodeTree *ntree = snode->edittree;
+ bNode *node;
+ bool retval = false;
- *r_node_border = 0;
+ *r_node_border = 0;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (snapNodeTest(&ar->v2d, node, snap_select)) {
- retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border);
- }
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (snapNodeTest(&ar->v2d, node, snap_select)) {
+ retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border);
+ }
+ }
- return retval;
+ return retval;
}
bool snapNodesTransform(
- TransInfo *t, const int mval[2],
- float r_loc[2], float *r_dist_px, char *r_node_border)
+ TransInfo *t, const int mval[2], float r_loc[2], float *r_dist_px, char *r_node_border)
{
- return snapNodes(
- t->settings, t->sa->spacedata.first, t->ar, mval, t->tsnap.modeSelect,
- r_loc, r_dist_px, r_node_border);
+ return snapNodes(t->settings,
+ t->sa->spacedata.first,
+ t->ar,
+ mval,
+ t->tsnap.modeSelect,
+ r_loc,
+ r_dist_px,
+ r_node_border);
}
/*================================================================*/
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action);
-
+static void applyGridIncrement(
+ TransInfo *t, float *val, int max_index, const float fac[3], GearsType action);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action)
{
- float fac[3];
+ float fac[3];
- fac[NO_GEARS] = t->snap[0];
- fac[BIG_GEARS] = t->snap[1];
- fac[SMALL_GEARS] = t->snap[2];
+ fac[NO_GEARS] = t->snap[0];
+ fac[BIG_GEARS] = t->snap[1];
+ fac[SMALL_GEARS] = t->snap[2];
- applyGridIncrement(t, val, t->idx_max, fac, action);
+ applyGridIncrement(t, val, t->idx_max, fac, action);
}
-
void snapGridIncrement(TransInfo *t, float *val)
{
- GearsType action;
+ GearsType action;
- /* only do something if using absolute or incremental grid snapping
- * and there is no valid snap point */
- if ((!(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) ||
- validSnap(t)) && !doForceIncrementSnap(t))
- {
- return;
- }
+ /* only do something if using absolute or incremental grid snapping
+ * and there is no valid snap point */
+ if ((!(t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) || validSnap(t)) &&
+ !doForceIncrementSnap(t)) {
+ return;
+ }
- action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
+ action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
- if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {
- action = SMALL_GEARS;
- }
+ if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {
+ action = SMALL_GEARS;
+ }
- snapGridIncrementAction(t, val, action);
+ snapGridIncrementAction(t, val, action);
}
void snapSequenceBounds(TransInfo *t, const int mval[2])
{
- float xmouse, ymouse;
- int frame;
- int mframe;
- TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
- /* reuse increment, strictly speaking could be another snap mode, but leave as is */
- if (!(t->modifiers & MOD_SNAP_INVERT))
- return;
-
- /* convert to frame range */
- UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
- mframe = round_fl_to_int(xmouse);
- /* now find the closest sequence */
- frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
-
- if (!ts->snap_left)
- frame = frame - (ts->max - ts->min);
-
- t->values[0] = frame - ts->min;
+ float xmouse, ymouse;
+ int frame;
+ int mframe;
+ TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data;
+ /* reuse increment, strictly speaking could be another snap mode, but leave as is */
+ if (!(t->modifiers & MOD_SNAP_INVERT))
+ return;
+
+ /* convert to frame range */
+ UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
+ mframe = round_fl_to_int(xmouse);
+ /* now find the closest sequence */
+ frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
+
+ if (!ts->snap_left)
+ frame = frame - (ts->max - ts->min);
+
+ t->values[0] = frame - ts->min;
}
-static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
+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;
-
- BLI_assert((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) || doForceIncrementSnap(t));
- BLI_assert(max_index <= 2);
-
- /* Early bailing out if no need to snap */
- if (fac[action] == 0.0f) {
- return;
- }
-
- if (use_aspect) {
- /* custom aspect for fcurve */
- if (t->spacetype == SPACE_GRAPH) {
- View2D *v2d = &t->ar->v2d;
- View2DGrid *grid;
- SpaceGraph *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);
-
- asp = asp_local;
- }
- }
-
- /* absolute snapping on grid based on global center */
- if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
- const float *center_global = t->center_global;
- bool use_local_axis = false;
-
- /* use a fallback for cursor selection,
- * this isn't useful as a global center for absolute grid snapping
- * since its not based on the position of the selection. */
- if (t->around == V3D_AROUND_CURSOR) {
- const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN);
- center_global = cd->global;
- }
-
- if (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
- use_local_axis = true;
- }
-
- 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];
-
- if (use_local_axis) {
- float local_axis[3];
- float pos_on_axis[3];
-
- copy_v3_v3(local_axis, t->con.mtx[i]);
- copy_v3_v3(pos_on_axis, t->con.mtx[i]);
-
- /* amount of movement on axis from initial pos */
- mul_v3_fl(pos_on_axis, val[i]);
-
- /* actual global position on axis */
- add_v3_v3(pos_on_axis, center_global);
-
- float min_dist = INFINITY;
- for (int j = 0; j < 3; j++) {
- if (fabs(local_axis[j]) < 0.01f) {
- /* Ignore very small (normalized) axis changes */
- continue;
- }
-
- /* closest point on grid */
- float grid_p = iter_fac * roundf(pos_on_axis[j] / iter_fac);
- float dist_p = fabs((grid_p - pos_on_axis[j]) / local_axis[j]);
-
- /* The amount of distance needed to travel along the
- * local axis to snap to the closest grid point */
- /* in the global j axis direction */
- float move_dist = (grid_p - center_global[j]) / local_axis[j];
-
- if (dist_p < min_dist) {
- min_dist = dist_p;
- val[i] = move_dist;
- }
- }
- }
- else {
- val[i] = iter_fac * roundf((val[i] + center_global[i]) / iter_fac) - 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);
- }
- }
+ 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;
+
+ BLI_assert((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) ||
+ doForceIncrementSnap(t));
+ BLI_assert(max_index <= 2);
+
+ /* Early bailing out if no need to snap */
+ if (fac[action] == 0.0f) {
+ return;
+ }
+
+ if (use_aspect) {
+ /* custom aspect for fcurve */
+ if (t->spacetype == SPACE_GRAPH) {
+ View2D *v2d = &t->ar->v2d;
+ View2DGrid *grid;
+ SpaceGraph *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);
+
+ asp = asp_local;
+ }
+ }
+
+ /* absolute snapping on grid based on global center */
+ if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
+ const float *center_global = t->center_global;
+ bool use_local_axis = false;
+
+ /* use a fallback for cursor selection,
+ * this isn't useful as a global center for absolute grid snapping
+ * since its not based on the position of the selection. */
+ if (t->around == V3D_AROUND_CURSOR) {
+ const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN);
+ center_global = cd->global;
+ }
+
+ if (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) {
+ use_local_axis = true;
+ }
+
+ 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];
+
+ if (use_local_axis) {
+ float local_axis[3];
+ float pos_on_axis[3];
+
+ copy_v3_v3(local_axis, t->con.mtx[i]);
+ copy_v3_v3(pos_on_axis, t->con.mtx[i]);
+
+ /* amount of movement on axis from initial pos */
+ mul_v3_fl(pos_on_axis, val[i]);
+
+ /* actual global position on axis */
+ add_v3_v3(pos_on_axis, center_global);
+
+ float min_dist = INFINITY;
+ for (int j = 0; j < 3; j++) {
+ if (fabs(local_axis[j]) < 0.01f) {
+ /* Ignore very small (normalized) axis changes */
+ continue;
+ }
+
+ /* closest point on grid */
+ float grid_p = iter_fac * roundf(pos_on_axis[j] / iter_fac);
+ float dist_p = fabs((grid_p - pos_on_axis[j]) / local_axis[j]);
+
+ /* The amount of distance needed to travel along the
+ * local axis to snap to the closest grid point */
+ /* in the global j axis direction */
+ float move_dist = (grid_p - center_global[j]) / local_axis[j];
+
+ if (dist_p < min_dist) {
+ min_dist = dist_p;
+ val[i] = move_dist;
+ }
+ }
+ }
+ else {
+ val[i] = iter_fac * roundf((val[i] + center_global[i]) / iter_fac) - 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);
+ }
+ }
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index f2692f57a35..93f89c1919e 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -45,7 +45,7 @@
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_anim.h" /* for duplis */
#include "BKE_editmesh.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@@ -70,78 +70,76 @@
#define MAX_CLIPPLANE_LEN 3
enum eViewProj {
- VIEW_PROJ_NONE = -1,
- VIEW_PROJ_ORTHO = 0,
- VIEW_PROJ_PERSP = -1,
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
};
typedef struct SnapData {
- short snap_to_flag;
- float mval[2];
- float pmat[4][4]; /* perspective matrix */
- float win_size[2];/* win x and y */
- enum eViewProj view_proj;
- float clip_plane[MAX_CLIPPLANE_LEN][4];
- short clip_plane_len;
+ short snap_to_flag;
+ float mval[2];
+ float pmat[4][4]; /* perspective matrix */
+ float win_size[2]; /* win x and y */
+ enum eViewProj view_proj;
+ float clip_plane[MAX_CLIPPLANE_LEN][4];
+ short clip_plane_len;
} SnapData;
typedef struct SnapObjectData {
- enum {
- SNAP_MESH = 1,
- SNAP_EDIT_MESH,
- } type;
+ enum {
+ SNAP_MESH = 1,
+ SNAP_EDIT_MESH,
+ } type;
} SnapObjectData;
typedef struct SnapObjectData_Mesh {
- SnapObjectData sd;
- BVHTreeFromMesh treedata;
- const struct MPoly *poly;
- BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
- uint has_looptris : 1;
- uint has_loose_edge : 1;
- uint has_loose_vert : 1;
+ SnapObjectData sd;
+ BVHTreeFromMesh treedata;
+ const struct MPoly *poly;
+ BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
+ uint has_looptris : 1;
+ uint has_loose_edge : 1;
+ uint has_loose_vert : 1;
} SnapObjectData_Mesh;
typedef struct SnapObjectData_EditMesh {
- SnapObjectData sd;
- BVHTreeFromEditMesh *bvh_trees[3];
- float min[3], max[3];
+ SnapObjectData sd;
+ BVHTreeFromEditMesh *bvh_trees[3];
+ float min[3], max[3];
} SnapObjectData_EditMesh;
struct SnapObjectContext {
- Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
-
- int flag;
-
- /* Optional: when performing screen-space projection.
- * otherwise this doesn't take viewport into account. */
- bool use_v3d;
- struct {
- const struct View3D *v3d;
- const struct ARegion *ar;
- } v3d_data;
-
-
- /* Object -> SnapObjectData map */
- struct {
- GHash *object_map;
- MemArena *mem_arena;
- } cache;
-
- /* Filter data, returns true to check this value */
- struct {
- struct {
- bool (*test_vert_fn)(BMVert *, void *user_data);
- bool (*test_edge_fn)(BMEdge *, void *user_data);
- bool (*test_face_fn)(BMFace *, void *user_data);
- void *user_data;
- } edit_mesh;
- } callbacks;
-
+ Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+
+ int flag;
+
+ /* Optional: when performing screen-space projection.
+ * otherwise this doesn't take viewport into account. */
+ bool use_v3d;
+ struct {
+ const struct View3D *v3d;
+ const struct ARegion *ar;
+ } v3d_data;
+
+ /* Object -> SnapObjectData map */
+ struct {
+ GHash *object_map;
+ MemArena *mem_arena;
+ } cache;
+
+ /* Filter data, returns true to check this value */
+ struct {
+ struct {
+ bool (*test_vert_fn)(BMVert *, void *user_data);
+ bool (*test_edge_fn)(BMEdge *, void *user_data);
+ bool (*test_face_fn)(BMFace *, void *user_data);
+ void *user_data;
+ } edit_mesh;
+ } callbacks;
};
/** \} */
@@ -155,51 +153,54 @@ struct SnapObjectContext {
*/
static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
{
- INIT_MINMAX(r_min, r_max);
- BMIter iter;
- BMVert *v;
+ INIT_MINMAX(r_min, r_max);
+ BMIter iter;
+ BMVert *v;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(r_min, r_max, v->co);
- }
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(r_min, r_max, v->co);
+ }
}
static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
- }
- else {
- SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
- /* start assuming that it has each of these element types */
- sod->has_looptris = true;
- sod->has_loose_edge = true;
- sod->has_loose_vert = true;
- }
-
- return *sod_p;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
+ }
+ else {
+ SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ /* start assuming that it has each of these element types */
+ sod->has_looptris = true;
+ sod->has_loose_edge = true;
+ sod->has_loose_vert = true;
+ }
+
+ return *sod_p;
}
/* Use `em->ob` as the key in ghash since the editmesh is used
* to create bvhtree and is the same for each linked object. */
-static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, BMEditMesh *em)
+static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
+ BMEditMesh *em)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
- }
- else {
- SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
- bm_mesh_minmax(em->bm, sod->min, sod->max);
- }
-
- return *sod_p;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
+ }
+ else {
+ SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
+ sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ bm_mesh_minmax(em->bm, sod->min, sod->max);
+ }
+
+ return *sod_p;
}
-typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+typedef void (*IterSnapObjsCallback)(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
/**
* Walks through all objects in the scene to create the list of objects to snap.
@@ -207,36 +208,35 @@ typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Obj
* \param sctx: Snap context to store data.
* \param snap_select: from enum #eSnapSelect.
*/
-static void iter_snap_objects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- IterSnapObjsCallback sob_callback,
- void *data)
+static void iter_snap_objects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ IterSnapObjsCallback sob_callback,
+ void *data)
{
- ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
- const View3D *v3d = sctx->v3d_data.v3d;
- const eSnapSelect snap_select = params->snap_select;
- const bool use_object_edit_cage = params->use_object_edit_cage;
-
- Base *base_act = view_layer->basact;
- for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
- !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
- (snap_select == SNAP_NOT_ACTIVE && base == base_act)))
- {
- Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
- if (obj_eval->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
- }
- free_object_duplilist(lb);
- }
-
- sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
- }
- }
+ ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
+ const View3D *v3d = sctx->v3d_data.v3d;
+ const eSnapSelect snap_select = params->snap_select;
+ const bool use_object_edit_cage = params->use_object_edit_cage;
+
+ Base *base_act = view_layer->basact;
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
+ !((snap_select == SNAP_NOT_SELECTED &&
+ ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
+ (snap_select == SNAP_NOT_ACTIVE && base == base_act))) {
+ Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
+ if (obj_eval->transflag & OB_DUPLI) {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
+ }
+ free_object_duplilist(lb);
+ }
+
+ sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
+ }
+ }
}
/** \} */
@@ -249,516 +249,567 @@ static void iter_snap_objects(
* Support for storing all depths, not just the first (raycast 'all') */
struct RayCastAll_Data {
- void *bvhdata;
+ void *bvhdata;
- /* internal vars for adding depths */
- BVHTree_RayCastCallback raycast_callback;
+ /* internal vars for adding depths */
+ BVHTree_RayCastCallback raycast_callback;
- const float(*obmat)[4];
- const float(*timat)[3];
+ const float (*obmat)[4];
+ const float (*timat)[3];
- float len_diff;
- float local_scale;
+ float len_diff;
+ float local_scale;
- Object *ob;
- unsigned int ob_uuid;
+ Object *ob;
+ unsigned int ob_uuid;
- /* output data */
- ListBase *hit_list;
- bool retval;
+ /* output data */
+ ListBase *hit_list;
+ bool retval;
};
-
-static struct SnapObjectHitDepth *hit_depth_create(
- const float depth, const float co[3], const float no[3], int index,
- Object *ob, const float obmat[4][4], unsigned int ob_uuid)
+static struct SnapObjectHitDepth *hit_depth_create(const float depth,
+ const float co[3],
+ const float no[3],
+ int index,
+ Object *ob,
+ const float obmat[4][4],
+ unsigned int ob_uuid)
{
- struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
+ struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
- hit->depth = depth;
- copy_v3_v3(hit->co, co);
- copy_v3_v3(hit->no, no);
- hit->index = index;
+ hit->depth = depth;
+ copy_v3_v3(hit->co, co);
+ copy_v3_v3(hit->no, no);
+ hit->index = index;
- hit->ob = ob;
- copy_m4_m4(hit->obmat, (float(*)[4])obmat);
- hit->ob_uuid = ob_uuid;
+ hit->ob = ob;
+ copy_m4_m4(hit->obmat, (float(*)[4])obmat);
+ hit->ob_uuid = ob_uuid;
- return hit;
+ return hit;
}
static int hit_depth_cmp(const void *arg1, const void *arg2)
{
- const struct SnapObjectHitDepth *h1 = arg1;
- const struct SnapObjectHitDepth *h2 = arg2;
- int val = 0;
-
- if (h1->depth < h2->depth) {
- val = -1;
- }
- else if (h1->depth > h2->depth) {
- val = 1;
- }
-
- return val;
+ const struct SnapObjectHitDepth *h1 = arg1;
+ const struct SnapObjectHitDepth *h2 = arg2;
+ int val = 0;
+
+ if (h1->depth < h2->depth) {
+ val = -1;
+ }
+ else if (h1->depth > h2->depth) {
+ val = 1;
+ }
+
+ return val;
}
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- struct RayCastAll_Data *data = userdata;
- data->raycast_callback(data->bvhdata, index, ray, hit);
- if (hit->index != -1) {
- /* get all values in worldspace */
- float location[3], normal[3];
- float depth;
-
- /* worldspace location */
- mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
- depth = (hit->dist + data->len_diff) / data->local_scale;
-
- /* worldspace normal */
- copy_v3_v3(normal, hit->no);
- mul_m3_v3((float(*)[3])data->timat, normal);
- normalize_v3(normal);
-
- struct SnapObjectHitDepth *hit_item = hit_depth_create(
- depth, location, normal, hit->index,
- data->ob, data->obmat, data->ob_uuid);
- BLI_addtail(data->hit_list, hit_item);
- }
+ struct RayCastAll_Data *data = userdata;
+ data->raycast_callback(data->bvhdata, index, ray, hit);
+ if (hit->index != -1) {
+ /* get all values in worldspace */
+ float location[3], normal[3];
+ float depth;
+
+ /* worldspace location */
+ mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
+ depth = (hit->dist + data->len_diff) / data->local_scale;
+
+ /* worldspace normal */
+ copy_v3_v3(normal, hit->no);
+ mul_m3_v3((float(*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ struct SnapObjectHitDepth *hit_item = hit_depth_create(
+ depth, location, normal, hit->index, data->ob, data->obmat, data->ob_uuid);
+ BLI_addtail(data->hit_list, hit_item);
+ }
}
-
-static bool raycastMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, Mesh *me, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- if (me->totpoly == 0) {
- return retval;
- }
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb) {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL))
- {
- return retval;
- }
- }
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- len_diff = 0.0f;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata = &sod->treedata;
-
- /* The tree is owned by the Mesh and may have been freed since we last used. */
- if (treedata->tree) {
- BLI_assert(treedata->cached);
- if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- else {
- /* Update Pointers. */
- if (treedata->vert && treedata->vert_allocated == false) {
- treedata->vert = me->mvert;
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop;
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
- }
- }
-
- if (treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
-
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
-
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- *r_index = treedata->looptri[hit.index].poly;
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+
+ if (me->totpoly == 0) {
+ return retval;
+ }
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb) {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) {
+ return retval;
+ }
+ }
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata = &sod->treedata;
+
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ if (treedata->tree) {
+ BLI_assert(treedata->cached);
+ if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ else {
+ /* Update Pointers. */
+ if (treedata->vert && treedata->vert_allocated == false) {
+ treedata->vert = me->mvert;
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop;
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (BLI_bvhtree_ray_cast(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ &hit,
+ treedata->raycast_callback,
+ treedata) != -1) {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = treedata->looptri[hit.index].poly;
+ }
+ }
+ }
+ }
+
+ return retval;
}
-static bool raycastEditMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastEditMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
- if (em->bm->totface == 0) {
- return retval;
- }
-
- BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
-
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL))
- {
- return retval;
- }
-
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- len_diff = 0.0f;
- }
-
- if (sod->bvh_trees[2] == NULL) {
- sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
- }
-
- BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
-
- BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
-
- if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
- free_bvhtree_from_editmesh(treedata);
- }
- }
-
- if (treedata->tree == NULL) {
- BVHCache **bvh_cache = NULL;
- BLI_bitmap *elem_mask = NULL;
- BMEditMesh *em_orig;
- int looptri_num_active = -1;
-
- /* Get original version of the edit_mesh. */
- em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- BMesh *bm = em_orig->bm;
- BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
-
- elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- bm, elem_mask,
- sctx->callbacks.edit_mesh.test_face_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- else {
- /* Only cache if bvhtree is created without a mask.
- * This helps keep a standardized bvhtree in cache. */
- bvh_cache = &em_bvh_cache;
- }
-
- bvhtree_from_editmesh_looptri_ex(
- treedata, em_orig, elem_mask, looptri_num_active,
- 0.0f, 4, 6, bvh_cache);
-
- if (elem_mask) {
- MEM_freeN(elem_mask);
- }
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- /* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+ if (em->bm->totface == 0) {
+ return retval;
+ }
+
+ BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) {
+ return retval;
+ }
+
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
+ }
+
+ BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
+
+ BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
+
+ if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
+ free_bvhtree_from_editmesh(treedata);
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BVHCache **bvh_cache = NULL;
+ BLI_bitmap *elem_mask = NULL;
+ BMEditMesh *em_orig;
+ int looptri_num_active = -1;
+
+ /* Get original version of the edit_mesh. */
+ em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ BMesh *bm = em_orig->bm;
+ BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
+
+ elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ bm,
+ elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ else {
+ /* Only cache if bvhtree is created without a mask.
+ * This helps keep a standardized bvhtree in cache. */
+ bvh_cache = &em_bvh_cache;
+ }
+
+ bvhtree_from_editmesh_looptri_ex(
+ treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, bvh_cache);
+
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
+ }
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (BLI_bvhtree_ray_cast(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ &hit,
+ treedata->raycast_callback,
+ treedata) != -1) {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ /* Get original version of the edit_mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
+ }
+ }
+ }
+ }
+
+ return retval;
}
-
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool raycastObj(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, bool use_occlusion_test,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObj(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ bool use_obedit,
+ bool use_occlusion_test,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- switch (ob->type) {
- case OB_MESH:
- {
- if (use_occlusion_test) {
- if (use_obedit && sctx->use_v3d &&
- XRAY_ENABLED(sctx->v3d_data.v3d))
- {
- /* Use of occlude geometry in editing mode disabled. */
- return false;
- }
-
- if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
- /* Do not hit objects that are in wire or bounding box
- * display mode. */
- return false;
- }
- }
-
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (use_obedit) {
- retval = raycastEditMesh(
- sctx,
- ray_start, ray_dir,
- ob, em, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- retval = raycastMesh(
- sctx,
- ray_start, ray_dir,
- ob, me, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return true;
- }
-
- return false;
+ bool retval = false;
+
+ switch (ob->type) {
+ case OB_MESH: {
+ if (use_occlusion_test) {
+ if (use_obedit && sctx->use_v3d && XRAY_ENABLED(sctx->v3d_data.v3d)) {
+ /* Use of occlude geometry in editing mode disabled. */
+ return false;
+ }
+
+ if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
+ /* Do not hit objects that are in wire or bounding box
+ * display mode. */
+ return false;
+ }
+ }
+
+ Mesh *me = ob->data;
+ if (BKE_object_is_in_editmode(ob)) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (use_obedit) {
+ retval = raycastEditMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ em,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ retval = raycastMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ me,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return true;
+ }
+
+ return false;
}
-
struct RaycastObjUserData {
- const float *ray_start;
- const float *ray_dir;
- unsigned int ob_index;
- /* read/write args */
- float *ray_depth;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- ListBase *r_hit_list;
- bool use_occlusion_test;
- bool ret;
+ const float *ray_start;
+ const float *ray_dir;
+ unsigned int ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool use_occlusion_test;
+ bool ret;
};
-static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
+static void raycast_obj_cb(
+ SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct RaycastObjUserData *dt = data;
-
- dt->ret |= raycastObj(
- sctx,
- dt->ray_start, dt->ray_dir,
- ob, obmat, dt->ob_index++,
- use_obedit, dt->use_occlusion_test,
- dt->ray_depth,
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat,
- dt->r_hit_list);
+ struct RaycastObjUserData *dt = data;
+
+ dt->ret |= raycastObj(sctx,
+ dt->ray_start,
+ dt->ray_dir,
+ ob,
+ obmat,
+ dt->ob_index++,
+ use_obedit,
+ dt->use_occlusion_test,
+ dt->ray_depth,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat,
+ dt->r_hit_list);
}
/**
@@ -788,202 +839,194 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob,
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-static bool raycastObjects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_dir[3],
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObjects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_dir[3],
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- struct RaycastObjUserData data = {
- .ray_start = ray_start,
- .ray_dir = ray_dir,
- .ob_index = 0,
- .ray_depth = ray_depth,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_index = r_index,
- .r_ob = r_ob,
- .r_obmat = r_obmat,
- .r_hit_list = r_hit_list,
- .use_occlusion_test = params->use_occlusion_test,
- .ret = false,
- };
-
- iter_snap_objects(sctx, params, raycast_obj_cb, &data);
-
- return data.ret;
+ struct RaycastObjUserData data = {
+ .ray_start = ray_start,
+ .ray_dir = ray_dir,
+ .ob_index = 0,
+ .ray_depth = ray_depth,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_index = r_index,
+ .r_ob = r_ob,
+ .r_obmat = r_obmat,
+ .r_hit_list = r_hit_list,
+ .use_occlusion_test = params->use_occlusion_test,
+ .ret = false,
+ };
+
+ iter_snap_objects(sctx, params, raycast_obj_cb, &data);
+
+ return data.ret;
}
-
/** \} */
/* -------------------------------------------------------------------- */
/** Snap Nearest utilities
* \{ */
- /* Test BoundBox */
-static bool snap_bound_box_check_dist(
- float min[3], float max[3], float lpmat[4][4],
- float win_size[2], float mval[2], float dist_px_sq)
+/* Test BoundBox */
+static bool snap_bound_box_check_dist(float min[3],
+ float max[3],
+ float lpmat[4][4],
+ float win_size[2],
+ float mval[2],
+ float dist_px_sq)
{
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- struct DistProjectedAABBPrecalc data_precalc;
- dist_squared_to_projected_aabb_precalc(
- &data_precalc, lpmat, win_size, mval);
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval);
- bool dummy[3];
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &data_precalc, min, max, dummy);
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(&data_precalc, min, max, dummy);
- if (bb_dist_px_sq > dist_px_sq) {
- return false;
- }
- return true;
+ if (bb_dist_px_sq > dist_px_sq) {
+ return false;
+ }
+ return true;
}
-static void cb_mvert_co_get(
- const int index, const float **co, const BVHTreeFromMesh *data)
+static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data)
{
- *co = data->vert[index].co;
+ *co = data->vert[index].co;
}
-static void cb_bvert_co_get(
- const int index, const float **co, const BMEditMesh *data)
+static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
- *co = eve->co;
+ BMVert *eve = BM_vert_at_index(data->bm, index);
+ *co = eve->co;
}
-static void cb_mvert_no_copy(
- const int index, float r_no[3], const BVHTreeFromMesh *data)
+static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
- const MVert *vert = data->vert + index;
+ const MVert *vert = data->vert + index;
- normal_short_to_float_v3(r_no, vert->no);
+ normal_short_to_float_v3(r_no, vert->no);
}
-static void cb_bvert_no_copy(
- const int index, float r_no[3], const BMEditMesh *data)
+static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
+ BMVert *eve = BM_vert_at_index(data->bm, index);
- copy_v3_v3(r_no, eve->no);
+ copy_v3_v3(r_no, eve->no);
}
-static void cb_medge_verts_get(
- const int index, int v_index[2], const BVHTreeFromMesh *data)
+static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data)
{
- const MEdge *edge = &data->edge[index];
-
- v_index[0] = edge->v1;
- v_index[1] = edge->v2;
+ const MEdge *edge = &data->edge[index];
+ v_index[0] = edge->v1;
+ v_index[1] = edge->v2;
}
-static void cb_bedge_verts_get(
- const int index, int v_index[2], const BMEditMesh *data)
+static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data)
{
- BMEdge *eed = BM_edge_at_index(data->bm, index);
+ BMEdge *eed = BM_edge_at_index(data->bm, index);
- v_index[0] = BM_elem_index_get(eed->v1);
- v_index[1] = BM_elem_index_get(eed->v2);
+ v_index[0] = BM_elem_index_get(eed->v1);
+ v_index[1] = BM_elem_index_get(eed->v2);
}
-static void cb_mlooptri_edges_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MEdge *medge = data->edge;
- const MLoop *mloop = data->loop;
- const MLoopTri *lt = &data->looptri[index];
- for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
- const MEdge *ed = &medge[mloop[lt->tri[j]].e];
- unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
- if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) &&
- ELEM(ed->v2, tri_edge[0], tri_edge[1]))
- {
- //printf("real edge found\n");
- v_index[j] = mloop[lt->tri[j]].e;
- }
- else
- v_index[j] = -1;
- }
+ const MEdge *medge = data->edge;
+ const MLoop *mloop = data->loop;
+ const MLoopTri *lt = &data->looptri[index];
+ for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
+ const MEdge *ed = &medge[mloop[lt->tri[j]].e];
+ unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
+ if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) {
+ //printf("real edge found\n");
+ v_index[j] = mloop[lt->tri[j]].e;
+ }
+ else
+ v_index[j] = -1;
+ }
}
-static void cb_mlooptri_verts_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MLoop *loop = data->loop;
- const MLoopTri *looptri = &data->looptri[index];
+ const MLoop *loop = data->loop;
+ const MLoopTri *looptri = &data->looptri[index];
- v_index[0] = loop[looptri->tri[0]].v;
- v_index[1] = loop[looptri->tri[1]].v;
- v_index[2] = loop[looptri->tri[2]].v;
+ v_index[0] = loop[looptri->tri[0]].v;
+ v_index[1] = loop[looptri->tri[1]].v;
+ v_index[2] = loop[looptri->tri[2]].v;
}
-static bool test_projected_vert_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float co[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_vert_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float co[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
- return false;
- }
-
- float co2d[2] = {
- (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
- (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
- };
-
- if (is_persp) {
- float w = mul_project_m4_v3_zfac(precalc->pmat, co);
- mul_v2_fl(co2d, 1.0f / w);
- }
-
- const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
- if (dist_sq < *dist_px_sq) {
- copy_v3_v3(r_co, co);
- *dist_px_sq = dist_sq;
- return true;
- }
- return false;
+ if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
+ return false;
+ }
+
+ float co2d[2] = {
+ (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
+ (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
+ };
+
+ if (is_persp) {
+ float w = mul_project_m4_v3_zfac(precalc->pmat, co);
+ mul_v2_fl(co2d, 1.0f / w);
+ }
+
+ const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
+ if (dist_sq < *dist_px_sq) {
+ copy_v3_v3(r_co, co);
+ *dist_px_sq = dist_sq;
+ return true;
+ }
+ return false;
}
-static bool test_projected_edge_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float va[3], const float vb[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_edge_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float va[3],
+ const float vb[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- float near_co[3], lambda;
- if (!isect_ray_seg_v3(
- precalc->ray_origin,
- precalc->ray_direction,
- va, vb, &lambda))
- {
- copy_v3_v3(near_co, va);
- }
- else {
- if (lambda <= 0.0f) {
- copy_v3_v3(near_co, va);
- }
- else if (lambda >= 1.0f) {
- copy_v3_v3(near_co, vb);
- }
- else {
- interp_v3_v3v3(near_co, va, vb, lambda);
- }
- }
-
- return test_projected_vert_dist(
- precalc, clip_plane, clip_plane_len,
- is_persp, near_co, dist_px_sq, r_co);
+ float near_co[3], lambda;
+ if (!isect_ray_seg_v3(precalc->ray_origin, precalc->ray_direction, va, vb, &lambda)) {
+ copy_v3_v3(near_co, va);
+ }
+ else {
+ if (lambda <= 0.0f) {
+ copy_v3_v3(near_co, va);
+ }
+ else if (lambda >= 1.0f) {
+ copy_v3_v3(near_co, vb);
+ }
+ else {
+ interp_v3_v3v3(near_co, va, vb, lambda);
+ }
+ }
+
+ return test_projected_vert_dist(
+ precalc, clip_plane, clip_plane_len, is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@@ -1000,132 +1043,128 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
typedef struct Nearest2dUserData {
- bool is_persp;
+ bool is_persp;
- void *userdata;
- Nearest2DGetVertCoCallback get_vert_co;
- Nearest2DGetEdgeVertsCallback get_edge_verts_index;
- Nearest2DGetTriVertsCallback get_tri_verts_index;
- Nearest2DGetTriEdgesCallback get_tri_edges_index;
- Nearest2DCopyVertNoCallback copy_vert_no;
+ void *userdata;
+ Nearest2DGetVertCoCallback get_vert_co;
+ Nearest2DGetEdgeVertsCallback get_edge_verts_index;
+ Nearest2DGetTriVertsCallback get_tri_verts_index;
+ Nearest2DGetTriEdgesCallback get_tri_edges_index;
+ Nearest2DCopyVertNoCallback copy_vert_no;
} Nearest2dUserData;
-
-static void cb_snap_vert(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_vert(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- const float *co;
- data->get_vert_co(index, &co, data->userdata);
-
- if (test_projected_vert_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp, co,
- &nearest->dist_sq,
- nearest->co))
- {
- data->copy_vert_no(index, nearest->no, data->userdata);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ const float *co;
+ data->get_vert_co(index, &co, data->userdata);
+
+ if (test_projected_vert_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ co,
+ &nearest->dist_sq,
+ nearest->co)) {
+ data->copy_vert_no(index, nearest->no, data->userdata);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- const float *v_pair[2];
- data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
- data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
-
- if (test_projected_edge_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp,
- v_pair[0], v_pair[1],
- &nearest->dist_sq,
- nearest->co))
- {
- sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ const float *v_pair[2];
+ data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
+ data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
+
+ if (test_projected_edge_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ v_pair[0],
+ v_pair[1],
+ &nearest->dist_sq,
+ nearest->co)) {
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- for (int i = 2; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ for (int i = 2; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
-static void cb_snap_tri_edges(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_edges(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int eindex[3];
- data->get_tri_edges_index(index, eindex, data->userdata);
- for (int i = 3; i--;) {
- if (eindex[i] != -1) {
- if (eindex[i] == nearest->index) {
- continue;
- }
- cb_snap_edge(
- userdata, eindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int eindex[3];
+ data->get_tri_edges_index(index, eindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (eindex[i] != -1) {
+ if (eindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_edge(userdata, eindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
+ }
}
-static void cb_snap_tri_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[3];
- data->get_tri_verts_index(index, vindex, data->userdata);
- for (int i = 3; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[3];
+ data->get_tri_verts_index(index, vindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
/** \} */
@@ -1134,1028 +1173,1124 @@ static void cb_snap_tri_verts(
/** \name Internal Object Snapping API
* \{ */
-static short snap_mesh_polygon(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_polygon(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = 0;
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(*dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- if (sod == NULL) {
- /* The object is in edit mode, and the key used
- * was the object referenced in BMEditMesh */
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
- }
-
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
-
- nearest2d.userdata = treedata;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
-
- const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
- const MLoop *ml = &treedata->loop[mp->loopstart];
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BLI_assert(treedata->edge != NULL);
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_edge(
- &nearest2d, ml->e, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_vert(
- &nearest2d, ml->v, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
-
- nearest2d.userdata = em;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- BMFace *f = BM_face_at_index(em->bm, *r_index);
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
- do {
- cb_snap_edge(
- &nearest2d, BM_elem_index_get(l_iter->e),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- do {
- cb_snap_vert(
- &nearest2d, BM_elem_index_get(l_iter->v),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- return elem;
- }
-
- return 0;
+ short elem = 0;
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(*dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ if (sod == NULL) {
+ /* The object is in edit mode, and the key used
+ * was the object referenced in BMEditMesh */
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
+ }
+
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
+
+ nearest2d.userdata = treedata;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
+
+ const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
+ const MLoop *ml = &treedata->loop[mp->loopstart];
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BLI_assert(treedata->edge != NULL);
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_edge(&nearest2d,
+ ml->e,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_vert(&nearest2d,
+ ml->v,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+
+ nearest2d.userdata = em;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ BMFace *f = BM_face_at_index(em->bm, *r_index);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
+ do {
+ cb_snap_edge(&nearest2d,
+ BM_elem_index_get(l_iter->e),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ do {
+ cb_snap_vert(&nearest2d,
+ BM_elem_index_get(l_iter->v),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ return elem;
+ }
+
+ return 0;
}
-
-static short snap_mesh_edge_verts_mixed(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], float original_dist_px,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ float original_dist_px,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = SCE_SNAP_MODE_EDGE;
-
- if (ob->type != OB_MESH) {
- return elem;
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(original_dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = BKE_editmesh_from_object(ob);
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
- }
-
- int vindex[2];
- nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
-
- const float *v_pair[2];
- nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
- nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
-
- float lambda;
- if (!isect_ray_seg_v3(
- neasrest_precalc.ray_origin,
- neasrest_precalc.ray_direction,
- v_pair[0], v_pair[1], &lambda))
- {
- /* do nothing */
- }
- else if (lambda < 0.25f || 0.75f < lambda) {
- int v_id = lambda < 0.5f ? 0 : 1;
-
- if (test_projected_vert_dist(
- &neasrest_precalc, NULL, 0,
- nearest2d.is_persp, v_pair[v_id],
- &nearest.dist_sq, nearest.co))
- {
- nearest.index = vindex[v_id];
- nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
- elem = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- }
-
- return elem;
+ short elem = SCE_SNAP_MODE_EDGE;
+
+ if (ob->type != OB_MESH) {
+ return elem;
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(original_dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ nearest2d.userdata = BKE_editmesh_from_object(ob);
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
+ }
+
+ int vindex[2];
+ nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
+
+ const float *v_pair[2];
+ nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
+ nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
+
+ float lambda;
+ if (!isect_ray_seg_v3(neasrest_precalc.ray_origin,
+ neasrest_precalc.ray_direction,
+ v_pair[0],
+ v_pair[1],
+ &lambda)) {
+ /* do nothing */
+ }
+ else if (lambda < 0.25f || 0.75f < lambda) {
+ int v_id = lambda < 0.5f ? 0 : 1;
+
+ if (test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ v_pair[v_id],
+ &nearest.dist_sq,
+ nearest.co)) {
+ nearest.index = vindex[v_id];
+ nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
+ elem = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ }
+
+ return elem;
}
-static short snapArmature(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapArmature(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
- return retval;
- }
-
- float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return retval;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- bArmature *arm = ob->data;
- if (arm->edbo) {
- for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->layer & arm->layer) {
- /* skip hidden or moving (selected) bones */
- if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- bool has_vert_snap = false;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->tail, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, eBone->tail,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
- }
- else if (ob->pose && ob->pose->chanbase.first) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- /* skip hidden bones */
- if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
- bool has_vert_snap = false;
- const float *head_vec = pchan->pose_head;
- const float *tail_vec = pchan->pose_tail;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, tail_vec, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, tail_vec,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
+ return retval;
+ }
+
+ float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_armature_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return retval;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ bArmature *arm = ob->data;
+ if (arm->edbo) {
+ for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ if (eBone->layer & arm->layer) {
+ /* skip hidden or moving (selected) bones */
+ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
+ bool has_vert_snap = false;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (ob->pose && ob->pose->chanbase.first) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ /* skip hidden bones */
+ if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
+ bool has_vert_snap = false;
+ const float *head_vec = pchan->pose_head;
+ const float *tail_vec = pchan->pose_tail;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ tail_vec,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ tail_vec,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCurve(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCurve(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- bool has_snap = false;
-
- /* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
- return 0;
- }
-
- Curve *cu = ob->data;
- float dist_px_sq = SQUARE(*dist_px);
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
- for (int u = 0; u < nu->pntsu; u++) {
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (use_obedit) {
- if (nu->bezt) {
- /* don't snap to selected (moving) or hidden */
- if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
- if (!(nu->bezt[u].f1 & SELECT) &&
- !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[0], &dist_px_sq,
- r_loc);
- }
- if (!(nu->bezt[u].f3 & SELECT) &&
- !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[2], &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* don't snap to selected (moving) or hidden */
- if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* curve is not visible outside editmode if nurb length less than two */
- if (nu->pntsu > 1) {
- if (nu->bezt) {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- }
- else {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- }
- }
- }
- }
- if (has_snap) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index yet. */
- *r_index = -1;
- }
- return SCE_SNAP_MODE_VERTEX;
- }
-
- return 0;
+ bool has_snap = false;
+
+ /* only vertex snapping mode (eg control points and handles) supported for now) */
+ if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
+ return 0;
+ }
+
+ Curve *cu = ob->data;
+ float dist_px_sq = SQUARE(*dist_px);
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (int u = 0; u < nu->pntsu; u++) {
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (use_obedit) {
+ if (nu->bezt) {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
+ if (!(nu->bezt[u].f1 & SELECT) &&
+ !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[0],
+ &dist_px_sq,
+ r_loc);
+ }
+ if (!(nu->bezt[u].f3 & SELECT) &&
+ !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[2],
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* curve is not visible outside editmode if nurb length less than two */
+ if (nu->pntsu > 1) {
+ if (nu->bezt) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ }
+ else {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (has_snap) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index yet. */
+ *r_index = -1;
+ }
+ return SCE_SNAP_MODE_VERTEX;
+ }
+
+ return 0;
}
/* may extend later (for now just snaps to empty center) */
-static short snapEmpty(
- SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapEmpty(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (ob->transflag & OB_DUPLI) {
- return retval;
- }
-
- /* for now only vertex supported */
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
- float co[3];
- copy_v3_v3(co, obmat[3]);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, co, &dist_px_sq, r_loc))
- {
- *dist_px = sqrtf(dist_px_sq);
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (retval) {
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (ob->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ /* for now only vertex supported */
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
+ float co[3];
+ copy_v3_v3(co, obmat[3]);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ co,
+ &dist_px_sq,
+ r_loc)) {
+ *dist_px = sqrtf(dist_px_sq);
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (retval) {
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCamera(
- const SnapObjectContext *sctx, SnapData *snapdata,
- Object *object, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCamera(const SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *object,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- Scene *scene = sctx->scene;
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
-
- float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
- MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
- MovieTracking *tracking;
-
- if (clip == NULL) {
- return retval;
- }
- if (object->transflag & OB_DUPLI) {
- return retval;
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- tracking = &clip->tracking;
-
- BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
-
- invert_m4_m4(orig_camera_imat, orig_camera_mat);
- invert_m4_m4(imat, obmat);
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- MovieTrackingObject *tracking_object;
- for (tracking_object = tracking->objects.first;
- tracking_object;
- tracking_object = tracking_object->next)
- {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- MovieTrackingTrack *track;
- float reconstructed_camera_mat[4][4],
- reconstructed_camera_imat[4][4];
- float (*vertex_obmat)[4];
-
- if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
- CFRA, reconstructed_camera_mat);
-
- invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
- }
-
- for (track = tracksbase->first; track; track = track->next) {
- float bundle_pos[3];
-
- if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
- continue;
- }
-
- copy_v3_v3(bundle_pos, track->bundle_pos);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- vertex_obmat = orig_camera_mat;
- }
- else {
- mul_m4_v3(reconstructed_camera_imat, bundle_pos);
- vertex_obmat = obmat;
- }
-
- mul_m4_v3(vertex_obmat, bundle_pos);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, bundle_pos, &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ Scene *scene = sctx->scene;
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
+
+ float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
+ MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
+ MovieTracking *tracking;
+
+ if (clip == NULL) {
+ return retval;
+ }
+ if (object->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ tracking = &clip->tracking;
+
+ BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+
+ invert_m4_m4(orig_camera_imat, orig_camera_mat);
+ invert_m4_m4(imat, obmat);
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ MovieTrackingObject *tracking_object;
+ for (tracking_object = tracking->objects.first; tracking_object;
+ tracking_object = tracking_object->next) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track;
+ float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
+ float(*vertex_obmat)[4];
+
+ if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ BKE_tracking_camera_get_reconstructed_interpolate(
+ tracking, tracking_object, CFRA, reconstructed_camera_mat);
+
+ invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
+ }
+
+ for (track = tracksbase->first; track; track = track->next) {
+ float bundle_pos[3];
+
+ if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
+ continue;
+ }
+
+ copy_v3_v3(bundle_pos, track->bundle_pos);
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ vertex_obmat = orig_camera_mat;
+ }
+ else {
+ mul_m4_v3(reconstructed_camera_imat, bundle_pos);
+ vertex_obmat = obmat;
+ }
+
+ mul_m4_v3(vertex_obmat, bundle_pos);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ bundle_pos,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, Mesh *me, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (me->totedge == 0) {
- return 0;
- }
- }
- else {
- if (me->totvert == 0) {
- return 0;
- }
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- float dist_px_sq = SQUARE(*dist_px);
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat, snapdata->win_size,
- snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata, dummy_treedata;
- BVHTree **bvhtree;
- treedata = &sod->treedata;
- bvhtree = sod->bvhtree;
-
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if ((sod->has_looptris && treedata->tree && !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
- (sod->has_loose_edge && bvhtree[0] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
- (sod->has_loose_vert && bvhtree[1] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])))
- {
- BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
- BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
- BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
-
- free_bvhtree_from_mesh(treedata);
- bvhtree[0] = NULL;
- bvhtree[1] = NULL;
- }
-
- if (sod->has_looptris && treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
- sod->has_looptris = (treedata->tree != NULL);
- if (sod->has_looptris) {
- /* Make sure that the array of edges is referenced in the callbacks. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- }
- if (sod->has_loose_edge && bvhtree[0] == NULL) {
- bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
- sod->has_loose_edge = bvhtree[0] != NULL;
-
- if (sod->has_loose_edge) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
-
- BLI_assert(treedata->edge_allocated == false);
- treedata->edge = dummy_treedata.edge;
- treedata->edge_allocated = dummy_treedata.edge_allocated;
- }
- }
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->has_loose_vert && bvhtree[1] == NULL) {
- bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
- sod->has_loose_vert = bvhtree[1] != NULL;
-
- if (sod->has_loose_vert) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
- }
- }
- }
- else {
- /* Not necessary, just to keep the data more consistent. */
- sod->has_loose_vert = false;
- }
-
- /* Update pointers. */
- if (treedata->vert_allocated == false) {
- treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
- }
- if (treedata->tree || bvhtree[0]) {
- if (treedata->edge_allocated == false) {
- /* If raycast has been executed before, `treedata->edge` can be NULL. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = treedata,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
- .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
- .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
- /* snap to loose verts */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_edges, &nearest2d);
- }
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
- else {
- BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge_verts, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_verts, &nearest2d);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (me->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (me->totvert == 0) {
+ return 0;
+ }
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ float dist_px_sq = SQUARE(*dist_px);
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata, dummy_treedata;
+ BVHTree **bvhtree;
+ treedata = &sod->treedata;
+ bvhtree = sod->bvhtree;
+
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if ((sod->has_looptris && treedata->tree &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
+ (sod->has_loose_edge && bvhtree[0] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
+ (sod->has_loose_vert && bvhtree[1] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) {
+ BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
+ BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
+ BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
+
+ free_bvhtree_from_mesh(treedata);
+ bvhtree[0] = NULL;
+ bvhtree[1] = NULL;
+ }
+
+ if (sod->has_looptris && treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+ sod->has_looptris = (treedata->tree != NULL);
+ if (sod->has_looptris) {
+ /* Make sure that the array of edges is referenced in the callbacks. */
+ treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
+ }
+ }
+ if (sod->has_loose_edge && bvhtree[0] == NULL) {
+ bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
+ sod->has_loose_edge = bvhtree[0] != NULL;
+
+ if (sod->has_loose_edge) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+
+ BLI_assert(treedata->edge_allocated == false);
+ treedata->edge = dummy_treedata.edge;
+ treedata->edge_allocated = dummy_treedata.edge_allocated;
+ }
+ }
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (sod->has_loose_vert && bvhtree[1] == NULL) {
+ bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
+ sod->has_loose_vert = bvhtree[1] != NULL;
+
+ if (sod->has_loose_vert) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+ }
+ }
+ }
+ else {
+ /* Not necessary, just to keep the data more consistent. */
+ sod->has_loose_vert = false;
+ }
+
+ /* Update pointers. */
+ if (treedata->vert_allocated == false) {
+ treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
+ }
+ if (treedata->tree || bvhtree[0]) {
+ if (treedata->edge_allocated == false) {
+ /* If raycast has been executed before, `treedata->edge` can be NULL. */
+ treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = treedata,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
+ .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
+ .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ /* snap to loose verts */
+ BLI_bvhtree_find_nearest_projected(bvhtree[1],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (bvhtree[0]) {
+ /* snap to loose edges */
+ BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_edges,
+ &nearest2d);
+ }
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ else {
+ BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
+ if (bvhtree[0]) {
+ /* snap to loose edges */
+ BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge_verts,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_verts,
+ &nearest2d);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
-static short snapEditMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, BMEditMesh *em, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapEditMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (em->bm->totedge == 0) {
- return 0;
- }
- }
- else {
- if (em->bm->totvert == 0) {
- return 0;
- }
- }
-
- BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
-
- BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
- UNUSED_VARS_NDEBUG(ob);
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- float dist_px_sq = SQUARE(*dist_px);
-
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!snap_bound_box_check_dist(
- sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->bvh_trees[0] == NULL) {
- sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_vert = sod->bvh_trees[0];
-
- if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
- free_bvhtree_from_editmesh(treedata_vert);
- }
- }
-
- if (treedata_vert->tree == NULL) {
- BLI_bitmap *verts_mask = NULL;
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, verts_mask,
- (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
-
- bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- MEM_freeN(verts_mask);
- }
- else {
- bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (sod->bvh_trees[1] == NULL) {
- sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_edge = sod->bvh_trees[1];
-
- if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
- free_bvhtree_from_editmesh(treedata_edge);
- }
- }
-
- if (treedata_edge->tree == NULL) {
- BLI_bitmap *edges_mask = NULL;
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, edges_mask,
- (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
-
- bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- MEM_freeN(edges_mask);
- }
- else {
- bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = em,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
-
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_vert->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_edge->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (em->bm->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (em->bm->totvert == 0) {
+ return 0;
+ }
+ }
+
+ BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
+
+ BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
+ UNUSED_VARS_NDEBUG(ob);
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ float dist_px_sq = SQUARE(*dist_px);
+
+ SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!snap_bound_box_check_dist(
+ sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (sod->bvh_trees[0] == NULL) {
+ sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
+ }
+ treedata_vert = sod->bvh_trees[0];
+
+ if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
+ free_bvhtree_from_editmesh(treedata_vert);
+ }
+ }
+
+ if (treedata_vert->tree == NULL) {
+ BLI_bitmap *verts_mask = NULL;
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH,
+ em->bm,
+ verts_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_verts_ex(
+ treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ MEM_freeN(verts_mask);
+ }
+ else {
+ bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (sod->bvh_trees[1] == NULL) {
+ sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
+ }
+ treedata_edge = sod->bvh_trees[1];
+
+ if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
+ free_bvhtree_from_editmesh(treedata_edge);
+ }
+ }
+
+ if (treedata_edge->tree == NULL) {
+ BLI_bitmap *edges_mask = NULL;
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH,
+ em->bm,
+ edges_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_edges_ex(
+ treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
+ MEM_freeN(edges_mask);
+ }
+ else {
+ bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = em,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
/**
@@ -2163,127 +2298,112 @@ static short snapEditMesh(
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static short snapObject(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObject(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- short retval = 0;
-
- switch (ob->type) {
- case OB_MESH:
- {
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (use_obedit) {
- retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- else if (ob->dt == OB_BOUNDBOX) {
- /* Do not snap to objects that are in bounding box display mode */
- return 0;
- }
-
- retval = snapMesh(
- sctx, snapdata, ob, me, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- case OB_ARMATURE:
- retval = snapArmature(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_CURVE:
- retval = snapCurve(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_EMPTY:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_GPENCIL:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_CAMERA:
- retval = snapCamera(
- sctx, snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ switch (ob->type) {
+ case OB_MESH: {
+ Mesh *me = ob->data;
+ if (BKE_object_is_in_editmode(ob)) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (use_obedit) {
+ retval = snapEditMesh(sctx, snapdata, ob, em, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ else if (ob->dt == OB_BOUNDBOX) {
+ /* Do not snap to objects that are in bounding box display mode */
+ return 0;
+ }
+
+ retval = snapMesh(sctx, snapdata, ob, me, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ case OB_ARMATURE:
+ retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_CURVE:
+ retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_EMPTY:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_GPENCIL:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_CAMERA:
+ retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return retval;
+ }
+
+ return 0;
}
-
struct SnapObjUserData {
- SnapData *snapdata;
- /* read/write args */
- float *dist_px;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- short ret;
+ SnapData *snapdata;
+ /* read/write args */
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ short ret;
};
-static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+static void sanp_obj_cb(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct SnapObjUserData *dt = data;
-
- short elem = snapObject(
- sctx, dt->snapdata,
- ob, obmat, is_obedit,
- /* read/write args */
- dt->dist_px,
- /* return args */
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat);
-
- if (elem) {
- dt->ret = elem;
- }
+ struct SnapObjUserData *dt = data;
+
+ short elem = snapObject(sctx,
+ dt->snapdata,
+ ob,
+ obmat,
+ is_obedit,
+ /* read/write args */
+ dt->dist_px,
+ /* return args */
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat);
+
+ if (elem) {
+ dt->ret = elem;
+ }
}
-
/**
* Main Snapping Function
* ======================
@@ -2309,29 +2429,32 @@ static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, flo
* \param r_ob: Hit object.
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
*/
-static short snapObjectsRay(
- SnapObjectContext *sctx, SnapData *snapdata,
- const struct SnapObjectParams *params,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObjectsRay(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ const struct SnapObjectParams *params,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- struct SnapObjUserData data = {
- .snapdata = snapdata,
- .dist_px = dist_px,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_ob = r_ob,
- .r_index = r_index,
- .r_obmat = r_obmat,
- .ret = 0,
- };
-
- iter_snap_objects(sctx, params, sanp_obj_cb, &data);
-
- return data.ret;
+ struct SnapObjUserData data = {
+ .snapdata = snapdata,
+ .dist_px = dist_px,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_ob = r_ob,
+ .r_index = r_index,
+ .r_obmat = r_obmat,
+ .ret = 0,
+ };
+
+ iter_snap_objects(sctx, params, sanp_obj_cb, &data);
+
+ return data.ret;
}
/** \} */
@@ -2340,95 +2463,99 @@ static short snapObjectsRay(
/** \name Public Object Snapping API
* \{ */
-SnapObjectContext *ED_transform_snap_object_context_create(
- Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag)
+SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain,
+ Scene *scene,
+ Depsgraph *depsgraph,
+ int flag)
{
- SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
+ SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
- sctx->flag = flag;
+ sctx->flag = flag;
- sctx->bmain = bmain;
- sctx->scene = scene;
- sctx->depsgraph = depsgraph;
+ sctx->bmain = bmain;
+ sctx->scene = scene;
+ sctx->depsgraph = depsgraph;
- sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
- sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
+ sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- return sctx;
+ return sctx;
}
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag,
- /* extra args for view3d */
- const ARegion *ar, const View3D *v3d)
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
+ Scene *scene,
+ Depsgraph *depsgraph,
+ int flag,
+ /* extra args for view3d */
+ const ARegion *ar,
+ const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag);
- sctx->use_v3d = true;
- sctx->v3d_data.ar = ar;
- sctx->v3d_data.v3d = v3d;
+ sctx->use_v3d = true;
+ sctx->v3d_data.ar = ar;
+ sctx->v3d_data.v3d = v3d;
- return sctx;
+ return sctx;
}
static void snap_object_data_free(void *sod_v)
{
- switch (((SnapObjectData *)sod_v)->type) {
- case SNAP_MESH:
- {
- SnapObjectData_Mesh *sod = sod_v;
- if (sod->treedata.tree) {
- free_bvhtree_from_mesh(&sod->treedata);
- }
- break;
- }
- case SNAP_EDIT_MESH:
- {
- SnapObjectData_EditMesh *sod = sod_v;
- for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
- if (sod->bvh_trees[i]) {
- free_bvhtree_from_editmesh(sod->bvh_trees[i]);
- }
- }
- break;
- }
- }
+ switch (((SnapObjectData *)sod_v)->type) {
+ case SNAP_MESH: {
+ SnapObjectData_Mesh *sod = sod_v;
+ if (sod->treedata.tree) {
+ free_bvhtree_from_mesh(&sod->treedata);
+ }
+ break;
+ }
+ case SNAP_EDIT_MESH: {
+ SnapObjectData_EditMesh *sod = sod_v;
+ for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
+ if (sod->bvh_trees[i]) {
+ free_bvhtree_from_editmesh(sod->bvh_trees[i]);
+ }
+ }
+ break;
+ }
+ }
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- BLI_memarena_free(sctx->cache.mem_arena);
+ BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_memarena_free(sctx->cache.mem_arena);
- MEM_freeN(sctx);
+ MEM_freeN(sctx);
}
void ED_transform_snap_object_context_set_editmesh_callbacks(
- SnapObjectContext *sctx,
- bool (*test_vert_fn)(BMVert *, void *user_data),
- bool (*test_edge_fn)(BMEdge *, void *user_data),
- bool (*test_face_fn)(BMFace *, void *user_data),
- void *user_data)
+ SnapObjectContext *sctx,
+ bool (*test_vert_fn)(BMVert *, void *user_data),
+ bool (*test_edge_fn)(BMEdge *, void *user_data),
+ bool (*test_face_fn)(BMFace *, void *user_data),
+ void *user_data)
{
- sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
- sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
- sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
+ sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
+ sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
+ sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
- sctx->callbacks.edit_mesh.user_data = user_data;
+ sctx->callbacks.edit_mesh.user_data = user_data;
}
-bool ED_transform_snap_object_project_ray_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- return raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ return raycastObjects(
+ sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
/**
@@ -2438,37 +2565,35 @@ bool ED_transform_snap_object_project_ray_ex(
* \param sort: Optionally sort the hits by depth.
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-bool ED_transform_snap_object_project_ray_all(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- if (ray_depth == -1.0f) {
- ray_depth = BVH_RAYCAST_DIST_MAX;
- }
+ if (ray_depth == -1.0f) {
+ ray_depth = BVH_RAYCAST_DIST_MAX;
+ }
#ifdef DEBUG
- float ray_depth_prev = ray_depth;
+ float ray_depth_prev = ray_depth;
#endif
- bool retval = raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- &ray_depth, NULL, NULL, NULL, NULL, NULL,
- r_hit_list);
+ bool retval = raycastObjects(
+ sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list);
- /* meant to be readonly for 'all' hits, ensure it is */
+ /* meant to be readonly for 'all' hits, ensure it is */
#ifdef DEBUG
- BLI_assert(ray_depth_prev == ray_depth);
+ BLI_assert(ray_depth_prev == ray_depth);
#endif
- if (sort) {
- BLI_listbase_sort(r_hit_list, hit_depth_cmp);
- }
+ if (sort) {
+ BLI_listbase_sort(r_hit_list, hit_depth_cmp);
+ }
- return retval;
+ return retval;
}
/**
@@ -2478,196 +2603,183 @@ bool ED_transform_snap_object_project_ray_all(
*
* \return Snap success
*/
-static bool transform_snap_context_project_ray_impl(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3], float *ray_depth,
- float r_co[3], float r_no[3])
+static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- bool ret;
+ bool ret;
- /* try snap edge, then face if it fails */
- ret = ED_transform_snap_object_project_ray_ex(
- sctx,
- params,
- ray_start, ray_normal, ray_depth,
- r_co, r_no, NULL,
- NULL, NULL);
+ /* try snap edge, then face if it fails */
+ ret = ED_transform_snap_object_project_ray_ex(
+ sctx, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, NULL, NULL);
- return ret;
+ return ret;
}
-bool ED_transform_snap_object_project_ray(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_origin[3], const float ray_direction[3], float *ray_depth,
- float r_co[3], float r_no[3])
+bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_origin[3],
+ const float ray_direction[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
-
- return transform_snap_context_project_ray_impl(
- sctx,
- params,
- ray_origin, ray_direction, ray_depth,
- r_co, r_no);
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
+ }
+
+ return transform_snap_context_project_ray_impl(
+ sctx, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
}
static short transform_snap_context_project_view3d_mixed_impl(
- SnapObjectContext *sctx,
- const unsigned short snap_to_flag,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+ SnapObjectContext *sctx,
+ const unsigned short snap_to_flag,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- BLI_assert(
- (snap_to_flag & (
- SCE_SNAP_MODE_VERTEX |
- SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE)) != 0);
-
- short retval = 0;
- bool has_hit = false;
- int index = -1;
-
- float loc[3], no[3], obmat[4][4];
- Object *ob = NULL;
-
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->regiondata;
-
- bool use_occlusion_test =
- params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
-
- if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
- float ray_start[3], ray_normal[3];
-
- if (!ED_view3d_win_to_ray_clipped_ex(
- sctx->depsgraph,
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
-
- has_hit = raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- &dummy_ray_depth, loc, no,
- &index, &ob, obmat, NULL);
-
- if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
- retval = SCE_SNAP_MODE_FACE;
- }
- }
-
- if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
- short elem;
- float dist_px_tmp = *dist_px;
-
- SnapData snapdata;
- copy_m4_m4(snapdata.pmat, rv3d->persmat);
- snapdata.win_size[0] = ar->winx;
- snapdata.win_size[1] = ar->winy;
- copy_v2_v2(snapdata.mval, mval);
- snapdata.snap_to_flag = snap_to_flag;
- snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
-
- planes_from_projmat(
- snapdata.pmat,
- NULL, NULL, NULL, NULL,
- snapdata.clip_plane[0], snapdata.clip_plane[1]);
-
- snapdata.clip_plane_len = 2;
-
- if (has_hit) {
- /* Compute the new clip_pane but do not add it yet. */
- float new_clipplane[4];
- plane_from_point_normal_v3(new_clipplane, loc, no);
- if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
- /* The plane is facing the wrong direction. */
- negate_v4(new_clipplane);
- }
-
- /* Small offset to simulate a kind of volume for edges and vertices. */
- new_clipplane[3] += 0.01f;
-
- /* Try to snap only to the polygon. */
- elem = snap_mesh_polygon(
- sctx, &snapdata, ob, obmat,
- &dist_px_tmp, loc, no, &index);
-
- if (elem) {
- retval = elem;
- }
-
- /* Add the new clip plane to the beginning of the list. */
- for (int i = snapdata.clip_plane_len; i != 0; i--) {
- copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
- }
- copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
- snapdata.clip_plane_len++;
- }
-
- elem = snapObjectsRay(
- sctx, &snapdata, params,
- &dist_px_tmp, loc, no, &index, &ob, obmat);
-
- if (elem) {
- retval = elem;
- }
-
- if ((retval == SCE_SNAP_MODE_EDGE) &&
- (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX))
- {
- retval = snap_mesh_edge_verts_mixed(
- sctx, &snapdata,
- ob, obmat, *dist_px,
- &dist_px_tmp, loc, no, &index);
- }
-
- *dist_px = dist_px_tmp;
- }
-
- if (retval) {
- copy_v3_v3(r_loc, loc);
- if (r_no) {
- copy_v3_v3(r_no, no);
- }
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- if (r_index) {
- *r_index = index;
- }
- return retval;
- }
-
- return 0;
+ BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) !=
+ 0);
+
+ short retval = 0;
+ bool has_hit = false;
+ int index = -1;
+
+ float loc[3], no[3], obmat[4][4];
+ Object *ob = NULL;
+
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
+
+ bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
+
+ if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
+ sctx->v3d_data.ar,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
+
+ has_hit = raycastObjects(
+ sctx, params, ray_start, ray_normal, &dummy_ray_depth, loc, no, &index, &ob, obmat, NULL);
+
+ if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
+ retval = SCE_SNAP_MODE_FACE;
+ }
+ }
+
+ if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
+ short elem;
+ float dist_px_tmp = *dist_px;
+
+ SnapData snapdata;
+ copy_m4_m4(snapdata.pmat, rv3d->persmat);
+ snapdata.win_size[0] = ar->winx;
+ snapdata.win_size[1] = ar->winy;
+ copy_v2_v2(snapdata.mval, mval);
+ snapdata.snap_to_flag = snap_to_flag;
+ snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+
+ planes_from_projmat(
+ snapdata.pmat, NULL, NULL, NULL, NULL, snapdata.clip_plane[0], snapdata.clip_plane[1]);
+
+ snapdata.clip_plane_len = 2;
+
+ if (has_hit) {
+ /* Compute the new clip_pane but do not add it yet. */
+ float new_clipplane[4];
+ plane_from_point_normal_v3(new_clipplane, loc, no);
+ if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
+ /* The plane is facing the wrong direction. */
+ negate_v4(new_clipplane);
+ }
+
+ /* Small offset to simulate a kind of volume for edges and vertices. */
+ new_clipplane[3] += 0.01f;
+
+ /* Try to snap only to the polygon. */
+ elem = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ /* Add the new clip plane to the beginning of the list. */
+ for (int i = snapdata.clip_plane_len; i != 0; i--) {
+ copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
+ }
+ copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
+ snapdata.clip_plane_len++;
+ }
+
+ elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ if ((retval == SCE_SNAP_MODE_EDGE) && (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ retval = snap_mesh_edge_verts_mixed(
+ sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index);
+ }
+
+ *dist_px = dist_px_tmp;
+ }
+
+ if (retval) {
+ copy_v3_v3(r_loc, loc);
+ if (r_no) {
+ copy_v3_v3(r_no, no);
+ }
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ if (r_index) {
+ *r_index = index;
+ }
+ return retval;
+ }
+
+ return 0;
}
-bool ED_transform_snap_object_project_view3d_ex(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- return transform_snap_context_project_view3d_mixed_impl(
- sctx,
- snap_to, params,
- mval, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat) != 0;
+ return transform_snap_context_project_view3d_mixed_impl(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
}
/**
@@ -2682,47 +2794,43 @@ bool ED_transform_snap_object_project_view3d_ex(
* \param r_no: hit normal (optional).
* \return Snap success
*/
-bool ED_transform_snap_object_project_view3d(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3])
+bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
- sctx,
- snap_to,
- params,
- mval, dist_px,
- r_loc, r_no, NULL,
- NULL, NULL);
+ return ED_transform_snap_object_project_view3d_ex(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL);
}
/**
* see: #ED_transform_snap_object_project_ray_all
*/
-bool ED_transform_snap_object_project_all_view3d_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- float ray_start[3], ray_normal[3];
-
- if (!ED_view3d_win_to_ray_clipped_ex(
- sctx->depsgraph,
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- return ED_transform_snap_object_project_ray_all(
- sctx,
- params,
- ray_start, ray_normal, ray_depth, sort,
- r_hit_list);
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
+ sctx->v3d_data.ar,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ return ED_transform_snap_object_project_ray_all(
+ sctx, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
}
/** \} */