Project option for snap to faces.
[blender-staging.git] / source / blender / editors / transform / transform_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): none yet.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include "MEM_guardedalloc.h"
26
27 #include "DNA_scene_types.h"
28 #include "DNA_space_types.h"
29 #include "DNA_windowmanager_types.h"
30
31 #include "RNA_access.h"
32 #include "RNA_define.h"
33 #include "RNA_enum_types.h"
34
35 #include "BLI_arithb.h"
36
37 #include "BKE_utildefines.h"
38 #include "BKE_context.h"
39 #include "BKE_global.h"
40
41 #include "WM_api.h"
42 #include "WM_types.h"
43
44 #include "UI_interface.h"
45
46 #include "ED_screen.h"
47
48 #include "transform.h"
49
50 typedef struct TransformModeItem
51 {
52         char *idname;
53         int             mode;
54 } TransformModeItem;
55
56 static float VecOne[3] = {1, 1, 1};
57
58 /* need constants for this */
59 EnumPropertyItem proportional_mode_types[] = {
60                 {0, "OFF", 0, "Off", ""},
61                 {1, "ON", 0, "On", ""},
62                 {2, "CONNECTED", 0, "Connected", ""},
63                 {0, NULL, 0, NULL, NULL}
64 };
65
66 char OP_TRANSLATION[] = "TFM_OT_translate";
67 char OP_ROTATION[] = "TFM_OT_rotate";
68 char OP_TOSPHERE[] = "TFM_OT_tosphere";
69 char OP_RESIZE[] = "TFM_OT_resize";
70 char OP_SHEAR[] = "TFM_OT_shear";
71 char OP_WARP[] = "TFM_OT_warp";
72 char OP_SHRINK_FATTEN[] = "TFM_OT_shrink_fatten";
73 char OP_TILT[] = "TFM_OT_tilt";
74 char OP_TRACKBALL[] = "TFM_OT_trackball";
75 char OP_MIRROR[] = "TFM_OT_mirror";
76 char OP_EDGE_SLIDE[] = "TFM_OT_edge_slide";
77
78
79 TransformModeItem transform_modes[] =
80 {
81         {OP_TRANSLATION, TFM_TRANSLATION},
82         {OP_ROTATION, TFM_ROTATION},
83         {OP_TOSPHERE, TFM_TOSPHERE},
84         {OP_RESIZE, TFM_RESIZE},
85         {OP_SHEAR, TFM_SHEAR},
86         {OP_WARP, TFM_WARP},
87         {OP_SHRINK_FATTEN, TFM_SHRINKFATTEN},
88         {OP_TILT, TFM_TILT},
89         {OP_TRACKBALL, TFM_TRACKBALL},
90         {OP_MIRROR, TFM_MIRROR},
91         {OP_EDGE_SLIDE, TFM_EDGE_SLIDE},
92         {NULL, 0}
93 };
94
95 static int select_orientation_exec(bContext *C, wmOperator *op)
96 {
97         int orientation = RNA_enum_get(op->ptr, "orientation");
98
99         BIF_selectTransformOrientationValue(C, orientation);
100         
101         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C));
102
103         return OPERATOR_FINISHED;
104 }
105
106 static int select_orientation_invoke(bContext *C, wmOperator *op, wmEvent *event)
107 {
108         uiPopupMenu *pup;
109         uiLayout *layout;
110
111         pup= uiPupMenuBegin(C, "Orientation", 0);
112         layout= uiPupMenuLayout(pup);
113         uiItemsEnumO(layout, "TFM_OT_select_orientation", "orientation");
114         uiPupMenuEnd(C, pup);
115
116         return OPERATOR_CANCELLED;
117 }
118
119 void TFM_OT_select_orientation(struct wmOperatorType *ot)
120 {
121         PropertyRNA *prop;
122
123         /* identifiers */
124         ot->name   = "Select Orientation";
125         ot->description= "Select transformation orientation.";
126         ot->idname = "TFM_OT_select_orientation";
127         ot->flag   = OPTYPE_UNDO;
128
129         /* api callbacks */
130         ot->invoke = select_orientation_invoke;
131         ot->exec   = select_orientation_exec;
132         ot->poll   = ED_operator_areaactive;
133
134         prop= RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
135         RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation.");
136         RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
137 }
138
139
140 static int delete_orientation_exec(bContext *C, wmOperator *op)
141 {
142         View3D *v3d = CTX_wm_view3d(C);
143         int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
144
145         BIF_removeTransformOrientationIndex(C, selected_index);
146         
147         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C));
148
149         return OPERATOR_FINISHED;
150 }
151
152 static int delete_orientation_invoke(bContext *C, wmOperator *op, wmEvent *event)
153 {
154         return delete_orientation_exec(C, op);
155 }
156
157 static int delete_orientation_poll(bContext *C)
158 {
159         int selected_index = -1;
160         View3D *v3d = CTX_wm_view3d(C);
161         
162         if (ED_operator_areaactive(C) == 0)
163                 return 0;
164         
165         
166         if(v3d) {
167                 selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
168         }
169         
170         return selected_index >= 0;
171 }
172
173 void TFM_OT_delete_orientation(struct wmOperatorType *ot)
174 {
175         /* identifiers */
176         ot->name   = "Delete Orientation";
177         ot->description= "Delete transformation orientation.";
178         ot->idname = "TFM_OT_delete_orientation";
179         ot->flag   = OPTYPE_UNDO;
180
181         /* api callbacks */
182         ot->invoke = delete_orientation_invoke;
183         ot->exec   = delete_orientation_exec;
184         ot->poll   = delete_orientation_poll;
185 }
186
187 static int create_orientation_exec(bContext *C, wmOperator *op)
188 {
189         char name[36];
190         int use = RNA_boolean_get(op->ptr, "use");
191         int overwrite = RNA_boolean_get(op->ptr, "overwrite");
192         
193         RNA_string_get(op->ptr, "name", name);
194
195         BIF_createTransformOrientation(C, op->reports, name, use, overwrite);
196
197         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C));
198         
199         return OPERATOR_FINISHED;
200 }
201
202 static int create_orientation_invoke(bContext *C, wmOperator *op, wmEvent *event)
203 {
204         return create_orientation_exec(C, op);
205 }
206
207 void TFM_OT_create_orientation(struct wmOperatorType *ot)
208 {
209         /* identifiers */
210         ot->name   = "Create Orientation";
211         ot->description= "Create transformation orientation from selection.";
212         ot->idname = "TFM_OT_create_orientation";
213         ot->flag   = OPTYPE_REGISTER|OPTYPE_UNDO;
214
215         /* api callbacks */
216         ot->invoke = create_orientation_invoke;
217         ot->exec   = create_orientation_exec;
218         ot->poll   = ED_operator_areaactive;
219         ot->flag   = OPTYPE_REGISTER|OPTYPE_UNDO;
220
221         RNA_def_string(ot->srna, "name", "", 35, "Name", "Text to insert at the cursor position.");
222         RNA_def_boolean(ot->srna, "use", 0, "Use after creation", "Select orientation after its creation");
223         RNA_def_boolean(ot->srna, "overwrite", 0, "Overwrite previous", "Overwrite previously created orientation with same name");
224 }
225
226 static void transformops_exit(bContext *C, wmOperator *op)
227 {
228         saveTransform(C, op->customdata, op);
229         MEM_freeN(op->customdata);
230         op->customdata = NULL;
231         G.moving = 0;
232 }
233
234 static int transformops_data(bContext *C, wmOperator *op, wmEvent *event)
235 {
236         int retval = 1;
237         if (op->customdata == NULL)
238         {
239                 TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data");
240                 TransformModeItem *tmode;
241                 int mode = -1;
242
243                 for (tmode = transform_modes; tmode->idname; tmode++)
244                 {
245                         if (op->type->idname == tmode->idname)
246                         {
247                                 mode = tmode->mode;
248                         }
249                 }
250
251                 if (mode == -1)
252                 {
253                         mode = RNA_int_get(op->ptr, "mode");
254                 }
255
256                 retval = initTransform(C, t, op, event, mode);
257                 G.moving = 1;
258
259                 /* store data */
260                 op->customdata = t;
261         }
262
263         return retval; /* return 0 on error */
264 }
265
266 static int transform_modal(bContext *C, wmOperator *op, wmEvent *event)
267 {
268         int exit_code;
269
270         TransInfo *t = op->customdata;
271
272         transformEvent(t, event);
273
274         transformApply(C, t);
275
276
277         exit_code = transformEnd(C, t);
278
279         if (exit_code != OPERATOR_RUNNING_MODAL)
280         {
281                 transformops_exit(C, op);
282         }
283
284         return exit_code;
285 }
286
287 static int transform_cancel(bContext *C, wmOperator *op)
288 {
289         TransInfo *t = op->customdata;
290
291         t->state = TRANS_CANCEL;
292         transformEnd(C, t);
293         transformops_exit(C, op);
294
295         return OPERATOR_CANCELLED;
296 }
297
298 static int transform_exec(bContext *C, wmOperator *op)
299 {
300         TransInfo *t;
301
302         if (!transformops_data(C, op, NULL))
303         {
304                 return OPERATOR_CANCELLED;
305         }
306
307         t = op->customdata;
308
309         t->options |= CTX_AUTOCONFIRM;
310
311         transformApply(C, t);
312
313         transformEnd(C, t);
314
315         transformops_exit(C, op);
316
317         return OPERATOR_FINISHED;
318 }
319
320 static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event)
321 {
322         if (!transformops_data(C, op, event))
323         {
324                 return OPERATOR_CANCELLED;
325         }
326
327         if(RNA_property_is_set(op->ptr, "value")) {
328                 return transform_exec(C, op);
329         }
330         else {
331                 TransInfo *t = op->customdata;
332
333                 /* add temp handler */
334                 WM_event_add_modal_handler(C, op);
335
336                 t->flag |= T_MODAL; // XXX meh maybe somewhere else
337
338                 return OPERATOR_RUNNING_MODAL;
339         }
340 }
341
342 void Properties_Proportional(struct wmOperatorType *ot)
343 {
344         RNA_def_enum(ot->srna, "proportional", proportional_mode_types, 0, "Proportional Editing", "");
345         RNA_def_enum(ot->srna, "proportional_editing_falloff", prop_mode_items, 0, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
346         RNA_def_float(ot->srna, "proportional_size", 1, 0, FLT_MAX, "Proportional Size", "", 0, 100);
347 }
348
349 void Properties_Snapping(struct wmOperatorType *ot, short align)
350 {
351         RNA_def_boolean(ot->srna, "snap", 0, "Snap to Point", "");
352         RNA_def_enum(ot->srna, "snap_mode", snap_mode_items, 0, "Mode", "");
353         RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
354
355         if (align)
356         {
357                 RNA_def_boolean(ot->srna, "snap_align", 0, "Align with Point Normal", "");
358                 RNA_def_float_vector(ot->srna, "snap_normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "", -FLT_MAX, FLT_MAX);
359         }
360 }
361
362 void Properties_Constraints(struct wmOperatorType *ot)
363 {
364         PropertyRNA *prop;
365
366         RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
367         prop= RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE);
368         RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation.");
369         RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
370 }
371
372 void TFM_OT_translate(struct wmOperatorType *ot)
373 {
374         /* identifiers */
375         ot->name   = "Translate";
376         ot->description= "Translate selected items.";
377         ot->idname = OP_TRANSLATION;
378         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
379
380         /* api callbacks */
381         ot->invoke = transform_invoke;
382         ot->exec   = transform_exec;
383         ot->modal  = transform_modal;
384         ot->cancel  = transform_cancel;
385         ot->poll   = ED_operator_areaactive;
386
387         RNA_def_float_vector(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
388
389         Properties_Proportional(ot);
390
391         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
392
393         Properties_Constraints(ot);
394
395         Properties_Snapping(ot, 1);
396 }
397
398 void TFM_OT_resize(struct wmOperatorType *ot)
399 {
400         /* identifiers */
401         ot->name   = "Resize";
402         ot->description= "Resize selected items."; 
403         ot->idname = OP_RESIZE;
404         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
405
406         /* api callbacks */
407         ot->invoke = transform_invoke;
408         ot->exec   = transform_exec;
409         ot->modal  = transform_modal;
410         ot->cancel  = transform_cancel;
411         ot->poll   = ED_operator_areaactive;
412
413         RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
414
415         Properties_Proportional(ot);
416
417         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
418
419         Properties_Constraints(ot);
420
421         Properties_Snapping(ot, 0);
422 }
423
424
425 void TFM_OT_trackball(struct wmOperatorType *ot)
426 {
427         /* identifiers */
428         ot->name   = "Trackball";
429         ot->description= "Trackball style rotation of selected items.";
430         ot->idname = OP_TRACKBALL;
431         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
432
433         /* api callbacks */
434         ot->invoke = transform_invoke;
435         ot->exec   = transform_exec;
436         ot->modal  = transform_modal;
437         ot->cancel  = transform_cancel;
438         ot->poll   = ED_operator_areaactive;
439
440         RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "angle", "", -FLT_MAX, FLT_MAX);
441
442         Properties_Proportional(ot);
443
444         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
445 }
446
447 void TFM_OT_rotate(struct wmOperatorType *ot)
448 {
449         /* identifiers */
450         ot->name   = "Rotate";
451         ot->description= "Rotate selected items.";
452         ot->idname = OP_ROTATION;
453         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
454
455         /* api callbacks */
456         ot->invoke = transform_invoke;
457         ot->exec   = transform_exec;
458         ot->modal  = transform_modal;
459         ot->cancel  = transform_cancel;
460         ot->poll   = ED_operator_areaactive;
461
462         RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI*2, M_PI*2);
463
464         Properties_Proportional(ot);
465
466         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
467
468         Properties_Constraints(ot);
469
470         Properties_Snapping(ot, 0);
471 }
472
473 void TFM_OT_tilt(struct wmOperatorType *ot)
474 {
475         /* identifiers */
476         ot->name   = "Tilt";
477     /*optionals - 
478         "Tilt selected vertices."
479         "Specify an extra axis rotation for selected vertices of 3d curve." */
480         ot->description= "Tilt selected control vertices of 3d curve."; 
481         ot->idname = OP_TILT;
482         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
483
484         /* api callbacks */
485         ot->invoke = transform_invoke;
486         ot->exec   = transform_exec;
487         ot->modal  = transform_modal;
488         ot->cancel  = transform_cancel;
489         ot->poll   = ED_operator_editcurve;
490
491         RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI*2, M_PI*2);
492
493         Properties_Proportional(ot);
494
495         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
496
497         Properties_Constraints(ot);
498 }
499
500 void TFM_OT_warp(struct wmOperatorType *ot)
501 {
502         /* identifiers */
503         ot->name   = "Warp";
504         ot->description= "Warp selected items around the cursor.";
505         ot->idname = OP_WARP;
506         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
507
508         /* api callbacks */
509         ot->invoke = transform_invoke;
510         ot->exec   = transform_exec;
511         ot->modal  = transform_modal;
512         ot->cancel  = transform_cancel;
513         ot->poll   = ED_operator_areaactive;
514
515         RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", 0, 1);
516
517         Properties_Proportional(ot);
518
519         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
520
521         // XXX Shear axis?
522 //      Properties_Constraints(ot);
523 }
524
525 void TFM_OT_shear(struct wmOperatorType *ot)
526 {
527         /* identifiers */
528         ot->name   = "Shear";
529         ot->description= "Shear selected items along the horizontal screen axis.";
530         ot->idname = OP_SHEAR;
531         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
532
533         /* api callbacks */
534         ot->invoke = transform_invoke;
535         ot->exec   = transform_exec;
536         ot->modal  = transform_modal;
537         ot->cancel  = transform_cancel;
538         ot->poll   = ED_operator_areaactive;
539
540         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
541
542         Properties_Proportional(ot);
543
544         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
545
546         // XXX Shear axis?
547 //      Properties_Constraints(ot);
548 }
549
550 void TFM_OT_shrink_fatten(struct wmOperatorType *ot)
551 {
552         /* identifiers */
553         ot->name   = "Shrink/Fatten";
554         ot->description= "Shrink/fatten selected vertices along normals.";
555         ot->idname = OP_SHRINK_FATTEN;
556         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
557
558         /* api callbacks */
559         ot->invoke = transform_invoke;
560         ot->exec   = transform_exec;
561         ot->modal  = transform_modal;
562         ot->cancel  = transform_cancel;
563         ot->poll   = ED_operator_editmesh;
564
565         RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
566
567         Properties_Proportional(ot);
568
569         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
570 }
571
572 void TFM_OT_tosphere(struct wmOperatorType *ot)
573 {
574         /* identifiers */
575         ot->name   = "To Sphere";
576     //added "around mesh center" to differentiate between "MESH_OT_vertices_to_sphere()" 
577         ot->description= "Move selected vertices outward in a spherical shape around mesh center.";
578         ot->idname = OP_TOSPHERE;
579         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
580
581         /* api callbacks */
582         ot->invoke = transform_invoke;
583         ot->exec   = transform_exec;
584         ot->modal  = transform_modal;
585         ot->cancel  = transform_cancel;
586         ot->poll   = ED_operator_areaactive;
587
588         RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
589
590         Properties_Proportional(ot);
591
592         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
593 }
594
595 void TFM_OT_mirror(struct wmOperatorType *ot)
596 {
597         /* identifiers */
598         ot->name   = "Mirror";
599         ot->description= "Mirror selected vertices around one or more axes.";
600         ot->idname = OP_MIRROR;
601         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
602
603         /* api callbacks */
604         ot->invoke = transform_invoke;
605         ot->exec   = transform_exec;
606         ot->modal  = transform_modal;
607         ot->cancel  = transform_cancel;
608         ot->poll   = ED_operator_areaactive;
609
610         Properties_Proportional(ot);
611         Properties_Constraints(ot);
612 }
613
614 void TFM_OT_edge_slide(struct wmOperatorType *ot)
615 {
616         /* identifiers */
617         ot->name   = "Edge Slide";
618         ot->description= "Slide an edge loop along a mesh."; 
619         ot->idname = OP_EDGE_SLIDE;
620         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
621
622         /* api callbacks */
623         ot->invoke = transform_invoke;
624         ot->exec   = transform_exec;
625         ot->modal  = transform_modal;
626         ot->cancel  = transform_cancel;
627         ot->poll   = ED_operator_editmesh;
628
629         RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
630
631         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
632 }
633
634 void TFM_OT_transform(struct wmOperatorType *ot)
635 {
636         static EnumPropertyItem transform_mode_types[] = {
637                         {TFM_INIT, "INIT", 0, "Init", ""},
638                         {TFM_DUMMY, "DUMMY", 0, "Dummy", ""},
639                         {TFM_TRANSLATION, "TRANSLATION", 0, "Translation", ""},
640                         {TFM_ROTATION, "ROTATION", 0, "Rotation", ""},
641                         {TFM_RESIZE, "RESIZE", 0, "Resize", ""},
642                         {TFM_TOSPHERE, "TOSPHERE", 0, "Tosphere", ""},
643                         {TFM_SHEAR, "SHEAR", 0, "Shear", ""},
644                         {TFM_WARP, "WARP", 0, "Warp", ""},
645                         {TFM_SHRINKFATTEN, "SHRINKFATTEN", 0, "Shrinkfatten", ""},
646                         {TFM_TILT, "TILT", 0, "Tilt", ""},
647                         {TFM_TRACKBALL, "TRACKBALL", 0, "Trackball", ""},
648                         {TFM_PUSHPULL, "PUSHPULL", 0, "Pushpull", ""},
649                         {TFM_CREASE, "CREASE", 0, "Crease", ""},
650                         {TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
651                         {TFM_BONESIZE, "BONESIZE", 0, "Bonesize", ""},
652                         {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
653                         {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
654                         {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
655                         {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
656                         {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
657                         {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
658                         {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
659                         {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
660                         {TFM_BEVEL, "BEVEL", 0, "Bevel", ""},
661                         {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
662                         {TFM_ALIGN, "ALIGN", 0, "Align", ""},
663                         {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
664                         {0, NULL, 0, NULL, NULL}
665         };
666
667         /* identifiers */
668         ot->name   = "Transform";
669         ot->description= "Transform selected items by mode type.";
670         ot->idname = "TFM_OT_transform";
671         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
672
673         /* api callbacks */
674         ot->invoke = transform_invoke;
675         ot->exec   = transform_exec;
676         ot->modal  = transform_modal;
677         ot->cancel  = transform_cancel;
678         ot->poll   = ED_operator_areaactive;
679
680         RNA_def_enum(ot->srna, "mode", transform_mode_types, 0, "Mode", "");
681
682         RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
683
684         Properties_Proportional(ot);
685         RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
686
687         Properties_Constraints(ot);
688 }
689
690 void transform_operatortypes(void)
691 {
692         WM_operatortype_append(TFM_OT_transform);
693         WM_operatortype_append(TFM_OT_translate);
694         WM_operatortype_append(TFM_OT_rotate);
695         WM_operatortype_append(TFM_OT_tosphere);
696         WM_operatortype_append(TFM_OT_resize);
697         WM_operatortype_append(TFM_OT_shear);
698         WM_operatortype_append(TFM_OT_warp);
699         WM_operatortype_append(TFM_OT_shrink_fatten);
700         WM_operatortype_append(TFM_OT_tilt);
701         WM_operatortype_append(TFM_OT_trackball);
702         WM_operatortype_append(TFM_OT_mirror);
703         WM_operatortype_append(TFM_OT_edge_slide);
704
705         WM_operatortype_append(TFM_OT_select_orientation);
706         WM_operatortype_append(TFM_OT_create_orientation);
707         WM_operatortype_append(TFM_OT_delete_orientation);
708 }
709
710 void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid)
711 {
712         wmKeyMapItem *km;
713         
714         /* transform.c, only adds modal map once, checks if it's there */
715         transform_modal_keymap(keyconf);
716         
717         switch(spaceid)
718         {
719                 case SPACE_VIEW3D:
720                         km = WM_keymap_add_item(keymap, "TFM_OT_translate", GKEY, KM_PRESS, 0, 0);
721
722                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
723
724                         km = WM_keymap_add_item(keymap, "TFM_OT_rotate", RKEY, KM_PRESS, 0, 0);
725
726                         km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
727
728                         km = WM_keymap_add_item(keymap, "TFM_OT_warp", WKEY, KM_PRESS, KM_SHIFT, 0);
729
730                         km = WM_keymap_add_item(keymap, "TFM_OT_tosphere", SKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0);
731
732                         km = WM_keymap_add_item(keymap, "TFM_OT_shear", SKEY, KM_PRESS, KM_ALT|KM_CTRL|KM_SHIFT, 0);
733
734                         km = WM_keymap_add_item(keymap, "TFM_OT_shrink_fatten", SKEY, KM_PRESS, KM_ALT, 0);
735
736                         km = WM_keymap_add_item(keymap, "TFM_OT_tilt", TKEY, KM_PRESS, 0, 0);
737
738                         km = WM_keymap_add_item(keymap, "TFM_OT_select_orientation", SPACEKEY, KM_PRESS, KM_ALT, 0);
739
740                         km = WM_keymap_add_item(keymap, "TFM_OT_create_orientation", SPACEKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
741                         RNA_boolean_set(km->ptr, "use", 1);
742
743                         km = WM_keymap_add_item(keymap, "TFM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
744
745                         break;
746                 case SPACE_ACTION:
747                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0);
748                         RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
749
750                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
751                         RNA_int_set(km->ptr, "mode", TFM_TIME_TRANSLATE);
752
753                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
754                         RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
755
756                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0);
757                         RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE);
758
759                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", TKEY, KM_PRESS, 0, 0);
760                         RNA_int_set(km->ptr, "mode", TFM_TIME_SLIDE);
761                         break;
762                 case SPACE_IPO:
763                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", GKEY, KM_PRESS, 0, 0);
764
765                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
766
767                                 // XXX the 'mode' identifier here is not quite right
768                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
769                         RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
770
771                         km = WM_keymap_add_item(keymap, "TFM_OT_rotate", RKEY, KM_PRESS, 0, 0);
772
773                         km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
774                         break;
775                 case SPACE_NLA:
776                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", GKEY, KM_PRESS, 0, 0);
777                         RNA_int_set(km->ptr, "mode", TFM_TRANSLATION);
778                         
779                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EVT_TWEAK_S, KM_ANY, 0, 0);
780                         RNA_int_set(km->ptr, "mode", TFM_TRANSLATION);
781                         
782                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
783                         RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
784                         
785                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, 0, 0);
786                         RNA_int_set(km->ptr, "mode", TFM_TIME_SCALE);
787                         break;
788                 case SPACE_NODE:
789                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", GKEY, KM_PRESS, 0, 0);
790
791                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_A, KM_ANY, 0, 0);
792                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
793
794                         km = WM_keymap_add_item(keymap, "TFM_OT_rotate", RKEY, KM_PRESS, 0, 0);
795
796                         km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
797                         break;
798                 case SPACE_SEQ:
799                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", GKEY, KM_PRESS, 0, 0);
800
801                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
802
803                         km= WM_keymap_add_item(keymap, "TFM_OT_transform", EKEY, KM_PRESS, 0, 0);
804                         RNA_int_set(km->ptr, "mode", TFM_TIME_EXTEND);
805                         break;
806                 case SPACE_IMAGE:
807                         km = WM_keymap_add_item(keymap, "TFM_OT_translate", GKEY, KM_PRESS, 0, 0);
808
809                         km= WM_keymap_add_item(keymap, "TFM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
810
811                         km = WM_keymap_add_item(keymap, "TFM_OT_rotate", RKEY, KM_PRESS, 0, 0);
812
813                         km = WM_keymap_add_item(keymap, "TFM_OT_resize", SKEY, KM_PRESS, 0, 0);
814
815                         km = WM_keymap_add_item(keymap, "TFM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0);
816                         break;
817                 default:
818                         break;
819         }
820 }
821