LEFT | RIGHT |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 11 matching lines...) Expand all Loading... |
22 * | 22 * |
23 * Contributor(s): none yet. | 23 * Contributor(s): none yet. |
24 * | 24 * |
25 * ***** END GPL LICENSE BLOCK ***** | 25 * ***** END GPL LICENSE BLOCK ***** |
26 */ | 26 */ |
27 | 27 |
28 /** \file blender/editors/transform/transform.c | 28 /** \file blender/editors/transform/transform.c |
29 * \ingroup edtransform | 29 * \ingroup edtransform |
30 */ | 30 */ |
31 | 31 |
| 32 |
32 #include <stdlib.h> | 33 #include <stdlib.h> |
33 #include <stdio.h> | 34 #include <stdio.h> |
34 #include <string.h> | 35 #include <string.h> |
35 #include <math.h> | 36 #include <math.h> |
36 #include <float.h> | 37 #include <float.h> |
37 | 38 |
38 #ifndef WIN32 | 39 #ifndef WIN32 |
39 # include <unistd.h> | 40 #include <unistd.h> |
40 #else | 41 #else |
41 # include <io.h> | 42 #include <io.h> |
42 #endif | 43 #endif |
43 | 44 |
44 #include "MEM_guardedalloc.h" | 45 #include "MEM_guardedalloc.h" |
45 | 46 |
46 #include "DNA_anim_types.h" | 47 #include "DNA_anim_types.h" |
47 #include "DNA_armature_types.h" | 48 #include "DNA_armature_types.h" |
48 #include "DNA_constraint_types.h" | 49 #include "DNA_constraint_types.h" |
49 #include "DNA_mesh_types.h" | 50 #include "DNA_mesh_types.h" |
50 #include "DNA_meshdata_types.h" | 51 #include "DNA_meshdata_types.h" |
51 #include "DNA_mask_types.h" | |
52 #include "DNA_movieclip_types.h" | 52 #include "DNA_movieclip_types.h" |
53 #include "DNA_scene_types.h" /* PET modes */ | 53 #include "DNA_scene_types.h"» » /* PET modes» » » */ |
54 | 54 |
55 #include "BLI_utildefines.h" | 55 #include "RNA_access.h" |
56 #include "BLI_math.h" | 56 |
57 #include "BLI_rect.h" | 57 #include "BIF_gl.h" |
58 #include "BLI_listbase.h" | 58 #include "BIF_glutil.h" |
59 #include "BLI_string.h" | |
60 #include "BLI_ghash.h" | |
61 #include "BLI_linklist.h" | |
62 | 59 |
63 #include "BKE_nla.h" | 60 #include "BKE_nla.h" |
64 #include "BKE_editmesh_bvh.h" | 61 #include "BKE_bmesh.h" |
65 #include "BKE_context.h" | 62 #include "BKE_context.h" |
66 #include "BKE_constraint.h" | 63 #include "BKE_constraint.h" |
67 #include "BKE_global.h" | 64 #include "BKE_global.h" |
68 #include "BKE_particle.h" | 65 #include "BKE_particle.h" |
69 #include "BKE_pointcache.h" | 66 #include "BKE_pointcache.h" |
70 #include "BKE_unit.h" | 67 #include "BKE_unit.h" |
71 #include "BKE_mask.h" | |
72 | |
73 #include "BIF_gl.h" | |
74 #include "BIF_glutil.h" | |
75 | 68 |
76 #include "ED_image.h" | 69 #include "ED_image.h" |
77 #include "ED_keyframing.h" | 70 #include "ED_keyframing.h" |
78 #include "ED_screen.h" | 71 #include "ED_screen.h" |
79 #include "ED_space_api.h" | 72 #include "ED_space_api.h" |
80 #include "ED_markers.h" | 73 #include "ED_markers.h" |
81 #include "ED_view3d.h" | 74 #include "ED_view3d.h" |
82 #include "ED_mesh.h" | 75 #include "ED_mesh.h" |
83 #include "ED_clip.h" | 76 #include "ED_clip.h" |
84 #include "ED_mask.h" | 77 |
85 #include "ED_node.h" | 78 #include "UI_view2d.h" |
86 | |
87 #include "WM_types.h" | 79 #include "WM_types.h" |
88 #include "WM_api.h" | 80 #include "WM_api.h" |
89 | 81 |
90 #include "UI_view2d.h" | 82 #include "BLI_math.h" |
91 #include "UI_interface_icons.h" | 83 #include "BLI_blenlib.h" |
| 84 #include "BLI_utildefines.h" |
| 85 #include "BLI_ghash.h" |
| 86 #include "BLI_linklist.h" |
| 87 #include "BLI_smallhash.h" |
| 88 #include "BLI_array.h" |
| 89 |
92 #include "UI_resources.h" | 90 #include "UI_resources.h" |
93 | 91 |
94 #include "RNA_access.h" | 92 //#include "blendef.h" |
95 | 93 // |
96 #include "BLF_api.h" | 94 //#include "mydevice.h" |
97 #include "BLF_translation.h" | |
98 | 95 |
99 #include "transform.h" | 96 #include "transform.h" |
100 | 97 |
101 #define MAX_INFO_LEN 256 | 98 #include <stdio.h> |
102 | 99 |
103 static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg)
; | 100 static void drawTransformApply(const struct bContext *C, struct ARegion *ar, voi
d *arg); |
104 static int doEdgeSlide(TransInfo *t, float perc); | 101 static int doEdgeSlide(TransInfo *t, float perc); |
105 static int doVertSlide(TransInfo *t, float perc); | |
106 | |
107 static void drawEdgeSlide(const struct bContext *C, TransInfo *t); | |
108 static void drawVertSlide(const struct bContext *C, TransInfo *t); | |
109 static void len_v3_ensure(float v[3], const float length); | |
110 static void postInputRotation(TransInfo *t, float values[3]); | |
111 | |
112 | |
113 /* Transform Callbacks */ | |
114 static void initWarp(TransInfo *t); | |
115 static eRedrawFlag handleEventWarp(TransInfo *t, const struct wmEvent *event); | |
116 static void Warp(TransInfo *t, const int mval[2]); | |
117 | |
118 static void initShear(TransInfo *t); | |
119 static eRedrawFlag handleEventShear(TransInfo *t, const struct wmEvent *event); | |
120 static void applyShear(TransInfo *t, const int mval[2]); | |
121 | |
122 static void initResize(TransInfo *t); | |
123 static void applyResize(TransInfo *t, const int mval[2]); | |
124 | |
125 static void initSkinResize(TransInfo *t); | |
126 static void applySkinResize(TransInfo *t, const int mval[2]); | |
127 | |
128 static void initTranslation(TransInfo *t); | |
129 static void applyTranslation(TransInfo *t, const int mval[2]); | |
130 | |
131 static void initToSphere(TransInfo *t); | |
132 static void applyToSphere(TransInfo *t, const int mval[2]); | |
133 | |
134 static void initRotation(TransInfo *t); | |
135 static void applyRotation(TransInfo *t, const int mval[2]); | |
136 | |
137 static void initShrinkFatten(TransInfo *t); | |
138 static void applyShrinkFatten(TransInfo *t, const int mval[2]); | |
139 | |
140 static void initTilt(TransInfo *t); | |
141 static void applyTilt(TransInfo *t, const int mval[2]); | |
142 | |
143 static void initCurveShrinkFatten(TransInfo *t); | |
144 static void applyCurveShrinkFatten(TransInfo *t, const int mval[2]); | |
145 | |
146 static void initMaskShrinkFatten(TransInfo *t); | |
147 static void applyMaskShrinkFatten(TransInfo *t, const int mval[2]); | |
148 | |
149 static void initTrackball(TransInfo *t); | |
150 static void applyTrackball(TransInfo *t, const int mval[2]); | |
151 | |
152 static void initPushPull(TransInfo *t); | |
153 static void applyPushPull(TransInfo *t, const int mval[2]); | |
154 | |
155 static void initBevelWeight(TransInfo *t); | |
156 static void applyBevelWeight(TransInfo *t, const int mval[2]); | |
157 | |
158 static void initCrease(TransInfo *t); | |
159 static void applyCrease(TransInfo *t, const int mval[2]); | |
160 | |
161 static void initBoneSize(TransInfo *t); | |
162 static void applyBoneSize(TransInfo *t, const int mval[2]); | |
163 | |
164 static void initBoneEnvelope(TransInfo *t); | |
165 static void applyBoneEnvelope(TransInfo *t, const int mval[2]); | |
166 | |
167 static void initBoneRoll(TransInfo *t); | |
168 static void applyBoneRoll(TransInfo *t, const int mval[2]); | |
169 | |
170 static void initEdgeSlide(TransInfo *t); | |
171 static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *even
t); | |
172 static void applyEdgeSlide(TransInfo *t, const int mval[2]); | |
173 | |
174 static void initVertSlide(TransInfo *t); | |
175 static eRedrawFlag handleEventVertSlide(TransInfo *t, const struct wmEvent *even
t); | |
176 static void applyVertSlide(TransInfo *t, const int mval[2]); | |
177 | |
178 static void initTimeTranslate(TransInfo *t); | |
179 static void applyTimeTranslate(TransInfo *t, const int mval[2]); | |
180 | |
181 static void initTimeSlide(TransInfo *t); | |
182 static void applyTimeSlide(TransInfo *t, const int mval[2]); | |
183 | |
184 static void initTimeScale(TransInfo *t); | |
185 static void applyTimeScale(TransInfo *t, const int mval[2]); | |
186 | |
187 static void initBakeTime(TransInfo *t); | |
188 static void applyBakeTime(TransInfo *t, const int mval[2]); | |
189 | |
190 static void initMirror(TransInfo *t); | |
191 static void applyMirror(TransInfo *t, const int mval[2]); | |
192 | |
193 static void initAlign(TransInfo *t); | |
194 static void applyAlign(TransInfo *t, const int mval[2]); | |
195 | |
196 static void initSeqSlide(TransInfo *t); | |
197 static void applySeqSlide(TransInfo *t, const int mval[2]); | |
198 /* end transform callbacks */ | |
199 | |
200 | |
201 static bool transdata_check_local_center(TransInfo *t) | |
202 { | |
203 return ((t->around == V3D_LOCAL) && ( | |
204 (t->flag & (T_OBJECT | T_POSE)) || | |
205 (t->obedit && ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_M
BALL, OB_ARMATURE)) || | |
206 (t->spacetype == SPACE_IPO)) | |
207 ); | |
208 } | |
209 | 102 |
210 /* ************************** SPACE DEPENDANT CODE ****************************
*/ | 103 /* ************************** SPACE DEPENDANT CODE ****************************
*/ |
211 | 104 |
212 void setTransformViewMatrices(TransInfo *t) | 105 void setTransformViewMatrices(TransInfo *t) |
213 { | 106 { |
214 » if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TY
PE_WINDOW) { | 107 » if (t->spacetype==SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE
_WINDOW) { |
215 RegionView3D *rv3d = t->ar->regiondata; | 108 RegionView3D *rv3d = t->ar->regiondata; |
216 | 109 |
217 copy_m4_m4(t->viewmat, rv3d->viewmat); | 110 copy_m4_m4(t->viewmat, rv3d->viewmat); |
218 copy_m4_m4(t->viewinv, rv3d->viewinv); | 111 copy_m4_m4(t->viewinv, rv3d->viewinv); |
219 copy_m4_m4(t->persmat, rv3d->persmat); | 112 copy_m4_m4(t->persmat, rv3d->persmat); |
220 copy_m4_m4(t->persinv, rv3d->persinv); | 113 copy_m4_m4(t->persinv, rv3d->persinv); |
221 t->persp = rv3d->persp; | 114 t->persp = rv3d->persp; |
222 } | 115 } |
223 else { | 116 else { |
224 unit_m4(t->viewmat); | 117 unit_m4(t->viewmat); |
225 unit_m4(t->viewinv); | 118 unit_m4(t->viewinv); |
226 unit_m4(t->persmat); | 119 unit_m4(t->persmat); |
227 unit_m4(t->persinv); | 120 unit_m4(t->persinv); |
228 t->persp = RV3D_ORTHO; | 121 t->persp = RV3D_ORTHO; |
229 } | 122 } |
230 | 123 |
231 calculateCenter2D(t); | 124 calculateCenter2D(t); |
232 } | 125 } |
233 | 126 |
234 static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy) | 127 static void convertViewVec2D(View2D *v2d, float vec[3], int dx, int dy) |
235 { | 128 { |
236 float divx, divy; | 129 float divx, divy; |
237 ········ | 130 ········ |
238 » divx = BLI_rcti_size_x(&v2d->mask); | 131 » divx= v2d->mask.xmax - v2d->mask.xmin; |
239 » divy = BLI_rcti_size_y(&v2d->mask); | 132 » divy= v2d->mask.ymax - v2d->mask.ymin; |
240 | 133 |
241 » r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx; | 134 » vec[0]= (v2d->cur.xmax - v2d->cur.xmin) * dx / divx; |
242 » r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy; | 135 » vec[1]= (v2d->cur.ymax - v2d->cur.ymin) * dy / divy; |
243 » r_vec[2] = 0.0f; | 136 » vec[2]= 0.0f; |
244 } | |
245 | |
246 static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy) | |
247 { | |
248 » float divx, divy; | |
249 » float mulx, muly; | |
250 | |
251 » divx = BLI_rcti_size_x(&v2d->mask); | |
252 » divy = BLI_rcti_size_y(&v2d->mask); | |
253 | |
254 » mulx = BLI_rctf_size_x(&v2d->cur); | |
255 » muly = BLI_rctf_size_y(&v2d->cur); | |
256 | |
257 » /* difference with convertViewVec2D */ | |
258 » /* clamp w/h, mask only */ | |
259 » if (mulx / divx < muly / divy) { | |
260 » » divy = divx; | |
261 » » muly = mulx; | |
262 » } | |
263 » else { | |
264 » » divx = divy; | |
265 » » mulx = muly; | |
266 » } | |
267 » /* end difference */ | |
268 | |
269 » r_vec[0] = mulx * dx / divx; | |
270 » r_vec[1] = muly * dy / divy; | |
271 » r_vec[2] = 0.0f; | |
272 } | 137 } |
273 | 138 |
274 void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) | 139 void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) |
275 { | 140 { |
276 if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WIN
DOW)) { | 141 if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WIN
DOW)) { |
277 » » const float mval_f[2] = {(float)dx, (float)dy}; | 142 » » float mval_f[2]; |
278 » » ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); | 143 » » mval_f[0] = dx; |
279 » } | 144 » » mval_f[1] = dy; |
280 » else if (t->spacetype == SPACE_IMAGE) { | 145 » » ED_view3d_win_to_delta(t->ar, mval_f, r_vec); |
| 146 » } |
| 147 » else if (t->spacetype==SPACE_IMAGE) { |
281 float aspx, aspy; | 148 float aspx, aspy; |
282 | 149 |
283 » » if (t->options & CTX_MASK) { | 150 » » convertViewVec2D(t->view, r_vec, dx, dy); |
284 | 151 |
285 » » » convertViewVec2D_mask(t->view, r_vec, dx, dy); | 152 » » ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); |
286 » » » ED_space_image_get_aspect(t->sa->spacedata.first, &aspx,
&aspy); | |
287 » » } | |
288 » » else { | |
289 » » » convertViewVec2D(t->view, r_vec, dx, dy); | |
290 » » » ED_space_image_get_uv_aspect(t->sa->spacedata.first, &as
px, &aspy); | |
291 » » } | |
292 | |
293 r_vec[0] *= aspx; | 153 r_vec[0] *= aspx; |
294 r_vec[1] *= aspy; | 154 r_vec[1] *= aspy; |
295 } | 155 } |
296 else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { | 156 else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { |
297 convertViewVec2D(t->view, r_vec, dx, dy); | 157 convertViewVec2D(t->view, r_vec, dx, dy); |
298 } | 158 } |
299 else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { | 159 else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { |
300 convertViewVec2D(&t->ar->v2d, r_vec, dx, dy); | 160 convertViewVec2D(&t->ar->v2d, r_vec, dx, dy); |
301 } | 161 } |
302 » else if (t->spacetype == SPACE_CLIP) { | 162 » else if (t->spacetype==SPACE_CLIP) { |
303 » » float aspx, aspy; | 163 » » View2D *v2d = t->view; |
304 | 164 » » float divx, divy; |
305 » » if (t->options & CTX_MASK) { | 165 |
306 » » » convertViewVec2D_mask(t->view, r_vec, dx, dy); | 166 » » divx = v2d->mask.xmax-v2d->mask.xmin; |
307 » » } | 167 » » divy = v2d->mask.ymax-v2d->mask.ymin; |
308 » » else { | 168 |
309 » » » convertViewVec2D(t->view, r_vec, dx, dy); | 169 » » r_vec[0] = (v2d->cur.xmax-v2d->cur.xmin)*(dx)/divx; |
310 » » } | 170 » » r_vec[1] = (v2d->cur.ymax-v2d->cur.ymin)*(dy)/divy; |
311 | 171 » » r_vec[2] = 0.0f; |
312 » » if (t->options & CTX_MOVIECLIP) { | |
313 » » » ED_space_clip_get_aspect_dimension_aware(t->sa->spacedat
a.first, &aspx, &aspy); | |
314 » » } | |
315 » » else if (t->options & CTX_MASK) { | |
316 » » » /* TODO - NOT WORKING, this isnt so bad since its only d
isplay aspect */ | |
317 » » » ED_space_clip_get_aspect(t->sa->spacedata.first, &aspx,
&aspy); | |
318 » » } | |
319 » » else { | |
320 » » » /* should never happen, quiet warnings */ | |
321 » » » BLI_assert(0); | |
322 » » » aspx = aspy = 1.0f; | |
323 » » } | |
324 | |
325 » » r_vec[0] *= aspx; | |
326 » » r_vec[1] *= aspy; | |
327 } | 172 } |
328 else { | 173 else { |
329 printf("%s: called in an invalid context\n", __func__); | 174 printf("%s: called in an invalid context\n", __func__); |
330 zero_v3(r_vec); | 175 zero_v3(r_vec); |
331 } | 176 } |
332 } | 177 } |
333 | 178 |
334 void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
ojTest flag) | 179 void projectIntView(TransInfo *t, const float vec[3], int adr[2]) |
335 { | 180 { |
336 » if (t->spacetype == SPACE_VIEW3D) { | 181 » if (t->spacetype==SPACE_VIEW3D) { |
337 » » if (t->ar->regiontype == RGN_TYPE_WINDOW) { | 182 » » if (t->ar->regiontype == RGN_TYPE_WINDOW) |
338 » » » if (ED_view3d_project_int_global(t->ar, vec, adr, flag)
!= V3D_PROJ_RET_OK) { | 183 » » » project_int_noclip(t->ar, vec, adr); |
339 » » » » adr[0] = (int)2140000000.0f; /* this is what wa
s done in 2.64, perhaps we can be smarter? */ | 184 » } |
340 » » » » adr[1] = (int)2140000000.0f; | 185 » else if (t->spacetype==SPACE_IMAGE) { |
341 » » » } | 186 » » float aspx, aspy, v[2]; |
342 » » } | 187 |
343 » } | 188 » » ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); |
344 » else if (t->spacetype == SPACE_IMAGE) { | 189 » » v[0]= vec[0]/aspx; |
345 » » SpaceImage *sima = t->sa->spacedata.first; | 190 » » v[1]= vec[1]/aspy; |
346 | 191 |
347 » » if (t->options & CTX_MASK) { | 192 » » UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); |
348 » » » /* not working quite right, TODO (see below too) */ | |
349 » » » float aspx, aspy; | |
350 » » » float v[2]; | |
351 | |
352 » » » ED_space_image_get_aspect(sima, &aspx, &aspy); | |
353 | |
354 » » » copy_v2_v2(v, vec); | |
355 | |
356 » » » v[0] = v[0] / aspx; | |
357 » » » v[1] = v[1] / aspy; | |
358 | |
359 » » » BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v)
; | |
360 | |
361 » » » v[0] = v[0] / aspx; | |
362 » » » v[1] = v[1] / aspy; | |
363 | |
364 » » » ED_image_point_pos__reverse(sima, t->ar, v, v); | |
365 | |
366 » » » adr[0] = v[0]; | |
367 » » » adr[1] = v[1]; | |
368 » » } | |
369 » » else { | |
370 » » » float aspx, aspy, v[2]; | |
371 | |
372 » » » ED_space_image_get_uv_aspect(t->sa->spacedata.first, &as
px, &aspy); | |
373 » » » v[0] = vec[0] / aspx; | |
374 » » » v[1] = vec[1] / aspy; | |
375 | |
376 » » » UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, ad
r + 1); | |
377 » » } | |
378 } | 193 } |
379 else if (t->spacetype == SPACE_ACTION) { | 194 else if (t->spacetype == SPACE_ACTION) { |
380 int out[2] = {0, 0}; | 195 int out[2] = {0, 0}; |
381 #if 0 | 196 #if 0 |
382 SpaceAction *sact = t->sa->spacedata.first; | 197 SpaceAction *sact = t->sa->spacedata.first; |
383 | 198 |
384 if (sact->flag & SACTION_DRAWTIME) { | 199 if (sact->flag & SACTION_DRAWTIME) { |
385 //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.fr
s_sec_base)); | 200 //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.fr
s_sec_base)); |
386 /* same as below */ | 201 /* same as below */ |
387 » » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], v
ec[1], out, out + 1); | 202 » » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], v
ec[1], out, out+1); |
388 » » } | 203 » » } |
389 else | 204 else |
390 #endif | 205 #endif |
391 { | 206 { |
392 » » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], v
ec[1], out, out + 1); | 207 » » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], v
ec[1], out, out+1); |
393 » » } | 208 » » } |
394 | 209 |
395 » » adr[0] = out[0]; | 210 » » adr[0]= out[0]; |
396 » » adr[1] = out[1]; | 211 » » adr[1]= out[1]; |
397 } | 212 } |
398 else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { | 213 else if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) { |
399 int out[2] = {0, 0}; | 214 int out[2] = {0, 0}; |
400 | 215 |
401 » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], o
ut, out + 1); | 216 » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], o
ut, out+1); |
402 » » adr[0] = out[0]; | 217 » » adr[0]= out[0]; |
403 » » adr[1] = out[1]; | 218 » » adr[1]= out[1]; |
404 » } | 219 » } |
405 » else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should
work */ | 220 » else if (t->spacetype==SPACE_SEQ) { /* XXX not tested yet, but should wo
rk */ |
406 int out[2] = {0, 0}; | 221 int out[2] = {0, 0}; |
407 | 222 |
408 » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], o
ut, out + 1); | 223 » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], o
ut, out+1); |
409 » » adr[0] = out[0]; | 224 » » adr[0]= out[0]; |
410 » » adr[1] = out[1]; | 225 » » adr[1]= out[1]; |
411 » } | 226 » } |
412 » else if (t->spacetype == SPACE_CLIP) { | 227 » else if (t->spacetype==SPACE_CLIP) { |
413 » » SpaceClip *sc = t->sa->spacedata.first; | 228 » » float v[2]; |
414 | 229 |
415 » » if (t->options & CTX_MASK) { | 230 » » copy_v2_v2(v, vec); |
416 » » » /* not working quite right, TODO (see above too) */ | 231 |
417 » » » float aspx, aspy; | 232 » » UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1); |
418 » » » float v[2]; | 233 » } |
419 | 234 } |
420 » » » ED_space_clip_get_aspect(sc, &aspx, &aspy); | 235 |
421 | 236 void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) |
422 » » » copy_v2_v2(v, vec); | |
423 | |
424 » » » v[0] = v[0] / aspx; | |
425 » » » v[1] = v[1] / aspy; | |
426 | |
427 » » » BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v); | |
428 | |
429 » » » v[0] = v[0] / aspx; | |
430 » » » v[1] = v[1] / aspy; | |
431 | |
432 » » » ED_clip_point_stable_pos__reverse(sc, t->ar, v, v); | |
433 | |
434 » » » adr[0] = v[0]; | |
435 » » » adr[1] = v[1]; | |
436 » » } | |
437 » » else if (t->options & CTX_MOVIECLIP) { | |
438 » » » float v[2], aspx, aspy; | |
439 | |
440 » » » copy_v2_v2(v, vec); | |
441 » » » ED_space_clip_get_aspect_dimension_aware(t->sa->spacedat
a.first, &aspx, &aspy); | |
442 | |
443 » » » v[0] /= aspx; | |
444 » » » v[1] /= aspy; | |
445 | |
446 » » » UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, ad
r + 1); | |
447 » » } | |
448 » » else { | |
449 » » » BLI_assert(0); | |
450 » » } | |
451 » } | |
452 » else if (t->spacetype == SPACE_NODE) { | |
453 » » UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], a
dr, adr + 1); | |
454 » } | |
455 } | |
456 void projectIntView(TransInfo *t, const float vec[3], int adr[2]) | |
457 { | |
458 » projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); | |
459 } | |
460 | |
461 void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV
3DProjTest flag) | |
462 { | 237 { |
463 switch (t->spacetype) { | 238 switch (t->spacetype) { |
464 case SPACE_VIEW3D: | 239 case SPACE_VIEW3D: |
465 { | 240 { |
466 if (t->ar->regiontype == RGN_TYPE_WINDOW) { | 241 if (t->ar->regiontype == RGN_TYPE_WINDOW) { |
467 » » » » /* allow points behind the view [#33643] */ | 242 » » » » project_float_noclip(t->ar, vec, adr); |
468 » » » » if (ED_view3d_project_float_global(t->ar, vec, a
dr, flag) != V3D_PROJ_RET_OK) { | |
469 » » » » » /* XXX, 2.64 and prior did this, weak! *
/ | |
470 » » » » » adr[0] = t->ar->winx / 2.0f; | |
471 » » » » » adr[1] = t->ar->winy / 2.0f; | |
472 » » » » } | |
473 return; | 243 return; |
474 } | 244 } |
475 break; | 245 break; |
476 } | 246 } |
477 case SPACE_IMAGE: | 247 case SPACE_IMAGE: |
478 case SPACE_CLIP: | 248 case SPACE_CLIP: |
479 case SPACE_IPO: | 249 case SPACE_IPO: |
480 case SPACE_NLA: | 250 case SPACE_NLA: |
481 { | 251 { |
482 int a[2]; | 252 int a[2]; |
483 projectIntView(t, vec, a); | 253 projectIntView(t, vec, a); |
484 adr[0] = a[0]; | 254 adr[0] = a[0]; |
485 adr[1] = a[1]; | 255 adr[1] = a[1]; |
486 return; | 256 return; |
487 } | 257 } |
488 } | 258 } |
489 | 259 |
490 zero_v2(adr); | 260 zero_v2(adr); |
491 } | 261 } |
492 void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) | |
493 { | |
494 projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); | |
495 } | |
496 | 262 |
497 void applyAspectRatio(TransInfo *t, float vec[2]) | 263 void applyAspectRatio(TransInfo *t, float vec[2]) |
498 { | 264 { |
499 » if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) { | 265 » if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { |
500 » » SpaceImage *sima = t->sa->spacedata.first; | 266 » » SpaceImage *sima= t->sa->spacedata.first; |
501 float aspx, aspy; | 267 float aspx, aspy; |
502 | 268 |
503 » » if ((sima->flag & SI_COORDFLOATS) == 0) { | 269 » » if ((sima->flag & SI_COORDFLOATS)==0) { |
504 int width, height; | 270 int width, height; |
505 » » » ED_space_image_get_size(sima, &width, &height); | 271 » » » ED_space_image_size(sima, &width, &height); |
506 | 272 |
507 vec[0] *= width; | 273 vec[0] *= width; |
508 vec[1] *= height; | 274 vec[1] *= height; |
509 } | 275 } |
510 | 276 |
511 » » ED_space_image_get_uv_aspect(sima, &aspx, &aspy); | 277 » » ED_space_image_uv_aspect(sima, &aspx, &aspy); |
512 vec[0] /= aspx; | 278 vec[0] /= aspx; |
513 vec[1] /= aspy; | 279 vec[1] /= aspy; |
514 } | 280 } |
515 » else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { | 281 » else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { |
516 » » if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { | 282 » » if (t->options & CTX_MOVIECLIP) { |
517 SpaceClip *sc = t->sa->spacedata.first; | 283 SpaceClip *sc = t->sa->spacedata.first; |
518 float aspx, aspy; | 284 float aspx, aspy; |
519 | 285 » » » int width, height; |
520 | 286 |
521 » » » if (t->options & CTX_MOVIECLIP) { | 287 » » » ED_space_clip_size(sc, &width, &height); |
522 » » » » ED_space_clip_get_aspect_dimension_aware(sc, &as
px, &aspy); | 288 » » » ED_space_clip_aspect(sc, &aspx, &aspy); |
523 | 289 |
524 » » » » vec[0] /= aspx; | 290 » » » vec[0] *= width / aspx; |
525 » » » » vec[1] /= aspy; | 291 » » » vec[1] *= height / aspy; |
526 » » » } | |
527 » » » else if (t->options & CTX_MASK) { | |
528 » » » » ED_space_clip_get_aspect(sc, &aspx, &aspy); | |
529 | |
530 » » » » vec[0] /= aspx; | |
531 » » » » vec[1] /= aspy; | |
532 » » » } | |
533 } | 292 } |
534 } | 293 } |
535 } | 294 } |
536 | 295 |
537 void removeAspectRatio(TransInfo *t, float vec[2]) | 296 void removeAspectRatio(TransInfo *t, float vec[2]) |
538 { | 297 { |
539 » if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) { | 298 » if ((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { |
540 » » SpaceImage *sima = t->sa->spacedata.first; | 299 » » SpaceImage *sima= t->sa->spacedata.first; |
541 float aspx, aspy; | 300 float aspx, aspy; |
542 | 301 |
543 » » if ((sima->flag & SI_COORDFLOATS) == 0) { | 302 » » if ((sima->flag & SI_COORDFLOATS)==0) { |
544 int width, height; | 303 int width, height; |
545 » » » ED_space_image_get_size(sima, &width, &height); | 304 » » » ED_space_image_size(sima, &width, &height); |
546 | 305 |
547 vec[0] /= width; | 306 vec[0] /= width; |
548 vec[1] /= height; | 307 vec[1] /= height; |
549 } | 308 } |
550 | 309 |
551 » » ED_space_image_get_uv_aspect(sima, &aspx, &aspy); | 310 » » ED_space_image_uv_aspect(sima, &aspx, &aspy); |
552 vec[0] *= aspx; | 311 vec[0] *= aspx; |
553 vec[1] *= aspy; | 312 vec[1] *= aspy; |
554 } | 313 } |
555 » else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { | 314 » else if ((t->spacetype==SPACE_CLIP) && (t->mode==TFM_TRANSLATION)) { |
556 » » if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { | 315 » » if (t->options & CTX_MOVIECLIP) { |
557 SpaceClip *sc = t->sa->spacedata.first; | 316 SpaceClip *sc = t->sa->spacedata.first; |
558 » » » float aspx = 1.0f, aspy = 1.0f; | 317 » » » float aspx, aspy; |
559 | 318 » » » int width, height; |
560 » » » if (t->options & CTX_MOVIECLIP) { | 319 |
561 » » » » ED_space_clip_get_aspect_dimension_aware(sc, &as
px, &aspy); | 320 » » » ED_space_clip_size(sc, &width, &height); |
562 » » » } | 321 » » » ED_space_clip_aspect(sc, &aspx, &aspy); |
563 » » » else if (t->options & CTX_MASK) { | 322 |
564 » » » » ED_space_clip_get_aspect(sc, &aspx, &aspy); | 323 » » » vec[0] *= aspx / width; |
565 » » » } | 324 » » » vec[1] *= aspy / height; |
566 | |
567 » » » vec[0] *= aspx; | |
568 » » » vec[1] *= aspy; | |
569 } | 325 } |
570 } | 326 } |
571 } | 327 } |
572 | 328 |
573 static void viewRedrawForce(const bContext *C, TransInfo *t) | 329 static void viewRedrawForce(const bContext *C, TransInfo *t) |
574 { | 330 { |
575 if (t->spacetype == SPACE_VIEW3D) { | 331 if (t->spacetype == SPACE_VIEW3D) { |
576 /* Do we need more refined tags? */ | 332 /* Do we need more refined tags? */ |
577 if (t->flag & T_POSE) | 333 if (t->flag & T_POSE) |
578 » » » WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); | 334 » » » WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); |
579 else | 335 else |
580 » » » WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL)
; | 336 » » » WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); |
581 | 337 » » |
582 /* for realtime animation record - send notifiers recognised by
animation editors */ | 338 /* for realtime animation record - send notifiers recognised by
animation editors */ |
583 // XXX: is this notifier a lame duck? | 339 // XXX: is this notifier a lame duck? |
584 if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) | 340 if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) |
585 » » » WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL); | 341 » » » WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, NULL); |
586 ················ | 342 ················ |
587 } | 343 } |
588 else if (t->spacetype == SPACE_ACTION) { | 344 else if (t->spacetype == SPACE_ACTION) { |
589 » » //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; | 345 » » //SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; |
590 » » WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED,
NULL); | 346 » » WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NUL
L); |
591 } | 347 } |
592 else if (t->spacetype == SPACE_IPO) { | 348 else if (t->spacetype == SPACE_IPO) { |
593 » » //SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; | 349 » » //SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; |
594 » » WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED,
NULL); | 350 » » WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NUL
L); |
595 } | 351 } |
596 else if (t->spacetype == SPACE_NLA) { | 352 else if (t->spacetype == SPACE_NLA) { |
597 » » WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL
); | 353 » » WM_event_add_notifier(C, NC_ANIMATION|ND_NLA|NA_EDITED, NULL); |
598 } | 354 } |
599 else if (t->spacetype == SPACE_NODE) { | 355 else if (t->spacetype == SPACE_NODE) { |
600 //ED_area_tag_redraw(t->sa); | 356 //ED_area_tag_redraw(t->sa); |
601 » » WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); | 357 » » WM_event_add_notifier(C, NC_SPACE|ND_SPACE_NODE_VIEW, NULL); |
602 } | 358 } |
603 else if (t->spacetype == SPACE_SEQ) { | 359 else if (t->spacetype == SPACE_SEQ) { |
604 » » WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); | 360 » » WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, NULL); |
605 » } | 361 » } |
606 » else if (t->spacetype == SPACE_IMAGE) { | 362 » else if (t->spacetype==SPACE_IMAGE) { |
607 » » if (t->options & CTX_MASK) { | 363 » » // XXX how to deal with lock? |
608 » » » Mask *mask = CTX_data_edit_mask(C); | 364 » » SpaceImage *sima= (SpaceImage*)t->sa->spacedata.first; |
609 | 365 » » if (sima->lock) WM_event_add_notifier(C, NC_GEOM|ND_DATA, t->obe
dit->data); |
610 » » » WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); | 366 » » else ED_area_tag_redraw(t->sa); |
611 » » } | 367 » } |
612 » » else { | 368 » else if (t->spacetype==SPACE_CLIP) { |
613 » » » // XXX how to deal with lock? | 369 » » SpaceClip *sc = (SpaceClip*)t->sa->spacedata.first; |
614 » » » SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; | 370 » » MovieClip *clip = ED_space_clip(sc); |
615 » » » if (sima->lock) WM_event_add_notifier(C, NC_GEOM | ND_DA
TA, t->obedit->data); | 371 |
616 » » » else ED_area_tag_redraw(t->sa); | 372 » » /* objects could be parented to tracking data, so send this for
viewport refresh */ |
617 » » } | 373 » » WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); |
618 » } | 374 |
619 » else if (t->spacetype == SPACE_CLIP) { | 375 » » WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); |
620 » » SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first; | |
621 | |
622 » » if (ED_space_clip_check_show_trackedit(sc)) { | |
623 » » » MovieClip *clip = ED_space_clip_get_clip(sc); | |
624 | |
625 » » » /* objects could be parented to tracking data, so send t
his for viewport refresh */ | |
626 » » » WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL)
; | |
627 | |
628 » » » WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip)
; | |
629 » » } | |
630 » » else if (ED_space_clip_check_show_maskedit(sc)) { | |
631 » » » Mask *mask = CTX_data_edit_mask(C); | |
632 | |
633 » » » WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); | |
634 » » } | |
635 } | 376 } |
636 } | 377 } |
637 | 378 |
638 static void viewRedrawPost(bContext *C, TransInfo *t) | 379 static void viewRedrawPost(bContext *C, TransInfo *t) |
639 { | 380 { |
640 ED_area_headerprint(t->sa, NULL); | 381 ED_area_headerprint(t->sa, NULL); |
641 ········ | 382 ········ |
642 if (t->spacetype == SPACE_VIEW3D) { | 383 if (t->spacetype == SPACE_VIEW3D) { |
643 /* if autokeying is enabled, send notifiers that keyframes were
added */ | 384 /* if autokeying is enabled, send notifiers that keyframes were
added */ |
644 if (IS_AUTOKEY_ON(t->scene)) | 385 if (IS_AUTOKEY_ON(t->scene)) |
645 » » » WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDI
TED, NULL); | 386 » » » WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED,
NULL); |
646 | |
647 » » /* redraw UV editor */ | |
648 » » if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVC
ALC_TRANSFORM_CORRECT)) | |
649 » » » WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); | |
650 ················ | 387 ················ |
651 /* XXX temp, first hack to get auto-render in compositor work (t
on) */ | 388 /* XXX temp, first hack to get auto-render in compositor work (t
on) */ |
652 » » WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_
scene(C)); | 389 » » WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM_DONE, CTX_data_sc
ene(C)); |
653 | 390 |
654 } | 391 } |
655 ········ | 392 ········ |
656 #if 0 // TRANSFORM_FIX_ME | 393 #if 0 // TRANSFORM_FIX_ME |
657 » if (t->spacetype == SPACE_VIEW3D) { | 394 » if (t->spacetype==SPACE_VIEW3D) { |
658 allqueue(REDRAWBUTSOBJECT, 0); | 395 allqueue(REDRAWBUTSOBJECT, 0); |
659 allqueue(REDRAWVIEW3D, 0); | 396 allqueue(REDRAWVIEW3D, 0); |
660 } | 397 } |
661 » else if (t->spacetype == SPACE_IMAGE) { | 398 » else if (t->spacetype==SPACE_IMAGE) { |
662 allqueue(REDRAWIMAGE, 0); | 399 allqueue(REDRAWIMAGE, 0); |
663 allqueue(REDRAWVIEW3D, 0); | 400 allqueue(REDRAWVIEW3D, 0); |
664 } | 401 } |
665 else if (ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) { | 402 else if (ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) { |
666 allqueue(REDRAWVIEW3D, 0); | 403 allqueue(REDRAWVIEW3D, 0); |
667 allqueue(REDRAWACTION, 0); | 404 allqueue(REDRAWACTION, 0); |
668 allqueue(REDRAWNLA, 0); | 405 allqueue(REDRAWNLA, 0); |
669 allqueue(REDRAWIPO, 0); | 406 allqueue(REDRAWIPO, 0); |
670 allqueue(REDRAWTIME, 0); | 407 allqueue(REDRAWTIME, 0); |
671 allqueue(REDRAWBUTSOBJECT, 0); | 408 allqueue(REDRAWBUTSOBJECT, 0); |
672 } | 409 } |
673 | 410 |
674 scrarea_queue_headredraw(curarea); | 411 scrarea_queue_headredraw(curarea); |
675 #endif | 412 #endif |
676 } | 413 } |
677 | 414 |
678 /* ************************** TRANSFORMATIONS **************************** */ | 415 /* ************************** TRANSFORMATIONS **************************** */ |
679 | 416 |
| 417 void BIF_selectOrientation(void) |
| 418 { |
| 419 #if 0 // TRANSFORM_FIX_ME |
| 420 short val; |
| 421 char *str_menu = BIF_menustringTransformOrientation("Orientation"); |
| 422 val= pupmenu(str_menu); |
| 423 MEM_freeN(str_menu); |
| 424 |
| 425 if (val >= 0) { |
| 426 G.vd->twmode = val; |
| 427 } |
| 428 #endif |
| 429 } |
| 430 |
680 static void view_editmove(unsigned short UNUSED(event)) | 431 static void view_editmove(unsigned short UNUSED(event)) |
681 { | 432 { |
682 #if 0 // TRANSFORM_FIX_ME | 433 #if 0 // TRANSFORM_FIX_ME |
683 int refresh = 0; | 434 int refresh = 0; |
684 /* Regular: Zoom in */ | 435 /* Regular: Zoom in */ |
685 /* Shift: Scroll up */ | 436 /* Shift: Scroll up */ |
686 /* Ctrl: Scroll right */ | 437 /* Ctrl: Scroll right */ |
687 /* Alt-Shift: Rotate up */ | 438 /* Alt-Shift: Rotate up */ |
688 /* Alt-Ctrl: Rotate right */ | 439 /* Alt-Ctrl: Rotate right */ |
689 | 440 |
690 /* only work in 3D window for now | 441 /* only work in 3D window for now |
691 * In the end, will have to send to event to a 2D window handler instead | 442 * In the end, will have to send to event to a 2D window handler instead |
692 */ | 443 */ |
693 if (Trans.flag & T_2D_EDIT) | 444 if (Trans.flag & T_2D_EDIT) |
694 return; | 445 return; |
695 | 446 |
696 switch (event) { | 447 switch (event) { |
697 case WHEELUPMOUSE: | 448 case WHEELUPMOUSE: |
698 | 449 |
699 » » » if (G.qual & LR_SHIFTKEY) { | 450 » » » if ( G.qual & LR_SHIFTKEY ) { |
700 » » » » if (G.qual & LR_ALTKEY) { | 451 » » » » if ( G.qual & LR_ALTKEY ) { |
701 G.qual &= ~LR_SHIFTKEY; | 452 G.qual &= ~LR_SHIFTKEY; |
702 persptoetsen(PAD2); | 453 persptoetsen(PAD2); |
703 G.qual |= LR_SHIFTKEY; | 454 G.qual |= LR_SHIFTKEY; |
704 } | 455 } |
705 else { | 456 else { |
706 persptoetsen(PAD2); | 457 persptoetsen(PAD2); |
707 } | 458 } |
708 } | 459 } |
709 » » » else if (G.qual & LR_CTRLKEY) { | 460 » » » else if ( G.qual & LR_CTRLKEY ) { |
710 » » » » if (G.qual & LR_ALTKEY) { | 461 » » » » if ( G.qual & LR_ALTKEY ) { |
711 G.qual &= ~LR_CTRLKEY; | 462 G.qual &= ~LR_CTRLKEY; |
712 persptoetsen(PAD4); | 463 persptoetsen(PAD4); |
713 G.qual |= LR_CTRLKEY; | 464 G.qual |= LR_CTRLKEY; |
714 } | 465 } |
715 else { | 466 else { |
716 persptoetsen(PAD4); | 467 persptoetsen(PAD4); |
717 } | 468 } |
718 } | 469 } |
719 else if (U.uiflag & USER_WHEELZOOMDIR) | 470 else if (U.uiflag & USER_WHEELZOOMDIR) |
720 persptoetsen(PADMINUS); | 471 persptoetsen(PADMINUS); |
721 else | 472 else |
722 persptoetsen(PADPLUSKEY); | 473 persptoetsen(PADPLUSKEY); |
723 | 474 |
724 refresh = 1; | 475 refresh = 1; |
725 break; | 476 break; |
726 case WHEELDOWNMOUSE: | 477 case WHEELDOWNMOUSE: |
727 » » » if (G.qual & LR_SHIFTKEY) { | 478 » » » if ( G.qual & LR_SHIFTKEY ) { |
728 » » » » if (G.qual & LR_ALTKEY) { | 479 » » » » if ( G.qual & LR_ALTKEY ) { |
729 G.qual &= ~LR_SHIFTKEY; | 480 G.qual &= ~LR_SHIFTKEY; |
730 persptoetsen(PAD8); | 481 persptoetsen(PAD8); |
731 G.qual |= LR_SHIFTKEY; | 482 G.qual |= LR_SHIFTKEY; |
732 } | 483 } |
733 else { | 484 else { |
734 persptoetsen(PAD8); | 485 persptoetsen(PAD8); |
735 } | 486 } |
736 } | 487 } |
737 » » » else if (G.qual & LR_CTRLKEY) { | 488 » » » else if ( G.qual & LR_CTRLKEY ) { |
738 » » » » if (G.qual & LR_ALTKEY) { | 489 » » » » if ( G.qual & LR_ALTKEY ) { |
739 G.qual &= ~LR_CTRLKEY; | 490 G.qual &= ~LR_CTRLKEY; |
740 persptoetsen(PAD6); | 491 persptoetsen(PAD6); |
741 G.qual |= LR_CTRLKEY; | 492 G.qual |= LR_CTRLKEY; |
742 } | 493 } |
743 else { | 494 else { |
744 persptoetsen(PAD6); | 495 persptoetsen(PAD6); |
745 } | 496 } |
746 } | 497 } |
747 else if (U.uiflag & USER_WHEELZOOMDIR) | 498 else if (U.uiflag & USER_WHEELZOOMDIR) |
748 persptoetsen(PADPLUSKEY); | 499 persptoetsen(PADPLUSKEY); |
749 else | 500 else |
750 persptoetsen(PADMINUS); | 501 persptoetsen(PADMINUS); |
751 | 502 |
752 refresh = 1; | 503 refresh = 1; |
753 break; | 504 break; |
754 } | 505 } |
755 | 506 |
756 if (refresh) | 507 if (refresh) |
757 setTransformViewMatrices(&Trans); | 508 setTransformViewMatrices(&Trans); |
758 #endif | 509 #endif |
759 } | 510 } |
760 | 511 |
761 /* ************************************************* */ | 512 /* ************************************************* */ |
762 | 513 |
763 /* NOTE: these defines are saved in keymap files, do not change values but just
add new ones */ | 514 /* NOTE: these defines are saved in keymap files, do not change values but just
add new ones */ |
764 #define TFM_MODAL_CANCEL 1 | 515 #define TFM_MODAL_CANCEL» » 1 |
765 #define TFM_MODAL_CONFIRM 2 | 516 #define TFM_MODAL_CONFIRM» » 2 |
766 #define TFM_MODAL_TRANSLATE 3 | 517 #define TFM_MODAL_TRANSLATE» » 3 |
767 #define TFM_MODAL_ROTATE 4 | 518 #define TFM_MODAL_ROTATE» » 4 |
768 #define TFM_MODAL_RESIZE 5 | 519 #define TFM_MODAL_RESIZE» » 5 |
769 #define TFM_MODAL_SNAP_INV_ON 6 | 520 #define TFM_MODAL_SNAP_INV_ON» 6 |
770 #define TFM_MODAL_SNAP_INV_OFF 7 | 521 #define TFM_MODAL_SNAP_INV_OFF» 7 |
771 #define TFM_MODAL_SNAP_TOGGLE 8 | 522 #define TFM_MODAL_SNAP_TOGGLE» 8 |
772 #define TFM_MODAL_AXIS_X 9 | 523 #define TFM_MODAL_AXIS_X» » 9 |
773 #define TFM_MODAL_AXIS_Y 10 | 524 #define TFM_MODAL_AXIS_Y» » 10 |
774 #define TFM_MODAL_AXIS_Z 11 | 525 #define TFM_MODAL_AXIS_Z» » 11 |
775 #define TFM_MODAL_PLANE_X 12 | 526 #define TFM_MODAL_PLANE_X» » 12 |
776 #define TFM_MODAL_PLANE_Y 13 | 527 #define TFM_MODAL_PLANE_Y» » 13 |
777 #define TFM_MODAL_PLANE_Z 14 | 528 #define TFM_MODAL_PLANE_Z» » 14 |
778 #define TFM_MODAL_CONS_OFF 15 | 529 #define TFM_MODAL_CONS_OFF» » 15 |
779 #define TFM_MODAL_ADD_SNAP 16 | 530 #define TFM_MODAL_ADD_SNAP» » 16 |
780 #define TFM_MODAL_REMOVE_SNAP 17 | 531 #define TFM_MODAL_REMOVE_SNAP» 17 |
781 /* 18 and 19 used by numinput, defined in transform.h | 532 /* 18 and 19 used by numinput, defined in transform.h |
782 * */ | 533 * */ |
783 #define TFM_MODAL_PROPSIZE_UP 20 | 534 #define TFM_MODAL_PROPSIZE_UP» 20 |
784 #define TFM_MODAL_PROPSIZE_DOWN 21 | 535 #define TFM_MODAL_PROPSIZE_DOWN»21 |
785 #define TFM_MODAL_AUTOIK_LEN_INC 22 | 536 #define TFM_MODAL_AUTOIK_LEN_INC 22 |
786 #define TFM_MODAL_AUTOIK_LEN_DEC 23 | 537 #define TFM_MODAL_AUTOIK_LEN_DEC 23 |
787 | 538 |
788 #define TFM_MODAL_EDGESLIDE_UP 24 | |
789 #define TFM_MODAL_EDGESLIDE_DOWN 25 | |
790 | |
791 /* for analog input, like trackpad */ | |
792 #define TFM_MODAL_PROPSIZE 26 | |
793 | |
794 /* called in transform_ops.c, on each regeneration of keymaps */ | 539 /* called in transform_ops.c, on each regeneration of keymaps */ |
795 wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) | 540 wmKeyMap* transform_modal_keymap(wmKeyConfig *keyconf) |
796 { | 541 { |
797 static EnumPropertyItem modal_items[] = { | 542 static EnumPropertyItem modal_items[] = { |
798 » » {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, | 543 » {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, |
799 » » {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | 544 » {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, |
800 » » {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, | 545 » {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, |
801 » » {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, | 546 » {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, |
802 » » {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, | 547 » {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, |
803 » » {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Invert Snap On", ""}, | 548 » {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Invert Snap On", ""}, |
804 » » {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Invert Snap Off", "
"}, | 549 » {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Invert Snap Off", ""}, |
805 » » {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""}, | 550 » {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""}, |
806 » » {TFM_MODAL_AXIS_X, "AXIS_X", 0, "Orientation X axis", ""}, | 551 » {TFM_MODAL_AXIS_X, "AXIS_X", 0, "Orientation X axis", ""}, |
807 » » {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Orientation Y axis", ""}, | 552 » {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Orientation Y axis", ""}, |
808 » » {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Orientation Z axis", ""}, | 553 » {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Orientation Z axis", ""}, |
809 » » {TFM_MODAL_PLANE_X, "PLANE_X", 0, "Orientation X plane", ""}, | 554 » {TFM_MODAL_PLANE_X, "PLANE_X", 0, "Orientation X plane", ""}, |
810 » » {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Orientation Y plane", ""}, | 555 » {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Orientation Y plane", ""}, |
811 » » {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Orientation Z plane", ""}, | 556 » {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Orientation Z plane", ""}, |
812 » » {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Remove Constraints", ""}, | 557 » {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Remove Constraints", ""}, |
813 » » {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""}, | 558 » {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""}, |
814 » » {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Poin
t", ""}, | 559 » {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""}, |
815 » » {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment
Up", ""}, | 560 » {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""}
, |
816 » » {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increm
ent Down", ""}, | 561 » {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down
", ""}, |
817 » » {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Pro
portional Influence", ""}, | 562 » {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportiona
l Influence", ""}, |
818 » » {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease
Proportional Influence", ""}, | 563 » {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proport
ional Influence", ""}, |
819 » » {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase M
ax AutoIK Chain Length", ""}, | 564 » {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoI
K Chain Length", ""}, |
820 » » {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease
Max AutoIK Chain Length", ""}, | 565 » {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max Aut
oIK Chain Length", ""}, |
821 » » {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next
Edge Slide Edge", ""}, | 566 » {0, NULL, 0, NULL, NULL}}; |
822 » » {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select pre
vious Edge Slide Edge", ""}, | 567 »······· |
823 » » {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportiona
l Influence", ""}, | 568 » wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "Transform Modal Map"); |
824 » » {0, NULL, 0, NULL, NULL} | |
825 » }; | |
826 »······· | |
827 » wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map"); | |
828 ········ | 569 ········ |
829 /* this function is called for each spacetype, only needs to add map onc
e */ | 570 /* this function is called for each spacetype, only needs to add map onc
e */ |
830 if (keymap && keymap->modal_items) return NULL; | 571 if (keymap && keymap->modal_items) return NULL; |
831 ········ | 572 ········ |
832 » keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items)
; | 573 » keymap= WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); |
833 ········ | 574 ········ |
834 /* items for modal map */ | 575 /* items for modal map */ |
835 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODA
L_CANCEL); | 576 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODA
L_CANCEL); |
836 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODA
L_CONFIRM); | 577 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODA
L_CONFIRM); |
837 WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_C
ONFIRM); | 578 WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_C
ONFIRM); |
838 WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL
_CONFIRM); | 579 WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL
_CONFIRM); |
839 | 580 |
840 WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLAT
E); | 581 WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLAT
E); |
841 WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE); | 582 WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE); |
842 WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, TFM_MODAL_RESIZE); | 583 WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, TFM_MODAL_RESIZE); |
843 ········ | 584 ········ |
844 WM_modalkeymap_add_item(keymap, TABKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL
_SNAP_TOGGLE); | 585 WM_modalkeymap_add_item(keymap, TABKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL
_SNAP_TOGGLE); |
845 | 586 |
846 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MO
DAL_SNAP_INV_ON); | 587 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MO
DAL_SNAP_INV_ON); |
847 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM_
MODAL_SNAP_INV_OFF); | 588 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM_
MODAL_SNAP_INV_OFF); |
848 | 589 |
849 WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_M
ODAL_SNAP_INV_ON); | 590 WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_M
ODAL_SNAP_INV_ON); |
850 WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM
_MODAL_SNAP_INV_OFF); | 591 WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM
_MODAL_SNAP_INV_OFF); |
851 ········ | 592 ········ |
852 WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, TFM_MODAL_ADD_SNAP
); | 593 WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, TFM_MODAL_ADD_SNAP
); |
853 WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_ALT, 0, TFM_MODAL_REM
OVE_SNAP); | 594 WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_ALT, 0, TFM_MODAL_REM
OVE_SNAP); |
854 | 595 |
855 WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PRO
PSIZE_UP); | 596 WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PRO
PSIZE_UP); |
856 WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_P
ROPSIZE_DOWN); | 597 WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_P
ROPSIZE_DOWN); |
857 WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODA
L_PROPSIZE_UP); | 598 WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODA
L_PROPSIZE_UP); |
858 WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_
PROPSIZE_DOWN); | 599 WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_
PROPSIZE_DOWN); |
859 WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE); | |
860 | |
861 WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM
_MODAL_EDGESLIDE_UP); | |
862 WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ALT, 0, TFM_M
ODAL_EDGESLIDE_DOWN); | |
863 ········ | 600 ········ |
864 WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MO
DAL_AUTOIK_LEN_INC); | 601 WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MO
DAL_AUTOIK_LEN_INC); |
865 WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_
MODAL_AUTOIK_LEN_DEC); | 602 WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_
MODAL_AUTOIK_LEN_DEC); |
866 WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, T
FM_MODAL_AUTOIK_LEN_INC); | 603 WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, T
FM_MODAL_AUTOIK_LEN_INC); |
867 WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM
_MODAL_AUTOIK_LEN_DEC); | 604 WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM
_MODAL_AUTOIK_LEN_DEC); |
868 ········ | 605 ········ |
869 return keymap; | 606 return keymap; |
870 } | 607 } |
871 | 608 |
872 static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
ode) | 609 |
873 { | 610 int transformEvent(TransInfo *t, wmEvent *event) |
874 » if (!(t->flag & T_NO_CONSTRAINT)) { | 611 { |
875 » » int constraint_axis, constraint_plane; | 612 » float mati[3][3]= MAT3_UNITY; |
876 » » int edit_2d = (t->flag & T_2D_EDIT); | |
877 » » const char *msg1 = "", *msg2 = "", *msg3 = ""; | |
878 » » char axis; | |
879 »······· | |
880 » » /* Initialize */ | |
881 » » switch (key_type) { | |
882 » » » case XKEY: | |
883 » » » » msg1 = IFACE_("along X"); | |
884 » » » » msg2 = IFACE_("along %s X"); | |
885 » » » » msg3 = IFACE_("locking %s X"); | |
886 » » » » axis = 'X'; | |
887 » » » » constraint_axis = CON_AXIS0; | |
888 » » » » break; | |
889 » » » case YKEY: | |
890 » » » » msg1 = IFACE_("along Y"); | |
891 » » » » msg2 = IFACE_("along %s Y"); | |
892 » » » » msg3 = IFACE_("locking %s Y"); | |
893 » » » » axis = 'Y'; | |
894 » » » » constraint_axis = CON_AXIS1; | |
895 » » » » break; | |
896 » » » case ZKEY: | |
897 » » » » msg1 = IFACE_("along Z"); | |
898 » » » » msg2 = IFACE_("along %s Z"); | |
899 » » » » msg3 = IFACE_("locking %s Z"); | |
900 » » » » axis = 'Z'; | |
901 » » » » constraint_axis = CON_AXIS2; | |
902 » » » » break; | |
903 » » » default: | |
904 » » » » /* Invalid key */ | |
905 » » » » return; | |
906 » » } | |
907 » » constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~cons
traint_axis)); | |
908 | |
909 » » if (edit_2d && (key_type != ZKEY)) { | |
910 » » » if (cmode == axis) { | |
911 » » » » stopConstraint(t); | |
912 » » » } | |
913 » » » else { | |
914 » » » » setUserConstraint(t, V3D_MANIP_GLOBAL, constrain
t_axis, msg1); | |
915 » » » } | |
916 » » } | |
917 » » else if (!edit_2d) { | |
918 » » » if (cmode == axis) { | |
919 » » » » if (t->con.orientation != V3D_MANIP_GLOBAL) { | |
920 » » » » » stopConstraint(t); | |
921 » » » » } | |
922 » » » » else { | |
923 » » » » » short orientation = (t->current_orientat
ion != V3D_MANIP_GLOBAL ? | |
924 » » » » » t->current_orientat
ion : V3D_MANIP_LOCAL); | |
925 » » » » » if (!(t->modifiers & MOD_CONSTRAINT_PLAN
E)) | |
926 » » » » » » setUserConstraint(t, orientation
, constraint_axis, msg2); | |
927 » » » » » else if (t->modifiers & MOD_CONSTRAINT_P
LANE) | |
928 » » » » » » setUserConstraint(t, orientation
, constraint_plane, msg3); | |
929 » » » » } | |
930 » » » } | |
931 » » » else { | |
932 » » » » if (!(t->modifiers & MOD_CONSTRAINT_PLANE)) | |
933 » » » » » setUserConstraint(t, V3D_MANIP_GLOBAL, c
onstraint_axis, msg2); | |
934 » » » » else if (t->modifiers & MOD_CONSTRAINT_PLANE) | |
935 » » » » » setUserConstraint(t, V3D_MANIP_GLOBAL, c
onstraint_plane, msg3); | |
936 » » » } | |
937 » » } | |
938 » » t->redraw |= TREDRAW_HARD; | |
939 » } | |
940 } | |
941 | |
942 int transformEvent(TransInfo *t, const wmEvent *event) | |
943 { | |
944 » float mati[3][3] = MAT3_UNITY; | |
945 char cmode = constraintModeToChar(t); | 613 char cmode = constraintModeToChar(t); |
946 int handled = 1; | 614 int handled = 1; |
947 » | 615 |
948 t->redraw |= handleMouseInput(t, &t->mouse, event); | 616 t->redraw |= handleMouseInput(t, &t->mouse, event); |
949 | 617 |
950 if (event->type == MOUSEMOVE) { | 618 if (event->type == MOUSEMOVE) { |
951 if (t->modifiers & MOD_CONSTRAINT_SELECT) | 619 if (t->modifiers & MOD_CONSTRAINT_SELECT) |
952 t->con.mode |= CON_SELECT; | 620 t->con.mode |= CON_SELECT; |
953 | 621 |
954 copy_v2_v2_int(t->mval, event->mval); | 622 copy_v2_v2_int(t->mval, event->mval); |
955 | 623 |
956 // t->redraw |= TREDRAW_SOFT; /* Use this for soft redraw. Might
cause flicker in object mode */ | 624 // t->redraw |= TREDRAW_SOFT; /* Use this for soft redraw. Might
cause flicker in object mode */ |
957 t->redraw |= TREDRAW_HARD; | 625 t->redraw |= TREDRAW_HARD; |
(...skipping 13 matching lines...) Expand all Loading... |
971 if (event->type == EVT_MODAL_MAP) { | 639 if (event->type == EVT_MODAL_MAP) { |
972 switch (event->val) { | 640 switch (event->val) { |
973 case TFM_MODAL_CANCEL: | 641 case TFM_MODAL_CANCEL: |
974 t->state = TRANS_CANCEL; | 642 t->state = TRANS_CANCEL; |
975 break; | 643 break; |
976 case TFM_MODAL_CONFIRM: | 644 case TFM_MODAL_CONFIRM: |
977 t->state = TRANS_CONFIRM; | 645 t->state = TRANS_CONFIRM; |
978 break; | 646 break; |
979 case TFM_MODAL_TRANSLATE: | 647 case TFM_MODAL_TRANSLATE: |
980 /* only switch when... */ | 648 /* only switch when... */ |
981 » » » » if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM
_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { | 649 » » » » if ( ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TF
M_TRACKBALL) ) { |
982 » » » » » resetTransModal(t); | |
983 resetTransRestrictions(t); | 650 resetTransRestrictions(t); |
984 restoreTransObjects(t); | 651 restoreTransObjects(t); |
985 initTranslation(t); | 652 initTranslation(t); |
986 initSnapping(t, NULL); // need to reinit
after mode change | 653 initSnapping(t, NULL); // need to reinit
after mode change |
987 t->redraw |= TREDRAW_HARD; | 654 t->redraw |= TREDRAW_HARD; |
988 WM_event_add_mousemove(t->context); | |
989 } | 655 } |
990 » » » » else if (t->mode == TFM_SEQ_SLIDE) { | 656 » » » » else if (t->mode == TFM_TRANSLATION) { |
991 » » » » » t->flag ^= T_ALT_TRANSFORM; | 657 » » » » » if (t->options & CTX_MOVIECLIP) { |
992 » » » » » t->redraw |= TREDRAW_HARD; | 658 » » » » » » restoreTransObjects(t); |
993 » » » » } | 659 |
994 » » » » else { | 660 » » » » » » t->flag ^= T_ALT_TRANSFORM; |
995 » » » » » if (t->obedit && t->obedit->type == OB_M
ESH) { | 661 » » » » » » t->redraw |= TREDRAW_HARD; |
996 » » » » » » if ((t->mode == TFM_TRANSLATION)
&& (t->spacetype == SPACE_VIEW3D)) { | |
997 » » » » » » » resetTransModal(t); | |
998 » » » » » » » resetTransRestrictions(t
); | |
999 » » » » » » » restoreTransObjects(t); | |
1000 | |
1001 » » » » » » » /* first try edge slide
*/ | |
1002 » » » » » » » initEdgeSlide(t); | |
1003 » » » » » » » /* if that fails, do ver
tex slide */ | |
1004 » » » » » » » if (t->state == TRANS_CA
NCEL) { | |
1005 » » » » » » » » t->state = TRANS
_STARTING; | |
1006 » » » » » » » » initVertSlide(t)
; | |
1007 » » » » » » » } | |
1008 » » » » » » » /* vert slide can fail o
n unconnected vertices (rare but possible) */ | |
1009 » » » » » » » if (t->state == TRANS_CA
NCEL) { | |
1010 » » » » » » » » t->state = TRANS
_STARTING; | |
1011 » » » » » » » » resetTransRestri
ctions(t); | |
1012 » » » » » » » » restoreTransObje
cts(t); | |
1013 » » » » » » » » initTranslation(
t); | |
1014 » » » » » » » } | |
1015 » » » » » » » initSnapping(t, NULL); /
/ need to reinit after mode change | |
1016 » » » » » » » t->redraw |= TREDRAW_HAR
D; | |
1017 » » » » » » » WM_event_add_mousemove(t
->context); | |
1018 » » » » » » } | |
1019 » » » » » } | |
1020 » » » » » else if (t->options & (CTX_MOVIECLIP | C
TX_MASK)) { | |
1021 » » » » » » if (t->mode == TFM_TRANSLATION)
{ | |
1022 » » » » » » » restoreTransObjects(t); | |
1023 | |
1024 » » » » » » » t->flag ^= T_ALT_TRANSFO
RM; | |
1025 » » » » » » » t->redraw |= TREDRAW_HAR
D; | |
1026 » » » » » » } | |
1027 } | 662 } |
1028 } | 663 } |
1029 break; | 664 break; |
1030 case TFM_MODAL_ROTATE: | 665 case TFM_MODAL_ROTATE: |
1031 /* only switch when... */ | 666 /* only switch when... */ |
1032 » » » » if (!(t->options & CTX_TEXTURE) && !(t->options
& (CTX_MOVIECLIP | CTX_MASK))) { | 667 » » » » if (!(t->options & CTX_TEXTURE) && !(t->options
& CTX_MOVIECLIP)) { |
1033 » » » » » if (ELEM6(t->mode, TFM_ROTATION, TFM_RES
IZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { | 668 » » » » » if ( ELEM4(t->mode, TFM_ROTATION, TFM_RE
SIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { |
1034 » » » » » » resetTransModal(t); | 669 » » » » » »······· |
1035 resetTransRestrictions(t); | 670 resetTransRestrictions(t); |
1036 ················································ | 671 ················································ |
1037 if (t->mode == TFM_ROTATION) { | 672 if (t->mode == TFM_ROTATION) { |
1038 restoreTransObjects(t); | 673 restoreTransObjects(t); |
1039 initTrackball(t); | 674 initTrackball(t); |
1040 } | 675 } |
1041 else { | 676 else { |
1042 restoreTransObjects(t); | 677 restoreTransObjects(t); |
1043 initRotation(t); | 678 initRotation(t); |
1044 } | 679 } |
1045 initSnapping(t, NULL); // need t
o reinit after mode change | 680 initSnapping(t, NULL); // need t
o reinit after mode change |
1046 t->redraw |= TREDRAW_HARD; | 681 t->redraw |= TREDRAW_HARD; |
1047 } | 682 } |
1048 } | 683 } |
1049 break; | 684 break; |
1050 case TFM_MODAL_RESIZE: | 685 case TFM_MODAL_RESIZE: |
1051 /* only switch when... */ | 686 /* only switch when... */ |
1052 » » » » if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION
, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { | 687 » » » » if ( ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATIO
N, TFM_TRACKBALL) ) { |
1053 » » » » » resetTransModal(t); | |
1054 resetTransRestrictions(t); | 688 resetTransRestrictions(t); |
1055 restoreTransObjects(t); | 689 restoreTransObjects(t); |
1056 initResize(t); | 690 initResize(t); |
1057 initSnapping(t, NULL); // need to reinit
after mode change | 691 initSnapping(t, NULL); // need to reinit
after mode change |
1058 t->redraw |= TREDRAW_HARD; | 692 t->redraw |= TREDRAW_HARD; |
1059 } | |
1060 else if (t->mode == TFM_SHRINKFATTEN) { | |
1061 t->flag ^= T_ALT_TRANSFORM; | |
1062 t->redraw |= TREDRAW_HARD; | |
1063 } | |
1064 else if (t->mode == TFM_RESIZE) { | |
1065 if (t->options & CTX_MOVIECLIP) { | |
1066 restoreTransObjects(t); | |
1067 | |
1068 t->flag ^= T_ALT_TRANSFORM; | |
1069 t->redraw |= TREDRAW_HARD; | |
1070 } | |
1071 } | 693 } |
1072 break; | 694 break; |
1073 ································ | 695 ································ |
1074 case TFM_MODAL_SNAP_INV_ON: | 696 case TFM_MODAL_SNAP_INV_ON: |
1075 t->modifiers |= MOD_SNAP_INVERT; | 697 t->modifiers |= MOD_SNAP_INVERT; |
1076 t->redraw |= TREDRAW_HARD; | 698 t->redraw |= TREDRAW_HARD; |
1077 break; | 699 break; |
1078 case TFM_MODAL_SNAP_INV_OFF: | 700 case TFM_MODAL_SNAP_INV_OFF: |
1079 t->modifiers &= ~MOD_SNAP_INVERT; | 701 t->modifiers &= ~MOD_SNAP_INVERT; |
1080 t->redraw |= TREDRAW_HARD; | 702 t->redraw |= TREDRAW_HARD; |
1081 break; | 703 break; |
1082 case TFM_MODAL_SNAP_TOGGLE: | 704 case TFM_MODAL_SNAP_TOGGLE: |
1083 t->modifiers ^= MOD_SNAP; | 705 t->modifiers ^= MOD_SNAP; |
1084 t->redraw |= TREDRAW_HARD; | 706 t->redraw |= TREDRAW_HARD; |
1085 break; | 707 break; |
1086 case TFM_MODAL_AXIS_X: | 708 case TFM_MODAL_AXIS_X: |
1087 » » » » if ((t->flag & T_NO_CONSTRAINT) == 0) { | 709 » » » » if ((t->flag & T_NO_CONSTRAINT)==0) { |
1088 if (cmode == 'X') { | 710 if (cmode == 'X') { |
1089 stopConstraint(t); | 711 stopConstraint(t); |
1090 } | 712 } |
1091 else { | 713 else { |
1092 if (t->flag & T_2D_EDIT) { | 714 if (t->flag & T_2D_EDIT) { |
1093 » » » » » » » setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X")); | 715 » » » » » » » setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS0), "along X"); |
1094 } | 716 } |
1095 else { | 717 else { |
1096 » » » » » » » setUserConstraint(t, t->
current_orientation, (CON_AXIS0), IFACE_("along %s X")); | 718 » » » » » » » setUserConstraint(t, t->
current_orientation, (CON_AXIS0), "along %s X"); |
1097 } | 719 } |
1098 } | 720 } |
1099 t->redraw |= TREDRAW_HARD; | 721 t->redraw |= TREDRAW_HARD; |
1100 } | 722 } |
1101 break; | 723 break; |
1102 case TFM_MODAL_AXIS_Y: | 724 case TFM_MODAL_AXIS_Y: |
1103 » » » » if ((t->flag & T_NO_CONSTRAINT) == 0) { | 725 » » » » if ((t->flag & T_NO_CONSTRAINT)==0) { |
1104 if (cmode == 'Y') { | 726 if (cmode == 'Y') { |
1105 stopConstraint(t); | 727 stopConstraint(t); |
1106 } | 728 } |
1107 else { | 729 else { |
1108 if (t->flag & T_2D_EDIT) { | 730 if (t->flag & T_2D_EDIT) { |
1109 » » » » » » » setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y")); | 731 » » » » » » » setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS1), "along Y"); |
1110 } | 732 } |
1111 else { | 733 else { |
1112 » » » » » » » setUserConstraint(t, t->
current_orientation, (CON_AXIS1), IFACE_("along %s Y")); | 734 » » » » » » » setUserConstraint(t, t->
current_orientation, (CON_AXIS1), "along %s Y"); |
1113 } | 735 } |
1114 } | 736 } |
1115 t->redraw |= TREDRAW_HARD; | 737 t->redraw |= TREDRAW_HARD; |
1116 } | 738 } |
1117 break; | 739 break; |
1118 case TFM_MODAL_AXIS_Z: | 740 case TFM_MODAL_AXIS_Z: |
1119 » » » » if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) ==
0) { | 741 » » » » if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0)
{ |
1120 if (cmode == 'Z') { | 742 if (cmode == 'Z') { |
1121 stopConstraint(t); | 743 stopConstraint(t); |
1122 } | 744 } |
1123 else { | 745 else { |
1124 » » » » » » setUserConstraint(t, t->current_
orientation, (CON_AXIS2), IFACE_("along %s Z")); | 746 » » » » » » setUserConstraint(t, t->current_
orientation, (CON_AXIS2), "along %s Z"); |
1125 } | 747 } |
1126 t->redraw |= TREDRAW_HARD; | 748 t->redraw |= TREDRAW_HARD; |
1127 } | 749 } |
1128 break; | 750 break; |
1129 case TFM_MODAL_PLANE_X: | 751 case TFM_MODAL_PLANE_X: |
1130 » » » » if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) ==
0) { | 752 » » » » if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0)
{ |
1131 if (cmode == 'X') { | 753 if (cmode == 'X') { |
1132 stopConstraint(t); | 754 stopConstraint(t); |
1133 } | 755 } |
| 756 else { |
| 757 setUserConstraint(t, t->current_
orientation, (CON_AXIS1|CON_AXIS2), "locking %s X"); |
| 758 } |
| 759 t->redraw |= TREDRAW_HARD; |
| 760 } |
| 761 break; |
| 762 case TFM_MODAL_PLANE_Y: |
| 763 if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0)
{ |
| 764 if (cmode == 'Y') { |
| 765 stopConstraint(t); |
| 766 } |
| 767 else { |
| 768 setUserConstraint(t, t->current_
orientation, (CON_AXIS0|CON_AXIS2), "locking %s Y"); |
| 769 } |
| 770 t->redraw |= TREDRAW_HARD; |
| 771 } |
| 772 break; |
| 773 case TFM_MODAL_PLANE_Z: |
| 774 if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))== 0)
{ |
| 775 if (cmode == 'Z') { |
| 776 stopConstraint(t); |
| 777 } |
| 778 else { |
| 779 setUserConstraint(t, t->current_
orientation, (CON_AXIS0|CON_AXIS1), "locking %s Z"); |
| 780 } |
| 781 t->redraw |= TREDRAW_HARD; |
| 782 } |
| 783 break; |
| 784 case TFM_MODAL_CONS_OFF: |
| 785 if ((t->flag & T_NO_CONSTRAINT)==0) { |
| 786 stopConstraint(t); |
| 787 t->redraw |= TREDRAW_HARD; |
| 788 } |
| 789 break; |
| 790 case TFM_MODAL_ADD_SNAP: |
| 791 addSnapPoint(t); |
| 792 t->redraw |= TREDRAW_HARD; |
| 793 break; |
| 794 case TFM_MODAL_REMOVE_SNAP: |
| 795 removeSnapPoint(t); |
| 796 t->redraw |= TREDRAW_HARD; |
| 797 break; |
| 798 case TFM_MODAL_PROPSIZE_UP: |
| 799 if (t->flag & T_PROP_EDIT) { |
| 800 t->prop_size*= 1.1f; |
| 801 if (t->spacetype==SPACE_VIEW3D && t->per
sp != RV3D_ORTHO) |
| 802 t->prop_size= MIN2(t->prop_size,
((View3D *)t->view)->far); |
| 803 calculatePropRatio(t); |
| 804 } |
| 805 t->redraw |= TREDRAW_HARD; |
| 806 break; |
| 807 case TFM_MODAL_PROPSIZE_DOWN: |
| 808 if (t->flag & T_PROP_EDIT) { |
| 809 t->prop_size*= 0.90909090f; |
| 810 calculatePropRatio(t); |
| 811 } |
| 812 t->redraw |= TREDRAW_HARD; |
| 813 break; |
| 814 case TFM_MODAL_AUTOIK_LEN_INC: |
| 815 if (t->flag & T_AUTOIK) |
| 816 transform_autoik_update(t, 1); |
| 817 t->redraw |= TREDRAW_HARD; |
| 818 break; |
| 819 case TFM_MODAL_AUTOIK_LEN_DEC: |
| 820 if (t->flag & T_AUTOIK)· |
| 821 transform_autoik_update(t, -1); |
| 822 t->redraw |= TREDRAW_HARD; |
| 823 break; |
| 824 default: |
| 825 handled = 0; |
| 826 break; |
| 827 } |
| 828 |
| 829 // Modal numinput events |
| 830 t->redraw |= handleNumInput(&(t->num), event); |
| 831 } |
| 832 /* else do non-mapped events */ |
| 833 else if (event->val == KM_PRESS) { |
| 834 switch (event->type) { |
| 835 case RIGHTMOUSE: |
| 836 t->state = TRANS_CANCEL; |
| 837 break; |
| 838 /* enforce redraw of transform when modifiers are used */ |
| 839 case LEFTSHIFTKEY: |
| 840 case RIGHTSHIFTKEY: |
| 841 t->modifiers |= MOD_CONSTRAINT_PLANE; |
| 842 t->redraw |= TREDRAW_HARD; |
| 843 break; |
| 844 |
| 845 case SPACEKEY: |
| 846 if ((t->spacetype==SPACE_VIEW3D) && event->alt) { |
| 847 #if 0 // TRANSFORM_FIX_ME |
| 848 int mval[2]; |
| 849 |
| 850 getmouseco_sc(mval); |
| 851 BIF_selectOrientation(); |
| 852 calc_manipulator_stats(curarea); |
| 853 copy_m3_m4(t->spacemtx, G.vd->twmat); |
| 854 warp_pointer(mval[0], mval[1]); |
| 855 #endif |
| 856 } |
| 857 else { |
| 858 t->state = TRANS_CONFIRM; |
| 859 } |
| 860 break; |
| 861 |
| 862 case MIDDLEMOUSE: |
| 863 if ((t->flag & T_NO_CONSTRAINT)==0) { |
| 864 /* exception for switching to dolly, or trackbal
l, in camera view */ |
| 865 if (t->flag & T_CAMERA) { |
| 866 if (t->mode==TFM_TRANSLATION) |
| 867 setLocalConstraint(t, (CON_AXIS2
), "along local Z"); |
| 868 else if (t->mode==TFM_ROTATION) { |
| 869 restoreTransObjects(t); |
| 870 initTrackball(t); |
| 871 } |
| 872 } |
| 873 else { |
| 874 t->modifiers |= MOD_CONSTRAINT_SELECT; |
| 875 if (t->con.mode & CON_APPLY) { |
| 876 stopConstraint(t); |
| 877 } |
| 878 else { |
| 879 if (event->shift) { |
| 880 initSelectConstraint(t,
t->spacemtx); |
| 881 } |
| 882 else { |
| 883 /* bit hackish... but it
prevents mmb select to print the orientation from menu */ |
| 884 strcpy(t->spacename, "gl
obal"); |
| 885 initSelectConstraint(t,
mati); |
| 886 } |
| 887 postSelectConstraint(t); |
| 888 } |
| 889 } |
| 890 t->redraw |= TREDRAW_HARD; |
| 891 } |
| 892 break; |
| 893 case ESCKEY: |
| 894 t->state = TRANS_CANCEL; |
| 895 break; |
| 896 case PADENTER: |
| 897 case RETKEY: |
| 898 t->state = TRANS_CONFIRM; |
| 899 break; |
| 900 case GKEY: |
| 901 /* only switch when... */ |
| 902 if ( ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKB
ALL) ) { |
| 903 resetTransRestrictions(t); |
| 904 restoreTransObjects(t); |
| 905 initTranslation(t); |
| 906 initSnapping(t, NULL); // need to reinit after m
ode change |
| 907 t->redraw |= TREDRAW_HARD; |
| 908 } |
| 909 break; |
| 910 case SKEY: |
| 911 /* only switch when... */ |
| 912 if ( ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_T
RACKBALL) ) { |
| 913 resetTransRestrictions(t); |
| 914 restoreTransObjects(t); |
| 915 initResize(t); |
| 916 initSnapping(t, NULL); // need to reinit after m
ode change |
| 917 t->redraw |= TREDRAW_HARD; |
| 918 } |
| 919 break; |
| 920 case RKEY: |
| 921 /* only switch when... */ |
| 922 if (!(t->options & CTX_TEXTURE) && !(t->options & CTX_MO
VIECLIP)) { |
| 923 if ( ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TF
M_TRACKBALL, TFM_TRANSLATION) ) { |
| 924 |
| 925 resetTransRestrictions(t); |
| 926 |
| 927 if (t->mode == TFM_ROTATION) { |
| 928 restoreTransObjects(t); |
| 929 initTrackball(t); |
| 930 } |
| 931 else { |
| 932 restoreTransObjects(t); |
| 933 initRotation(t); |
| 934 } |
| 935 initSnapping(t, NULL); // need to reinit
after mode change |
| 936 t->redraw |= TREDRAW_HARD; |
| 937 } |
| 938 } |
| 939 break; |
| 940 case CKEY: |
| 941 if (event->alt) { |
| 942 t->flag ^= T_PROP_CONNECTED; |
| 943 sort_trans_data_dist(t); |
| 944 calculatePropRatio(t); |
| 945 t->redraw= 1; |
| 946 } |
| 947 else { |
| 948 stopConstraint(t); |
| 949 t->redraw |= TREDRAW_HARD; |
| 950 } |
| 951 break; |
| 952 case XKEY: |
| 953 if ((t->flag & T_NO_CONSTRAINT)==0) { |
| 954 if (t->flag & T_2D_EDIT) { |
| 955 if (cmode == 'X') { |
| 956 stopConstraint(t); |
| 957 } |
| 958 else { |
| 959 setUserConstraint(t, V3D_MANIP_G
LOBAL, (CON_AXIS0), "along X"); |
| 960 } |
| 961 } |
| 962 else { |
| 963 if (cmode == 'X') { |
| 964 if (t->con.orientation != V3D_MA
NIP_GLOBAL) { |
| 965 stopConstraint(t); |
| 966 } |
| 967 else { |
| 968 short orientation = t->c
urrent_orientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCA
L; |
| 969 if ((t->modifiers & MOD_
CONSTRAINT_PLANE) == 0) |
| 970 setUserConstrain
t(t, orientation, (CON_AXIS0), "along %s X"); |
| 971 else if (t->modifiers &
MOD_CONSTRAINT_PLANE) |
| 972 setUserConstrain
t(t, orientation, (CON_AXIS1|CON_AXIS2), "locking %s X"); |
| 973 } |
| 974 } |
| 975 else { |
| 976 if ((t->modifiers & MOD_CONSTRAI
NT_PLANE) == 0) |
| 977 setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS0), "along %s X"); |
| 978 else if (t->modifiers & MOD_CONS
TRAINT_PLANE) |
| 979 setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS1|CON_AXIS2), "locking %s X"); |
| 980 } |
| 981 } |
| 982 t->redraw |= TREDRAW_HARD; |
| 983 } |
| 984 break; |
| 985 case YKEY: |
| 986 if ((t->flag & T_NO_CONSTRAINT)==0) { |
| 987 if (t->flag & T_2D_EDIT) { |
| 988 if (cmode == 'Y') { |
| 989 stopConstraint(t); |
| 990 } |
| 991 else { |
| 992 setUserConstraint(t, V3D_MANIP_G
LOBAL, (CON_AXIS1), "along Y"); |
| 993 } |
| 994 } |
| 995 else { |
| 996 if (cmode == 'Y') { |
| 997 if (t->con.orientation != V3D_MA
NIP_GLOBAL) { |
| 998 stopConstraint(t); |
| 999 } |
| 1000 else { |
| 1001 short orientation = t->c
urrent_orientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCA
L; |
| 1002 if ((t->modifiers & MOD_
CONSTRAINT_PLANE) == 0) |
| 1003 setUserConstrain
t(t, orientation, (CON_AXIS1), "along %s Y"); |
| 1004 else if (t->modifiers &
MOD_CONSTRAINT_PLANE) |
| 1005 setUserConstrain
t(t, orientation, (CON_AXIS0|CON_AXIS2), "locking %s Y"); |
| 1006 } |
| 1007 } |
| 1008 else { |
| 1009 if ((t->modifiers & MOD_CONSTRAI
NT_PLANE) == 0) |
| 1010 setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS1), "along %s Y"); |
| 1011 else if (t->modifiers & MOD_CONS
TRAINT_PLANE) |
| 1012 setUserConstraint(t, V3D
_MANIP_GLOBAL, (CON_AXIS0|CON_AXIS2), "locking %s Y"); |
| 1013 } |
| 1014 } |
| 1015 t->redraw |= TREDRAW_HARD; |
| 1016 } |
| 1017 break; |
| 1018 case ZKEY: |
| 1019 if ((t->flag & (T_NO_CONSTRAINT|T_2D_EDIT))==0) { |
| 1020 if (cmode == 'Z') { |
| 1021 if (t->con.orientation != V3D_MANIP_GLOB
AL) { |
| 1022 stopConstraint(t); |
| 1023 } |
| 1024 else { |
| 1025 short orientation = t->current_o
rientation != V3D_MANIP_GLOBAL ? t->current_orientation : V3D_MANIP_LOCAL; |
| 1026 if ((t->modifiers & MOD_CONSTRAI
NT_PLANE) == 0) |
| 1027 setUserConstraint(t, ori
entation, (CON_AXIS2), "along %s Z"); |
| 1028 else if (t->modifiers & MOD_CONS
TRAINT_PLANE) |
| 1029 setUserConstraint(t, ori
entation, (CON_AXIS0|CON_AXIS1), "locking %s Z"); |
| 1030 } |
| 1031 } |
| 1032 else { |
| 1033 if ((t->modifiers & MOD_CONSTRAINT_PLANE
) == 0) |
| 1034 setUserConstraint(t, V3D_MANIP_G
LOBAL, (CON_AXIS2), "along %s Z"); |
| 1035 else if (t->modifiers & MOD_CONSTRAINT_P
LANE) |
| 1036 setUserConstraint(t, V3D_MANIP_G
LOBAL, (CON_AXIS0|CON_AXIS1), "locking %s Z"); |
| 1037 } |
| 1038 t->redraw |= TREDRAW_HARD; |
| 1039 } |
| 1040 break; |
| 1041 case OKEY: |
| 1042 if (t->flag & T_PROP_EDIT && event->shift) { |
| 1043 t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MA
X; |
| 1044 calculatePropRatio(t); |
| 1045 t->redraw |= TREDRAW_HARD; |
| 1046 } |
| 1047 break; |
| 1048 case PADPLUSKEY: |
| 1049 if (event->alt && t->flag & T_PROP_EDIT) { |
| 1050 t->prop_size *= 1.1f; |
| 1051 if (t->spacetype==SPACE_VIEW3D && t->persp != RV
3D_ORTHO) |
| 1052 t->prop_size= MIN2(t->prop_size, ((View3
D *)t->view)->far); |
| 1053 calculatePropRatio(t); |
| 1054 } |
| 1055 t->redraw= 1; |
| 1056 break; |
| 1057 case PAGEUPKEY: |
| 1058 case WHEELDOWNMOUSE: |
| 1059 if (t->flag & T_AUTOIK) { |
| 1060 transform_autoik_update(t, 1); |
| 1061 } |
| 1062 else view_editmove(event->type); |
| 1063 t->redraw= 1; |
| 1064 break; |
| 1065 case PADMINUS: |
| 1066 if (event->alt && t->flag & T_PROP_EDIT) { |
| 1067 t->prop_size*= 0.90909090f; |
| 1068 calculatePropRatio(t); |
| 1069 } |
| 1070 t->redraw= 1; |
| 1071 break; |
| 1072 case PAGEDOWNKEY: |
| 1073 case WHEELUPMOUSE: |
| 1074 if (t->flag & T_AUTOIK) { |
| 1075 transform_autoik_update(t, -1); |
| 1076 } |
| 1077 else view_editmove(event->type); |
| 1078 t->redraw= 1; |
| 1079 break; |
| 1080 default: |
| 1081 handled = 0; |
| 1082 break; |
| 1083 } |
| 1084 |
| 1085 // Numerical input events |
| 1086 t->redraw |= handleNumInput(&(t->num), event); |
| 1087 |
| 1088 // Snapping key events |
| 1089 t->redraw |= handleSnapping(t, event); |
| 1090 |
| 1091 } |
| 1092 else if (event->val==KM_RELEASE) { |
| 1093 switch (event->type) { |
| 1094 case LEFTSHIFTKEY: |
| 1095 case RIGHTSHIFTKEY: |
| 1096 t->modifiers &= ~MOD_CONSTRAINT_PLANE; |
| 1097 t->redraw |= TREDRAW_HARD; |
| 1098 break; |
| 1099 |
| 1100 case MIDDLEMOUSE: |
| 1101 if ((t->flag & T_NO_CONSTRAINT)==0) { |
| 1102 t->modifiers &= ~MOD_CONSTRAINT_SELECT; |
| 1103 postSelectConstraint(t); |
| 1104 t->redraw |= TREDRAW_HARD; |
| 1105 } |
| 1106 break; |
| 1107 // case LEFTMOUSE: |
| 1108 // case RIGHTMOUSE: |
| 1109 // if (WM_modal_tweak_exit(event, t->event_type)) |
| 1110 //// if (t->options & CTX_TWEAK) |
| 1111 // t->state = TRANS_CONFIRM; |
| 1112 // break; |
| 1113 default: |
| 1114 handled = 0; |
| 1115 break; |
| 1116 } |
| 1117 |
| 1118 /* confirm transform if launch key is released after mouse move
*/ |
| 1119 if (t->flag & T_RELEASE_CONFIRM) { |
| 1120 /* XXX Keyrepeat bug in Xorg fucks this up, will test wh
en fixed */ |
| 1121 if (event->type == t->launch_event && (t->launch_event =
= LEFTMOUSE || t->launch_event == RIGHTMOUSE)) { |
| 1122 t->state = TRANS_CONFIRM; |
| 1123 } |
| 1124 } |
| 1125 } |
| 1126 |
| 1127 // Per transform event, if present |
| 1128 if (t->handleEvent) |
| 1129 t->redraw |= t->handleEvent(t, event); |
| 1130 |
| 1131 if (handled || t->redraw) |
| 1132 return 0; |
| 1133 else |
1134 return OPERATOR_PASS_THROUGH; | 1134 return OPERATOR_PASS_THROUGH; |
1135 } | 1135 } |
1136 | 1136 |
1137 int calculateTransformCenter(bContext *C, int centerMode, float *vec) | 1137 int calculateTransformCenter(bContext *C, int centerMode, float *cent3d, int *ce
nt2d) |
1138 { | 1138 { |
1139 TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); | 1139 TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); |
1140 int success = 1; | 1140 int success = 1; |
| 1141 |
| 1142 t->state = TRANS_RUNNING; |
| 1143 |
| 1144 t->options = CTX_NONE; |
| 1145 |
| 1146 t->mode = TFM_DUMMY; |
| 1147 |
| 1148 initTransInfo(C, t, NULL, NULL); // internal data, mouse, vectors |
| 1149 |
| 1150 createTransData(C, t); // make TransData struct
s from selection |
| 1151 |
| 1152 t->around = centerMode; // override userdefined
mode |
| 1153 |
| 1154 if (t->total == 0) { |
| 1155 success = 0; |
| 1156 } |
| 1157 else { |
| 1158 success = 1; |
| 1159 |
| 1160 calculateCenter(t); |
| 1161 |
| 1162 if(cent2d) |
| 1163 copy_v2_v2_int(cent2d, t->center2d); |
| 1164 if(cent3d) { |
| 1165 // Copy center from constraint center. Transform center
can be local |
| 1166 copy_v3_v3(cent3d, t->con.center); |
| 1167 } |
| 1168 } |
| 1169 |
| 1170 |
| 1171 /* aftertrans does insert ipos and action channels, and clears base flag
s, doesnt read transdata */ |
| 1172 special_aftertrans_update(C, t); |
| 1173 |
| 1174 postTrans(C, t); |
| 1175 |
| 1176 MEM_freeN(t); |
| 1177 |
| 1178 return success; |
| 1179 } |
| 1180 |
| 1181 typedef enum { |
| 1182 UP, |
| 1183 DOWN, |
| 1184 LEFT, |
| 1185 RIGHT |
| 1186 } ArrowDirection; |
| 1187 static void drawArrow(ArrowDirection d, short offset, short length, short size) |
| 1188 { |
| 1189 switch (d) { |
| 1190 case LEFT: |
| 1191 offset = -offset; |
| 1192 length = -length; |
| 1193 size = -size; |
| 1194 case RIGHT: |
| 1195 glBegin(GL_LINES); |
| 1196 glVertex2s(offset, 0); |
| 1197 glVertex2s(offset + length, 0); |
| 1198 glVertex2s(offset + length, 0); |
| 1199 glVertex2s(offset + length - size, -size); |
| 1200 glVertex2s(offset + length, 0); |
| 1201 glVertex2s(offset + length - size, size); |
| 1202 glEnd(); |
| 1203 break; |
| 1204 case DOWN: |
| 1205 offset = -offset; |
| 1206 length = -length; |
| 1207 size = -size; |
| 1208 case UP: |
| 1209 glBegin(GL_LINES); |
| 1210 glVertex2s(0, offset); |
| 1211 glVertex2s(0, offset + length); |
| 1212 glVertex2s(0, offset + length); |
| 1213 glVertex2s(-size, offset + length - size); |
| 1214 glVertex2s(0, offset + length); |
| 1215 glVertex2s(size, offset + length - size); |
| 1216 glEnd(); |
| 1217 break; |
| 1218 } |
| 1219 } |
| 1220 |
| 1221 static void drawArrowHead(ArrowDirection d, short size) |
| 1222 { |
| 1223 switch (d) { |
| 1224 case LEFT: |
| 1225 size = -size; |
| 1226 case RIGHT: |
| 1227 glBegin(GL_LINES); |
| 1228 glVertex2s(0, 0); |
| 1229 glVertex2s(-size, -size); |
| 1230 glVertex2s(0, 0); |
| 1231 glVertex2s(-size, size); |
| 1232 glEnd(); |
| 1233 break; |
| 1234 case DOWN: |
| 1235 size = -size; |
| 1236 case UP: |
| 1237 glBegin(GL_LINES); |
| 1238 glVertex2s(0, 0); |
| 1239 glVertex2s(-size, -size); |
| 1240 glVertex2s(0, 0); |
| 1241 glVertex2s(size, -size); |
| 1242 glEnd(); |
| 1243 break; |
| 1244 } |
| 1245 } |
| 1246 |
| 1247 static void drawArc(float size, float angle_start, float angle_end, int segments
) |
| 1248 { |
| 1249 float delta = (angle_end - angle_start) / segments; |
| 1250 float angle; |
| 1251 |
| 1252 glBegin(GL_LINE_STRIP); |
| 1253 |
| 1254 for ( angle = angle_start; angle < angle_end; angle += delta) { |
| 1255 glVertex2f(cosf(angle) * size, sinf(angle) * size); |
| 1256 } |
| 1257 glVertex2f(cosf(angle_end) * size, sinf(angle_end) * size); |
| 1258 |
| 1259 glEnd(); |
| 1260 } |
| 1261 |
| 1262 static int helpline_poll(bContext *C) |
| 1263 { |
| 1264 ARegion *ar= CTX_wm_region(C); |
| 1265 ········ |
| 1266 if (ar && ar->regiontype==RGN_TYPE_WINDOW) |
| 1267 return 1; |
| 1268 return 0; |
| 1269 } |
| 1270 |
| 1271 static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) |
| 1272 { |
| 1273 TransInfo *t = (TransInfo*)customdata; |
| 1274 |
| 1275 if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) { |
| 1276 float vecrot[3], cent[2]; |
| 1277 int mval[2]; |
| 1278 |
| 1279 mval[0]= x; |
| 1280 mval[1]= y; |
| 1281 |
| 1282 copy_v3_v3(vecrot, t->center); |
| 1283 if (t->flag & T_EDIT) { |
| 1284 Object *ob= t->obedit; |
| 1285 if (ob) mul_m4_v3(ob->obmat, vecrot); |
| 1286 } |
| 1287 else if (t->flag & T_POSE) { |
| 1288 Object *ob=t->poseobj; |
| 1289 if (ob) mul_m4_v3(ob->obmat, vecrot); |
| 1290 } |
| 1291 |
| 1292 projectFloatView(t, vecrot, cent); // no overflow in extrem
e cases |
| 1293 |
| 1294 glPushMatrix(); |
| 1295 |
| 1296 switch (t->helpline) { |
| 1297 case HLP_SPRING: |
| 1298 UI_ThemeColor(TH_WIRE); |
| 1299 |
| 1300 setlinestyle(3); |
| 1301 glBegin(GL_LINE_STRIP); |
| 1302 glVertex2iv(t->mval); |
| 1303 glVertex2fv(cent); |
| 1304 glEnd(); |
| 1305 |
| 1306 glTranslatef(mval[0], mval[1], 0); |
| 1307 glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0],
cent[1] - t->mval[1])), 0, 0, 1); |
| 1308 |
| 1309 setlinestyle(0); |
| 1310 glLineWidth(3.0); |
| 1311 drawArrow(UP, 5, 10, 5); |
| 1312 drawArrow(DOWN, 5, 10, 5); |
| 1313 glLineWidth(1.0); |
| 1314 break; |
| 1315 case HLP_HARROW: |
| 1316 UI_ThemeColor(TH_WIRE); |
| 1317 |
| 1318 glTranslatef(mval[0], mval[1], 0); |
| 1319 |
| 1320 glLineWidth(3.0); |
| 1321 drawArrow(RIGHT, 5, 10, 5); |
| 1322 drawArrow(LEFT, 5, 10, 5); |
| 1323 glLineWidth(1.0); |
| 1324 break; |
| 1325 case HLP_VARROW: |
| 1326 UI_ThemeColor(TH_WIRE); |
| 1327 |
| 1328 glTranslatef(mval[0], mval[1], 0); |
| 1329 |
| 1330 glLineWidth(3.0); |
| 1331 glBegin(GL_LINES); |
| 1332 drawArrow(UP, 5, 10, 5); |
| 1333 drawArrow(DOWN, 5, 10, 5); |
| 1334 glLineWidth(1.0); |
| 1335 break; |
| 1336 case HLP_ANGLE: |
| 1337 { |
| 1338 float dx = t->mval[0] - cent[0], dy = t-
>mval[1] - cent[1]; |
| 1339 float angle = atan2f(dy, dx); |
| 1340 float dist = sqrtf(dx*dx + dy*dy); |
| 1341 float delta_angle = MIN2(15.0f / dist, (
float)M_PI/4.0f); |
| 1342 float spacing_angle = MIN2(5.0f / dist,
(float)M_PI/12.0f); |
| 1343 UI_ThemeColor(TH_WIRE); |
| 1344 |
| 1345 setlinestyle(3); |
| 1346 glBegin(GL_LINE_STRIP); |
| 1347 glVertex2iv(t->mval); |
| 1348 glVertex2fv(cent); |
| 1349 glEnd(); |
| 1350 |
| 1351 glTranslatef(cent[0] - t->mval[0] + mval
[0], cent[1] - t->mval[1] + mval[1], 0); |
| 1352 |
| 1353 setlinestyle(0); |
| 1354 glLineWidth(3.0); |
| 1355 drawArc(dist, angle - delta_angle, angle
- spacing_angle, 10); |
| 1356 drawArc(dist, angle + spacing_angle, ang
le + delta_angle, 10); |
| 1357 |
| 1358 glPushMatrix(); |
| 1359 |
| 1360 glTranslatef(cosf(angle - delta_angle) *
dist, sinf(angle - delta_angle) * dist, 0); |
| 1361 glRotatef(RAD2DEGF(angle - delta_angle),
0, 0, 1); |
| 1362 |
| 1363 drawArrowHead(DOWN, 5); |
| 1364 |
| 1365 glPopMatrix(); |
| 1366 |
| 1367 glTranslatef(cosf(angle + delta_angle) *
dist, sinf(angle + delta_angle) * dist, 0); |
| 1368 glRotatef(RAD2DEGF(angle + delta_angle),
0, 0, 1); |
| 1369 |
| 1370 drawArrowHead(UP, 5); |
| 1371 |
| 1372 glLineWidth(1.0); |
| 1373 break; |
| 1374 } |
| 1375 case HLP_TRACKBALL: |
| 1376 { |
| 1377 unsigned char col[3], col2[3]; |
| 1378 UI_GetThemeColor3ubv(TH_GRID, col); |
| 1379 |
| 1380 glTranslatef(mval[0], mval[1], 0); |
| 1381 |
| 1382 glLineWidth(3.0); |
| 1383 |
| 1384 UI_make_axis_color(col, col2, 'X'); |
| 1385 glColor3ubv((GLubyte *)col2); |
| 1386 |
| 1387 drawArrow(RIGHT, 5, 10, 5); |
| 1388 drawArrow(LEFT, 5, 10, 5); |
| 1389 |
| 1390 UI_make_axis_color(col, col2, 'Y'); |
| 1391 glColor3ubv((GLubyte *)col2); |
| 1392 |
| 1393 drawArrow(UP, 5, 10, 5); |
| 1394 drawArrow(DOWN, 5, 10, 5); |
| 1395 glLineWidth(1.0); |
| 1396 break; |
| 1397 } |
| 1398 } |
| 1399 |
| 1400 glPopMatrix(); |
| 1401 } |
| 1402 } |
| 1403 |
| 1404 static void drawTransformView(const struct bContext *C, struct ARegion *UNUSED(a
r), void *arg) |
| 1405 { |
| 1406 TransInfo *t = arg; |
| 1407 |
| 1408 drawConstraint(t); |
| 1409 drawPropCircle(C, t); |
| 1410 drawSnapping(C, t); |
| 1411 } |
| 1412 |
| 1413 #if 0 |
| 1414 static void drawTransformPixel(const struct bContext *UNUSED(C), struct ARegion
*UNUSED(ar), void *UNUSED(arg)) |
| 1415 { |
| 1416 // TransInfo *t = arg; |
| 1417 // |
| 1418 // drawHelpline(C, t->mval[0], t->mval[1], t); |
| 1419 } |
| 1420 #endif |
| 1421 |
| 1422 void saveTransform(bContext *C, TransInfo *t, wmOperator *op) |
| 1423 { |
| 1424 ToolSettings *ts = CTX_data_tool_settings(C); |
| 1425 int constraint_axis[3] = {0, 0, 0}; |
| 1426 int proportional = 0; |
| 1427 PropertyRNA *prop; |
| 1428 |
| 1429 // Save back mode in case we're in the generic operator |
| 1430 if ((prop= RNA_struct_find_property(op->ptr, "mode"))) { |
| 1431 RNA_property_enum_set(op->ptr, prop, t->mode); |
| 1432 } |
| 1433 |
| 1434 if ((prop= RNA_struct_find_property(op->ptr, "value"))) { |
| 1435 float *values= (t->flag & T_AUTOVALUES) ? t->auto_values : t->va
lues; |
| 1436 if (RNA_property_array_check(prop)) { |
| 1437 RNA_property_float_set_array(op->ptr, prop, values); |
| 1438 } |
| 1439 else { |
| 1440 RNA_property_float_set(op->ptr, prop, values[0]); |
| 1441 } |
| 1442 } |
| 1443 |
| 1444 /* convert flag to enum */ |
| 1445 switch (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) { |
| 1446 case (T_PROP_EDIT|T_PROP_CONNECTED): |
| 1447 proportional = PROP_EDIT_CONNECTED; |
| 1448 break; |
| 1449 case T_PROP_EDIT: |
| 1450 proportional = PROP_EDIT_ON; |
| 1451 break; |
| 1452 default: |
| 1453 proportional = PROP_EDIT_OFF; |
| 1454 } |
| 1455 |
| 1456 // If modal, save settings back in scene if not set as operator argument |
| 1457 if (t->flag & T_MODAL) { |
| 1458 |
| 1459 /* save settings if not set in operator */ |
| 1460 if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &
& |
| 1461 !RNA_property_is_set(op->ptr, prop)) |
| 1462 { |
| 1463 if (t->obedit) |
| 1464 ts->proportional = proportional; |
| 1465 else |
| 1466 ts->proportional_objects = (proportional != PROP
_EDIT_OFF); |
| 1467 } |
| 1468 |
| 1469 if ((prop = RNA_struct_find_property(op->ptr, "proportional_size
")) && |
| 1470 !RNA_property_is_set(op->ptr, prop)) |
| 1471 { |
| 1472 ts->proportional_size = t->prop_size; |
| 1473 } |
| 1474 |
| 1475 if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit
_falloff")) && |
| 1476 !RNA_property_is_set(op->ptr, prop)) |
| 1477 { |
| 1478 ts->prop_mode = t->prop_mode; |
| 1479 } |
| 1480 ················ |
| 1481 /* do we check for parameter? */ |
| 1482 if (t->modifiers & MOD_SNAP) { |
| 1483 ts->snap_flag |= SCE_SNAP; |
| 1484 } |
| 1485 else { |
| 1486 ts->snap_flag &= ~SCE_SNAP; |
| 1487 } |
| 1488 |
| 1489 if (t->spacetype == SPACE_VIEW3D) { |
| 1490 if ((prop = RNA_struct_find_property(op->ptr, "constrain
t_orientation")) && |
| 1491 !RNA_property_is_set(op->ptr, prop)) |
| 1492 { |
| 1493 View3D *v3d = t->view; |
| 1494 |
| 1495 v3d->twmode = t->current_orientation; |
| 1496 } |
| 1497 } |
| 1498 } |
| 1499 ········ |
| 1500 if (RNA_struct_find_property(op->ptr, "proportional")) { |
| 1501 RNA_enum_set(op->ptr, "proportional", proportional); |
| 1502 RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode)
; |
| 1503 RNA_float_set(op->ptr, "proportional_size", t->prop_size); |
| 1504 } |
| 1505 |
| 1506 if ((prop = RNA_struct_find_property(op->ptr, "axis"))) { |
| 1507 RNA_property_float_set_array(op->ptr, prop, t->axis); |
| 1508 } |
| 1509 |
| 1510 if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) { |
| 1511 RNA_property_boolean_set(op->ptr, prop, t->flag & T_MIRROR); |
| 1512 } |
| 1513 |
| 1514 if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { |
| 1515 /* constraint orientation can be global, event if user selects s
omething else |
| 1516 * so use the orientation in the constraint if set |
| 1517 * */ |
| 1518 if (t->con.mode & CON_APPLY) { |
| 1519 RNA_enum_set(op->ptr, "constraint_orientation", t->con.o
rientation); |
| 1520 } |
| 1521 else { |
| 1522 RNA_enum_set(op->ptr, "constraint_orientation", t->curre
nt_orientation); |
| 1523 } |
| 1524 |
| 1525 if (t->con.mode & CON_APPLY) { |
| 1526 if (t->con.mode & CON_AXIS0) { |
| 1527 constraint_axis[0] = 1; |
| 1528 } |
| 1529 if (t->con.mode & CON_AXIS1) { |
| 1530 constraint_axis[1] = 1; |
| 1531 } |
| 1532 if (t->con.mode & CON_AXIS2) { |
| 1533 constraint_axis[2] = 1; |
| 1534 } |
| 1535 } |
| 1536 |
| 1537 RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); |
| 1538 } |
| 1539 } |
| 1540 |
| 1541 /* note: caller needs to free 't' on a 0 return */ |
| 1542 int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
mode) |
| 1543 { |
| 1544 int options = 0; |
| 1545 PropertyRNA *prop; |
| 1546 |
| 1547 t->context = C; |
| 1548 |
| 1549 /* added initialize, for external calls to set stuff in TransInfo, like
undo string */ |
| 1550 |
| 1551 t->state = TRANS_STARTING; |
| 1552 |
| 1553 if ( (prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_
property_is_set(op->ptr, prop)) { |
| 1554 if (RNA_property_boolean_get(op->ptr, prop)) { |
| 1555 options |= CTX_TEXTURE; |
| 1556 } |
| 1557 } |
| 1558 ········ |
| 1559 t->options = options; |
| 1560 |
| 1561 t->mode = mode; |
| 1562 |
| 1563 t->launch_event = event ? event->type : -1; |
| 1564 |
| 1565 if (t->launch_event == EVT_TWEAK_R) { |
| 1566 t->launch_event = RIGHTMOUSE; |
| 1567 } |
| 1568 else if (t->launch_event == EVT_TWEAK_L) { |
| 1569 t->launch_event = LEFTMOUSE; |
| 1570 } |
| 1571 |
| 1572 // XXX Remove this when wm_operator_call_internal doesn't use window->ev
entstate (which can have type = 0) |
| 1573 // For manipulator only, so assume LEFTMOUSE |
| 1574 if (t->launch_event == 0) { |
| 1575 t->launch_event = LEFTMOUSE; |
| 1576 } |
| 1577 |
| 1578 if (!initTransInfo(C, t, op, event)) { /* internal data, mouse, vectors
*/ |
| 1579 return 0; |
| 1580 } |
| 1581 |
| 1582 if (t->spacetype == SPACE_VIEW3D) { |
| 1583 //calc_manipulator_stats(curarea); |
| 1584 initTransformOrientation(C, t); |
| 1585 |
| 1586 t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, d
rawTransformApply, t, REGION_DRAW_PRE_VIEW); |
| 1587 t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, dr
awTransformView, t, REGION_DRAW_POST_VIEW); |
| 1588 //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type,
drawTransformPixel, t, REGION_DRAW_POST_PIXEL); |
| 1589 t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(
C), helpline_poll, drawHelpline, t); |
| 1590 } |
| 1591 else if (t->spacetype == SPACE_IMAGE) { |
| 1592 unit_m3(t->spacemtx); |
| 1593 t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, dr
awTransformView, t, REGION_DRAW_POST_VIEW); |
| 1594 //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type,
drawTransformPixel, t, REGION_DRAW_POST_PIXEL); |
| 1595 t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(
C), helpline_poll, drawHelpline, t); |
| 1596 } |
| 1597 else if (t->spacetype == SPACE_CLIP) { |
| 1598 unit_m3(t->spacemtx); |
| 1599 t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, dr
awTransformView, t, REGION_DRAW_POST_VIEW); |
| 1600 t->options |= CTX_MOVIECLIP; |
| 1601 } |
| 1602 else |
| 1603 unit_m3(t->spacemtx); |
| 1604 |
| 1605 createTransData(C, t); // make TransData structs from s
election |
| 1606 |
| 1607 if (t->total == 0) { |
| 1608 postTrans(C, t); |
| 1609 return 0; |
| 1610 } |
| 1611 |
| 1612 /* Stupid code to have Ctrl-Click on manipulator work ok */ |
| 1613 if (event) { |
| 1614 wmKeyMap *keymap = WM_keymap_active(CTX_wm_manager(C), op->type-
>modalkeymap); |
| 1615 wmKeyMapItem *kmi; |
| 1616 |
| 1617 for (kmi = keymap->items.first; kmi; kmi = kmi->next) { |
| 1618 if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val
== KM_PRESS) { |
| 1619 if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY)
&& event->ctrl) || |
| 1620 (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY
) && event->shift) || |
| 1621 (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) &&
event->alt) || |
| 1622 ((kmi->type == OSKEY) &&
event->oskey) ) |
| 1623 { |
| 1624 t->modifiers |= MOD_SNAP_INVERT; |
| 1625 } |
| 1626 break; |
| 1627 } |
| 1628 } |
| 1629 |
| 1630 } |
| 1631 |
| 1632 initSnapping(t, op); // Initialize snapping data AFTER mode flags |
| 1633 |
| 1634 /* EVIL! posemode code can switch translation to rotate when 1 bone is s
elected. will be removed (ton) */ |
| 1635 /* EVIL2: we gave as argument also texture space context bit... was clea
red */ |
| 1636 /* EVIL3: extend mode for animation editors also switches modes... but i
s best way to avoid duplicate code */ |
| 1637 mode = t->mode; |
| 1638 |
| 1639 calculatePropRatio(t); |
| 1640 calculateCenter(t); |
| 1641 |
| 1642 initMouseInput(t, &t->mouse, t->center2d, t->imval); |
| 1643 |
| 1644 switch (mode) { |
| 1645 case TFM_TRANSLATION: |
| 1646 initTranslation(t); |
| 1647 break; |
| 1648 case TFM_ROTATION: |
| 1649 initRotation(t); |
| 1650 break; |
| 1651 case TFM_RESIZE: |
| 1652 initResize(t); |
| 1653 break; |
| 1654 case TFM_TOSPHERE: |
| 1655 initToSphere(t); |
| 1656 break; |
| 1657 case TFM_SHEAR: |
| 1658 initShear(t); |
| 1659 break; |
| 1660 case TFM_WARP: |
| 1661 initWarp(t); |
| 1662 break; |
| 1663 case TFM_SHRINKFATTEN: |
| 1664 initShrinkFatten(t); |
| 1665 break; |
| 1666 case TFM_TILT: |
| 1667 initTilt(t); |
| 1668 break; |
| 1669 case TFM_CURVE_SHRINKFATTEN: |
| 1670 initCurveShrinkFatten(t); |
| 1671 break; |
| 1672 case TFM_TRACKBALL: |
| 1673 initTrackball(t); |
| 1674 break; |
| 1675 case TFM_PUSHPULL: |
| 1676 initPushPull(t); |
| 1677 break; |
| 1678 case TFM_CREASE: |
| 1679 initCrease(t); |
| 1680 break; |
| 1681 case TFM_BONESIZE: |
| 1682 { /* used for both B-Bone width (bonesize) as for deform-d
ist (envelope) */ |
| 1683 bArmature *arm= t->poseobj->data; |
| 1684 if (arm->drawtype==ARM_ENVELOPE) |
| 1685 initBoneEnvelope(t); |
| 1686 else |
| 1687 initBoneSize(t); |
| 1688 } |
| 1689 break; |
| 1690 case TFM_BONE_ENVELOPE: |
| 1691 initBoneEnvelope(t); |
| 1692 break; |
| 1693 case TFM_EDGE_SLIDE: |
| 1694 initEdgeSlide(t); |
| 1695 break; |
| 1696 case TFM_BONE_ROLL: |
| 1697 initBoneRoll(t); |
| 1698 break; |
| 1699 case TFM_TIME_TRANSLATE: |
| 1700 initTimeTranslate(t); |
| 1701 break; |
| 1702 case TFM_TIME_SLIDE: |
| 1703 initTimeSlide(t); |
| 1704 break; |
| 1705 case TFM_TIME_SCALE: |
| 1706 initTimeScale(t); |
| 1707 break; |
| 1708 case TFM_TIME_DUPLICATE: |
| 1709 /* same as TFM_TIME_EXTEND, but we need the mode info for later· |
| 1710 * so that duplicate-culling will work properly |
| 1711 */ |
| 1712 if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) |
| 1713 initTranslation(t); |
| 1714 else |
| 1715 initTimeTranslate(t); |
| 1716 t->mode = mode; |
| 1717 break; |
| 1718 case TFM_TIME_EXTEND: |
| 1719 /* now that transdata has been made, do like for TFM_TIME_TRANSL
ATE (for most Animation |
| 1720 * Editors because they have only 1D transforms for time values)
or TFM_TRANSLATION |
| 1721 * (for Graph/NLA Editors only since they uses 'standard' transf
orms to get 2D movement) |
| 1722 * depending on which editor this was called from |
| 1723 */ |
| 1724 if (ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) |
| 1725 initTranslation(t); |
| 1726 else |
| 1727 initTimeTranslate(t); |
| 1728 break; |
| 1729 case TFM_BAKE_TIME: |
| 1730 initBakeTime(t); |
| 1731 break; |
| 1732 case TFM_MIRROR: |
| 1733 initMirror(t); |
| 1734 break; |
| 1735 case TFM_BEVEL: |
| 1736 initBevel(t); |
| 1737 break; |
| 1738 case TFM_BWEIGHT: |
| 1739 initBevelWeight(t); |
| 1740 break; |
| 1741 case TFM_ALIGN: |
| 1742 initAlign(t); |
| 1743 break; |
| 1744 case TFM_SEQ_SLIDE: |
| 1745 initSeqSlide(t); |
| 1746 break; |
| 1747 } |
| 1748 |
| 1749 if (t->state == TRANS_CANCEL) { |
| 1750 postTrans(C, t); |
| 1751 return 0; |
| 1752 } |
| 1753 |
| 1754 |
| 1755 /* overwrite initial values if operator supplied a non-null vector */ |
| 1756 if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_
is_set(op->ptr, prop)) { |
| 1757 float values[4]= {0}; /* in case value isn't length 4, avoid uni
nitialized memory */ |
| 1758 |
| 1759 if (RNA_property_array_check(prop)) { |
| 1760 RNA_float_get_array(op->ptr, "value", values); |
| 1761 } |
| 1762 else { |
| 1763 values[0]= RNA_float_get(op->ptr, "value"); |
| 1764 } |
| 1765 |
| 1766 copy_v4_v4(t->values, values); |
| 1767 copy_v4_v4(t->auto_values, values); |
| 1768 t->flag |= T_AUTOVALUES; |
| 1769 } |
| 1770 |
| 1771 /* Transformation axis from operator */ |
| 1772 if ((prop = RNA_struct_find_property(op->ptr, "axis")) && RNA_property_i
s_set(op->ptr, prop)) { |
| 1773 RNA_property_float_get_array(op->ptr, prop, t->axis); |
| 1774 normalize_v3(t->axis); |
| 1775 copy_v3_v3(t->axis_orig, t->axis); |
| 1776 } |
| 1777 |
| 1778 /* Constraint init from operator */ |
| 1779 if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && RNA
_property_is_set(op->ptr, prop)) { |
| 1780 int constraint_axis[3]; |
| 1781 |
| 1782 RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); |
| 1783 |
| 1784 if (constraint_axis[0] || constraint_axis[1] || constraint_axis[
2]) { |
| 1785 t->con.mode |= CON_APPLY; |
| 1786 |
| 1787 if (constraint_axis[0]) { |
| 1788 t->con.mode |= CON_AXIS0; |
| 1789 } |
| 1790 if (constraint_axis[1]) { |
| 1791 t->con.mode |= CON_AXIS1; |
| 1792 } |
| 1793 if (constraint_axis[2]) { |
| 1794 t->con.mode |= CON_AXIS2; |
| 1795 } |
| 1796 |
| 1797 setUserConstraint(t, t->current_orientation, t->con.mode
, "%s"); |
| 1798 } |
| 1799 } |
| 1800 |
| 1801 t->context = NULL; |
| 1802 |
| 1803 return 1; |
| 1804 } |
| 1805 |
| 1806 void transformApply(bContext *C, TransInfo *t) |
| 1807 { |
| 1808 t->context = C; |
| 1809 |
| 1810 if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->r
edraw & TREDRAW_SOFT))) { |
| 1811 selectConstraint(t); |
| 1812 if (t->transform) { |
| 1813 t->transform(t, t->mval); // calls recalcData() |
| 1814 viewRedrawForce(C, t); |
| 1815 } |
| 1816 t->redraw = TREDRAW_NOTHING; |
| 1817 } |
| 1818 else if (t->redraw & TREDRAW_SOFT) { |
| 1819 viewRedrawForce(C, t); |
| 1820 } |
| 1821 |
| 1822 /* If auto confirm is on, break after one pass */ |
| 1823 if (t->options & CTX_AUTOCONFIRM) { |
| 1824 t->state = TRANS_CONFIRM; |
| 1825 } |
| 1826 |
| 1827 if (BKE_ptcache_get_continue_physics()) { |
| 1828 // TRANSFORM_FIX_ME |
| 1829 //do_screenhandlers(G.curscreen); |
| 1830 t->redraw |= TREDRAW_HARD; |
| 1831 } |
| 1832 |
| 1833 t->context = NULL; |
| 1834 } |
| 1835 |
| 1836 static void drawTransformApply(const bContext *C, struct ARegion *UNUSED(ar), vo
id *arg) |
| 1837 { |
| 1838 TransInfo *t = arg; |
| 1839 |
| 1840 if (t->redraw & TREDRAW_SOFT) { |
| 1841 t->redraw |= TREDRAW_HARD; |
| 1842 transformApply((bContext *)C, t); |
| 1843 } |
| 1844 } |
| 1845 |
| 1846 int transformEnd(bContext *C, TransInfo *t) |
| 1847 { |
| 1848 int exit_code = OPERATOR_RUNNING_MODAL; |
| 1849 |
| 1850 t->context = C; |
| 1851 |
| 1852 if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) { |
| 1853 /* handle restoring objects */ |
| 1854 if (t->state == TRANS_CANCEL) { |
| 1855 /* exception, edge slide transformed UVs too */ |
| 1856 if (t->mode==TFM_EDGE_SLIDE) |
| 1857 doEdgeSlide(t, 0.0f); |
| 1858 ························ |
| 1859 exit_code = OPERATOR_CANCELLED; |
| 1860 restoreTransObjects(t); // calls recalcData() |
| 1861 } |
| 1862 else { |
| 1863 exit_code = OPERATOR_FINISHED; |
| 1864 } |
| 1865 |
| 1866 /* aftertrans does insert keyframes, and clears base flags, does
nt read transdata */ |
| 1867 special_aftertrans_update(C, t); |
| 1868 |
| 1869 /* free data */ |
| 1870 postTrans(C, t); |
| 1871 |
| 1872 /* send events out for redraws */ |
| 1873 viewRedrawPost(C, t); |
| 1874 |
| 1875 /* Undo as last, certainly after special_trans_update! */ |
| 1876 |
| 1877 if (t->state == TRANS_CANCEL) { |
| 1878 // if (t->undostr) ED_undo_push(C, t->undostr); |
| 1879 } |
| 1880 else { |
| 1881 // if (t->undostr) ED_undo_push(C, t->undostr); |
| 1882 // else ED_undo_push(C, transform_to_undostr(t)); |
| 1883 } |
| 1884 t->undostr= NULL; |
| 1885 |
| 1886 viewRedrawForce(C, t); |
| 1887 } |
| 1888 |
| 1889 t->context = NULL; |
| 1890 |
| 1891 return exit_code; |
| 1892 } |
| 1893 |
| 1894 /* ************************** TRANSFORM LOCKS **************************** */ |
| 1895 |
| 1896 static void protectedTransBits(short protectflag, float *vec) |
| 1897 { |
| 1898 if (protectflag & OB_LOCK_LOCX) |
| 1899 vec[0]= 0.0f; |
| 1900 if (protectflag & OB_LOCK_LOCY) |
| 1901 vec[1]= 0.0f; |
| 1902 if (protectflag & OB_LOCK_LOCZ) |
| 1903 vec[2]= 0.0f; |
| 1904 } |
| 1905 |
| 1906 static void protectedSizeBits(short protectflag, float *size) |
| 1907 { |
| 1908 if (protectflag & OB_LOCK_SCALEX) |
| 1909 size[0]= 1.0f; |
| 1910 if (protectflag & OB_LOCK_SCALEY) |
| 1911 size[1]= 1.0f; |
| 1912 if (protectflag & OB_LOCK_SCALEZ) |
| 1913 size[2]= 1.0f; |
| 1914 } |
| 1915 |
| 1916 static void protectedRotateBits(short protectflag, float *eul, float *oldeul) |
| 1917 { |
| 1918 if (protectflag & OB_LOCK_ROTX) |
| 1919 eul[0]= oldeul[0]; |
| 1920 if (protectflag & OB_LOCK_ROTY) |
| 1921 eul[1]= oldeul[1]; |
| 1922 if (protectflag & OB_LOCK_ROTZ) |
| 1923 eul[2]= oldeul[2]; |
| 1924 } |
| 1925 |
| 1926 |
| 1927 /* this function only does the delta rotation */ |
| 1928 /* axis-angle is usually internally stored as quats... */ |
| 1929 static void protectedAxisAngleBits(short protectflag, float axis[3], float *angl
e, float oldAxis[3], float oldAngle) |
| 1930 { |
| 1931 /* check that protection flags are set */ |
| 1932 if ((protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)
) == 0) |
| 1933 return; |
| 1934 ········ |
| 1935 if (protectflag & OB_LOCK_ROT4D) { |
| 1936 /* axis-angle getting limited as 4D entities that they are... */ |
| 1937 if (protectflag & OB_LOCK_ROTW) |
| 1938 *angle= oldAngle; |
| 1939 if (protectflag & OB_LOCK_ROTX) |
| 1940 axis[0]= oldAxis[0]; |
| 1941 if (protectflag & OB_LOCK_ROTY) |
| 1942 axis[1]= oldAxis[1]; |
| 1943 if (protectflag & OB_LOCK_ROTZ) |
| 1944 axis[2]= oldAxis[2]; |
| 1945 } |
| 1946 else { |
| 1947 /* axis-angle get limited with euler... */ |
| 1948 float eul[3], oldeul[3]; |
| 1949 ················ |
| 1950 axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle); |
| 1951 axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngl
e); |
| 1952 ················ |
| 1953 if (protectflag & OB_LOCK_ROTX) |
| 1954 eul[0]= oldeul[0]; |
| 1955 if (protectflag & OB_LOCK_ROTY) |
| 1956 eul[1]= oldeul[1]; |
| 1957 if (protectflag & OB_LOCK_ROTZ) |
| 1958 eul[2]= oldeul[2]; |
| 1959 ················ |
| 1960 eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT); |
| 1961 ················ |
| 1962 /* when converting to axis-angle, we need a special exception fo
r the case when there is no axis */ |
| 1963 if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) { |
| 1964 /* for now, rotate around y-axis then (so that it simply
becomes the roll) */ |
| 1965 axis[1]= 1.0f; |
| 1966 } |
| 1967 } |
| 1968 } |
| 1969 |
| 1970 /* this function only does the delta rotation */ |
| 1971 static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
at) |
| 1972 { |
| 1973 /* check that protection flags are set */ |
| 1974 if ((protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)
) == 0) |
| 1975 return; |
| 1976 ········ |
| 1977 if (protectflag & OB_LOCK_ROT4D) { |
| 1978 /* quaternions getting limited as 4D entities that they are... *
/ |
| 1979 if (protectflag & OB_LOCK_ROTW) |
| 1980 quat[0]= oldquat[0]; |
| 1981 if (protectflag & OB_LOCK_ROTX) |
| 1982 quat[1]= oldquat[1]; |
| 1983 if (protectflag & OB_LOCK_ROTY) |
| 1984 quat[2]= oldquat[2]; |
| 1985 if (protectflag & OB_LOCK_ROTZ) |
| 1986 quat[3]= oldquat[3]; |
| 1987 } |
| 1988 else { |
| 1989 /* quaternions get limited with euler... (compatibility mode) */ |
| 1990 float eul[3], oldeul[3], nquat[4], noldquat[4]; |
| 1991 float qlen; |
| 1992 |
| 1993 qlen= normalize_qt_qt(nquat, quat); |
| 1994 normalize_qt_qt(noldquat, oldquat); |
| 1995 |
| 1996 quat_to_eul(eul, nquat); |
| 1997 quat_to_eul(oldeul, noldquat); |
| 1998 |
| 1999 if (protectflag & OB_LOCK_ROTX) |
| 2000 eul[0]= oldeul[0]; |
| 2001 if (protectflag & OB_LOCK_ROTY) |
| 2002 eul[1]= oldeul[1]; |
| 2003 if (protectflag & OB_LOCK_ROTZ) |
| 2004 eul[2]= oldeul[2]; |
| 2005 |
| 2006 eul_to_quat(quat, eul); |
| 2007 |
| 2008 /* restore original quat size */ |
| 2009 mul_qt_fl(quat, qlen); |
| 2010 ················ |
| 2011 /* quaternions flip w sign to accumulate rotations correctly */ |
| 2012 if ( (nquat[0]<0.0f && quat[0]>0.0f) || (nquat[0]>0.0f && quat[0
]<0.0f) ) { |
| 2013 mul_qt_fl(quat, -1.0f); |
| 2014 } |
| 2015 } |
| 2016 } |
| 2017 |
| 2018 /* ******************* TRANSFORM LIMITS ********************** */ |
| 2019 |
| 2020 static void constraintTransLim(TransInfo *t, TransData *td) |
| 2021 { |
| 2022 if (td->con) { |
| 2023 bConstraintTypeInfo *ctiLoc= get_constraint_typeinfo(CONSTRAINT_
TYPE_LOCLIMIT); |
| 2024 bConstraintTypeInfo *ctiDist= get_constraint_typeinfo(CONSTRAINT
_TYPE_DISTLIMIT); |
| 2025 ················ |
| 2026 bConstraintOb cob= {NULL}; |
| 2027 bConstraint *con; |
| 2028 float ctime = (float)(t->scene->r.cfra); |
| 2029 ················ |
| 2030 /* Make a temporary bConstraintOb for using these limit constrai
nts |
| 2031 * - they only care that cob->matrix is correctly set ;-) |
| 2032 * - current space should be local |
| 2033 */ |
| 2034 unit_m4(cob.matrix); |
| 2035 copy_v3_v3(cob.matrix[3], td->loc); |
| 2036 ················ |
| 2037 /* Evaluate valid constraints */ |
| 2038 for (con= td->con; con; con= con->next) { |
| 2039 bConstraintTypeInfo *cti = NULL; |
| 2040 ListBase targets = {NULL, NULL}; |
| 2041 float tmat[4][4]; |
| 2042 ························ |
| 2043 /* only consider constraint if enabled */ |
| 2044 if (con->flag & CONSTRAINT_DISABLE) continue; |
| 2045 if (con->enforce == 0.0f) continue; |
| 2046 ························ |
| 2047 /* only use it if it's tagged for this purpose (and the
right type) */ |
| 2048 if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { |
| 2049 bLocLimitConstraint *data= con->data; |
| 2050 ································ |
| 2051 if ((data->flag2 & LIMIT_TRANSFORM)==0) |
| 2052 continue; |
| 2053 cti = ctiLoc; |
| 2054 } |
| 2055 else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) { |
| 2056 bDistLimitConstraint *data= con->data; |
| 2057 ································ |
| 2058 if ((data->flag & LIMITDIST_TRANSFORM)==0) |
| 2059 continue; |
| 2060 cti = ctiDist; |
| 2061 } |
| 2062 ························ |
| 2063 if (cti) { |
| 2064 /* do space conversions */ |
| 2065 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2066 /* just multiply by td->mtx (this should
be ok) */ |
| 2067 copy_m4_m4(tmat, cob.matrix); |
| 2068 mul_m4_m3m4(cob.matrix, td->mtx, tmat); |
| 2069 } |
| 2070 else if (con->ownspace != CONSTRAINT_SPACE_LOCAL
) { |
| 2071 /* skip... incompatable spacetype */ |
| 2072 continue; |
| 2073 } |
| 2074 ································ |
| 2075 /* get constraint targets if needed */ |
| 2076 get_constraint_targets_for_solving(con, &cob, &t
argets, ctime); |
| 2077 ································ |
| 2078 /* do constraint */ |
| 2079 cti->evaluate_constraint(con, &cob, &targets); |
| 2080 ································ |
| 2081 /* convert spaces again */ |
| 2082 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2083 /* just multiply by td->mtx (this should
be ok) */ |
| 2084 copy_m4_m4(tmat, cob.matrix); |
| 2085 mul_m4_m3m4(cob.matrix, td->smtx, tmat); |
| 2086 } |
| 2087 ································ |
| 2088 /* free targets list */ |
| 2089 BLI_freelistN(&targets); |
| 2090 } |
| 2091 } |
| 2092 ················ |
| 2093 /* copy results from cob->matrix */ |
| 2094 copy_v3_v3(td->loc, cob.matrix[3]); |
| 2095 } |
| 2096 } |
| 2097 |
| 2098 static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) |
| 2099 { |
| 2100 /* Make a temporary bConstraintOb for use by limit constraints |
| 2101 * - they only care that cob->matrix is correctly set ;-) |
| 2102 * - current space should be local |
| 2103 */ |
| 2104 memset(cob, 0, sizeof(bConstraintOb)); |
| 2105 if (td->ext) { |
| 2106 if (td->ext->rotOrder == ROT_MODE_QUAT) { |
| 2107 /* quats */ |
| 2108 /* objects and bones do normalization first too, otherwi
se |
| 2109 * we don't necessarily end up with a rotation matrix, a
nd |
| 2110 * then conversion back to quat gives a different result
*/ |
| 2111 float quat[4]; |
| 2112 normalize_qt_qt(quat, td->ext->quat); |
| 2113 quat_to_mat4(cob->matrix, quat); |
| 2114 } |
| 2115 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { |
| 2116 /* axis angle */ |
| 2117 axis_angle_to_mat4(cob->matrix, &td->ext->quat[1], td->e
xt->quat[0]); |
| 2118 } |
| 2119 else { |
| 2120 /* eulers */ |
| 2121 eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrde
r); |
| 2122 } |
| 2123 } |
| 2124 } |
| 2125 |
| 2126 static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) |
| 2127 { |
| 2128 if (td->con) { |
| 2129 bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYP
E_ROTLIMIT); |
| 2130 bConstraintOb cob; |
| 2131 bConstraint *con; |
| 2132 int dolimit = 0; |
| 2133 ················ |
| 2134 /* Evaluate valid constraints */ |
| 2135 for (con= td->con; con; con= con->next) { |
| 2136 /* only consider constraint if enabled */ |
| 2137 if (con->flag & CONSTRAINT_DISABLE) continue; |
| 2138 if (con->enforce == 0.0f) continue; |
| 2139 ························ |
| 2140 /* we're only interested in Limit-Rotation constraints *
/ |
| 2141 if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { |
| 2142 bRotLimitConstraint *data= con->data; |
| 2143 float tmat[4][4]; |
| 2144 ································ |
| 2145 /* only use it if it's tagged for this purpose *
/ |
| 2146 if ((data->flag2 & LIMIT_TRANSFORM)==0) |
| 2147 continue; |
| 2148 |
| 2149 /* skip incompatable spacetypes */ |
| 2150 if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD,
CONSTRAINT_SPACE_LOCAL)) |
| 2151 continue; |
| 2152 |
| 2153 /* only do conversion if necessary, to preserve
quats and eulers */ |
| 2154 if (!dolimit) { |
| 2155 constraintob_from_transdata(&cob, td); |
| 2156 dolimit= 1; |
| 2157 } |
| 2158 ································ |
| 2159 /* do space conversions */ |
| 2160 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2161 /* just multiply by td->mtx (this should
be ok) */ |
| 2162 copy_m4_m4(tmat, cob.matrix); |
| 2163 mul_m4_m3m4(cob.matrix, td->mtx, tmat); |
| 2164 } |
| 2165 ································ |
| 2166 /* do constraint */ |
| 2167 cti->evaluate_constraint(con, &cob, NULL); |
| 2168 ································ |
| 2169 /* convert spaces again */ |
| 2170 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2171 /* just multiply by td->mtx (this should
be ok) */ |
| 2172 copy_m4_m4(tmat, cob.matrix); |
| 2173 mul_m4_m3m4(cob.matrix, td->smtx, tmat); |
| 2174 } |
| 2175 } |
| 2176 } |
| 2177 ················ |
| 2178 if (dolimit) { |
| 2179 /* copy results from cob->matrix */ |
| 2180 if (td->ext->rotOrder == ROT_MODE_QUAT) { |
| 2181 /* quats */ |
| 2182 mat4_to_quat(td->ext->quat, cob.matrix); |
| 2183 } |
| 2184 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { |
| 2185 /* axis angle */ |
| 2186 mat4_to_axis_angle(&td->ext->quat[1], &td->ext->
quat[0], cob.matrix); |
| 2187 } |
| 2188 else { |
| 2189 /* eulers */ |
| 2190 mat4_to_eulO(td->ext->rot, td->ext->rotOrder, co
b.matrix); |
| 2191 } |
| 2192 } |
| 2193 } |
| 2194 } |
| 2195 |
| 2196 static void constraintSizeLim(TransInfo *t, TransData *td) |
| 2197 { |
| 2198 if (td->con && td->ext) { |
| 2199 bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYP
E_SIZELIMIT); |
| 2200 bConstraintOb cob= {NULL}; |
| 2201 bConstraint *con; |
| 2202 ················ |
| 2203 /* Make a temporary bConstraintOb for using these limit constrai
nts |
| 2204 * - they only care that cob->matrix is correctly set ;-) |
| 2205 * - current space should be local |
| 2206 */ |
| 2207 if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { |
| 2208 /* scale val and reset size */ |
| 2209 return; // TODO: fix this case |
| 2210 } |
| 2211 else { |
| 2212 /* Reset val if SINGLESIZE but using a constraint */ |
| 2213 if (td->flag & TD_SINGLESIZE) |
| 2214 return; |
| 2215 ························ |
| 2216 size_to_mat4(cob.matrix, td->ext->size); |
| 2217 } |
| 2218 ················ |
| 2219 /* Evaluate valid constraints */ |
| 2220 for (con= td->con; con; con= con->next) { |
| 2221 /* only consider constraint if enabled */ |
| 2222 if (con->flag & CONSTRAINT_DISABLE) continue; |
| 2223 if (con->enforce == 0.0f) continue; |
| 2224 ························ |
| 2225 /* we're only interested in Limit-Scale constraints */ |
| 2226 if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { |
| 2227 bSizeLimitConstraint *data= con->data; |
| 2228 float tmat[4][4]; |
| 2229 ································ |
| 2230 /* only use it if it's tagged for this purpose *
/ |
| 2231 if ((data->flag2 & LIMIT_TRANSFORM)==0) |
| 2232 continue; |
| 2233 ································ |
| 2234 /* do space conversions */ |
| 2235 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2236 /* just multiply by td->mtx (this should
be ok) */ |
| 2237 copy_m4_m4(tmat, cob.matrix); |
| 2238 mul_m4_m3m4(cob.matrix, td->mtx, tmat); |
| 2239 } |
| 2240 else if (con->ownspace != CONSTRAINT_SPACE_LOCAL
) { |
| 2241 /* skip... incompatable spacetype */ |
| 2242 continue; |
| 2243 } |
| 2244 ································ |
| 2245 /* do constraint */ |
| 2246 cti->evaluate_constraint(con, &cob, NULL); |
| 2247 ································ |
| 2248 /* convert spaces again */ |
| 2249 if (con->ownspace == CONSTRAINT_SPACE_WORLD) { |
| 2250 /* just multiply by td->mtx (this should
be ok) */ |
| 2251 copy_m4_m4(tmat, cob.matrix); |
| 2252 mul_m4_m3m4(cob.matrix, td->smtx, tmat); |
| 2253 } |
| 2254 } |
| 2255 } |
| 2256 ················ |
| 2257 /* copy results from cob->matrix */ |
| 2258 if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { |
| 2259 /* scale val and reset size */ |
| 2260 return; // TODO: fix this case |
| 2261 } |
| 2262 else { |
| 2263 /* Reset val if SINGLESIZE but using a constraint */ |
| 2264 if (td->flag & TD_SINGLESIZE) |
| 2265 return; |
| 2266 ························ |
| 2267 mat4_to_size(td->ext->size, cob.matrix); |
| 2268 } |
| 2269 } |
| 2270 } |
| 2271 |
| 2272 /* ************************** WARP *************************** */ |
| 2273 |
| 2274 static void postInputWarp(TransInfo *t, float values[3]) |
| 2275 { |
| 2276 mul_v3_fl(values, (float)(M_PI * 2)); |
| 2277 |
| 2278 if (t->customData) { /* non-null value indicates reversed input */ |
| 2279 negate_v3(values); |
| 2280 } |
| 2281 } |
| 2282 |
| 2283 void initWarp(TransInfo *t) |
| 2284 { |
| 2285 float max[3], min[3]; |
| 2286 int i; |
| 2287 ········ |
| 2288 t->mode = TFM_WARP; |
| 2289 t->transform = Warp; |
| 2290 t->handleEvent = handleEventWarp; |
| 2291 ········ |
| 2292 setInputPostFct(&t->mouse, postInputWarp); |
| 2293 initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); |
| 2294 ········ |
| 2295 t->idx_max = 0; |
| 2296 t->num.idx_max = 0; |
| 2297 t->snap[0] = 0.0f; |
| 2298 t->snap[1] = 5.0f / 180.0f * (float)M_PI; |
| 2299 t->snap[2] = 1.0f / 180.0f * (float)M_PI; |
| 2300 ········ |
| 2301 t->num.increment = 1.0f; |
| 2302 |
| 2303 t->flag |= T_NO_CONSTRAINT; |
| 2304 ········ |
| 2305 /* we need min/max in view space */ |
| 2306 for (i = 0; i < t->total; i++) { |
| 2307 float center[3]; |
| 2308 copy_v3_v3(center, t->data[i].center); |
| 2309 mul_m3_v3(t->data[i].mtx, center); |
| 2310 mul_m4_v3(t->viewmat, center); |
| 2311 sub_v3_v3(center, t->viewmat[3]); |
| 2312 if (i) |
| 2313 minmax_v3v3_v3(min, max, center); |
| 2314 else { |
| 2315 copy_v3_v3(max, center); |
| 2316 copy_v3_v3(min, center); |
| 2317 } |
| 2318 } |
| 2319 |
| 2320 mid_v3_v3v3(t->center, min, max); |
| 2321 |
| 2322 if (max[0] == min[0]) max[0] += 0.1f; /* not optimal, but flipping is be
tter than invalid garbage (i.e. division by zero!) */ |
| 2323 t->val= (max[0]-min[0])/2.0f; /* t->val is X dimension projected boundbo
x */ |
| 2324 } |
| 2325 |
| 2326 int handleEventWarp(TransInfo *t, wmEvent *event) |
| 2327 { |
| 2328 int status = 0; |
| 2329 ········ |
| 2330 if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { |
| 2331 // Use customData pointer to signal warp direction |
| 2332 if (t->customData == NULL) |
| 2333 t->customData = (void*)1; |
| 2334 else |
| 2335 t->customData = NULL; |
| 2336 ················ |
| 2337 status = 1; |
| 2338 } |
| 2339 ········ |
| 2340 return status; |
| 2341 } |
| 2342 |
| 2343 int Warp(TransInfo *t, const int UNUSED(mval[2])) |
| 2344 { |
| 2345 TransData *td = t->data; |
| 2346 float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3
]; |
| 2347 int i; |
| 2348 char str[50]; |
| 2349 ········ |
| 2350 curs= give_cursor(t->scene, t->view); |
| 2351 /* |
| 2352 * gcursor is the one used for helpline. |
| 2353 * It has to be in the same space as the drawing loop |
| 2354 * (that means it needs to be in the object's space when in edit mode an
d |
| 2355 * in global space in object mode) |
| 2356 * |
| 2357 * cursor is used for calculations. |
| 2358 * It needs to be in view space, but we need to take object's offset |
| 2359 * into account if in Edit mode. |
| 2360 */ |
| 2361 copy_v3_v3(cursor, curs); |
| 2362 copy_v3_v3(gcursor, cursor); |
| 2363 if (t->flag & T_EDIT) { |
| 2364 sub_v3_v3(cursor, t->obedit->obmat[3]); |
| 2365 sub_v3_v3(gcursor, t->obedit->obmat[3]); |
| 2366 mul_m3_v3(t->data->smtx, gcursor); |
| 2367 } |
| 2368 mul_m4_v3(t->viewmat, cursor); |
| 2369 sub_v3_v3(cursor, t->viewmat[3]); |
| 2370 ········ |
| 2371 /* amount of radians for warp */ |
| 2372 circumfac = t->values[0]; |
| 2373 ········ |
| 2374 snapGrid(t, &circumfac); |
| 2375 applyNumInput(&t->num, &circumfac); |
| 2376 ········ |
| 2377 /* header print for NumInput */ |
| 2378 if (hasNumInput(&t->num)) { |
| 2379 char c[20]; |
| 2380 ················ |
| 2381 outputNumInput(&(t->num), c); |
| 2382 ················ |
| 2383 sprintf(str, "Warp: %s", c); |
| 2384 |
| 2385 circumfac = DEG2RADF(circumfac); |
| 2386 } |
| 2387 else { |
| 2388 /* default header print */ |
| 2389 sprintf(str, "Warp: %.3f", RAD2DEGF(circumfac)); |
| 2390 } |
| 2391 ········ |
| 2392 t->values[0] = circumfac; |
| 2393 |
| 2394 circumfac /= 2; /* only need 180 on each side to make 360 */ |
| 2395 ········ |
| 2396 for (i = 0; i < t->total; i++, td++) { |
| 2397 float loc[3]; |
| 2398 if (td->flag & TD_NOACTION) |
| 2399 break; |
| 2400 ················ |
| 2401 if (td->flag & TD_SKIP) |
| 2402 continue; |
| 2403 ················ |
| 2404 /* translate point to center, rotate in such a way that outline=
=distance */ |
| 2405 copy_v3_v3(vec, td->iloc); |
| 2406 mul_m3_v3(td->mtx, vec); |
| 2407 mul_m4_v3(t->viewmat, vec); |
| 2408 sub_v3_v3(vec, t->viewmat[3]); |
| 2409 ················ |
| 2410 dist= vec[0]-cursor[0]; |
| 2411 ················ |
| 2412 /* t->val is X dimension projected boundbox */ |
| 2413 phi0= (circumfac*dist/t->val); |
| 2414 ················ |
| 2415 vec[1]= (vec[1]-cursor[1]); |
| 2416 ················ |
| 2417 co= (float)cos(phi0); |
| 2418 si= (float)sin(phi0); |
| 2419 loc[0]= -si*vec[1]+cursor[0]; |
| 2420 loc[1]= co*vec[1]+cursor[1]; |
| 2421 loc[2]= vec[2]; |
| 2422 ················ |
| 2423 mul_m4_v3(t->viewinv, loc); |
| 2424 sub_v3_v3(loc, t->viewinv[3]); |
| 2425 mul_m3_v3(td->smtx, loc); |
| 2426 ················ |
| 2427 sub_v3_v3(loc, td->iloc); |
| 2428 mul_v3_fl(loc, td->factor); |
| 2429 add_v3_v3v3(td->loc, td->iloc, loc); |
| 2430 } |
| 2431 ········ |
| 2432 recalcData(t); |
| 2433 ········ |
| 2434 ED_area_headerprint(t->sa, str); |
| 2435 ········ |
| 2436 return 1; |
| 2437 } |
| 2438 |
| 2439 /* ************************** SHEAR *************************** */ |
| 2440 |
| 2441 static void postInputShear(TransInfo *UNUSED(t), float values[3]) |
| 2442 { |
| 2443 mul_v3_fl(values, 0.05f); |
| 2444 } |
| 2445 |
| 2446 void initShear(TransInfo *t) |
| 2447 { |
| 2448 t->mode = TFM_SHEAR; |
| 2449 t->transform = Shear; |
| 2450 t->handleEvent = handleEventShear; |
| 2451 ········ |
| 2452 setInputPostFct(&t->mouse, postInputShear); |
| 2453 initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); |
| 2454 ········ |
| 2455 t->idx_max = 0; |
| 2456 t->num.idx_max = 0; |
| 2457 t->snap[0] = 0.0f; |
| 2458 t->snap[1] = 0.1f; |
| 2459 t->snap[2] = t->snap[1] * 0.1f; |
| 2460 ········ |
| 2461 t->num.increment = 0.1f; |
| 2462 |
| 2463 t->flag |= T_NO_CONSTRAINT; |
| 2464 } |
| 2465 |
| 2466 int handleEventShear(TransInfo *t, wmEvent *event) |
| 2467 { |
| 2468 int status = 0; |
| 2469 ········ |
| 2470 if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { |
| 2471 // Use customData pointer to signal Shear direction |
| 2472 if (t->customData == NULL) { |
| 2473 initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE
); |
| 2474 t->customData = (void*)1; |
| 2475 } |
| 2476 else { |
| 2477 initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLU
TE); |
| 2478 t->customData = NULL; |
| 2479 } |
| 2480 |
| 2481 status = 1; |
| 2482 } |
| 2483 ········ |
| 2484 return status; |
| 2485 } |
| 2486 |
| 2487 |
| 2488 int Shear(TransInfo *t, const int UNUSED(mval[2])) |
| 2489 { |
| 2490 TransData *td = t->data; |
| 2491 float vec[3]; |
| 2492 float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3]
; |
| 2493 float value; |
| 2494 int i; |
| 2495 char str[50]; |
| 2496 ········ |
| 2497 copy_m3_m4(persmat, t->viewmat); |
| 2498 invert_m3_m3(persinv, persmat); |
| 2499 ········ |
| 2500 value = t->values[0]; |
| 2501 ········ |
| 2502 snapGrid(t, &value); |
| 2503 ········ |
| 2504 applyNumInput(&t->num, &value); |
| 2505 ········ |
| 2506 /* header print for NumInput */ |
| 2507 if (hasNumInput(&t->num)) { |
| 2508 char c[20]; |
| 2509 ················ |
| 2510 outputNumInput(&(t->num), c); |
| 2511 ················ |
| 2512 sprintf(str, "Shear: %s %s", c, t->proptext); |
| 2513 } |
| 2514 else { |
| 2515 /* default header print */ |
| 2516 sprintf(str, "Shear: %.3f %s", value, t->proptext); |
| 2517 } |
| 2518 ········ |
| 2519 t->values[0] = value; |
| 2520 |
| 2521 unit_m3(smat); |
| 2522 ········ |
| 2523 // Custom data signals shear direction |
| 2524 if (t->customData == NULL) |
| 2525 smat[1][0] = value; |
| 2526 else |
| 2527 smat[0][1] = value; |
| 2528 ········ |
| 2529 mul_m3_m3m3(tmat, smat, persmat); |
| 2530 mul_m3_m3m3(totmat, persinv, tmat); |
| 2531 ········ |
| 2532 for (i = 0 ; i < t->total; i++, td++) { |
| 2533 if (td->flag & TD_NOACTION) |
| 2534 break; |
| 2535 ················ |
| 2536 if (td->flag & TD_SKIP) |
| 2537 continue; |
| 2538 ················ |
| 2539 if (t->obedit) { |
| 2540 float mat3[3][3]; |
| 2541 mul_m3_m3m3(mat3, totmat, td->mtx); |
| 2542 mul_m3_m3m3(tmat, td->smtx, mat3); |
| 2543 } |
| 2544 else { |
| 2545 copy_m3_m3(tmat, totmat); |
| 2546 } |
| 2547 sub_v3_v3v3(vec, td->center, t->center); |
| 2548 ················ |
| 2549 mul_m3_v3(tmat, vec); |
| 2550 ················ |
| 2551 add_v3_v3(vec, t->center); |
| 2552 sub_v3_v3(vec, td->center); |
| 2553 ················ |
| 2554 mul_v3_fl(vec, td->factor); |
| 2555 ················ |
| 2556 add_v3_v3v3(td->loc, td->iloc, vec); |
| 2557 } |
| 2558 ········ |
| 2559 recalcData(t); |
| 2560 ········ |
| 2561 ED_area_headerprint(t->sa, str); |
| 2562 |
| 2563 return 1; |
| 2564 } |
| 2565 |
| 2566 /* ************************** RESIZE *************************** */ |
| 2567 |
| 2568 void initResize(TransInfo *t) |
| 2569 { |
| 2570 t->mode = TFM_RESIZE; |
| 2571 t->transform = Resize; |
| 2572 ········ |
| 2573 initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); |
| 2574 ········ |
| 2575 t->flag |= T_NULL_ONE; |
| 2576 t->num.flag |= NUM_NULL_ONE; |
| 2577 t->num.flag |= NUM_AFFECT_ALL; |
| 2578 if (!t->obedit) { |
| 2579 t->flag |= T_NO_ZERO; |
| 2580 t->num.flag |= NUM_NO_ZERO; |
| 2581 } |
| 2582 ········ |
| 2583 t->idx_max = 2; |
| 2584 t->num.idx_max = 2; |
| 2585 t->snap[0] = 0.0f; |
| 2586 t->snap[1] = 0.1f; |
| 2587 t->snap[2] = t->snap[1] * 0.1f; |
| 2588 |
| 2589 t->num.increment = t->snap[1]; |
| 2590 } |
| 2591 |
| 2592 static void headerResize(TransInfo *t, float vec[3], char *str) |
| 2593 { |
| 2594 char tvec[60]; |
| 2595 char *spos= str; |
| 2596 if (hasNumInput(&t->num)) { |
| 2597 outputNumInput(&(t->num), tvec); |
| 2598 } |
| 2599 else { |
| 2600 BLI_snprintf(&tvec[0], 20, "%.4f", vec[0]); |
| 2601 BLI_snprintf(&tvec[20], 20, "%.4f", vec[1]); |
| 2602 BLI_snprintf(&tvec[40], 20, "%.4f", vec[2]); |
| 2603 } |
| 2604 ········ |
| 2605 if (t->con.mode & CON_APPLY) { |
| 2606 switch (t->num.idx_max) { |
| 2607 case 0: |
| 2608 spos += sprintf(spos, "Scale: %s%s %s", &tvec[0], t->con
.text, t->proptext); |
| 2609 break; |
| 2610 case 1: |
| 2611 spos += sprintf(spos, "Scale: %s : %s%s %s", &tvec[0], &
tvec[20], t->con.text, t->proptext); |
| 2612 break; |
| 2613 case 2: |
| 2614 spos += sprintf(spos, "Scale: %s : %s : %s%s %s", &tvec[
0], &tvec[20], &tvec[40], t->con.text, t->proptext); |
| 2615 } |
| 2616 } |
| 2617 else { |
| 2618 if (t->flag & T_2D_EDIT) |
| 2619 spos += sprintf(spos, "Scale X: %s Y: %s%s %s", &tvec[
0], &tvec[20], t->con.text, t->proptext); |
| 2620 else |
| 2621 spos += sprintf(spos, "Scale X: %s Y: %s Z: %s%s %s",
&tvec[0], &tvec[20], &tvec[40], t->con.text, t->proptext); |
| 2622 } |
| 2623 ········ |
| 2624 if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) { |
| 2625 spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); |
| 2626 } |
| 2627 |
| 2628 (void)spos; |
| 2629 } |
| 2630 |
| 2631 #define SIGN(a) (a<-FLT_EPSILON?1:a>FLT_EPSILON?2:3) |
| 2632 #define VECSIGNFLIP(a, b) ((SIGN(a[0]) & SIGN(b[0]))==0 || (SIGN(a[1]) & SIGN(b[
1]))==0 || (SIGN(a[2]) & SIGN(b[2]))==0) |
| 2633 |
| 2634 /* smat is reference matrix, only scaled */ |
| 2635 static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) |
| 2636 { |
| 2637 float vec[3]; |
| 2638 ········ |
| 2639 copy_v3_v3(vec, mat[0]); |
| 2640 size[0]= normalize_v3(vec); |
| 2641 copy_v3_v3(vec, mat[1]); |
| 2642 size[1]= normalize_v3(vec); |
| 2643 copy_v3_v3(vec, mat[2]); |
| 2644 size[2]= normalize_v3(vec); |
| 2645 ········ |
| 2646 /* first tried with dotproduct... but the sign flip is crucial */ |
| 2647 if ( VECSIGNFLIP(mat[0], smat[0]) ) size[0]= -size[0]; |
| 2648 if ( VECSIGNFLIP(mat[1], smat[1]) ) size[1]= -size[1]; |
| 2649 if ( VECSIGNFLIP(mat[2], smat[2]) ) size[2]= -size[2]; |
| 2650 } |
| 2651 |
| 2652 |
| 2653 static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) |
| 2654 { |
| 2655 float tmat[3][3], smat[3][3], center[3]; |
| 2656 float vec[3]; |
| 2657 ········ |
| 2658 if (t->flag & T_EDIT) { |
| 2659 mul_m3_m3m3(smat, mat, td->mtx); |
| 2660 mul_m3_m3m3(tmat, td->smtx, smat); |
| 2661 } |
| 2662 else { |
| 2663 copy_m3_m3(tmat, mat); |
| 2664 } |
| 2665 ········ |
| 2666 if (t->con.applySize) { |
| 2667 t->con.applySize(t, td, tmat); |
| 2668 } |
| 2669 ········ |
| 2670 /* local constraint shouldn't alter center */ |
| 2671 if ((t->around == V3D_LOCAL) && |
| 2672 ( (t->flag & (T_OBJECT|T_POSE)) || |
| 2673 ((t->flag & T_EDIT) && (t->settings->selectmode & (SCE_SELEC
T_EDGE|SCE_SELECT_FACE))) || |
| 2674 (t->obedit && t->obedit->type == OB_ARMATURE)) |
| 2675 ) |
| 2676 { |
| 2677 copy_v3_v3(center, td->center); |
| 2678 } |
| 2679 else { |
| 2680 copy_v3_v3(center, t->center); |
| 2681 } |
| 2682 |
| 2683 if (td->ext) { |
| 2684 float fsize[3]; |
| 2685 ················ |
| 2686 if (t->flag & (T_OBJECT|T_TEXTURE|T_POSE)) { |
| 2687 float obsizemat[3][3]; |
| 2688 // Reorient the size mat to fit the oriented object. |
| 2689 mul_m3_m3m3(obsizemat, tmat, td->axismtx); |
| 2690 //print_m3("obsizemat", obsizemat); |
| 2691 TransMat3ToSize(obsizemat, td->axismtx, fsize); |
| 2692 //print_v3("fsize", fsize); |
| 2693 } |
| 2694 else { |
| 2695 mat3_to_size(fsize, tmat); |
| 2696 } |
| 2697 ················ |
| 2698 protectedSizeBits(td->protectflag, fsize); |
| 2699 ················ |
| 2700 if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't re
size objects itself |
| 2701 if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_AP
PLY)) { |
| 2702 /* scale val and reset size */ |
| 2703 *td->val = td->ival * (1 + (fsize[0] - 1) * td-
>factor); |
| 2704 ································ |
| 2705 td->ext->size[0] = td->ext->isize[0]; |
| 2706 td->ext->size[1] = td->ext->isize[1]; |
| 2707 td->ext->size[2] = td->ext->isize[2]; |
| 2708 } |
| 2709 else { |
| 2710 /* Reset val if SINGLESIZE but using a constrain
t */ |
| 2711 if (td->flag & TD_SINGLESIZE) |
| 2712 *td->val = td->ival; |
| 2713 ································ |
| 2714 td->ext->size[0] = td->ext->isize[0] * (1 + (fsi
ze[0] - 1) * td->factor); |
| 2715 td->ext->size[1] = td->ext->isize[1] * (1 + (fsi
ze[1] - 1) * td->factor); |
| 2716 td->ext->size[2] = td->ext->isize[2] * (1 + (fsi
ze[2] - 1) * td->factor); |
| 2717 } |
| 2718 } |
| 2719 ················ |
| 2720 constraintSizeLim(t, td); |
| 2721 } |
| 2722 ········ |
| 2723 /* For individual element center, Editmode need to use iloc */ |
| 2724 if (t->flag & T_POINTS) |
| 2725 sub_v3_v3v3(vec, td->iloc, center); |
| 2726 else |
| 2727 sub_v3_v3v3(vec, td->center, center); |
| 2728 ········ |
| 2729 mul_m3_v3(tmat, vec); |
| 2730 ········ |
| 2731 add_v3_v3(vec, center); |
| 2732 if (t->flag & T_POINTS) |
| 2733 sub_v3_v3(vec, td->iloc); |
| 2734 else |
| 2735 sub_v3_v3(vec, td->center); |
| 2736 ········ |
| 2737 mul_v3_fl(vec, td->factor); |
| 2738 ········ |
| 2739 if (t->flag & (T_OBJECT|T_POSE)) { |
| 2740 mul_m3_v3(td->smtx, vec); |
| 2741 } |
| 2742 ········ |
| 2743 protectedTransBits(td->protectflag, vec); |
| 2744 add_v3_v3v3(td->loc, td->iloc, vec); |
| 2745 ········ |
| 2746 constraintTransLim(t, td); |
| 2747 } |
| 2748 |
| 2749 int Resize(TransInfo *t, const int mval[2]) |
| 2750 { |
| 2751 TransData *td; |
| 2752 float size[3], mat[3][3]; |
| 2753 float ratio; |
| 2754 int i; |
| 2755 char str[200]; |
| 2756 ········ |
| 2757 /* for manipulator, center handle, the scaling can't be done relative to
center */ |
| 2758 if ( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) { |
| 2759 ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]
))/100.0f; |
| 2760 } |
| 2761 else { |
| 2762 ratio = t->values[0]; |
| 2763 } |
| 2764 ········ |
| 2765 size[0] = size[1] = size[2] = ratio; |
| 2766 ········ |
| 2767 snapGrid(t, size); |
| 2768 ········ |
| 2769 if (hasNumInput(&t->num)) { |
| 2770 applyNumInput(&t->num, size); |
| 2771 constraintNumInput(t, size); |
| 2772 } |
| 2773 ········ |
| 2774 applySnapping(t, size); |
| 2775 ········ |
| 2776 if (t->flag & T_AUTOVALUES) { |
| 2777 copy_v3_v3(size, t->auto_values); |
| 2778 } |
| 2779 ········ |
| 2780 copy_v3_v3(t->values, size); |
| 2781 ········ |
| 2782 size_to_mat3(mat, size); |
| 2783 ········ |
| 2784 if (t->con.applySize) { |
| 2785 t->con.applySize(t, NULL, mat); |
| 2786 } |
| 2787 ········ |
| 2788 copy_m3_m3(t->mat, mat); // used in manipulator |
| 2789 ········ |
| 2790 headerResize(t, size, str); |
| 2791 ········ |
| 2792 for (i = 0, td=t->data; i < t->total; i++, td++) { |
| 2793 if (td->flag & TD_NOACTION) |
| 2794 break; |
| 2795 ················ |
| 2796 if (td->flag & TD_SKIP) |
| 2797 continue; |
| 2798 ················ |
| 2799 ElementResize(t, td, mat); |
| 2800 } |
| 2801 ········ |
| 2802 /* evil hack - redo resize if cliping needed */ |
| 2803 if (t->flag & T_CLIP_UV && clipUVTransform(t, size, 1)) { |
| 2804 size_to_mat3(mat, size); |
| 2805 ················ |
| 2806 if (t->con.applySize) |
| 2807 t->con.applySize(t, NULL, mat); |
| 2808 ················ |
| 2809 for (i = 0, td=t->data; i < t->total; i++, td++) |
| 2810 ElementResize(t, td, mat); |
| 2811 } |
| 2812 ········ |
| 2813 recalcData(t); |
| 2814 ········ |
| 2815 ED_area_headerprint(t->sa, str); |
| 2816 ········ |
| 2817 return 1; |
| 2818 } |
| 2819 |
| 2820 /* ************************** TOSPHERE *************************** */ |
| 2821 |
| 2822 void initToSphere(TransInfo *t) |
| 2823 { |
| 2824 TransData *td = t->data; |
| 2825 int i; |
| 2826 ········ |
| 2827 t->mode = TFM_TOSPHERE; |
| 2828 t->transform = ToSphere; |
| 2829 ········ |
| 2830 initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); |
| 2831 ········ |
| 2832 t->idx_max = 0; |
| 2833 t->num.idx_max = 0; |
| 2834 t->snap[0] = 0.0f; |
| 2835 t->snap[1] = 0.1f; |
| 2836 t->snap[2] = t->snap[1] * 0.1f; |
| 2837 ········ |
| 2838 t->num.increment = t->snap[1]; |
| 2839 |
| 2840 t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE; |
| 2841 t->flag |= T_NO_CONSTRAINT; |
| 2842 ········ |
| 2843 // Calculate average radius |
| 2844 for (i = 0 ; i < t->total; i++, td++) { |
| 2845 t->val += len_v3v3(t->center, td->iloc); |
| 2846 } |
| 2847 ········ |
| 2848 t->val /= (float)t->total; |
| 2849 } |
| 2850 |
| 2851 int ToSphere(TransInfo *t, const int UNUSED(mval[2])) |
| 2852 { |
| 2853 float vec[3]; |
| 2854 float ratio, radius; |
| 2855 int i; |
| 2856 char str[64]; |
| 2857 TransData *td = t->data; |
| 2858 ········ |
| 2859 ratio = t->values[0]; |
| 2860 ········ |
| 2861 snapGrid(t, &ratio); |
| 2862 ········ |
| 2863 applyNumInput(&t->num, &ratio); |
| 2864 ········ |
| 2865 if (ratio < 0) |
| 2866 ratio = 0.0f; |
| 2867 else if (ratio > 1) |
| 2868 ratio = 1.0f; |
| 2869 ········ |
| 2870 t->values[0] = ratio; |
| 2871 |
| 2872 /* header print for NumInput */ |
| 2873 if (hasNumInput(&t->num)) { |
| 2874 char c[20]; |
| 2875 ················ |
| 2876 outputNumInput(&(t->num), c); |
| 2877 ················ |
| 2878 sprintf(str, "To Sphere: %s %s", c, t->proptext); |
| 2879 } |
| 2880 else { |
| 2881 /* default header print */ |
| 2882 sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext); |
| 2883 } |
| 2884 ········ |
| 2885 ········ |
| 2886 for (i = 0 ; i < t->total; i++, td++) { |
| 2887 float tratio; |
| 2888 if (td->flag & TD_NOACTION) |
| 2889 break; |
| 2890 ················ |
| 2891 if (td->flag & TD_SKIP) |
| 2892 continue; |
| 2893 ················ |
| 2894 sub_v3_v3v3(vec, td->iloc, t->center); |
| 2895 ················ |
| 2896 radius = normalize_v3(vec); |
| 2897 ················ |
| 2898 tratio = ratio * td->factor; |
| 2899 ················ |
| 2900 mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio); |
| 2901 ················ |
| 2902 add_v3_v3v3(td->loc, t->center, vec); |
| 2903 } |
| 2904 ········ |
| 2905 ········ |
| 2906 recalcData(t); |
| 2907 ········ |
| 2908 ED_area_headerprint(t->sa, str); |
| 2909 ········ |
| 2910 return 1; |
| 2911 } |
| 2912 |
| 2913 /* ************************** ROTATION *************************** */ |
| 2914 |
| 2915 |
| 2916 static void postInputRotation(TransInfo *t, float values[3]) |
| 2917 { |
| 2918 if ((t->con.mode & CON_APPLY) && t->con.applyRot) { |
| 2919 t->con.applyRot(t, NULL, t->axis, values); |
| 2920 } |
| 2921 } |
| 2922 |
| 2923 void initRotation(TransInfo *t) |
| 2924 { |
| 2925 t->mode = TFM_ROTATION; |
| 2926 t->transform = Rotation; |
| 2927 ········ |
| 2928 setInputPostFct(&t->mouse, postInputRotation); |
| 2929 initMouseInputMode(t, &t->mouse, INPUT_ANGLE); |
| 2930 ········ |
| 2931 t->idx_max = 0; |
| 2932 t->num.idx_max = 0; |
| 2933 t->snap[0] = 0.0f; |
| 2934 t->snap[1] = (float)((5.0/180)*M_PI); |
| 2935 t->snap[2] = t->snap[1] * 0.2f; |
| 2936 ········ |
| 2937 t->num.increment = 1.0f; |
| 2938 |
| 2939 if (t->flag & T_2D_EDIT) |
| 2940 t->flag |= T_NO_CONSTRAINT; |
| 2941 |
| 2942 negate_v3_v3(t->axis, t->viewinv[2]); |
| 2943 normalize_v3(t->axis); |
| 2944 |
| 2945 copy_v3_v3(t->axis_orig, t->axis); |
| 2946 } |
| 2947 |
| 2948 static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
around) |
| 2949 { |
| 2950 float vec[3], totmat[3][3], smat[3][3]; |
| 2951 float eul[3], fmat[3][3], quat[4]; |
| 2952 float *center = t->center; |
| 2953 |
| 2954 /* local constraint shouldn't alter center */ |
| 2955 if (around == V3D_LOCAL) { |
| 2956 if ( (t->flag & (T_OBJECT|T_POSE)) || |
| 2957 (t->settings->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)
) || |
| 2958 (t->obedit && t->obedit->type == OB_ARMATURE)) |
| 2959 { |
| 2960 center = td->center; |
| 2961 } |
| 2962 } |
| 2963 |
| 2964 if (t->flag & T_POINTS) { |
| 2965 mul_m3_m3m3(totmat, mat, td->mtx); |
| 2966 mul_m3_m3m3(smat, td->smtx, totmat); |
| 2967 ················ |
| 2968 sub_v3_v3v3(vec, td->iloc, center); |
| 2969 mul_m3_v3(smat, vec); |
| 2970 ················ |
| 2971 add_v3_v3v3(td->loc, vec, center); |
| 2972 ················ |
| 2973 sub_v3_v3v3(vec, td->loc, td->iloc); |
| 2974 protectedTransBits(td->protectflag, vec); |
| 2975 add_v3_v3v3(td->loc, td->iloc, vec); |
| 2976 ················ |
| 2977 ················ |
| 2978 if (td->flag & TD_USEQUAT) { |
| 2979 mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, N
ULL, NULL, NULL); |
| 2980 mat3_to_quat(quat, fmat); // Actual transform |
| 2981 ························ |
| 2982 if (td->ext->quat) { |
| 2983 mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat)
; |
| 2984 ································ |
| 2985 /* is there a reason not to have this here? -jah
ka */ |
| 2986 protectedQuaternionBits(td->protectflag, td->ext
->quat, td->ext->iquat); |
| 2987 } |
| 2988 } |
| 2989 } |
| 2990 /** |
| 2991 * HACK WARNING |
| 2992 * |
| 2993 * This is some VERY ugly special case to deal with pose mode. |
| 2994 * |
| 2995 * The problem is that mtx and smtx include each bone orientation. |
| 2996 * |
| 2997 * That is needed to rotate each bone properly, HOWEVER, to calculate |
| 2998 * the translation component, we only need the actual armature object's |
| 2999 * matrix (and inverse). That is not all though. Once the proper transla
tion |
| 3000 * has been computed, it has to be converted back into the bone's space. |
| 3001 */ |
| 3002 else if (t->flag & T_POSE) { |
| 3003 float pmtx[3][3], imtx[3][3]; |
| 3004 ················ |
| 3005 // Extract and invert armature object matrix |
| 3006 copy_m3_m4(pmtx, t->poseobj->obmat); |
| 3007 invert_m3_m3(imtx, pmtx); |
| 3008 ················ |
| 3009 if ((td->flag & TD_NO_LOC) == 0) { |
| 3010 sub_v3_v3v3(vec, td->center, center); |
| 3011 ························ |
| 3012 mul_m3_v3(pmtx, vec); // To Global space |
| 3013 mul_m3_v3(mat, vec); // Applying rotation |
| 3014 mul_m3_v3(imtx, vec); // To Local space |
| 3015 ························ |
| 3016 add_v3_v3(vec, center); |
| 3017 /* vec now is the location where the object has to be */ |
| 3018 ························ |
| 3019 sub_v3_v3v3(vec, vec, td->center); // Translation needed
from the initial location |
| 3020 ························ |
| 3021 /* special exception, see TD_PBONE_LOCAL_MTX definition
comments */ |
| 3022 if (td->flag & TD_PBONE_LOCAL_MTX_P) { |
| 3023 /* do nothing */ |
| 3024 } |
| 3025 else if (td->flag & TD_PBONE_LOCAL_MTX_C) { |
| 3026 mul_m3_v3(pmtx, vec); // To Global space |
| 3027 mul_m3_v3(td->ext->l_smtx, vec);// To Pose space
(Local Location) |
| 3028 } |
| 3029 else { |
| 3030 mul_m3_v3(pmtx, vec); // To Global space |
| 3031 mul_m3_v3(td->smtx, vec);// To Pose space |
| 3032 } |
| 3033 |
| 3034 protectedTransBits(td->protectflag, vec); |
| 3035 ························ |
| 3036 add_v3_v3v3(td->loc, td->iloc, vec); |
| 3037 ························ |
| 3038 constraintTransLim(t, td); |
| 3039 } |
| 3040 ················ |
| 3041 /* rotation */ |
| 3042 /* MORE HACK: as in some cases the matrix to apply location and
rot/scale is not the same, |
| 3043 * and ElementRotation() might be called in Translation context
(with align snapping), |
| 3044 * we need to be sure to actually use the *rotation* matrix here
... |
| 3045 * So no other way than storing it in some dedicated members of
td->ext! */ |
| 3046 if ((t->flag & T_V3D_ALIGN)==0) { /* align mode doesn't rotate o
bjects itself */ |
| 3047 /* euler or quaternion/axis-angle? */ |
| 3048 if (td->ext->rotOrder == ROT_MODE_QUAT) { |
| 3049 mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext-
>r_smtx, NULL, NULL, NULL, NULL, NULL); |
| 3050 ································ |
| 3051 mat3_to_quat(quat, fmat); /* Actual transform */ |
| 3052 ································ |
| 3053 mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat)
; |
| 3054 /* this function works on end result */ |
| 3055 protectedQuaternionBits(td->protectflag, td->ext
->quat, td->ext->iquat); |
| 3056 ································ |
| 3057 } |
| 3058 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { |
| 3059 /* calculate effect based on quats */ |
| 3060 float iquat[4], tquat[4]; |
| 3061 ································ |
| 3062 axis_angle_to_quat(iquat, td->ext->irotAxis, td-
>ext->irotAngle); |
| 3063 ································ |
| 3064 mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext-
>r_smtx, NULL, NULL, NULL, NULL, NULL); |
| 3065 mat3_to_quat(quat, fmat); /* Actual transform */ |
| 3066 mul_qt_qtqt(tquat, quat, iquat); |
| 3067 ································ |
| 3068 quat_to_axis_angle(td->ext->rotAxis, td->ext->ro
tAngle, tquat); |
| 3069 ································ |
| 3070 /* this function works on end result */ |
| 3071 protectedAxisAngleBits(td->protectflag, td->ext-
>rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); |
| 3072 } |
| 3073 else {· |
| 3074 float eulmat[3][3]; |
| 3075 ································ |
| 3076 mul_m3_m3m3(totmat, mat, td->ext->r_mtx); |
| 3077 mul_m3_m3m3(smat, td->ext->r_smtx, totmat); |
| 3078 ································ |
| 3079 /* calculate the total rotatation in eulers */ |
| 3080 copy_v3_v3(eul, td->ext->irot); |
| 3081 eulO_to_mat3(eulmat, eul, td->ext->rotOrder); |
| 3082 ································ |
| 3083 /* mat = transform, obmat = bone rotation */ |
| 3084 mul_m3_m3m3(fmat, smat, eulmat); |
| 3085 ································ |
| 3086 mat3_to_compatible_eulO(eul, td->ext->rot, td->e
xt->rotOrder, fmat); |
| 3087 ································ |
| 3088 /* and apply (to end result only) */ |
| 3089 protectedRotateBits(td->protectflag, eul, td->ex
t->irot); |
| 3090 copy_v3_v3(td->ext->rot, eul); |
| 3091 } |
| 3092 ························ |
| 3093 constraintRotLim(t, td); |
| 3094 } |
| 3095 } |
| 3096 else { |
| 3097 if ((td->flag & TD_NO_LOC) == 0) { |
| 3098 /* translation */ |
| 3099 sub_v3_v3v3(vec, td->center, center); |
| 3100 mul_m3_v3(mat, vec); |
| 3101 add_v3_v3(vec, center); |
| 3102 /* vec now is the location where the object has to be */ |
| 3103 sub_v3_v3(vec, td->center); |
| 3104 mul_m3_v3(td->smtx, vec); |
| 3105 ························ |
| 3106 protectedTransBits(td->protectflag, vec); |
| 3107 ························ |
| 3108 add_v3_v3v3(td->loc, td->iloc, vec); |
| 3109 } |
| 3110 ················ |
| 3111 ················ |
| 3112 constraintTransLim(t, td); |
| 3113 ················ |
| 3114 /* rotation */ |
| 3115 if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate o
bjects itself |
| 3116 /* euler or quaternion? */ |
| 3117 if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag
& TD_USEQUAT)) { |
| 3118 mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL,
NULL, NULL, NULL, NULL); |
| 3119 mat3_to_quat(quat, fmat); // Actual transf
orm |
| 3120 ································ |
| 3121 mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat)
; |
| 3122 /* this function works on end result */ |
| 3123 protectedQuaternionBits(td->protectflag, td->ext
->quat, td->ext->iquat); |
| 3124 } |
| 3125 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { |
| 3126 /* calculate effect based on quats */ |
| 3127 float iquat[4], tquat[4]; |
| 3128 ································ |
| 3129 axis_angle_to_quat(iquat, td->ext->irotAxis, td-
>ext->irotAngle); |
| 3130 ································ |
| 3131 mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL,
NULL, NULL, NULL, NULL); |
| 3132 mat3_to_quat(quat, fmat); // Actual transf
orm |
| 3133 mul_qt_qtqt(tquat, quat, iquat); |
| 3134 ································ |
| 3135 quat_to_axis_angle(td->ext->rotAxis, td->ext->ro
tAngle, tquat); |
| 3136 ································ |
| 3137 /* this function works on end result */ |
| 3138 protectedAxisAngleBits(td->protectflag, td->ext-
>rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); |
| 3139 } |
| 3140 else { |
| 3141 float obmat[3][3]; |
| 3142 ································ |
| 3143 mul_m3_m3m3(totmat, mat, td->mtx); |
| 3144 mul_m3_m3m3(smat, td->smtx, totmat); |
| 3145 ································ |
| 3146 /* calculate the total rotatation in eulers */ |
| 3147 add_v3_v3v3(eul, td->ext->irot, td->ext->drot);
/* we have to correct for delta rot */ |
| 3148 eulO_to_mat3(obmat, eul, td->ext->rotOrder); |
| 3149 /* mat = transform, obmat = object rotation */ |
| 3150 mul_m3_m3m3(fmat, smat, obmat); |
| 3151 ································ |
| 3152 mat3_to_compatible_eulO(eul, td->ext->rot, td->e
xt->rotOrder, fmat); |
| 3153 ································ |
| 3154 /* correct back for delta rot */ |
| 3155 sub_v3_v3v3(eul, eul, td->ext->drot); |
| 3156 ································ |
| 3157 /* and apply */ |
| 3158 protectedRotateBits(td->protectflag, eul, td->ex
t->irot); |
| 3159 copy_v3_v3(td->ext->rot, eul); |
| 3160 } |
| 3161 ························ |
| 3162 constraintRotLim(t, td); |
| 3163 } |
| 3164 } |
| 3165 } |
| 3166 |
| 3167 static void applyRotation(TransInfo *t, float angle, float axis[3]) |
| 3168 { |
| 3169 TransData *td = t->data; |
| 3170 float mat[3][3]; |
| 3171 int i; |
| 3172 ········ |
| 3173 vec_rot_to_mat3(mat, axis, angle); |
| 3174 ········ |
| 3175 for (i = 0 ; i < t->total; i++, td++) { |
| 3176 ················ |
| 3177 if (td->flag & TD_NOACTION) |
| 3178 break; |
| 3179 ················ |
| 3180 if (td->flag & TD_SKIP) |
| 3181 continue; |
| 3182 ················ |
| 3183 if (t->con.applyRot) { |
| 3184 t->con.applyRot(t, td, axis, NULL); |
| 3185 vec_rot_to_mat3(mat, axis, angle * td->factor); |
| 3186 } |
| 3187 else if (t->flag & T_PROP_EDIT) { |
| 3188 vec_rot_to_mat3(mat, axis, angle * td->factor); |
| 3189 } |
| 3190 ················ |
| 3191 ElementRotation(t, td, mat, t->around); |
| 3192 } |
| 3193 } |
| 3194 |
| 3195 int Rotation(TransInfo *t, const int UNUSED(mval[2])) |
| 3196 { |
| 3197 char str[128], *spos= str; |
| 3198 ········ |
| 3199 float final; |
| 3200 |
| 3201 final = t->values[0]; |
| 3202 ········ |
| 3203 snapGrid(t, &final); |
| 3204 ········ |
| 3205 if ((t->con.mode & CON_APPLY) && t->con.applyRot) { |
| 3206 t->con.applyRot(t, NULL, t->axis, NULL); |
| 3207 } |
| 3208 else { |
| 3209 /* reset axis if constraint is not set */ |
| 3210 copy_v3_v3(t->axis, t->axis_orig); |
| 3211 } |
| 3212 ········ |
| 3213 applySnapping(t, &final); |
| 3214 ········ |
| 3215 if (hasNumInput(&t->num)) { |
| 3216 char c[20]; |
| 3217 ················ |
| 3218 applyNumInput(&t->num, &final); |
| 3219 ················ |
| 3220 outputNumInput(&(t->num), c); |
| 3221 ················ |
| 3222 spos+= sprintf(spos, "Rot: %s %s %s", &c[0], t->con.text, t->pro
ptext); |
| 3223 |
| 3224 /* Clamp between -180 and 180 */ |
| 3225 final= angle_wrap_rad(DEG2RADF(final)); |
| 3226 } |
| 3227 else { |
| 3228 spos += sprintf(spos, "Rot: %.2f%s %s", RAD2DEGF(final), t->con.
text, t->proptext); |
| 3229 } |
| 3230 ········ |
| 3231 if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) { |
| 3232 spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); |
| 3233 } |
| 3234 (void)spos; |
| 3235 |
| 3236 t->values[0] = final; |
| 3237 ········ |
| 3238 applyRotation(t, final, t->axis); |
| 3239 ········ |
| 3240 recalcData(t); |
| 3241 ········ |
| 3242 ED_area_headerprint(t->sa, str); |
| 3243 ········ |
| 3244 return 1; |
| 3245 } |
| 3246 |
| 3247 |
| 3248 /* ************************** TRACKBALL *************************** */ |
| 3249 |
| 3250 void initTrackball(TransInfo *t) |
| 3251 { |
| 3252 t->mode = TFM_TRACKBALL; |
| 3253 t->transform = Trackball; |
| 3254 |
| 3255 initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL); |
| 3256 |
| 3257 t->idx_max = 1; |
| 3258 t->num.idx_max = 1; |
| 3259 t->snap[0] = 0.0f; |
| 3260 t->snap[1] = (float)((5.0/180)*M_PI); |
| 3261 t->snap[2] = t->snap[1] * 0.2f; |
| 3262 |
| 3263 t->num.increment = 1.0f; |
| 3264 |
| 3265 t->flag |= T_NO_CONSTRAINT; |
| 3266 } |
| 3267 |
| 3268 static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
ngles[2]) |
| 3269 { |
| 3270 TransData *td = t->data; |
| 3271 float mat[3][3], smat[3][3], totmat[3][3]; |
| 3272 int i; |
| 3273 |
| 3274 vec_rot_to_mat3(smat, axis1, angles[0]); |
| 3275 vec_rot_to_mat3(totmat, axis2, angles[1]); |
| 3276 |
| 3277 mul_m3_m3m3(mat, smat, totmat); |
| 3278 |
| 3279 for (i = 0 ; i < t->total; i++, td++) { |
| 3280 if (td->flag & TD_NOACTION) |
| 3281 break; |
| 3282 |
| 3283 if (td->flag & TD_SKIP) |
| 3284 continue; |
| 3285 |
| 3286 if (t->flag & T_PROP_EDIT) { |
| 3287 vec_rot_to_mat3(smat, axis1, td->factor * angles[0]); |
| 3288 vec_rot_to_mat3(totmat, axis2, td->factor * angles[1]); |
| 3289 |
| 3290 mul_m3_m3m3(mat, smat, totmat); |
| 3291 } |
| 3292 |
| 3293 ElementRotation(t, td, mat, t->around); |
| 3294 } |
| 3295 } |
| 3296 |
| 3297 int Trackball(TransInfo *t, const int UNUSED(mval[2])) |
| 3298 { |
| 3299 char str[128], *spos= str; |
| 3300 float axis1[3], axis2[3]; |
| 3301 float mat[3][3], totmat[3][3], smat[3][3]; |
| 3302 float phi[2]; |
| 3303 |
| 3304 copy_v3_v3(axis1, t->persinv[0]); |
| 3305 copy_v3_v3(axis2, t->persinv[1]); |
| 3306 normalize_v3(axis1); |
| 3307 normalize_v3(axis2); |
| 3308 |
| 3309 phi[0] = t->values[0]; |
| 3310 phi[1] = t->values[1]; |
| 3311 |
| 3312 snapGrid(t, phi); |
| 3313 |
| 3314 if (hasNumInput(&t->num)) { |
| 3315 char c[40]; |
| 3316 |
| 3317 applyNumInput(&t->num, phi); |
| 3318 |
| 3319 outputNumInput(&(t->num), c); |
| 3320 |
| 3321 spos += sprintf(spos, "Trackball: %s %s %s", &c[0], &c[20], t->p
roptext); |
| 3322 |
| 3323 phi[0] = DEG2RADF(phi[0]); |
| 3324 phi[1] = DEG2RADF(phi[1]); |
| 3325 } |
| 3326 else { |
| 3327 spos += sprintf(spos, "Trackball: %.2f %.2f %s", RAD2DEGF(phi[0]
), RAD2DEGF(phi[1]), t->proptext); |
| 3328 } |
| 3329 |
| 3330 if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) { |
| 3331 spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); |
| 3332 } |
| 3333 (void)spos; |
| 3334 |
| 3335 vec_rot_to_mat3(smat, axis1, phi[0]); |
| 3336 vec_rot_to_mat3(totmat, axis2, phi[1]); |
| 3337 |
| 3338 mul_m3_m3m3(mat, smat, totmat); |
| 3339 |
| 3340 // TRANSFORM_FIX_ME |
| 3341 //copy_m3_m3(t->mat, mat); // used in manipulator |
| 3342 |
| 3343 applyTrackball(t, axis1, axis2, phi); |
| 3344 |
| 3345 recalcData(t); |
| 3346 |
| 3347 ED_area_headerprint(t->sa, str); |
| 3348 |
| 3349 return 1; |
| 3350 } |
| 3351 |
| 3352 /* ************************** TRANSLATION *************************** */ |
| 3353 |
| 3354 void initTranslation(TransInfo *t) |
| 3355 { |
| 3356 if (t->spacetype == SPACE_ACTION) { |
| 3357 /* this space uses time translate */ |
| 3358 t->state = TRANS_CANCEL; |
| 3359 } |
| 3360 |
| 3361 t->mode = TFM_TRANSLATION; |
| 3362 t->transform = Translation; |
| 3363 |
| 3364 initMouseInputMode(t, &t->mouse, INPUT_VECTOR); |
| 3365 |
| 3366 t->idx_max = (t->flag & T_2D_EDIT)? 1: 2; |
| 3367 t->num.flag = 0; |
| 3368 t->num.idx_max = t->idx_max; |
| 3369 |
| 3370 if (t->spacetype == SPACE_VIEW3D) { |
| 3371 RegionView3D *rv3d = t->ar->regiondata; |
| 3372 |
| 3373 if (rv3d) { |
| 3374 t->snap[0] = 0.0f; |
| 3375 t->snap[1] = rv3d->gridview * 1.0f; |
| 3376 t->snap[2] = t->snap[1] * 0.1f; |
| 3377 } |
| 3378 } |
| 3379 else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) { |
| 3380 t->snap[0] = 0.0f; |
| 3381 t->snap[1] = 0.125f; |
| 3382 t->snap[2] = 0.0625f; |
| 3383 } |
| 3384 else { |
| 3385 t->snap[0] = 0.0f; |
| 3386 t->snap[1] = t->snap[2] = 1.0f; |
| 3387 } |
| 3388 |
| 3389 t->num.increment = t->snap[1]; |
| 3390 } |
| 3391 |
| 3392 static void headerTranslation(TransInfo *t, float vec[3], char *str) |
| 3393 { |
| 3394 char *spos= str; |
| 3395 char tvec[60]; |
| 3396 char distvec[20]; |
| 3397 char autoik[20]; |
| 3398 float dist; |
| 3399 |
| 3400 if (hasNumInput(&t->num)) { |
| 3401 outputNumInput(&(t->num), tvec); |
| 3402 dist = len_v3(t->num.val); |
| 3403 } |
| 3404 else { |
| 3405 float dvec[3]; |
| 3406 |
| 3407 copy_v3_v3(dvec, vec); |
| 3408 applyAspectRatio(t, dvec); |
| 3409 |
| 3410 dist = len_v3(vec); |
| 3411 if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { |
| 3412 int i, do_split= t->scene->unit.flag & USER_UNIT_OPT_SPL
IT ? 1:0; |
| 3413 |
| 3414 for (i=0; i<3; i++) |
| 3415 bUnit_AsString(&tvec[i*20], 20, dvec[i]*t->scene
->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); |
| 3416 } |
| 3417 else { |
| 3418 sprintf(&tvec[0], "%.4f", dvec[0]); |
| 3419 sprintf(&tvec[20], "%.4f", dvec[1]); |
| 3420 sprintf(&tvec[40], "%.4f", dvec[2]); |
| 3421 } |
| 3422 } |
| 3423 |
| 3424 if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) |
| 3425 bUnit_AsString(distvec, sizeof(distvec), dist*t->scene->unit.sca
le_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_U
NIT_OPT_SPLIT, 0); |
| 3426 else if ( dist > 1e10f || dist < -1e10f ) /* prevent string buffer
overflow */ |
| 3427 sprintf(distvec, "%.4e", dist); |
| 3428 else |
| 3429 sprintf(distvec, "%.4f", dist); |
| 3430 |
| 3431 if (t->flag & T_AUTOIK) { |
| 3432 short chainlen= t->settings->autoik_chainlen; |
| 3433 |
| 3434 if (chainlen) |
| 3435 sprintf(autoik, "AutoIK-Len: %d", chainlen); |
| 3436 else |
| 3437 autoik[0]= '\0'; |
| 3438 } |
| 3439 else |
| 3440 autoik[0]= '\0'; |
| 3441 |
| 3442 if (t->con.mode & CON_APPLY) { |
| 3443 switch (t->num.idx_max) { |
| 3444 case 0: |
| 3445 spos += sprintf(spos, "D: %s (%s)%s %s %s", &tvec[0], d
istvec, t->con.text, t->proptext, &autoik[0]); |
| 3446 break; |
| 3447 case 1: |
| 3448 spos += sprintf(spos, "D: %s D: %s (%s)%s %s %s", &tv
ec[0], &tvec[20], distvec, t->con.text, t->proptext, &autoik[0]); |
| 3449 break; |
| 3450 case 2: |
| 3451 spos += sprintf(spos, "D: %s D: %s D: %s (%s)%s %s %
s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoik[0
]); |
| 3452 } |
| 3453 } |
| 3454 else { |
| 3455 if (t->flag & T_2D_EDIT) |
| 3456 spos += sprintf(spos, "Dx: %s Dy: %s (%s)%s %s", &tvec
[0], &tvec[20], distvec, t->con.text, t->proptext); |
| 3457 else |
| 3458 spos += sprintf(spos, "Dx: %s Dy: %s Dz: %s (%s)%s %s
%s", &tvec[0], &tvec[20], &tvec[40], distvec, t->con.text, t->proptext, &autoi
k[0]); |
| 3459 } |
| 3460 ········ |
| 3461 if (t->flag & (T_PROP_EDIT|T_PROP_CONNECTED)) { |
| 3462 spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); |
| 3463 } |
| 3464 (void)spos; |
| 3465 } |
| 3466 |
| 3467 static void applyTranslation(TransInfo *t, float vec[3]) |
| 3468 { |
| 3469 TransData *td = t->data; |
| 3470 float tvec[3]; |
| 3471 int i; |
| 3472 |
| 3473 for (i = 0 ; i < t->total; i++, td++) { |
| 3474 if (td->flag & TD_NOACTION) |
| 3475 break; |
| 3476 ················ |
| 3477 if (td->flag & TD_SKIP) |
| 3478 continue; |
| 3479 ················ |
| 3480 /* handle snapping rotation before doing the translation */ |
| 3481 if (usingSnappingNormal(t)) { |
| 3482 if (validSnappingNormal(t)) { |
| 3483 float *original_normal; |
| 3484 float axis[3]; |
| 3485 float quat[4]; |
| 3486 float mat[3][3]; |
| 3487 float angle; |
| 3488 ································ |
| 3489 /* In pose mode, we want to align normals with Y
axis of bones... */ |
| 3490 if (t->flag & T_POSE) |
| 3491 original_normal = td->axismtx[1]; |
| 3492 else |
| 3493 original_normal = td->axismtx[2]; |
| 3494 ································ |
| 3495 cross_v3_v3v3(axis, original_normal, t->tsnap.sn
apNormal); |
| 3496 angle = saacos(dot_v3v3(original_normal, t->tsna
p.snapNormal)); |
| 3497 ································ |
| 3498 axis_angle_to_quat(quat, axis, angle); |
| 3499 ································ |
| 3500 quat_to_mat3(mat, quat); |
| 3501 ································ |
| 3502 ElementRotation(t, td, mat, V3D_LOCAL); |
| 3503 } |
| 3504 else { |
| 3505 float mat[3][3]; |
| 3506 ································ |
| 3507 unit_m3(mat); |
| 3508 ································ |
| 3509 ElementRotation(t, td, mat, V3D_LOCAL); |
| 3510 } |
| 3511 } |
| 3512 ················ |
| 3513 if (t->con.applyVec) { |
| 3514 float pvec[3]; |
| 3515 t->con.applyVec(t, td, vec, tvec, pvec); |
| 3516 } |
| 3517 else { |
| 3518 copy_v3_v3(tvec, vec); |
| 3519 } |
| 3520 ················ |
| 3521 mul_m3_v3(td->smtx, tvec); |
| 3522 mul_v3_fl(tvec, td->factor); |
| 3523 ················ |
| 3524 protectedTransBits(td->protectflag, tvec); |
| 3525 ················ |
| 3526 if (td->loc) |
| 3527 add_v3_v3v3(td->loc, td->iloc, tvec); |
| 3528 ················ |
| 3529 constraintTransLim(t, td); |
| 3530 } |
| 3531 } |
| 3532 |
| 3533 /* uses t->vec to store actual translation in */ |
| 3534 int Translation(TransInfo *t, const int UNUSED(mval[2])) |
| 3535 { |
| 3536 char str[250]; |
| 3537 |
| 3538 if (t->con.mode & CON_APPLY) { |
| 3539 float pvec[3] = {0.0f, 0.0f, 0.0f}; |
| 3540 float tvec[3]; |
| 3541 if (hasNumInput(&t->num)) { |
| 3542 removeAspectRatio(t, t->values); |
| 3543 } |
| 3544 applySnapping(t, t->values); |
| 3545 t->con.applyVec(t, NULL, t->values, tvec, pvec); |
| 3546 copy_v3_v3(t->values, tvec); |
| 3547 headerTranslation(t, pvec, str); |
| 3548 } |
| 3549 else { |
| 3550 snapGrid(t, t->values); |
| 3551 applyNumInput(&t->num, t->values); |
| 3552 if (hasNumInput(&t->num)) { |
| 3553 removeAspectRatio(t, t->values); |
| 3554 } |
| 3555 applySnapping(t, t->values); |
| 3556 headerTranslation(t, t->values, str); |
| 3557 } |
| 3558 |
| 3559 applyTranslation(t, t->values); |
| 3560 |
| 3561 /* evil hack - redo translation if clipping needed */ |
| 3562 if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 0)) |
| 3563 applyTranslation(t, t->values); |
| 3564 |
| 3565 recalcData(t); |
| 3566 |
| 3567 ED_area_headerprint(t->sa, str); |
| 3568 |
| 3569 return 1; |
| 3570 } |
| 3571 |
| 3572 /* ************************** SHRINK/FATTEN *************************** */ |
| 3573 |
| 3574 void initShrinkFatten(TransInfo *t) |
| 3575 { |
| 3576 // If not in mesh edit mode, fallback to Resize |
| 3577 if (t->obedit==NULL || t->obedit->type != OB_MESH) { |
| 3578 initResize(t); |
| 3579 } |
| 3580 else { |
| 3581 t->mode = TFM_SHRINKFATTEN; |
| 3582 t->transform = ShrinkFatten; |
| 3583 |
| 3584 initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); |
| 3585 |
| 3586 t->idx_max = 0; |
| 3587 t->num.idx_max = 0; |
| 3588 t->snap[0] = 0.0f; |
| 3589 t->snap[1] = 1.0f; |
| 3590 t->snap[2] = t->snap[1] * 0.1f; |
| 3591 |
| 3592 t->num.increment = t->snap[1]; |
| 3593 |
| 3594 t->flag |= T_NO_CONSTRAINT; |
| 3595 } |
| 3596 } |
| 3597 |
| 3598 |
| 3599 |
| 3600 int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) |
| 3601 { |
| 3602 float vec[3]; |
| 3603 float distance; |
| 3604 int i; |
| 3605 char str[64]; |
| 3606 TransData *td = t->data; |
| 3607 |
| 3608 distance = -t->values[0]; |
| 3609 |
| 3610 snapGrid(t, &distance); |
| 3611 |
| 3612 applyNumInput(&t->num, &distance); |
| 3613 |
| 3614 /* header print for NumInput */ |
| 3615 if (hasNumInput(&t->num)) { |
| 3616 char c[20]; |
| 3617 |
| 3618 outputNumInput(&(t->num), c); |
| 3619 |
| 3620 sprintf(str, "Shrink/Fatten: %s %s", c, t->proptext); |
| 3621 } |
| 3622 else { |
| 3623 /* default header print */ |
| 3624 sprintf(str, "Shrink/Fatten: %.4f %s", distance, t->proptext); |
| 3625 } |
| 3626 |
| 3627 t->values[0] = distance; |
| 3628 |
| 3629 for (i = 0 ; i < t->total; i++, td++) { |
| 3630 if (td->flag & TD_NOACTION) |
| 3631 break; |
| 3632 |
| 3633 if (td->flag & TD_SKIP) |
| 3634 continue; |
| 3635 |
| 3636 copy_v3_v3(vec, td->axismtx[2]); |
| 3637 mul_v3_fl(vec, distance); |
| 3638 mul_v3_fl(vec, td->factor); |
| 3639 |
| 3640 add_v3_v3v3(td->loc, td->iloc, vec); |
| 3641 } |
| 3642 |
| 3643 recalcData(t); |
| 3644 |
| 3645 ED_area_headerprint(t->sa, str); |
| 3646 |
| 3647 return 1; |
| 3648 } |
| 3649 |
| 3650 /* ************************** TILT *************************** */ |
| 3651 |
| 3652 void initTilt(TransInfo *t) |
| 3653 { |
| 3654 t->mode = TFM_TILT; |
| 3655 t->transform = Tilt; |
| 3656 |
| 3657 initMouseInputMode(t, &t->mouse, INPUT_ANGLE); |
| 3658 |
| 3659 t->idx_max = 0; |
| 3660 t->num.idx_max = 0; |
| 3661 t->snap[0] = 0.0f; |
| 3662 t->snap[1] = (float)((5.0/180)*M_PI); |
| 3663 t->snap[2] = t->snap[1] * 0.2f; |
| 3664 |
| 3665 t->num.increment = t->snap[1]; |
| 3666 |
| 3667 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 3668 } |
| 3669 |
| 3670 |
| 3671 |
| 3672 int Tilt(TransInfo *t, const int UNUSED(mval[2])) |
| 3673 { |
| 3674 TransData *td = t->data; |
| 3675 int i; |
| 3676 char str[50]; |
| 3677 |
| 3678 float final; |
| 3679 |
| 3680 final = t->values[0]; |
| 3681 |
| 3682 snapGrid(t, &final); |
| 3683 |
| 3684 if (hasNumInput(&t->num)) { |
| 3685 char c[20]; |
| 3686 |
| 3687 applyNumInput(&t->num, &final); |
| 3688 |
| 3689 outputNumInput(&(t->num), c); |
| 3690 |
| 3691 sprintf(str, "Tilt: %s %s", &c[0], t->proptext); |
| 3692 |
| 3693 final = DEG2RADF(final); |
| 3694 } |
| 3695 else { |
| 3696 sprintf(str, "Tilt: %.2f %s", RAD2DEGF(final), t->proptext); |
| 3697 } |
| 3698 |
| 3699 for (i = 0 ; i < t->total; i++, td++) { |
| 3700 if (td->flag & TD_NOACTION) |
| 3701 break; |
| 3702 |
| 3703 if (td->flag & TD_SKIP) |
| 3704 continue; |
| 3705 |
| 3706 if (td->val) { |
| 3707 *td->val = td->ival + final * td->factor; |
| 3708 } |
| 3709 } |
| 3710 |
| 3711 recalcData(t); |
| 3712 |
| 3713 ED_area_headerprint(t->sa, str); |
| 3714 |
| 3715 return 1; |
| 3716 } |
| 3717 |
| 3718 |
| 3719 /* ******************** Curve Shrink/Fatten *************** */ |
| 3720 |
| 3721 void initCurveShrinkFatten(TransInfo *t) |
| 3722 { |
| 3723 t->mode = TFM_CURVE_SHRINKFATTEN; |
| 3724 t->transform = CurveShrinkFatten; |
| 3725 |
| 3726 initMouseInputMode(t, &t->mouse, INPUT_SPRING); |
| 3727 |
| 3728 t->idx_max = 0; |
| 3729 t->num.idx_max = 0; |
| 3730 t->snap[0] = 0.0f; |
| 3731 t->snap[1] = 0.1f; |
| 3732 t->snap[2] = t->snap[1] * 0.1f; |
| 3733 |
| 3734 t->num.increment = t->snap[1]; |
| 3735 |
| 3736 t->flag |= T_NO_ZERO; |
| 3737 t->num.flag |= NUM_NO_ZERO; |
| 3738 |
| 3739 t->flag |= T_NO_CONSTRAINT; |
| 3740 } |
| 3741 |
| 3742 int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) |
| 3743 { |
| 3744 TransData *td = t->data; |
| 3745 float ratio; |
| 3746 int i; |
| 3747 char str[50]; |
| 3748 |
| 3749 ratio = t->values[0]; |
| 3750 |
| 3751 snapGrid(t, &ratio); |
| 3752 |
| 3753 applyNumInput(&t->num, &ratio); |
| 3754 |
| 3755 /* header print for NumInput */ |
| 3756 if (hasNumInput(&t->num)) { |
| 3757 char c[20]; |
| 3758 |
| 3759 outputNumInput(&(t->num), c); |
| 3760 sprintf(str, "Shrink/Fatten: %s", c); |
| 3761 } |
| 3762 else { |
| 3763 sprintf(str, "Shrink/Fatten: %3f", ratio); |
| 3764 } |
| 3765 |
| 3766 for (i = 0 ; i < t->total; i++, td++) { |
| 3767 if (td->flag & TD_NOACTION) |
| 3768 break; |
| 3769 |
| 3770 if (td->flag & TD_SKIP) |
| 3771 continue; |
| 3772 |
| 3773 if (td->val) { |
| 3774 // *td->val= ratio; |
| 3775 *td->val= td->ival*ratio; |
| 3776 if (*td->val <= 0.0f) *td->val = 0.001f; |
| 3777 } |
| 3778 } |
| 3779 |
| 3780 recalcData(t); |
| 3781 |
| 3782 ED_area_headerprint(t->sa, str); |
| 3783 |
| 3784 return 1; |
| 3785 } |
| 3786 |
| 3787 /* ************************** PUSH/PULL *************************** */ |
| 3788 |
| 3789 void initPushPull(TransInfo *t) |
| 3790 { |
| 3791 t->mode = TFM_PUSHPULL; |
| 3792 t->transform = PushPull; |
| 3793 |
| 3794 initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); |
| 3795 |
| 3796 t->idx_max = 0; |
| 3797 t->num.idx_max = 0; |
| 3798 t->snap[0] = 0.0f; |
| 3799 t->snap[1] = 1.0f; |
| 3800 t->snap[2] = t->snap[1] * 0.1f; |
| 3801 |
| 3802 t->num.increment = t->snap[1]; |
| 3803 } |
| 3804 |
| 3805 |
| 3806 int PushPull(TransInfo *t, const int UNUSED(mval[2])) |
| 3807 { |
| 3808 float vec[3], axis[3]; |
| 3809 float distance; |
| 3810 int i; |
| 3811 char str[128]; |
| 3812 TransData *td = t->data; |
| 3813 |
| 3814 distance = t->values[0]; |
| 3815 |
| 3816 snapGrid(t, &distance); |
| 3817 |
| 3818 applyNumInput(&t->num, &distance); |
| 3819 |
| 3820 /* header print for NumInput */ |
| 3821 if (hasNumInput(&t->num)) { |
| 3822 char c[20]; |
| 3823 |
| 3824 outputNumInput(&(t->num), c); |
| 3825 |
| 3826 sprintf(str, "Push/Pull: %s%s %s", c, t->con.text, t->proptext); |
| 3827 } |
| 3828 else { |
| 3829 /* default header print */ |
| 3830 sprintf(str, "Push/Pull: %.4f%s %s", distance, t->con.text, t->p
roptext); |
| 3831 } |
| 3832 |
| 3833 t->values[0] = distance; |
| 3834 |
| 3835 if (t->con.applyRot && t->con.mode & CON_APPLY) { |
| 3836 t->con.applyRot(t, NULL, axis, NULL); |
| 3837 } |
| 3838 |
| 3839 for (i = 0 ; i < t->total; i++, td++) { |
| 3840 if (td->flag & TD_NOACTION) |
| 3841 break; |
| 3842 |
| 3843 if (td->flag & TD_SKIP) |
| 3844 continue; |
| 3845 |
| 3846 sub_v3_v3v3(vec, t->center, td->center); |
| 3847 if (t->con.applyRot && t->con.mode & CON_APPLY) { |
| 3848 t->con.applyRot(t, td, axis, NULL); |
| 3849 if (isLockConstraint(t)) { |
| 3850 float dvec[3]; |
| 3851 project_v3_v3v3(dvec, vec, axis); |
| 3852 sub_v3_v3(vec, dvec); |
| 3853 } |
| 3854 else { |
| 3855 project_v3_v3v3(vec, vec, axis); |
| 3856 } |
| 3857 } |
| 3858 normalize_v3(vec); |
| 3859 mul_v3_fl(vec, distance); |
| 3860 mul_v3_fl(vec, td->factor); |
| 3861 |
| 3862 add_v3_v3v3(td->loc, td->iloc, vec); |
| 3863 } |
| 3864 |
| 3865 recalcData(t); |
| 3866 |
| 3867 ED_area_headerprint(t->sa, str); |
| 3868 |
| 3869 return 1; |
| 3870 } |
| 3871 |
| 3872 /* ************************** BEVEL **************************** */ |
| 3873 |
| 3874 void initBevel(TransInfo *t) |
| 3875 { |
| 3876 t->transform = Bevel; |
| 3877 t->handleEvent = handleEventBevel; |
| 3878 |
| 3879 initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); |
| 3880 |
| 3881 t->mode = TFM_BEVEL; |
| 3882 t->flag |= T_NO_CONSTRAINT; |
| 3883 t->num.flag |= NUM_NO_NEGATIVE; |
| 3884 |
| 3885 t->idx_max = 0; |
| 3886 t->num.idx_max = 0; |
| 3887 t->snap[0] = 0.0f; |
| 3888 t->snap[1] = 0.1f; |
| 3889 t->snap[2] = t->snap[1] * 0.1f; |
| 3890 |
| 3891 t->num.increment = t->snap[1]; |
| 3892 |
| 3893 /* DON'T KNOW WHY THIS IS NEEDED */ |
| 3894 if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) { |
| 3895 /* save the initial mouse co */ |
| 3896 G.editBMesh->imval[0] = t->imval[0]; |
| 3897 G.editBMesh->imval[1] = t->imval[1]; |
| 3898 } |
| 3899 else { |
| 3900 /* restore the mouse co from a previous call to initTransform()
*/ |
| 3901 t->imval[0] = G.editBMesh->imval[0]; |
| 3902 t->imval[1] = G.editBMesh->imval[1]; |
| 3903 } |
| 3904 } |
| 3905 |
| 3906 int handleEventBevel(TransInfo *t, wmEvent *event) |
| 3907 { |
| 3908 if (event->val == KM_PRESS) { |
| 3909 if (!G.editBMesh) return 0; |
| 3910 |
| 3911 switch (event->type) { |
| 3912 case MIDDLEMOUSE: |
| 3913 G.editBMesh->options ^= BME_BEVEL_VERT; |
| 3914 t->state = TRANS_CANCEL; |
| 3915 return 1; |
| 3916 //case PADPLUSKEY: |
| 3917 // G.editBMesh->options ^= BME_BEVEL_RES; |
| 3918 // G.editBMesh->res += 1; |
| 3919 // if (G.editBMesh->res > 4) { |
| 3920 // G.editBMesh->res = 4; |
| 3921 // } |
| 3922 // t->state = TRANS_CANCEL; |
| 3923 // return 1; |
| 3924 //case PADMINUS: |
| 3925 // G.editBMesh->options ^= BME_BEVEL_RES; |
| 3926 // G.editBMesh->res -= 1; |
| 3927 // if (G.editBMesh->res < 0) { |
| 3928 // G.editBMesh->res = 0; |
| 3929 // } |
| 3930 // t->state = TRANS_CANCEL; |
| 3931 // return 1; |
| 3932 default: |
| 3933 return 0; |
| 3934 } |
| 3935 } |
| 3936 return 0; |
| 3937 } |
| 3938 |
| 3939 int Bevel(TransInfo *t, const int UNUSED(mval[2])) |
| 3940 { |
| 3941 float distance, d; |
| 3942 int i; |
| 3943 char str[128]; |
| 3944 const char *mode; |
| 3945 TransData *td = t->data; |
| 3946 |
| 3947 mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal"
; |
| 3948 distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothin
g special */ |
| 3949 |
| 3950 distance = fabs(distance); |
| 3951 |
| 3952 snapGrid(t, &distance); |
| 3953 |
| 3954 applyNumInput(&t->num, &distance); |
| 3955 |
| 3956 /* header print for NumInput */ |
| 3957 if (hasNumInput(&t->num)) { |
| 3958 char c[20]; |
| 3959 |
| 3960 outputNumInput(&(t->num), c); |
| 3961 |
| 3962 sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, m
ode); |
| 3963 } |
| 3964 else { |
| 3965 /* default header print */ |
| 3966 sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", di
stance, mode); |
| 3967 } |
| 3968 |
| 3969 if (distance < 0) distance = -distance; |
| 3970 for (i = 0 ; i < t->total; i++, td++) { |
| 3971 if (td->axismtx[1][0] > 0 && distance > td->axismtx[1][0]) { |
| 3972 d = td->axismtx[1][0]; |
| 3973 } |
| 3974 else { |
| 3975 d = distance; |
| 3976 } |
| 3977 madd_v3_v3v3fl(td->loc, td->center, td->axismtx[0], (*td->val) *
d); |
| 3978 } |
| 3979 |
| 3980 recalcData(t); |
| 3981 |
| 3982 ED_area_headerprint(t->sa, str); |
| 3983 |
| 3984 return 1; |
| 3985 } |
| 3986 |
| 3987 /* ************************** BEVEL WEIGHT *************************** */ |
| 3988 |
| 3989 void initBevelWeight(TransInfo *t) |
| 3990 { |
| 3991 t->mode = TFM_BWEIGHT; |
| 3992 t->transform = BevelWeight; |
| 3993 |
| 3994 initMouseInputMode(t, &t->mouse, INPUT_SPRING); |
| 3995 |
| 3996 t->idx_max = 0; |
| 3997 t->num.idx_max = 0; |
| 3998 t->snap[0] = 0.0f; |
| 3999 t->snap[1] = 0.1f; |
| 4000 t->snap[2] = t->snap[1] * 0.1f; |
| 4001 |
| 4002 t->num.increment = t->snap[1]; |
| 4003 |
| 4004 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 4005 } |
| 4006 |
| 4007 int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) |
| 4008 { |
| 4009 TransData *td = t->data; |
| 4010 float weight; |
| 4011 int i; |
| 4012 char str[50]; |
| 4013 |
| 4014 weight = t->values[0]; |
| 4015 |
| 4016 weight -= 1.0f; |
| 4017 if (weight > 1.0f) weight = 1.0f; |
| 4018 |
| 4019 snapGrid(t, &weight); |
| 4020 |
| 4021 applyNumInput(&t->num, &weight); |
| 4022 |
| 4023 /* header print for NumInput */ |
| 4024 if (hasNumInput(&t->num)) { |
| 4025 char c[20]; |
| 4026 |
| 4027 outputNumInput(&(t->num), c); |
| 4028 |
| 4029 if (weight >= 0.0f) |
| 4030 sprintf(str, "Bevel Weight: +%s %s", c, t->proptext); |
| 4031 else |
| 4032 sprintf(str, "Bevel Weight: %s %s", c, t->proptext); |
| 4033 } |
| 4034 else { |
| 4035 /* default header print */ |
| 4036 if (weight >= 0.0f) |
| 4037 sprintf(str, "Bevel Weight: +%.3f %s", weight, t->propte
xt); |
| 4038 else |
| 4039 sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptex
t); |
| 4040 } |
| 4041 |
| 4042 for (i = 0 ; i < t->total; i++, td++) { |
| 4043 if (td->flag & TD_NOACTION) |
| 4044 break; |
| 4045 |
| 4046 if (td->val) { |
| 4047 *td->val = td->ival + weight * td->factor; |
| 4048 if (*td->val < 0.0f) *td->val = 0.0f; |
| 4049 if (*td->val > 1.0f) *td->val = 1.0f; |
| 4050 } |
| 4051 } |
| 4052 |
| 4053 recalcData(t); |
| 4054 |
| 4055 ED_area_headerprint(t->sa, str); |
| 4056 |
| 4057 return 1; |
| 4058 } |
| 4059 |
| 4060 /* ************************** CREASE *************************** */ |
| 4061 |
| 4062 void initCrease(TransInfo *t) |
| 4063 { |
| 4064 t->mode = TFM_CREASE; |
| 4065 t->transform = Crease; |
| 4066 |
| 4067 initMouseInputMode(t, &t->mouse, INPUT_SPRING); |
| 4068 |
| 4069 t->idx_max = 0; |
| 4070 t->num.idx_max = 0; |
| 4071 t->snap[0] = 0.0f; |
| 4072 t->snap[1] = 0.1f; |
| 4073 t->snap[2] = t->snap[1] * 0.1f; |
| 4074 |
| 4075 t->num.increment = t->snap[1]; |
| 4076 |
| 4077 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 4078 } |
| 4079 |
| 4080 int Crease(TransInfo *t, const int UNUSED(mval[2])) |
| 4081 { |
| 4082 TransData *td = t->data; |
| 4083 float crease; |
| 4084 int i; |
| 4085 char str[50]; |
| 4086 |
| 4087 crease = t->values[0]; |
| 4088 |
| 4089 crease -= 1.0f; |
| 4090 if (crease > 1.0f) crease = 1.0f; |
| 4091 |
| 4092 snapGrid(t, &crease); |
| 4093 |
| 4094 applyNumInput(&t->num, &crease); |
| 4095 |
| 4096 /* header print for NumInput */ |
| 4097 if (hasNumInput(&t->num)) { |
| 4098 char c[20]; |
| 4099 |
| 4100 outputNumInput(&(t->num), c); |
| 4101 |
| 4102 if (crease >= 0.0f) |
| 4103 sprintf(str, "Crease: +%s %s", c, t->proptext); |
| 4104 else |
| 4105 sprintf(str, "Crease: %s %s", c, t->proptext); |
| 4106 } |
| 4107 else { |
| 4108 /* default header print */ |
| 4109 if (crease >= 0.0f) |
| 4110 sprintf(str, "Crease: +%.3f %s", crease, t->proptext); |
| 4111 else |
| 4112 sprintf(str, "Crease: %.3f %s", crease, t->proptext); |
| 4113 } |
| 4114 |
| 4115 for (i = 0 ; i < t->total; i++, td++) { |
| 4116 if (td->flag & TD_NOACTION) |
| 4117 break; |
| 4118 |
| 4119 if (td->flag & TD_SKIP) |
| 4120 continue; |
| 4121 |
| 4122 if (td->val) { |
| 4123 *td->val = td->ival + crease * td->factor; |
| 4124 if (*td->val < 0.0f) *td->val = 0.0f; |
| 4125 if (*td->val > 1.0f) *td->val = 1.0f; |
| 4126 } |
| 4127 } |
| 4128 |
| 4129 recalcData(t); |
| 4130 |
| 4131 ED_area_headerprint(t->sa, str); |
| 4132 |
| 4133 return 1; |
| 4134 } |
| 4135 |
| 4136 /* ******************** EditBone (B-bone) width scaling *************** */ |
| 4137 |
| 4138 void initBoneSize(TransInfo *t) |
| 4139 { |
| 4140 t->mode = TFM_BONESIZE; |
| 4141 t->transform = BoneSize; |
| 4142 |
| 4143 initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); |
| 4144 |
| 4145 t->idx_max = 2; |
| 4146 t->num.idx_max = 2; |
| 4147 t->num.flag |= NUM_NULL_ONE; |
| 4148 t->num.flag |= NUM_AFFECT_ALL; |
| 4149 t->snap[0] = 0.0f; |
| 4150 t->snap[1] = 0.1f; |
| 4151 t->snap[2] = t->snap[1] * 0.1f; |
| 4152 |
| 4153 t->num.increment = t->snap[1]; |
| 4154 } |
| 4155 |
| 4156 static void headerBoneSize(TransInfo *t, float vec[3], char *str) |
| 4157 { |
| 4158 char tvec[60]; |
| 4159 if (hasNumInput(&t->num)) { |
| 4160 outputNumInput(&(t->num), tvec); |
| 4161 } |
| 4162 else { |
| 4163 sprintf(&tvec[0], "%.4f", vec[0]); |
| 4164 sprintf(&tvec[20], "%.4f", vec[1]); |
| 4165 sprintf(&tvec[40], "%.4f", vec[2]); |
| 4166 } |
| 4167 |
| 4168 /* hmm... perhaps the y-axis values don't need to be shown? */ |
| 4169 if (t->con.mode & CON_APPLY) { |
| 4170 if (t->num.idx_max == 0) |
| 4171 sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t
->proptext); |
| 4172 else |
| 4173 sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tve
c[20], &tvec[40], t->con.text, t->proptext); |
| 4174 } |
| 4175 else { |
| 4176 sprintf(str, "ScaleB X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[
20], &tvec[40], t->con.text, t->proptext); |
| 4177 } |
| 4178 } |
| 4179 |
| 4180 static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) |
| 4181 { |
| 4182 float tmat[3][3], smat[3][3], oldy; |
| 4183 float sizemat[3][3]; |
| 4184 |
| 4185 mul_m3_m3m3(smat, mat, td->mtx); |
| 4186 mul_m3_m3m3(tmat, td->smtx, smat); |
| 4187 |
| 4188 if (t->con.applySize) { |
| 4189 t->con.applySize(t, td, tmat); |
| 4190 } |
| 4191 |
| 4192 /* we've tucked the scale in loc */ |
| 4193 oldy= td->iloc[1]; |
| 4194 size_to_mat3(sizemat, td->iloc); |
| 4195 mul_m3_m3m3(tmat, tmat, sizemat); |
| 4196 mat3_to_size(td->loc, tmat); |
| 4197 td->loc[1]= oldy; |
| 4198 } |
| 4199 |
| 4200 int BoneSize(TransInfo *t, const int mval[2]) |
| 4201 { |
| 4202 TransData *td = t->data; |
| 4203 float size[3], mat[3][3]; |
| 4204 float ratio; |
| 4205 int i; |
| 4206 char str[60]; |
| 4207 ········ |
| 4208 // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT |
| 4209 /* for manipulator, center handle, the scaling can't be done relative to
center */ |
| 4210 if ((t->flag & T_USES_MANIPULATOR) && t->con.mode==0) { |
| 4211 ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]
))/100.0f; |
| 4212 } |
| 4213 else { |
| 4214 ratio = t->values[0]; |
| 4215 } |
| 4216 ········ |
| 4217 size[0] = size[1] = size[2] = ratio; |
| 4218 ········ |
| 4219 snapGrid(t, size); |
| 4220 ········ |
| 4221 if (hasNumInput(&t->num)) { |
| 4222 applyNumInput(&t->num, size); |
| 4223 constraintNumInput(t, size); |
| 4224 } |
| 4225 ········ |
| 4226 size_to_mat3(mat, size); |
| 4227 ········ |
| 4228 if (t->con.applySize) { |
| 4229 t->con.applySize(t, NULL, mat); |
| 4230 } |
| 4231 ········ |
| 4232 copy_m3_m3(t->mat, mat); // used in manipulator |
| 4233 ········ |
| 4234 headerBoneSize(t, size, str); |
| 4235 ········ |
| 4236 for (i = 0 ; i < t->total; i++, td++) { |
| 4237 if (td->flag & TD_NOACTION) |
| 4238 break; |
| 4239 ················ |
| 4240 if (td->flag & TD_SKIP) |
| 4241 continue; |
| 4242 ················ |
| 4243 ElementBoneSize(t, td, mat); |
| 4244 } |
| 4245 ········ |
| 4246 recalcData(t); |
| 4247 ········ |
| 4248 ED_area_headerprint(t->sa, str); |
| 4249 ········ |
| 4250 return 1; |
| 4251 } |
| 4252 |
| 4253 |
| 4254 /* ******************** EditBone envelope *************** */ |
| 4255 |
| 4256 void initBoneEnvelope(TransInfo *t) |
| 4257 { |
| 4258 t->mode = TFM_BONE_ENVELOPE; |
| 4259 t->transform = BoneEnvelope; |
| 4260 ········ |
| 4261 initMouseInputMode(t, &t->mouse, INPUT_SPRING); |
| 4262 ········ |
| 4263 t->idx_max = 0; |
| 4264 t->num.idx_max = 0; |
| 4265 t->snap[0] = 0.0f; |
| 4266 t->snap[1] = 0.1f; |
| 4267 t->snap[2] = t->snap[1] * 0.1f; |
| 4268 ········ |
| 4269 t->num.increment = t->snap[1]; |
| 4270 |
| 4271 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 4272 } |
| 4273 |
| 4274 int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) |
| 4275 { |
| 4276 TransData *td = t->data; |
| 4277 float ratio; |
| 4278 int i; |
| 4279 char str[50]; |
| 4280 ········ |
| 4281 ratio = t->values[0]; |
| 4282 ········ |
| 4283 snapGrid(t, &ratio); |
| 4284 ········ |
| 4285 applyNumInput(&t->num, &ratio); |
| 4286 ········ |
| 4287 /* header print for NumInput */ |
| 4288 if (hasNumInput(&t->num)) { |
| 4289 char c[20]; |
| 4290 ················ |
| 4291 outputNumInput(&(t->num), c); |
| 4292 sprintf(str, "Envelope: %s", c); |
| 4293 } |
| 4294 else { |
| 4295 sprintf(str, "Envelope: %3f", ratio); |
| 4296 } |
| 4297 ········ |
| 4298 for (i = 0 ; i < t->total; i++, td++) { |
| 4299 if (td->flag & TD_NOACTION) |
| 4300 break; |
| 4301 ················ |
| 4302 if (td->flag & TD_SKIP) |
| 4303 continue; |
| 4304 ················ |
| 4305 if (td->val) { |
| 4306 /* if the old/original value was 0.0f, then just use rat
io */ |
| 4307 if (td->ival) |
| 4308 *td->val= td->ival*ratio; |
| 4309 else |
| 4310 *td->val= ratio; |
| 4311 } |
| 4312 } |
| 4313 ········ |
| 4314 recalcData(t); |
| 4315 ········ |
| 4316 ED_area_headerprint(t->sa, str); |
| 4317 ········ |
| 4318 return 1; |
| 4319 } |
| 4320 |
| 4321 /* ******************** Edge Slide *************** */ |
| 4322 static BMEdge *get_other_edge(BMVert *v, BMEdge *e) |
| 4323 { |
| 4324 BMIter iter; |
| 4325 BMEdge *e2; |
| 4326 |
| 4327 BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) { |
| 4328 if (BM_elem_flag_test(e2, BM_ELEM_SELECT) && e2 != e) |
| 4329 return e2; |
| 4330 } |
| 4331 |
| 4332 return NULL; |
| 4333 } |
| 4334 |
| 4335 static BMLoop *get_next_loop(BMVert *v, BMLoop *l, |
| 4336 BMEdge *olde, BMEdge *nexte, float vec[3]) |
| 4337 { |
| 4338 BMLoop *firstl; |
| 4339 float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f}; |
| 4340 int i=0; |
| 4341 |
| 4342 firstl = l; |
| 4343 do { |
| 4344 l = BM_face_other_edge_loop(l->f, l->e, v); |
| 4345 if (l->radial_next == l) |
| 4346 return NULL; |
| 4347 ················ |
| 4348 if (l->e == nexte) { |
| 4349 if (i) { |
| 4350 mul_v3_fl(a, 1.0f / (float)i); |
| 4351 } |
| 4352 else { |
| 4353 float f1[3], f2[3], f3[3]; |
| 4354 |
| 4355 sub_v3_v3v3(f1, BM_edge_other_vert(olde, v)->co,
v->co); |
| 4356 sub_v3_v3v3(f2, BM_edge_other_vert(nexte, v)->co
, v->co); |
| 4357 |
| 4358 cross_v3_v3v3(f3, f1, l->f->no); |
| 4359 cross_v3_v3v3(a, f2, l->f->no); |
| 4360 mul_v3_fl(a, -1.0f); |
| 4361 |
| 4362 add_v3_v3(a, f3); |
| 4363 mul_v3_fl(a, 0.5f); |
| 4364 } |
| 4365 ························ |
| 4366 copy_v3_v3(vec, a); |
| 4367 return l; |
| 4368 } |
| 4369 else { |
| 4370 sub_v3_v3v3(n, BM_edge_other_vert(l->e, v)->co, v->co); |
| 4371 add_v3_v3v3(a, a, n); |
| 4372 i += 1; |
| 4373 } |
| 4374 |
| 4375 if (BM_face_other_edge_loop(l->f, l->e, v)->e == nexte) { |
| 4376 if (i) |
| 4377 mul_v3_fl(a, 1.0f / (float)i); |
| 4378 ························ |
| 4379 copy_v3_v3(vec, a); |
| 4380 return BM_face_other_edge_loop(l->f, l->e, v); |
| 4381 } |
| 4382 ················ |
| 4383 l = l->radial_next; |
| 4384 } while (l != firstl);· |
| 4385 |
| 4386 if (i) |
| 4387 mul_v3_fl(a, 1.0f / (float)i); |
| 4388 ········ |
| 4389 copy_v3_v3(vec, a); |
| 4390 ········ |
| 4391 return NULL; |
| 4392 } |
| 4393 |
| 4394 static int createSlideVerts(TransInfo *t) |
| 4395 { |
| 4396 Mesh *me = t->obedit->data; |
| 4397 BMEditMesh *em = me->edit_btmesh; |
| 4398 BMesh *bm = em->bm; |
| 4399 BMIter iter, iter2; |
| 4400 BMEdge *e, *e1 /*, *ee, *le */ /* UNUSED */; |
| 4401 BMVert *v, *v2, *first; |
| 4402 BMLoop *l, *l1, *l2; |
| 4403 TransDataSlideVert *sv_array; |
| 4404 BMBVHTree *btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL); |
| 4405 SmallHash table; |
| 4406 SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); |
| 4407 View3D *v3d = t->sa ? t->sa->spacedata.first : NULL; |
| 4408 RegionView3D *rv3d = t->ar ? t->ar->regiondata : NULL; /* background mod
e support */ |
| 4409 ARegion *ar = t->ar; |
| 4410 float projectMat[4][4]; |
| 4411 float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f}
; |
| 4412 float vec[3], vec2[3], lastvec[3] /*, size, dis=0.0, z */ /* UNUSED */; |
| 4413 int numsel, i, j; |
| 4414 |
| 4415 if (!v3d) { |
| 4416 /* ok, let's try to survive this */ |
| 4417 unit_m4(projectMat); |
| 4418 } |
| 4419 else { |
| 4420 ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); |
| 4421 } |
| 4422 ········ |
| 4423 BLI_smallhash_init(&sld->vhash); |
| 4424 BLI_smallhash_init(&sld->origfaces); |
| 4425 BLI_smallhash_init(&table); |
| 4426 ········ |
| 4427 /*ensure valid selection*/ |
| 4428 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { |
| 4429 if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { |
| 4430 numsel = 0; |
| 4431 BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { |
| 4432 if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { |
| 4433 /* BMESH_TODO: this is probably very evi
l, |
| 4434 * set v->e to a selected edge*/ |
| 4435 v->e = e; |
| 4436 |
| 4437 numsel++; |
| 4438 } |
| 4439 } |
| 4440 |
| 4441 if (numsel == 0 || numsel > 2) { |
| 4442 MEM_freeN(sld); |
| 4443 BMBVH_FreeBVH(btree); |
| 4444 return 0; /* invalid edge selection */ |
| 4445 } |
| 4446 } |
| 4447 } |
| 4448 |
| 4449 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { |
| 4450 if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { |
| 4451 if (!BM_edge_is_manifold(e)) { |
| 4452 MEM_freeN(sld); |
| 4453 BMBVH_FreeBVH(btree); |
| 4454 return 0; /* can only handle exactly 2 faces aro
und each edge */ |
| 4455 } |
| 4456 } |
| 4457 } |
| 4458 |
| 4459 j = 0; |
| 4460 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { |
| 4461 if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { |
| 4462 BM_elem_flag_enable(v, BM_ELEM_TAG); |
| 4463 BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_PO
INTER(j)); |
| 4464 j += 1; |
| 4465 } |
| 4466 else { |
| 4467 BM_elem_flag_disable(v, BM_ELEM_TAG); |
| 4468 } |
| 4469 } |
| 4470 |
| 4471 if (!j) { |
| 4472 MEM_freeN(sld); |
| 4473 BMBVH_FreeBVH(btree); |
| 4474 return 0; |
| 4475 } |
| 4476 |
| 4477 sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); |
| 4478 |
| 4479 j = 0; |
| 4480 while (1) { |
| 4481 v = NULL; |
| 4482 BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { |
| 4483 if (BM_elem_flag_test(v, BM_ELEM_TAG)) |
| 4484 break; |
| 4485 |
| 4486 } |
| 4487 |
| 4488 if (!v) |
| 4489 break; |
| 4490 |
| 4491 if (!v->e) |
| 4492 continue; |
| 4493 ················ |
| 4494 first = v; |
| 4495 |
| 4496 /*walk along the edge loop*/ |
| 4497 e = v->e; |
| 4498 |
| 4499 /*first, rewind*/ |
| 4500 numsel = 0; |
| 4501 do { |
| 4502 e = get_other_edge(v, e); |
| 4503 if (!e) { |
| 4504 e = v->e; |
| 4505 break; |
| 4506 } |
| 4507 |
| 4508 numsel += 1; |
| 4509 |
| 4510 if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM
_TAG)) |
| 4511 break; |
| 4512 |
| 4513 v = BM_edge_other_vert(e, v); |
| 4514 } while (e != first->e); |
| 4515 |
| 4516 BM_elem_flag_disable(v, BM_ELEM_TAG); |
| 4517 |
| 4518 l1 = l2 = l = NULL; |
| 4519 l1 = e->l; |
| 4520 l2 = e->l->radial_next; |
| 4521 |
| 4522 l = BM_face_other_edge_loop(l1->f, l1->e, v); |
| 4523 sub_v3_v3v3(vec, BM_edge_other_vert(l->e, v)->co, v->co); |
| 4524 |
| 4525 if (l2 != l1) { |
| 4526 l = BM_face_other_edge_loop(l2->f, l2->e, v); |
| 4527 sub_v3_v3v3(vec2, BM_edge_other_vert(l->e, v)->co, v->co
); |
| 4528 } |
| 4529 else { |
| 4530 l2 = NULL; |
| 4531 } |
| 4532 |
| 4533 /*iterate over the loop*/ |
| 4534 first = v; |
| 4535 do { |
| 4536 TransDataSlideVert *sv = sv_array + j; |
| 4537 |
| 4538 sv->v = v; |
| 4539 sv->origvert = *v; |
| 4540 copy_v3_v3(sv->upvec, vec); |
| 4541 if (l2) |
| 4542 copy_v3_v3(sv->downvec, vec2); |
| 4543 |
| 4544 l = BM_face_other_edge_loop(l1->f, l1->e, v); |
| 4545 sv->up = BM_edge_other_vert(l->e, v); |
| 4546 |
| 4547 if (l2) { |
| 4548 l = BM_face_other_edge_loop(l2->f, l2->e, v); |
| 4549 sv->down = BM_edge_other_vert(l->e, v); |
| 4550 } |
| 4551 |
| 4552 v2=v, v = BM_edge_other_vert(e, v); |
| 4553 |
| 4554 e1 = e; |
| 4555 e = get_other_edge(v, e); |
| 4556 if (!e) { |
| 4557 //v2=v, v = BM_edge_other_vert(l1->e, v); |
| 4558 |
| 4559 sv = sv_array + j + 1; |
| 4560 sv->v = v; |
| 4561 sv->origvert = *v; |
| 4562 ································ |
| 4563 l = BM_face_other_edge_loop(l1->f, l1->e, v); |
| 4564 sv->up = BM_edge_other_vert(l->e, v); |
| 4565 sub_v3_v3v3(sv->upvec, BM_edge_other_vert(l->e,
v)->co, v->co); |
| 4566 |
| 4567 if (l2) { |
| 4568 l = BM_face_other_edge_loop(l2->f, l2->e
, v); |
| 4569 sv->down = BM_edge_other_vert(l->e, v); |
| 4570 sub_v3_v3v3(sv->downvec, BM_edge_other_v
ert(l->e, v)->co, v->co); |
| 4571 } |
| 4572 |
| 4573 BM_elem_flag_disable(v, BM_ELEM_TAG); |
| 4574 BM_elem_flag_disable(v2, BM_ELEM_TAG); |
| 4575 ································ |
| 4576 j += 2; |
| 4577 break; |
| 4578 } |
| 4579 |
| 4580 l1 = get_next_loop(v, l1, e1, e, vec); |
| 4581 l2 = l2 ? get_next_loop(v, l2, e1, e, vec2) : NULL; |
| 4582 |
| 4583 j += 1; |
| 4584 |
| 4585 BM_elem_flag_disable(v, BM_ELEM_TAG); |
| 4586 BM_elem_flag_disable(v2, BM_ELEM_TAG); |
| 4587 } while (e != first->e && l1); |
| 4588 } |
| 4589 |
| 4590 //EDBM_flag_disable_all(em, BM_ELEM_SELECT); |
| 4591 |
| 4592 sld->sv = sv_array; |
| 4593 sld->totsv = j; |
| 4594 ········ |
| 4595 /*find mouse vector*/ |
| 4596 /* dis = z = -1.0f; */ /* UNUSED */ |
| 4597 /* size = 50.0; */ /* UNUSED */ |
| 4598 zero_v3(lastvec); zero_v3(dir); |
| 4599 /* ee = le = NULL; */ /* UNUSED */ |
| 4600 BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { |
| 4601 if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { |
| 4602 BMIter iter2; |
| 4603 BMEdge *e2; |
| 4604 float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]},
d; |
| 4605 ················································ |
| 4606 /* search cross edges for visible edge to the mouse curs
or, |
| 4607 * then use the shared vertex to calculate screen vector
*/ |
| 4608 dis2 = -1.0f; |
| 4609 for (i=0; i<2; i++) { |
| 4610 v = i?e->v1:e->v2; |
| 4611 BM_ITER_ELEM (e2, &iter2, v, BM_EDGES_OF_VERT) { |
| 4612 if (BM_elem_flag_test(e2, BM_ELEM_SELECT
)) |
| 4613 continue; |
| 4614 ········································ |
| 4615 if (!BMBVH_EdgeVisible(btree, e2, ar, v3
d, t->obedit)) |
| 4616 continue; |
| 4617 ········································ |
| 4618 j = GET_INT_FROM_POINTER(BLI_smallhash_l
ookup(&table, (uintptr_t)v)); |
| 4619 |
| 4620 if (sv_array[j].down) { |
| 4621 ED_view3d_project_float_v3(ar, s
v_array[j].down->co, vec1, projectMat); |
| 4622 } |
| 4623 else { |
| 4624 add_v3_v3v3(vec1, v->co, sv_arra
y[j].downvec); |
| 4625 ED_view3d_project_float_v3(ar, v
ec1, vec1, projectMat); |
| 4626 } |
| 4627 ········································ |
| 4628 if (sv_array[j].up) { |
| 4629 ED_view3d_project_float_v3(ar, s
v_array[j].up->co, vec2, projectMat); |
| 4630 } |
| 4631 else { |
| 4632 add_v3_v3v3(vec1, v->co, sv_arra
y[j].upvec); |
| 4633 ED_view3d_project_float_v3(ar, v
ec2, vec2, projectMat); |
| 4634 } |
| 4635 |
| 4636 d = dist_to_line_segment_v2(mval, vec1,
vec2); |
| 4637 if (dis2 == -1.0f || d < dis2) { |
| 4638 dis2 = d; |
| 4639 /* ee = e2; */ /* UNUSED */ |
| 4640 /* size = len_v3v3(vec1, vec2);
*/ /* UNUSED */ |
| 4641 sub_v3_v3v3(dir, vec1, vec2); |
| 4642 } |
| 4643 } |
| 4644 } |
| 4645 } |
| 4646 } |
| 4647 |
| 4648 bmesh_edit_begin(bm, BMO_OP_FLAG_UNTAN_MULTIRES); |
| 4649 |
| 4650 /*create copies of faces for customdata projection*/ |
| 4651 sv_array = sld->sv; |
| 4652 for (i=0; i<sld->totsv; i++, sv_array++) { |
| 4653 BMIter fiter, liter; |
| 4654 BMFace *f; |
| 4655 BMLoop *l; |
| 4656 ················ |
| 4657 BM_ITER_ELEM (f, &fiter, sv_array->v, BM_FACES_OF_VERT) { |
| 4658 ························ |
| 4659 if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)
) { |
| 4660 BMFace *copyf = BM_face_copy(bm, f, TRUE, TRUE); |
| 4661 ································ |
| 4662 BM_face_select_set(bm, copyf, FALSE); |
| 4663 BM_elem_flag_enable(copyf, BM_ELEM_HIDDEN); |
| 4664 BM_ITER_ELEM (l, &liter, copyf, BM_LOOPS_OF_FACE
) { |
| 4665 BM_vert_select_set(bm, l->v, FALSE); |
| 4666 BM_elem_flag_enable(l->v, BM_ELEM_HIDDEN
); |
| 4667 BM_edge_select_set(bm, l->e, FALSE); |
| 4668 BM_elem_flag_enable(l->e, BM_ELEM_HIDDEN
); |
| 4669 } |
| 4670 |
| 4671 BLI_smallhash_insert(&sld->origfaces, (uintptr_t
)f, copyf); |
| 4672 } |
| 4673 } |
| 4674 |
| 4675 BLI_smallhash_insert(&sld->vhash, (uintptr_t)sv_array->v, sv_arr
ay); |
| 4676 } |
| 4677 ········ |
| 4678 sld->origfaces_init = TRUE; |
| 4679 sld->em = em; |
| 4680 ········ |
| 4681 /*zero out start*/ |
| 4682 zero_v3(start); |
| 4683 ········ |
| 4684 /*dir holds a vector along edge loop*/ |
| 4685 copy_v3_v3(end, dir); |
| 4686 mul_v3_fl(end, 0.5); |
| 4687 ········ |
| 4688 sld->start[0] = t->mval[0] + start[0]; |
| 4689 sld->start[1] = t->mval[1] + start[1]; |
| 4690 |
| 4691 sld->end[0] = t->mval[0] + end[0]; |
| 4692 sld->end[1] = t->mval[1] + end[1]; |
| 4693 ········ |
| 4694 sld->perc = 0.0f; |
| 4695 ········ |
| 4696 t->customData = sld; |
| 4697 ········ |
| 4698 BLI_smallhash_release(&table); |
| 4699 BMBVH_FreeBVH(btree); |
| 4700 ········ |
| 4701 return 1; |
| 4702 } |
| 4703 |
| 4704 void projectSVData(TransInfo *t, int final) |
| 4705 { |
| 4706 SlideData *sld = t->customData; |
| 4707 TransDataSlideVert *sv; |
| 4708 BMEditMesh *em = sld->em; |
| 4709 SmallHash visit; |
| 4710 int i; |
| 4711 |
| 4712 if (!em) |
| 4713 return; |
| 4714 ········ |
| 4715 if (!(t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) |
| 4716 return; |
| 4717 |
| 4718 /* don't do this at all for non-basis shape keys, too easy to |
| 4719 * accidentally break uv maps or vertex colors then */ |
| 4720 if (em->bm->shapenr > 1) |
| 4721 return; |
| 4722 |
| 4723 BLI_smallhash_init(&visit); |
| 4724 ········ |
| 4725 for (i=0, sv = sld->sv; i < sld->totsv; sv++, i++) { |
| 4726 BMIter fiter; |
| 4727 BMFace *f; |
| 4728 ················ |
| 4729 |
| 4730 /* BMESH_TODO, this interpolates between vertex/loops which are
not moved |
| 4731 * (are only apart of a face attached to a slide vert), couldn't
we iterate BM_LOOPS_OF_VERT |
| 4732 * here and only iterpolate those? */ |
| 4733 BM_ITER_ELEM (f, &fiter, sv->v, BM_FACES_OF_VERT) { |
| 4734 BMIter liter; |
| 4735 BMLoop *l; |
| 4736 |
| 4737 BMFace *f_copy; /* the copy of 'f' */ |
| 4738 BMFace *f_copy_flip; /* the copy of 'f' or detect if we
need to flip to the shorter side. */ |
| 4739 |
| 4740 char is_sel, is_hide; |
| 4741 |
| 4742 ························ |
| 4743 if (BLI_smallhash_haskey(&visit, (uintptr_t)f)) |
| 4744 continue; |
| 4745 ························ |
| 4746 BLI_smallhash_insert(&visit, (uintptr_t)f, NULL); |
| 4747 ························ |
| 4748 /* the face attributes of the copied face will get |
| 4749 * copied over, so its necessary to save the selection |
| 4750 * and hidden state*/ |
| 4751 is_sel = BM_elem_flag_test(f, BM_ELEM_SELECT); |
| 4752 is_hide = BM_elem_flag_test(f, BM_ELEM_HIDDEN); |
| 4753 ························ |
| 4754 f_copy = BLI_smallhash_lookup(&sld->origfaces, (uintptr_
t)f); |
| 4755 ························ |
| 4756 /* project onto copied projection face */ |
| 4757 BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { |
| 4758 f_copy_flip = f_copy; |
| 4759 |
| 4760 if (BM_elem_flag_test(l->e, BM_ELEM_SELECT) || B
M_elem_flag_test(l->prev->e, BM_ELEM_SELECT)) { |
| 4761 /* the loop is attached of the selected
edges that are sliding */ |
| 4762 BMLoop *l_ed_sel = l; |
| 4763 ········································ |
| 4764 if (!BM_elem_flag_test(l->e, BM_ELEM_SEL
ECT)) |
| 4765 l_ed_sel = l_ed_sel->prev; |
| 4766 ········································ |
| 4767 if (sld->perc < 0.0f) { |
| 4768 if (BM_vert_in_face(l_ed_sel->ra
dial_next->f, sv->down)) { |
| 4769 f_copy_flip = BLI_smallh
ash_lookup(&sld->origfaces, (uintptr_t)l_ed_sel->radial_next->f); |
| 4770 } |
| 4771 } |
| 4772 else if (sld->perc > 0.0f) { |
| 4773 if (BM_vert_in_face(l_ed_sel->ra
dial_next->f, sv->up)) { |
| 4774 f_copy_flip = BLI_smallh
ash_lookup(&sld->origfaces, (uintptr_t)l_ed_sel->radial_next->f); |
| 4775 } |
| 4776 } |
| 4777 |
| 4778 BLI_assert(f_copy_flip != NULL); |
| 4779 if (!f_copy_flip) { |
| 4780 continue; /* shouldn't happen,
but protection */ |
| 4781 } |
| 4782 } |
| 4783 else { |
| 4784 /* the loop is attached to only one vert
ex and not a selected edge, |
| 4785 * this means we have to find a selected
edges face going in the right direction |
| 4786 * to copy from else we get bad distorti
on see: [#31080] */ |
| 4787 BMIter eiter; |
| 4788 BMEdge *e_sel; |
| 4789 |
| 4790 BM_ITER_ELEM (e_sel, &eiter, l->v, BM_ED
GES_OF_VERT) { |
| 4791 if (BM_elem_flag_test(e_sel, BM_
ELEM_SELECT)) {; |
| 4792 break; |
| 4793 } |
| 4794 } |
| 4795 |
| 4796 if (e_sel) { |
| 4797 /* warning if the UV's are not c
ontiguous, this will copy from the _wrong_ UVs |
| 4798 * in fact whenever the face bei
ng copied is not 'f_copy' this can happen, |
| 4799 * we could be a lot smarter abo
ut this but would need to deal with every UV channel or |
| 4800 * add a way to mask out lauers
when calling #BM_loop_interp_from_face() */ |
| 4801 if (sld->perc < 0.0f) { |
| 4802 if (BM_vert_in_face(e_se
l->l->f, sv->down)) { |
| 4803 f_copy_flip = BL
I_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); |
| 4804 } |
| 4805 else if (BM_vert_in_face
(e_sel->l->radial_next->f, sv->down)) { |
| 4806 f_copy_flip = BL
I_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); |
| 4807 } |
| 4808 |
| 4809 } |
| 4810 else if (sld->perc > 0.0f) { |
| 4811 if (BM_vert_in_face(e_se
l->l->f, sv->up)) { |
| 4812 f_copy_flip = BL
I_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); |
| 4813 } |
| 4814 else if (BM_vert_in_face
(e_sel->l->radial_next->f, sv->up)) { |
| 4815 f_copy_flip = BL
I_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); |
| 4816 } |
| 4817 } |
| 4818 } |
| 4819 |
| 4820 } |
| 4821 ································ |
| 4822 /* only loop data, no vertex data since that con
tains shape keys, |
| 4823 * and we do not want to mess up other shape key
s */ |
| 4824 BM_loop_interp_from_face(em->bm, l, f_copy_flip,
FALSE, FALSE); |
| 4825 |
| 4826 if (final) { |
| 4827 BM_loop_interp_multires(em->bm, l, f_cop
y_flip); |
| 4828 if (f_copy != f_copy_flip) { |
| 4829 BM_loop_interp_multires(em->bm,
l, f_copy); |
| 4830 } |
| 4831 } |
| 4832 } |
| 4833 ························ |
| 4834 /* make sure face-attributes are correct (e.g. MTexPoly)
*/ |
| 4835 BM_elem_attrs_copy(em->bm, em->bm, f_copy, f); |
| 4836 ························ |
| 4837 /* restore selection and hidden flags */ |
| 4838 BM_face_select_set(em->bm, f, is_sel); |
| 4839 if (!is_hide) { |
| 4840 /* this check is a workaround for bug, see note
- [#30735], |
| 4841 * without this edge can be hidden and selected
*/ |
| 4842 BM_elem_hide_set(em->bm, f, is_hide); |
| 4843 } |
| 4844 } |
| 4845 } |
| 4846 ········ |
| 4847 BLI_smallhash_release(&visit); |
| 4848 } |
| 4849 |
| 4850 void freeSlideTempFaces(SlideData *sld) |
| 4851 { |
| 4852 if (sld->origfaces_init) { |
| 4853 SmallHashIter hiter; |
| 4854 BMFace *copyf; |
| 4855 |
| 4856 copyf = BLI_smallhash_iternew(&sld->origfaces, &hiter, NULL); |
| 4857 for (; copyf; copyf=BLI_smallhash_iternext(&hiter, NULL)) { |
| 4858 BM_face_verts_kill(sld->em->bm, copyf); |
| 4859 } |
| 4860 |
| 4861 BLI_smallhash_release(&sld->origfaces); |
| 4862 |
| 4863 sld->origfaces_init = FALSE; |
| 4864 } |
| 4865 } |
| 4866 |
| 4867 |
| 4868 void freeSlideVerts(TransInfo *t) |
| 4869 { |
| 4870 SlideData *sld = t->customData; |
| 4871 ········ |
| 4872 #if 0 /*BMESH_TODO*/ |
| 4873 if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { |
| 4874 TransDataSlideVert *sv; |
| 4875 LinkNode *look = sld->vertlist; |
| 4876 GHash *vertgh = sld->vhash; |
| 4877 while (look) { |
| 4878 sv = BLI_ghash_lookup(vertgh, (EditVert*)look->link); |
| 4879 if (sv != NULL) { |
| 4880 sv->up->f &= !SELECT; |
| 4881 sv->down->f &= !SELECT; |
| 4882 } |
| 4883 look = look->next; |
| 4884 } |
| 4885 } |
| 4886 #endif |
| 4887 ········ |
| 4888 if (!sld) |
| 4889 return; |
| 4890 ········ |
| 4891 freeSlideTempFaces(sld); |
| 4892 |
| 4893 bmesh_edit_end(sld->em->bm, BMO_OP_FLAG_UNTAN_MULTIRES); |
| 4894 |
| 4895 BLI_smallhash_release(&sld->vhash); |
| 4896 ········ |
| 4897 MEM_freeN(sld->sv); |
| 4898 MEM_freeN(sld); |
| 4899 ········ |
| 4900 t->customData = NULL; |
| 4901 ········ |
| 4902 recalcData(t); |
| 4903 } |
| 4904 |
| 4905 void initEdgeSlide(TransInfo *t) |
| 4906 { |
| 4907 SlideData *sld; |
| 4908 |
| 4909 t->mode = TFM_EDGE_SLIDE; |
| 4910 t->transform = EdgeSlide; |
| 4911 ········ |
| 4912 if (!createSlideVerts(t)) { |
| 4913 t->state= TRANS_CANCEL; |
| 4914 return; |
| 4915 } |
| 4916 ········ |
| 4917 sld = t->customData; |
| 4918 |
| 4919 if (!sld) |
| 4920 return; |
| 4921 |
| 4922 t->customFree = freeSlideVerts; |
| 4923 |
| 4924 /* set custom point first if you want value to be initialized by init */ |
| 4925 setCustomPoints(t, &t->mouse, sld->end, sld->start); |
| 4926 initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); |
| 4927 ········ |
| 4928 t->idx_max = 0; |
| 4929 t->num.idx_max = 0; |
| 4930 t->snap[0] = 0.0f; |
| 4931 t->snap[1] = 0.1f; |
| 4932 t->snap[2] = t->snap[1] * 0.1f; |
| 4933 |
| 4934 t->num.increment = t->snap[1]; |
| 4935 |
| 4936 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 4937 } |
| 4938 |
| 4939 static int doEdgeSlide(TransInfo *t, float perc) |
| 4940 { |
| 4941 SlideData *sld = t->customData; |
| 4942 TransDataSlideVert *svlist = sld->sv, *sv; |
| 4943 float vec[3]; |
| 4944 int i; |
| 4945 |
| 4946 sld->perc = perc; |
| 4947 |
| 4948 sv = svlist; |
| 4949 for (i=0; i<sld->totsv; i++, sv++) { |
| 4950 if (perc > 0.0f) { |
| 4951 copy_v3_v3(vec, sv->upvec); |
| 4952 mul_v3_fl(vec, perc); |
| 4953 add_v3_v3v3(sv->v->co, sv->origvert.co, vec); |
| 4954 } |
| 4955 else { |
| 4956 copy_v3_v3(vec, sv->downvec); |
| 4957 mul_v3_fl(vec, -perc); |
| 4958 add_v3_v3v3(sv->v->co, sv->origvert.co, vec); |
| 4959 } |
| 4960 } |
| 4961 ········ |
| 4962 projectSVData(t, 0); |
| 4963 ········ |
| 4964 return 1; |
| 4965 } |
| 4966 |
| 4967 int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) |
| 4968 { |
| 4969 char str[50]; |
| 4970 float final; |
| 4971 |
| 4972 final = t->values[0]; |
| 4973 |
| 4974 snapGrid(t, &final); |
| 4975 |
| 4976 /* only do this so out of range values are not displayed */ |
| 4977 CLAMP(final, -1.0f, 1.0f); |
| 4978 |
| 4979 if (hasNumInput(&t->num)) { |
| 4980 char c[20]; |
| 4981 |
| 4982 applyNumInput(&t->num, &final); |
| 4983 |
| 4984 outputNumInput(&(t->num), c); |
| 4985 |
| 4986 sprintf(str, "Edge Slide: %s", &c[0]); |
| 4987 } |
| 4988 else { |
| 4989 sprintf(str, "Edge Slide: %.2f", final); |
| 4990 } |
| 4991 |
| 4992 CLAMP(final, -1.0f, 1.0f); |
| 4993 |
| 4994 t->values[0] = final; |
| 4995 |
| 4996 /*do stuff here*/ |
| 4997 if (t->customData) |
| 4998 doEdgeSlide(t, final); |
| 4999 else { |
| 5000 strcpy(str, "Invalid Edge Selection"); |
| 5001 t->state = TRANS_CANCEL; |
| 5002 } |
| 5003 |
| 5004 recalcData(t); |
| 5005 |
| 5006 ED_area_headerprint(t->sa, str); |
| 5007 |
| 5008 return 1; |
| 5009 } |
| 5010 |
| 5011 /* ******************** EditBone roll *************** */ |
| 5012 |
| 5013 void initBoneRoll(TransInfo *t) |
| 5014 { |
| 5015 t->mode = TFM_BONE_ROLL; |
| 5016 t->transform = BoneRoll; |
| 5017 |
| 5018 initMouseInputMode(t, &t->mouse, INPUT_ANGLE); |
| 5019 |
| 5020 t->idx_max = 0; |
| 5021 t->num.idx_max = 0; |
| 5022 t->snap[0] = 0.0f; |
| 5023 t->snap[1] = (float)((5.0/180)*M_PI); |
| 5024 t->snap[2] = t->snap[1] * 0.2f; |
| 5025 |
| 5026 t->num.increment = 1.0f; |
| 5027 |
| 5028 t->flag |= T_NO_CONSTRAINT|T_NO_PROJECT; |
| 5029 } |
| 5030 |
| 5031 int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) |
| 5032 { |
| 5033 TransData *td = t->data; |
| 5034 int i; |
| 5035 char str[50]; |
| 5036 |
| 5037 float final; |
| 5038 |
| 5039 final = t->values[0]; |
| 5040 |
| 5041 snapGrid(t, &final); |
| 5042 |
| 5043 if (hasNumInput(&t->num)) { |
| 5044 char c[20]; |
| 5045 |
| 5046 applyNumInput(&t->num, &final); |
| 5047 |
| 5048 outputNumInput(&(t->num), c); |
| 5049 |
| 5050 sprintf(str, "Roll: %s", &c[0]); |
| 5051 |
| 5052 final = DEG2RADF(final); |
| 5053 } |
| 5054 else { |
| 5055 sprintf(str, "Roll: %.2f", RAD2DEGF(final)); |
| 5056 } |
| 5057 |
| 5058 /* set roll values */ |
| 5059 for (i = 0; i < t->total; i++, td++) { |
| 5060 if (td->flag & TD_NOACTION) |
| 5061 break; |
| 5062 |
| 5063 if (td->flag & TD_SKIP) |
| 5064 continue; |
| 5065 |
| 5066 *(td->val) = td->ival - final; |
| 5067 } |
| 5068 |
| 5069 recalcData(t); |
| 5070 |
| 5071 ED_area_headerprint(t->sa, str); |
| 5072 |
| 5073 return 1; |
| 5074 } |
| 5075 |
| 5076 /* ************************** BAKE TIME ******************* */ |
| 5077 |
| 5078 void initBakeTime(TransInfo *t) |
| 5079 { |
| 5080 t->transform = BakeTime; |
| 5081 initMouseInputMode(t, &t->mouse, INPUT_NONE); |
| 5082 |
| 5083 t->idx_max = 0; |
| 5084 t->num.idx_max = 0; |
| 5085 t->snap[0] = 0.0f; |
| 5086 t->snap[1] = 1.0f; |
| 5087 t->snap[2] = t->snap[1] * 0.1f; |
| 5088 |
| 5089 t->num.increment = t->snap[1]; |
| 5090 } |
| 5091 |
| 5092 int BakeTime(TransInfo *t, const int mval[2]) |
| 5093 { |
| 5094 TransData *td = t->data; |
| 5095 float time; |
| 5096 int i; |
| 5097 char str[50]; |
| 5098 |
| 5099 float fac = 0.1f; |
| 5100 |
| 5101 if (t->mouse.precision) { |
| 5102 /* calculate ratio for shiftkey pos, and for total, and blend th
ese for precision */ |
| 5103 time= (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac
; |
| 5104 time+= 0.1f*((float)(t->center2d[0]*fac - mval[0]) -time); |
| 5105 } |
| 5106 else { |
| 5107 time = (float)(t->center2d[0] - mval[0])*fac; |
| 5108 } |
| 5109 |
| 5110 snapGrid(t, &time); |
| 5111 |
| 5112 applyNumInput(&t->num, &time); |
| 5113 |
| 5114 /* header print for NumInput */ |
| 5115 if (hasNumInput(&t->num)) { |
| 5116 char c[20]; |
| 5117 |
| 5118 outputNumInput(&(t->num), c); |
| 5119 |
| 5120 if (time >= 0.0f) |
| 5121 sprintf(str, "Time: +%s %s", c, t->proptext); |
| 5122 else |
| 5123 sprintf(str, "Time: %s %s", c, t->proptext); |
| 5124 } |
| 5125 else { |
| 5126 /* default header print */ |
| 5127 if (time >= 0.0f) |
| 5128 sprintf(str, "Time: +%.3f %s", time, t->proptext); |
| 5129 else |
| 5130 sprintf(str, "Time: %.3f %s", time, t->proptext); |
| 5131 } |
| 5132 |
| 5133 for (i = 0 ; i < t->total; i++, td++) { |
| 5134 if (td->flag & TD_NOACTION) |
| 5135 break; |
| 5136 |
| 5137 if (td->flag & TD_SKIP) |
| 5138 continue; |
| 5139 |
| 5140 if (td->val) { |
| 5141 *td->val = td->ival + time * td->factor; |
| 5142 if (td->ext->size && *td->val < *td->ext->size) *td->val
= *td->ext->size; |
| 5143 if (td->ext->quat && *td->val > *td->ext->quat) *td->val
= *td->ext->quat; |
| 5144 } |
| 5145 } |
| 5146 |
| 5147 recalcData(t); |
| 5148 |
| 5149 ED_area_headerprint(t->sa, str); |
| 5150 |
| 5151 return 1; |
| 5152 } |
| 5153 |
| 5154 /* ************************** MIRROR *************************** */ |
| 5155 |
| 5156 void initMirror(TransInfo *t) |
| 5157 { |
| 5158 t->transform = Mirror; |
| 5159 initMouseInputMode(t, &t->mouse, INPUT_NONE); |
| 5160 |
| 5161 t->flag |= T_NULL_ONE; |
| 5162 if (!t->obedit) { |
| 5163 t->flag |= T_NO_ZERO; |
| 5164 } |
| 5165 } |
| 5166 |
| 5167 int Mirror(TransInfo *t, const int UNUSED(mval[2])) |
| 5168 { |
| 5169 TransData *td; |
| 5170 float size[3], mat[3][3]; |
| 5171 int i; |
| 5172 char str[200]; |
| 5173 |
| 5174 /* |
| 5175 * OPTIMIZATION: |
| 5176 * This still recalcs transformation on mouse move |
| 5177 * while it should only recalc on constraint change |
| 5178 * */ |
| 5179 |
| 5180 /* if an axis has been selected */ |
| 5181 if (t->con.mode & CON_APPLY) { |
| 5182 size[0] = size[1] = size[2] = -1; |
| 5183 |
| 5184 size_to_mat3(mat, size); |
| 5185 |
| 5186 if (t->con.applySize) { |
| 5187 t->con.applySize(t, NULL, mat); |
| 5188 } |
| 5189 |
| 5190 sprintf(str, "Mirror%s", t->con.text); |
| 5191 |
| 5192 for (i = 0, td=t->data; i < t->total; i++, td++) { |
| 5193 if (td->flag & TD_NOACTION) |
| 5194 break; |
| 5195 |
| 5196 if (td->flag & TD_SKIP) |
| 5197 continue; |
| 5198 |
| 5199 ElementResize(t, td, mat); |
| 5200 } |
| 5201 |
| 5202 recalcData(t); |
| 5203 |
| 5204 ED_area_headerprint(t->sa, str); |
| 5205 } |
| 5206 else { |
| 5207 size[0] = size[1] = size[2] = 1; |
| 5208 |
| 5209 size_to_mat3(mat, size); |
| 5210 |
| 5211 for (i = 0, td=t->data; i < t->total; i++, td++) { |
| 5212 if (td->flag & TD_NOACTION) |
| 5213 break; |
| 5214 |
| 5215 if (td->flag & TD_SKIP) |
| 5216 continue; |
| 5217 |
| 5218 ElementResize(t, td, mat); |
| 5219 } |
| 5220 |
| 5221 recalcData(t); |
| 5222 |
| 5223 if (t->flag & T_2D_EDIT) |
| 5224 ED_area_headerprint(t->sa, "Select a mirror axis (X, Y)"
); |
| 5225 else |
| 5226 ED_area_headerprint(t->sa, "Select a mirror axis (X, Y,
Z)"); |
| 5227 } |
| 5228 |
| 5229 return 1; |
| 5230 } |
| 5231 |
| 5232 /* ************************** ALIGN *************************** */ |
| 5233 |
| 5234 void initAlign(TransInfo *t) |
| 5235 { |
| 5236 t->flag |= T_NO_CONSTRAINT; |
| 5237 |
| 5238 t->transform = Align; |
| 5239 |
| 5240 initMouseInputMode(t, &t->mouse, INPUT_NONE); |
| 5241 } |
| 5242 |
| 5243 int Align(TransInfo *t, const int UNUSED(mval[2])) |
| 5244 { |
| 5245 TransData *td = t->data; |
| 5246 float center[3]; |
| 5247 int i; |
| 5248 |
| 5249 /* saving original center */ |
| 5250 copy_v3_v3(center, t->center); |
| 5251 |
| 5252 for (i = 0 ; i < t->total; i++, td++) { |
| 5253 float mat[3][3], invmat[3][3]; |
| 5254 |
| 5255 if (td->flag & TD_NOACTION) |
| 5256 break; |
| 5257 |
| 5258 if (td->flag & TD_SKIP) |
| 5259 continue; |
| 5260 |
| 5261 /* around local centers */ |
| 5262 if (t->flag & (T_OBJECT|T_POSE)) { |
| 5263 copy_v3_v3(t->center, td->center); |
| 5264 } |
| 5265 else { |
| 5266 if (t->settings->selectmode & SCE_SELECT_FACE) { |
| 5267 copy_v3_v3(t->center, td->center); |
| 5268 } |
| 5269 } |
| 5270 |
| 5271 invert_m3_m3(invmat, td->axismtx); |
| 5272 |
| 5273 mul_m3_m3m3(mat, t->spacemtx, invmat); |
| 5274 |
| 5275 ElementRotation(t, td, mat, t->around); |
| 5276 } |
| 5277 |
| 5278 /* restoring original center */ |
| 5279 copy_v3_v3(t->center, center); |
| 5280 |
| 5281 recalcData(t); |
| 5282 |
| 5283 ED_area_headerprint(t->sa, "Align"); |
| 5284 |
| 5285 return 1; |
| 5286 } |
| 5287 |
| 5288 /* ************************** SEQ SLIDE *************************** */ |
| 5289 |
| 5290 void initSeqSlide(TransInfo *t) |
| 5291 { |
| 5292 t->transform = SeqSlide; |
| 5293 |
| 5294 initMouseInputMode(t, &t->mouse, INPUT_VECTOR); |
| 5295 |
| 5296 t->idx_max = 1; |
| 5297 t->num.flag = 0; |
| 5298 t->num.idx_max = t->idx_max; |
| 5299 |
| 5300 t->snap[0] = 0.0f; |
| 5301 t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base); |
| 5302 t->snap[2] = 10.0f; |
| 5303 |
| 5304 t->num.increment = t->snap[1]; |
| 5305 } |
| 5306 |
| 5307 static void headerSeqSlide(TransInfo *t, float val[2], char *str) |
| 5308 { |
| 5309 char tvec[60]; |
| 5310 |
| 5311 if (hasNumInput(&t->num)) { |
| 5312 outputNumInput(&(t->num), tvec); |
| 5313 } |
| 5314 else { |
| 5315 sprintf(&tvec[0], "%.0f, %.0f", val[0], val[1]); |
| 5316 } |
| 5317 |
| 5318 sprintf(str, "Sequence Slide: %s%s", &tvec[0], t->con.text); |
| 5319 } |
| 5320 |
| 5321 static void applySeqSlide(TransInfo *t, float val[2]) |
| 5322 { |
| 5323 TransData *td = t->data; |
| 5324 int i; |
| 5325 |
| 5326 for (i = 0 ; i < t->total; i++, td++) { |
| 5327 float tvec[2]; |
| 5328 |
| 5329 if (td->flag & TD_NOACTION) |
| 5330 break; |
| 5331 |
| 5332 if (td->flag & TD_SKIP) |
| 5333 continue; |
| 5334 |
| 5335 copy_v2_v2(tvec, val); |
| 5336 |
| 5337 mul_v2_fl(tvec, td->factor); |
| 5338 |
| 5339 td->loc[0] = td->iloc[0] + tvec[0]; |
| 5340 td->loc[1] = td->iloc[1] + tvec[1]; |
| 5341 } |
| 5342 } |
| 5343 |
| 5344 int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) |
| 5345 { |
| 5346 char str[200]; |
| 5347 |
| 5348 if (t->con.mode & CON_APPLY) { |
| 5349 float pvec[3] = {0.0f, 0.0f, 0.0f}; |
| 5350 float tvec[3]; |
| 5351 t->con.applyVec(t, NULL, t->values, tvec, pvec); |
| 5352 copy_v3_v3(t->values, tvec); |
| 5353 } |
| 5354 else { |
| 5355 snapGrid(t, t->values); |
| 5356 applyNumInput(&t->num, t->values); |
| 5357 } |
| 5358 |
| 5359 t->values[0] = floor(t->values[0] + 0.5f); |
| 5360 t->values[1] = floor(t->values[1] + 0.5f); |
| 5361 |
| 5362 headerSeqSlide(t, t->values, str); |
| 5363 applySeqSlide(t, t->values); |
| 5364 |
| 5365 recalcData(t); |
| 5366 |
| 5367 ED_area_headerprint(t->sa, str); |
| 5368 |
| 5369 return 1; |
| 5370 } |
| 5371 |
| 5372 /* ************************** ANIM EDITORS - TRANSFORM TOOLS *******************
******** */ |
| 5373 |
| 5374 /* ---------------- Special Helpers for Various Settings ------------- */ |
| 5375 |
| 5376 |
| 5377 /* This function returns the snapping 'mode' for Animation Editors only |
| 5378 * We cannot use the standard snapping due to NLA-strip scaling complexities. |
| 5379 */ |
| 5380 // XXX these modifier checks should be keymappable |
| 5381 static short getAnimEdit_SnapMode(TransInfo *t) |
| 5382 { |
| 5383 short autosnap= SACTSNAP_OFF; |
| 5384 ········ |
| 5385 if (t->spacetype == SPACE_ACTION) { |
| 5386 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; |
| 5387 ················ |
| 5388 if (saction) |
| 5389 autosnap= saction->autosnap; |
| 5390 } |
| 5391 else if (t->spacetype == SPACE_IPO) { |
| 5392 SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; |
| 5393 ················ |
| 5394 if (sipo) |
| 5395 autosnap= sipo->autosnap; |
| 5396 } |
| 5397 else if (t->spacetype == SPACE_NLA) { |
| 5398 SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; |
| 5399 ················ |
| 5400 if (snla) |
| 5401 autosnap= snla->autosnap; |
| 5402 } |
| 5403 else { |
| 5404 autosnap= SACTSNAP_OFF; |
| 5405 } |
| 5406 ········ |
| 5407 /* toggle autosnap on/off· |
| 5408 * - when toggling on, prefer nearest frame over 1.0 frame incremen
ts |
| 5409 */ |
| 5410 if (t->modifiers & MOD_SNAP_INVERT) { |
| 5411 if (autosnap) |
| 5412 autosnap= SACTSNAP_OFF; |
| 5413 else |
| 5414 autosnap= SACTSNAP_FRAME; |
| 5415 } |
| 5416 |
| 5417 return autosnap; |
| 5418 } |
| 5419 |
| 5420 /* This function is used for testing if an Animation Editor is displaying |
| 5421 * its data in frames or seconds (and the data needing to be edited as such). |
| 5422 * Returns 1 if in seconds, 0 if in frames |
| 5423 */ |
| 5424 static short getAnimEdit_DrawTime(TransInfo *t) |
| 5425 { |
| 5426 short drawtime; |
| 5427 |
| 5428 if (t->spacetype == SPACE_ACTION) { |
| 5429 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; |
| 5430 ················ |
| 5431 drawtime = (saction->flag & SACTION_DRAWTIME)? 1 : 0; |
| 5432 } |
| 5433 else if (t->spacetype == SPACE_NLA) { |
| 5434 SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first; |
| 5435 ················ |
| 5436 drawtime = (snla->flag & SNLA_DRAWTIME)? 1 : 0; |
| 5437 } |
| 5438 else if (t->spacetype == SPACE_IPO) { |
| 5439 SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; |
| 5440 ················ |
| 5441 drawtime = (sipo->flag & SIPO_DRAWTIME)? 1 : 0; |
| 5442 }······· |
| 5443 else { |
| 5444 drawtime = 0; |
| 5445 } |
| 5446 |
| 5447 return drawtime; |
| 5448 } |
| 5449 |
| 5450 |
| 5451 /* This function is used by Animation Editor specific transform functions to do |
| 5452 * the Snap Keyframe to Nearest Frame/Marker |
| 5453 */ |
| 5454 static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
AnimData *adt, short autosnap) |
| 5455 { |
| 5456 /* snap key to nearest frame? */ |
| 5457 if (autosnap == SACTSNAP_FRAME) { |
| 5458 |
| 5459 #if 0 /* 'doTime' disabled for now */ |
| 5460 |
| 5461 const Scene *scene= t->scene; |
| 5462 const short doTime= 0; //getAnimEdit_DrawTime(t); // NOTE: this
works, but may be confusing behavior given the option's label, hence disabled |
| 5463 const double secf= FPS; |
| 5464 #endif |
| 5465 double val; |
| 5466 ················ |
| 5467 /* convert frame to nla-action time (if needed) */ |
| 5468 if (adt) |
| 5469 val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CO
NVERT_MAP); |
| 5470 else |
| 5471 val= *(td->val); |
| 5472 ················ |
| 5473 #if 0 /* 'doTime' disabled for now */ |
| 5474 |
| 5475 /* do the snapping to nearest frame/second */ |
| 5476 if (doTime) { |
| 5477 val= (float)(floor((val/secf) + 0.5f) * secf); |
| 5478 } |
| 5479 else |
| 5480 #endif |
| 5481 { |
| 5482 val= floorf(val+0.5f); |
| 5483 } |
| 5484 ················ |
| 5485 /* convert frame out of nla-action time */ |
| 5486 if (adt) |
| 5487 *(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CO
NVERT_UNMAP); |
| 5488 else |
| 5489 *(td->val)= val; |
| 5490 } |
| 5491 /* snap key to nearest marker? */ |
| 5492 else if (autosnap == SACTSNAP_MARKER) { |
| 5493 float val; |
| 5494 ················ |
| 5495 /* convert frame to nla-action time (if needed) */ |
| 5496 if (adt) |
| 5497 val= BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CO
NVERT_MAP); |
| 5498 else |
| 5499 val= *(td->val); |
| 5500 ················ |
| 5501 /* snap to nearest marker */ |
| 5502 // TODO: need some more careful checks for where data comes from |
| 5503 val= (float)ED_markers_find_nearest_marker_time(&t->scene->marke
rs, val); |
| 5504 ················ |
| 5505 /* convert frame out of nla-action time */ |
| 5506 if (adt) |
| 5507 *(td->val)= BKE_nla_tweakedit_remap(adt, val, NLATIME_CO
NVERT_UNMAP); |
| 5508 else |
| 5509 *(td->val)= val; |
| 5510 } |
| 5511 ········ |
| 5512 /* if the handles are to be moved too (as side-effect of keyframes movin
g, to keep the general effect)· |
| 5513 * offset them by the same amount so that the general angles are maintai
ned (i.e. won't change while· |
| 5514 * handles are free-to-roam and keyframes are snap-locked) |
| 5515 */ |
| 5516 if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { |
| 5517 td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival; |
| 5518 } |
| 5519 if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { |
| 5520 td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival; |
| 5521 } |
| 5522 } |
| 5523 |
| 5524 /* ----------------- Translation ----------------------- */ |
| 5525 |
| 5526 void initTimeTranslate(TransInfo *t) |
| 5527 { |
| 5528 /* this tool is only really available in the Action Editor... */ |
| 5529 if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) { |
| 5530 t->state = TRANS_CANCEL; |
| 5531 } |
| 5532 |
| 5533 t->mode = TFM_TIME_TRANSLATE; |
| 5534 t->transform = TimeTranslate; |
| 5535 |
| 5536 initMouseInputMode(t, &t->mouse, INPUT_NONE); |
| 5537 |
| 5538 /* num-input has max of (n-1) */ |
| 5539 t->idx_max = 0; |
| 5540 t->num.flag = 0; |
| 5541 t->num.idx_max = t->idx_max; |
| 5542 |
| 5543 /* initialize snap like for everything else */ |
| 5544 t->snap[0] = 0.0f; |
| 5545 t->snap[1] = t->snap[2] = 1.0f; |
| 5546 |
| 5547 t->num.increment = t->snap[1]; |
| 5548 } |
| 5549 |
| 5550 static void headerTimeTranslate(TransInfo *t, char *str) |
| 5551 { |
| 5552 char tvec[60]; |
| 5553 |
| 5554 /* if numeric input is active, use results from that, otherwise apply sn
apping to result */ |
| 5555 if (hasNumInput(&t->num)) { |
| 5556 outputNumInput(&(t->num), tvec); |
| 5557 } |
| 5558 else { |
| 5559 const Scene *scene = t->scene; |
| 5560 const short autosnap= getAnimEdit_SnapMode(t); |
| 5561 const short doTime = getAnimEdit_DrawTime(t); |
| 5562 const double secf= FPS; |
| 5563 float val = t->values[0]; |
| 5564 ················ |
| 5565 /* apply snapping + frame->seconds conversions */ |
| 5566 if (autosnap == SACTSNAP_STEP) { |
| 5567 if (doTime) |
| 5568 val= floorf((double)val/secf + 0.5f); |
| 5569 else |
| 5570 val= floorf(val + 0.5f); |
| 5571 } |
| 5572 else { |
| 5573 if (doTime) |
| 5574 val= (float)((double)val / secf); |
| 5575 } |
| 5576 ················ |
| 5577 if (autosnap == SACTSNAP_FRAME) |
| 5578 sprintf(&tvec[0], "%d.00 (%.4f)", (int)val, val); |
| 5579 else |
| 5580 sprintf(&tvec[0], "%.4f", val); |
| 5581 } |
| 5582 |
| 5583 sprintf(str, "DeltaX: %s", &tvec[0]); |
| 5584 } |
| 5585 |
| 5586 static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) |
| 5587 { |
| 5588 TransData *td = t->data; |
| 5589 TransData2D *td2d = t->data2d; |
| 5590 Scene *scene = t->scene; |
| 5591 int i; |
| 5592 |
| 5593 const short doTime= getAnimEdit_DrawTime(t); |
| 5594 const double secf= FPS; |
| 5595 |
| 5596 const short autosnap= getAnimEdit_SnapMode(t); |
| 5597 |
| 5598 float deltax, val /* , valprev */; |
| 5599 |
| 5600 /* it doesn't matter whether we apply to t->data or t->data2d, but t->da
ta2d is more convenient */ |
| 5601 for (i = 0 ; i < t->total; i++, td++, td2d++) { |
| 5602 /* it is assumed that td->extra is a pointer to the AnimData, |
| 5603 * whose active action is where this keyframe comes from |
| 5604 * (this is only valid when not in NLA) |
| 5605 */ |
| 5606 AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; |
| 5607 |
| 5608 /* valprev = *td->val; */ /* UNUSED */ |
| 5609 |
| 5610 /* check if any need to apply nla-mapping */ |
| 5611 if (adt && t->spacetype != SPACE_SEQ) { |
| 5612 deltax = t->values[0]; |
| 5613 |
| 5614 if (autosnap == SACTSNAP_STEP) { |
| 5615 if (doTime) |
| 5616 deltax= (float)(floor((deltax/secf) + 0.
5f) * secf); |
| 5617 else |
| 5618 deltax= (float)(floor(deltax + 0.5f)); |
| 5619 } |
| 5620 |
| 5621 val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CON
VERT_MAP); |
| 5622 val += deltax; |
| 5623 *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_C
ONVERT_UNMAP); |
| 5624 } |
| 5625 else { |
| 5626 deltax = val = t->values[0]; |
| 5627 |
| 5628 if (autosnap == SACTSNAP_STEP) { |
| 5629 if (doTime) |
| 5630 val= (float)(floor((deltax/secf) + 0.5f)
* secf); |
| 5631 else |
| 5632 val= (float)(floor(val + 0.5f)); |
| 5633 } |
| 5634 |
| 5635 *(td->val) = td->ival + val; |
| 5636 } |
| 5637 |
| 5638 /* apply nearest snapping */ |
| 5639 doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); |
| 5640 } |
| 5641 } |
| 5642 |
| 5643 int TimeTranslate(TransInfo *t, const int mval[2]) |
| 5644 { |
| 5645 View2D *v2d = (View2D *)t->view; |
| 5646 float cval[2], sval[2]; |
| 5647 char str[200]; |
| 5648 |
| 5649 /* calculate translation amount from mouse movement - in 'time-grid spac
e' */ |
| 5650 UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); |
| 5651 UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[
1]); |
| 5652 |
| 5653 /* we only need to calculate effect for time (applyTimeTranslate only ne
eds that) */ |
| 5654 t->values[0] = cval[0] - sval[0]; |
| 5655 |
| 5656 /* handle numeric-input stuff */ |
| 5657 t->vec[0] = t->values[0]; |
| 5658 applyNumInput(&t->num, &t->vec[0]); |
| 5659 t->values[0] = t->vec[0]; |
| 5660 headerTimeTranslate(t, str); |
| 5661 |
| 5662 applyTimeTranslate(t, sval[0]); |
| 5663 |
| 5664 recalcData(t); |
| 5665 |
| 5666 ED_area_headerprint(t->sa, str); |
| 5667 |
| 5668 return 1; |
| 5669 } |
| 5670 |
| 5671 /* ----------------- Time Slide ----------------------- */ |
| 5672 |
| 5673 void initTimeSlide(TransInfo *t) |
| 5674 { |
| 5675 /* this tool is only really available in the Action Editor... */ |
| 5676 if (t->spacetype == SPACE_ACTION) { |
| 5677 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; |
| 5678 |
| 5679 /* set flag for drawing stuff */ |
| 5680 saction->flag |= SACTION_MOVING; |
| 5681 } |
| 5682 else { |
| 5683 t->state = TRANS_CANCEL; |
| 5684 } |
| 5685 |
| 5686 |
| 5687 t->mode = TFM_TIME_SLIDE; |
| 5688 t->transform = TimeSlide; |
| 5689 t->flag |= T_FREE_CUSTOMDATA; |
| 5690 |
| 5691 initMouseInputMode(t, &t->mouse, INPUT_NONE); |
| 5692 |
| 5693 /* num-input has max of (n-1) */ |
| 5694 t->idx_max = 0; |
| 5695 t->num.flag = 0; |
| 5696 t->num.idx_max = t->idx_max; |
| 5697 |
| 5698 /* initialize snap like for everything else */ |
| 5699 t->snap[0] = 0.0f; |
| 5700 t->snap[1] = t->snap[2] = 1.0f; |
| 5701 |
| 5702 t->num.increment = t->snap[1]; |
| 5703 } |
| 5704 |
| 5705 static void headerTimeSlide(TransInfo *t, float sval, char *str) |
| 5706 { |
| 5707 char tvec[60]; |
| 5708 |
| 5709 if (hasNumInput(&t->num)) { |
| 5710 outputNumInput(&(t->num), tvec); |
| 5711 } |
| 5712 else { |
| 5713 float minx= *((float *)(t->customData)); |
| 5714 float maxx= *((float *)(t->customData) + 1); |
| 5715 float cval= t->values[0]; |
| 5716 float val; |
| 5717 |
| 5718 val= 2.0f*(cval-sval) / (maxx-minx); |
| 5719 CLAMP(val, -1.0f, 1.0f); |
| 5720 |
| 5721 sprintf(&tvec[0], "%.4f", val); |
| 5722 } |
| 5723 |
| 5724 sprintf(str, "TimeSlide: %s", &tvec[0]); |
| 5725 } |
| 5726 |
| 5727 static void applyTimeSlide(TransInfo *t, float sval) |
| 5728 { |
| 5729 TransData *td = t->data; |
| 5730 int i; |
| 5731 |
| 5732 float minx= *((float *)(t->customData)); |
| 5733 float maxx= *((float *)(t->customData) + 1); |
| 5734 |
| 5735 /* set value for drawing black line */ |
| 5736 if (t->spacetype == SPACE_ACTION) { |
| 5737 SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; |
| 5738 float cvalf = t->values[0]; |
| 5739 |
| 5740 saction->timeslide= cvalf; |
| 5741 } |
| 5742 |
| 5743 /* it doesn't matter whether we apply to t->data or t->data2d, but t->da
ta2d is more convenient */ |
| 5744 for (i = 0 ; i < t->total; i++, td++) { |
| 5745 /* it is assumed that td->extra is a pointer to the AnimData, |
| 5746 * whose active action is where this keyframe comes from |
| 5747 * (this is only valid when not in NLA) |
| 5748 */ |
| 5749 AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; |
| 5750 float cval = t->values[0]; |
| 5751 |
| 5752 /* apply NLA-mapping to necessary values */ |
| 5753 if (adt) |
| 5754 cval= BKE_nla_tweakedit_remap(adt, cval, NLATIME_CONVERT
_UNMAP); |
| 5755 |
| 5756 /* only apply to data if in range */ |
| 5757 if ((sval > minx) && (sval < maxx)) { |
| 5758 float cvalc= CLAMPIS(cval, minx, maxx); |
| 5759 float timefac; |
| 5760 |
| 5761 /* left half? */ |
| 5762 if (td->ival < sval) { |
| 5763 timefac= (sval - td->ival) / (sval - minx); |
| 5764 *(td->val)= cvalc - timefac * (cvalc - minx); |
| 5765 } |
| 5766 else { |
| 5767 timefac= (td->ival - sval) / (maxx - sval); |
| 5768 *(td->val)= cvalc + timefac * (maxx - cvalc); |
| 5769 } |
| 5770 } |
| 5771 } |
| 5772 } |
| 5773 |
| 5774 int TimeSlide(TransInfo *t, const int mval[2]) |
| 5775 { |
| 5776 View2D *v2d = (View2D *)t->view; |
| 5777 float cval[2], sval[2]; |
| 5778 float minx= *((float *)(t->customData)); |
| 5779 float maxx= *((float *)(t->customData) + 1); |
| 5780 char str[200]; |
| 5781 |
| 5782 /* calculate mouse co-ordinates */ |
| 5783 UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); |
| 5784 UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &sval[0], &sval[
1]); |
| 5785 |
| 5786 /* t->values[0] stores cval[0], which is the current mouse-pointer locat
ion (in frames) */ |
| 5787 // XXX Need to be able to repeat this |
| 5788 t->values[0] = cval[0]; |
| 5789 |
| 5790 /* handle numeric-input stuff */ |
| 5791 t->vec[0] = 2.0f*(cval[0]-sval[0]) / (maxx-minx); |
| 5792 applyNumInput(&t->num, &t->vec[0]); |
| 5793 t->values[0] = (maxx-minx) * t->vec[0] / 2.0f + sval[0]; |
| 5794 |
| 5795 headerTimeSlide(t, sval[0], str); |
| 5796 applyTimeSlide(t, sval[0]); |
| 5797 |
| 5798 recalcData(t); |
| 5799 |
| 5800 ED_area_headerprint(t->sa, str); |
| 5801 |
| 5802 return 1; |
| 5803 } |
| 5804 |
| 5805 /* ----------------- Scaling ----------------------- */ |
| 5806 |
| 5807 void initTimeScale(TransInfo *t) |
| 5808 { |
| 5809 int center[2]; |
| 5810 |
| 5811 /* this tool is only really available in the Action Editor |
| 5812 * AND NLA Editor (for strip scaling) |
| 5813 */ |
| 5814 if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) { |
| 5815 t->state = TRANS_CANCEL; |
| 5816 } |
| 5817 |
| 5818 t->mode = TFM_TIME_SCALE; |
| 5819 t->transform = TimeScale; |
| 5820 |
| 5821 /* recalculate center2d to use CFRA and mouse Y, since that's |
| 5822 * what is used in time scale */ |
| 5823 t->center[0] = t->scene->r.cfra; |
| 5824 projectIntView(t, t->center, center); |
| 5825 center[1] = t->imval[1]; |
| 5826 |
| 5827 /* force a reinit with the center2d used here */ |
| 5828 initMouseInput(t, &t->mouse, center, t->imval); |
| 5829 |
| 5830 initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); |
| 5831 |
| 5832 t->flag |= T_NULL_ONE; |
| 5833 t->num.flag |= NUM_NULL_ONE; |
| 5834 |
| 5835 /* num-input has max of (n-1) */ |
| 5836 t->idx_max = 0; |
| 5837 t->num.flag = 0; |
| 5838 t->num.idx_max = t->idx_max; |
| 5839 |
| 5840 /* initialize snap like for everything else */ |
| 5841 t->snap[0] = 0.0f; |
| 5842 t->snap[1] = t->snap[2] = 1.0f; |
| 5843 |
| 5844 t->num.increment = t->snap[1]; |
| 5845 } |
| 5846 |
| 5847 static void headerTimeScale(TransInfo *t, char *str) |
| 5848 { |
| 5849 char tvec[60]; |
| 5850 |
| 5851 if (hasNumInput(&t->num)) |
| 5852 outputNumInput(&(t->num), tvec); |
| 5853 else |
| 5854 sprintf(&tvec[0], "%.4f", t->values[0]); |
| 5855 |
| 5856 sprintf(str, "ScaleX: %s", &tvec[0]); |
| 5857 } |
| 5858 |
| 5859 static void applyTimeScale(TransInfo *t) |
| 5860 { |
| 5861 Scene *scene = t->scene; |
| 5862 TransData *td = t->data; |
| 5863 TransData2D *td2d = t->data2d; |
| 5864 int i; |
| 5865 |
| 5866 const short autosnap= getAnimEdit_SnapMode(t); |
| 5867 const short doTime= getAnimEdit_DrawTime(t); |
| 5868 const double secf= FPS; |
| 5869 |
| 5870 |
| 5871 for (i = 0 ; i < t->total; i++, td++, td2d++) { |
| 5872 /* it is assumed that td->extra is a pointer to the AnimData, |
| 5873 * whose active action is where this keyframe comes from |
| 5874 * (this is only valid when not in NLA) |
| 5875 */ |
| 5876 AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL; |
| 5877 float startx= CFRA; |
| 5878 float fac= t->values[0]; |
| 5879 |
| 5880 if (autosnap == SACTSNAP_STEP) { |
| 5881 if (doTime) |
| 5882 fac= (float)(floor(fac/secf + 0.5f) * secf); |
| 5883 else |
| 5884 fac= (float)(floor(fac + 0.5f)); |
| 5885 } |
| 5886 |
| 5887 /* check if any need to apply nla-mapping */ |
| 5888 if (adt) |
| 5889 startx= BKE_nla_tweakedit_remap(adt, startx, NLATIME_CON
VERT_UNMAP); |
| 5890 |
| 5891 /* now, calculate the new value */ |
| 5892 *(td->val) = td->ival - startx; |
| 5893 *(td->val) *= fac; |
| 5894 *(td->val) += startx; |
| 5895 |
| 5896 /* apply nearest snapping */ |
| 5897 doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); |
| 5898 } |
| 5899 } |
| 5900 |
| 5901 int TimeScale(TransInfo *t, const int UNUSED(mval[2])) |
| 5902 { |
| 5903 char str[200]; |
| 5904 ········ |
| 5905 /* handle numeric-input stuff */ |
| 5906 t->vec[0] = t->values[0]; |
| 5907 applyNumInput(&t->num, &t->vec[0]); |
| 5908 t->values[0] = t->vec[0]; |
| 5909 headerTimeScale(t, str); |
| 5910 |
| 5911 applyTimeScale(t); |
| 5912 |
| 5913 recalcData(t); |
| 5914 |
| 5915 ED_area_headerprint(t->sa, str); |
| 5916 |
| 5917 return 1; |
| 5918 } |
| 5919 |
| 5920 /* ************************************ */ |
| 5921 |
| 5922 void BIF_TransformSetUndo(const char *UNUSED(str)) |
| 5923 { |
| 5924 // TRANSFORM_FIX_ME |
| 5925 //Trans.undostr= str; |
| 5926 } |
LEFT | RIGHT |