1286ac850f6adbeb19598919dbe0fcf0d4afe797
[blender.git] / source / blender / editors / object / object_edit.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2008 full recode
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/object/object_edit.c
27  *  \ingroup edobj
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include <time.h>
34 #include <float.h>
35 #include <ctype.h>
36 #include <stddef.h> //for offsetof
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43 #include "BLI_editVert.h"
44 #include "BLI_ghash.h"
45 #include "BLI_rand.h"
46
47 #include "DNA_armature_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_group_types.h"
50 #include "DNA_lattice_types.h"
51 #include "DNA_material_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_property_types.h"
54 #include "DNA_scene_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_object_force.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_vfont_types.h"
59
60 #include "IMB_imbuf_types.h"
61
62 #include "BKE_anim.h"
63 #include "BKE_constraint.h"
64 #include "BKE_context.h"
65 #include "BKE_curve.h"
66 #include "BKE_effect.h"
67 #include "BKE_depsgraph.h"
68 #include "BKE_font.h"
69 #include "BKE_image.h"
70 #include "BKE_library.h"
71 #include "BKE_main.h"
72 #include "BKE_material.h"
73 #include "BKE_mball.h"
74 #include "BKE_mesh.h"
75 #include "BKE_object.h"
76 #include "BKE_paint.h"
77 #include "BKE_pointcache.h"
78 #include "BKE_property.h"
79 #include "BKE_sca.h"
80 #include "BKE_softbody.h"
81 #include "BKE_modifier.h"
82
83 #include "ED_armature.h"
84 #include "ED_curve.h"
85 #include "ED_mesh.h"
86 #include "ED_mball.h"
87 #include "ED_lattice.h"
88 #include "ED_object.h"
89 #include "ED_screen.h"
90 #include "ED_util.h"
91 #include "ED_image.h"
92
93 #include "RNA_access.h"
94 #include "RNA_define.h"
95 #include "RNA_enum_types.h"
96
97 /* for menu/popup icons etc etc*/
98
99 #include "UI_interface.h"
100 #include "WM_api.h"
101 #include "WM_types.h"
102
103 #include "object_intern.h"      // own include
104
105 /* ************* XXX **************** */
106 static void error(const char *UNUSED(arg)) {}
107 static void waitcursor(int UNUSED(val)) {}
108 static int pupmenu(const char *UNUSED(msg)) {return 0;}
109
110 /* port over here */
111 static void error_libdata(void) {}
112
113 Object *ED_object_context(bContext *C)
114 {
115         return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
116 }
117
118 /* find the correct active object per context
119  * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
120 Object *ED_object_active_context(bContext *C)
121 {
122         Object *ob= NULL;
123         if(C) {
124                 ob= ED_object_context(C);
125                 if (!ob) ob= CTX_data_active_object(C);
126         }
127         return ob;
128 }
129
130
131 /* ********* clear/set restrict view *********/
132 static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
133 {
134         Main *bmain= CTX_data_main(C);
135         ScrArea *sa= CTX_wm_area(C);
136         View3D *v3d= sa->spacedata.first;
137         Scene *scene= CTX_data_scene(C);
138         Base *base;
139         int changed = 0;
140         
141         /* XXX need a context loop to handle such cases */
142         for(base = FIRSTBASE; base; base=base->next){
143                 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
144                         base->flag |= SELECT;
145                         base->object->flag = base->flag;
146                         base->object->restrictflag &= ~OB_RESTRICT_VIEW; 
147                         changed = 1;
148                 }
149         }
150         if (changed) {
151                 DAG_id_type_tag(bmain, ID_OB);
152                 DAG_scene_sort(bmain, scene);
153                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
154         }
155
156         return OPERATOR_FINISHED;
157 }
158
159 void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
160 {
161         
162         /* identifiers */
163         ot->name= "Clear Restrict View";
164         ot->description = "Reveal the object by setting the hide flag";
165         ot->idname= "OBJECT_OT_hide_view_clear";
166         
167         /* api callbacks */
168         ot->exec= object_hide_view_clear_exec;
169         ot->poll= ED_operator_view3d_active;
170         
171         /* flags */
172         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
173 }
174
175 static int object_hide_view_set_exec(bContext *C, wmOperator *op)
176 {
177         Main *bmain= CTX_data_main(C);
178         Scene *scene= CTX_data_scene(C);
179         short changed = 0;
180         const int unselected= RNA_boolean_get(op->ptr, "unselected");
181         
182         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
183                 if(!unselected) {
184                         if (base->flag & SELECT){
185                                 base->flag &= ~SELECT;
186                                 base->object->flag = base->flag;
187                                 base->object->restrictflag |= OB_RESTRICT_VIEW;
188                                 changed = 1;
189                                 if (base==BASACT) {
190                                         ED_base_object_activate(C, NULL);
191                                 }
192                         }
193                 }
194                 else {
195                         if (!(base->flag & SELECT)){
196                                 base->object->restrictflag |= OB_RESTRICT_VIEW;
197                                 changed = 1;
198                         }
199                 }       
200         }
201         CTX_DATA_END;
202
203         if (changed) {
204                 DAG_id_type_tag(bmain, ID_OB);
205                 DAG_scene_sort(bmain, scene);
206                 
207                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
208                 
209         }
210
211         return OPERATOR_FINISHED;
212 }
213
214 void OBJECT_OT_hide_view_set(wmOperatorType *ot)
215 {
216         /* identifiers */
217         ot->name= "Set Restrict View";
218         ot->description = "Hide the object by setting the hide flag";
219         ot->idname= "OBJECT_OT_hide_view_set";
220         
221         /* api callbacks */
222         ot->exec= object_hide_view_set_exec;
223         ot->poll= ED_operator_view3d_active;
224         
225         /* flags */
226         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
227         
228         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
229         
230 }
231
232 /* 99% same as above except no need for scene refreshing (TODO, update render preview) */
233 static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
234 {
235         short changed= 0;
236
237         /* XXX need a context loop to handle such cases */
238         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
239                 if(ob->restrictflag & OB_RESTRICT_RENDER) {
240                         ob->restrictflag &= ~OB_RESTRICT_RENDER;
241                         changed= 1;
242                 }
243         }
244         CTX_DATA_END;
245
246         if(changed)
247                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_OUTLINER, NULL);
248
249         return OPERATOR_FINISHED;
250 }
251
252 void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
253 {
254
255         /* identifiers */
256         ot->name= "Clear Restrict Render";
257         ot->description = "Reveal the render object by setting the hide render flag";
258         ot->idname= "OBJECT_OT_hide_render_clear";
259
260         /* api callbacks */
261         ot->exec= object_hide_render_clear_exec;
262         ot->poll= ED_operator_view3d_active;
263
264         /* flags */
265         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
266 }
267
268 static int object_hide_render_set_exec(bContext *C, wmOperator *op)
269 {
270         const int unselected= RNA_boolean_get(op->ptr, "unselected");
271
272         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
273                 if(!unselected) {
274                         if (base->flag & SELECT){
275                                 base->object->restrictflag |= OB_RESTRICT_RENDER;
276                         }
277                 }
278                 else {
279                         if (!(base->flag & SELECT)){
280                                 base->object->restrictflag |= OB_RESTRICT_RENDER;
281                         }
282                 }
283         }
284         CTX_DATA_END;
285         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_OUTLINER, NULL);
286         return OPERATOR_FINISHED;
287 }
288
289 void OBJECT_OT_hide_render_set(wmOperatorType *ot)
290 {
291         /* identifiers */
292         ot->name= "Set Restrict Render";
293         ot->description = "Hide the render object by setting the hide render flag";
294         ot->idname= "OBJECT_OT_hide_render_set";
295
296         /* api callbacks */
297         ot->exec= object_hide_render_set_exec;
298         ot->poll= ED_operator_view3d_active;
299
300         /* flags */
301         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
302
303         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
304 }
305
306 /* ******************* toggle editmode operator  ***************** */
307
308 void ED_object_exit_editmode(bContext *C, int flag)
309 {
310         /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
311
312         Scene *scene= CTX_data_scene(C);
313         Object *obedit= CTX_data_edit_object(C);
314         int freedata = flag & EM_FREEDATA;
315         
316         if(obedit==NULL) return;
317         
318         if(flag & EM_WAITCURSOR) waitcursor(1);
319         if(obedit->type==OB_MESH) {
320                 Mesh *me= obedit->data;
321                 
322 //              if(EM_texFaceCheck())
323                 
324                 if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
325                         error("Too many vertices");
326                         return;
327                 }
328                 load_editMesh(scene, obedit);
329                 
330                 if(freedata) {
331                         free_editMesh(me->edit_mesh);
332                         MEM_freeN(me->edit_mesh);
333                         me->edit_mesh= NULL;
334                 }
335                 
336                 if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
337                         mesh_octree_table(NULL, NULL, NULL, 'e');
338                         mesh_mirrtopo_table(NULL, 'e');
339                 }
340         }
341         else if (obedit->type==OB_ARMATURE) {   
342                 ED_armature_from_edit(obedit);
343                 if(freedata)
344                         ED_armature_edit_free(obedit);
345         }
346         else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
347                 load_editNurb(obedit);
348                 if(freedata) free_editNurb(obedit);
349         }
350         else if(obedit->type==OB_FONT && freedata) {
351                 load_editText(obedit);
352                 if(freedata) free_editText(obedit);
353         }
354         else if(obedit->type==OB_LATTICE) {
355                 load_editLatt(obedit);
356                 if(freedata) free_editLatt(obedit);
357         }
358         else if(obedit->type==OB_MBALL) {
359                 load_editMball(obedit);
360                 if(freedata) free_editMball(obedit);
361         }
362
363         /* freedata only 0 now on file saves and render */
364         if(freedata) {
365                 ListBase pidlist;
366                 PTCacheID *pid;
367
368                 /* for example; displist make is different in editmode */
369                 scene->obedit= NULL; // XXX for context
370
371                 /* flag object caches as outdated */
372                 BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0);
373                 for(pid=pidlist.first; pid; pid=pid->next) {
374                         if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
375                                 pid->cache->flag |= PTCACHE_OUTDATED;
376                 }
377                 BLI_freelistN(&pidlist);
378                 
379                 BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
380
381                 /* also flush ob recalc, doesn't take much overhead, but used for particles */
382                 DAG_id_tag_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
383         
384                 if(flag & EM_DO_UNDO)
385                         ED_undo_push(C, "Editmode");
386         
387                 if(flag & EM_WAITCURSOR) waitcursor(0);
388         
389                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
390
391                 obedit->mode &= ~OB_MODE_EDIT;
392         }
393 }
394
395
396 void ED_object_enter_editmode(bContext *C, int flag)
397 {
398         Scene *scene= CTX_data_scene(C);
399         Base *base= NULL;
400         Object *ob;
401         ScrArea *sa= CTX_wm_area(C);
402         View3D *v3d= NULL;
403         int ok= 0;
404         
405         if(scene->id.lib) return;
406         
407         if(sa && sa->spacetype==SPACE_VIEW3D)
408                 v3d= sa->spacedata.first;
409         
410         if((flag & EM_IGNORE_LAYER)==0) {
411                 base= CTX_data_active_base(C); /* active layer checked here for view3d */
412
413                 if(base==NULL) return;
414                 else if(v3d && (base->lay & v3d->lay)==0) return;
415                 else if(!v3d && (base->lay & scene->lay)==0) return;
416         }
417         else {
418                 base= scene->basact;
419         }
420
421         if (ELEM3(NULL, base, base->object, base->object->data)) return;
422
423         ob = base->object;
424         
425         if (object_data_is_libdata(ob)) {
426                 error_libdata();
427                 return;
428         }
429         
430         if(flag & EM_WAITCURSOR) waitcursor(1);
431
432         ob->restore_mode = ob->mode;
433
434         /* note, when switching scenes the object can have editmode data but
435          * not be scene->obedit: bug 22954, this avoids calling self eternally */
436         if((ob->restore_mode & OB_MODE_EDIT)==0)
437                 ED_object_toggle_modes(C, ob->mode);
438
439         ob->mode= OB_MODE_EDIT;
440         
441         if(ob->type==OB_MESH) {
442                 ok= 1;
443                 scene->obedit= ob;      // context sees this
444                 
445                 make_editMesh(scene, ob);
446
447                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
448         }
449         else if (ob->type==OB_ARMATURE){
450                 bArmature *arm= base->object->data;
451                 if (!arm) return;
452                 /*
453                  * The function object_data_is_libdata make a problem here, the
454                  * check for ob->proxy return 0 and let blender enter to edit mode
455                  * this causa a crash when you try leave the edit mode.
456                  * The problem is that i can't remove the ob->proxy check from
457                  * object_data_is_libdata that prevent the bugfix #6614, so
458                  * i add this little hack here.
459                  */
460                 if(arm->id.lib) {
461                         error_libdata();
462                         return;
463                 }
464                 ok=1;
465                 scene->obedit= ob;
466                 ED_armature_to_edit(ob);
467                 /* to ensure all goes in restposition and without striding */
468                 DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX: should this be OB_RECALC_DATA?
469
470                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, scene);
471         }
472         else if(ob->type==OB_FONT) {
473                 scene->obedit= ob; // XXX for context
474                 ok= 1;
475                 make_editText(ob);
476
477                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_TEXT, scene);
478         }
479         else if(ob->type==OB_MBALL) {
480                 scene->obedit= ob; // XXX for context
481                 ok= 1;
482                 make_editMball(ob);
483
484                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MBALL, scene);
485         }
486         else if(ob->type==OB_LATTICE) {
487                 scene->obedit= ob; // XXX for context
488                 ok= 1;
489                 make_editLatt(ob);
490                 
491                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_LATTICE, scene);
492         }
493         else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
494                 ok= 1;
495                 scene->obedit= ob; // XXX for context
496                 make_editNurb(ob);
497                 
498                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_CURVE, scene);
499         }
500         
501         if(ok) {
502                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
503         }
504         else {
505                 scene->obedit= NULL; // XXX for context
506                 ob->mode &= ~OB_MODE_EDIT;
507                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
508         }
509         
510         if(flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
511         if(flag & EM_WAITCURSOR) waitcursor(0);
512 }
513
514 static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
515 {
516         ToolSettings *toolsettings =  CTX_data_tool_settings(C);
517
518         if(!CTX_data_edit_object(C))
519                 ED_object_enter_editmode(C, EM_WAITCURSOR);
520         else
521                 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
522         
523         ED_space_image_uv_sculpt_update(CTX_wm_manager(C), toolsettings);
524
525         return OPERATOR_FINISHED;
526 }
527
528 static int editmode_toggle_poll(bContext *C)
529 {
530         Object *ob = CTX_data_active_object(C);
531
532         /* covers proxies too */
533         if(ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib)
534                 return 0;
535
536         if (ob->restrictflag & OB_RESTRICT_VIEW)
537                 return 0;
538
539         return (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
540                 ob->type == OB_FONT || ob->type == OB_MBALL ||
541                 ob->type == OB_LATTICE || ob->type == OB_SURF ||
542                 ob->type == OB_CURVE);
543 }
544
545 void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
546 {
547         
548         /* identifiers */
549         ot->name= "Toggle Editmode";
550         ot->description = "Toggle object's editmode";
551         ot->idname= "OBJECT_OT_editmode_toggle";
552         
553         /* api callbacks */
554         ot->exec= editmode_toggle_exec;
555         
556         ot->poll= editmode_toggle_poll;
557         
558         /* flags */
559         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
560 }
561
562 /* *************************** */
563
564 static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
565 {
566         Base *base= CTX_data_active_base(C);
567         
568         if(base->object->type==OB_ARMATURE) {
569                 if(base->object==CTX_data_edit_object(C)) {
570                         ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
571                         ED_armature_enter_posemode(C, base);
572                 }
573                 else if(base->object->mode & OB_MODE_POSE)
574                         ED_armature_exit_posemode(C, base);
575                 else
576                         ED_armature_enter_posemode(C, base);
577                 
578                 return OPERATOR_FINISHED;
579         }
580         
581         return OPERATOR_PASS_THROUGH;
582 }
583
584 void OBJECT_OT_posemode_toggle(wmOperatorType *ot) 
585 {
586         /* identifiers */
587         ot->name= "Toggle Pose Mode";
588         ot->idname= "OBJECT_OT_posemode_toggle";
589         ot->description= "Enable or disable posing/selecting bones";
590         
591         /* api callbacks */
592         ot->exec= posemode_exec;
593         ot->poll= ED_operator_object_active_editable;
594         
595         /* flag */
596         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
597 }
598
599 static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
600 {       
601 //XXX no longer used - to be removed - replaced by game_properties_copy_exec
602         bProperty *prop;
603         Base *base;
604         int nr, tot=0;
605         char *str;
606         
607         prop= ob->prop.first;
608         while(prop) {
609                 tot++;
610                 prop= prop->next;
611         }
612         
613         str= MEM_callocN(50 + 33*tot, "copymenu prop");
614         
615         if (tot)
616                 strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
617         else
618                 strcpy(str, "Copy Property %t|Clear All (no properties on active)");
619         
620         tot= 0; 
621         prop= ob->prop.first;
622         while(prop) {
623                 tot++;
624                 strcat(str, "|");
625                 strcat(str, prop->name);
626                 prop= prop->next;
627         }
628
629         nr= pupmenu(str);
630         
631         if ( nr==1 || nr==2 ) {
632                 for(base= FIRSTBASE; base; base= base->next) {
633                         if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
634                                 if (nr==1) { /* replace */
635                                         copy_properties( &base->object->prop, &ob->prop );
636                                 } else {
637                                         for(prop = ob->prop.first; prop; prop= prop->next ) {
638                                                 set_ob_property(base->object, prop);
639                                         }
640                                 }
641                         }
642                 }
643         } else if(nr>0) {
644                 prop = BLI_findlink(&ob->prop, nr-4); /* account for first 3 menu items & menu index starting at 1*/
645                 
646                 if(prop) {
647                         for(base= FIRSTBASE; base; base= base->next) {
648                                 if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
649                                         set_ob_property(base->object, prop);
650                                 }
651                         }
652                 }
653         }
654         MEM_freeN(str);
655         
656 }
657
658 static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
659 {
660 //XXX no longer used - to be removed - replaced by logicbricks_copy_exec
661         Base *base;
662         
663         for(base= FIRSTBASE; base; base= base->next) {
664                 if(base->object != ob) {
665                         if(TESTBASELIB(v3d, base)) {
666                                 
667                                 /* first: free all logic */
668                                 free_sensors(&base->object->sensors);                           
669                                 unlink_controllers(&base->object->controllers);
670                                 free_controllers(&base->object->controllers);
671                                 unlink_actuators(&base->object->actuators);
672                                 free_actuators(&base->object->actuators);
673                                 
674                                 /* now copy it, this also works without logicbricks! */
675                                 clear_sca_new_poins_ob(ob);
676                                 copy_sensors(&base->object->sensors, &ob->sensors);
677                                 copy_controllers(&base->object->controllers, &ob->controllers);
678                                 copy_actuators(&base->object->actuators, &ob->actuators);
679                                 set_sca_new_poins_ob(base->object);
680                                 
681                                 /* some menu settings */
682                                 base->object->scavisflag= ob->scavisflag;
683                                 base->object->scaflag= ob->scaflag;
684                                 
685                                 /* set the initial state */
686                                 base->object->state= ob->state;
687                                 base->object->init_state= ob->init_state;
688                         }
689                 }
690         }
691 }
692
693 /* both pointers should exist */
694 static void copy_texture_space(Object *to, Object *ob)
695 {
696         float *poin1= NULL, *poin2= NULL;
697         short texflag= 0;
698         
699         if(ob->type==OB_MESH) {
700                 texflag= ((Mesh *)ob->data)->texflag;
701                 poin2= ((Mesh *)ob->data)->loc;
702         }
703         else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
704                 texflag= ((Curve *)ob->data)->texflag;
705                 poin2= ((Curve *)ob->data)->loc;
706         }
707         else if(ob->type==OB_MBALL) {
708                 texflag= ((MetaBall *)ob->data)->texflag;
709                 poin2= ((MetaBall *)ob->data)->loc;
710         }
711         else
712                 return;
713                 
714         if(to->type==OB_MESH) {
715                 ((Mesh *)to->data)->texflag= texflag;
716                 poin1= ((Mesh *)to->data)->loc;
717         }
718         else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
719                 ((Curve *)to->data)->texflag= texflag;
720                 poin1= ((Curve *)to->data)->loc;
721         }
722         else if(to->type==OB_MBALL) {
723                 ((MetaBall *)to->data)->texflag= texflag;
724                 poin1= ((MetaBall *)to->data)->loc;
725         }
726         else
727                 return;
728         
729         memcpy(poin1, poin2, 9*sizeof(float));  /* this was noted in DNA_mesh, curve, mball */
730         
731         if(to->type==OB_MESH) ;
732         else if(to->type==OB_MBALL) tex_space_mball(to);
733         else tex_space_curve(to->data);
734         
735 }
736
737 /* UNUSED, keep incase we want to copy functionality for use elsewhere */
738 static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
739 {
740         Object *ob;
741         Base *base;
742         Curve *cu, *cu1;
743         Nurb *nu;
744         int do_scene_sort= 0;
745         
746         if(scene->id.lib) return;
747
748         if(!(ob=OBACT)) return;
749         
750         if(scene->obedit) { // XXX get from context
751                 /* obedit_copymenu(); */
752                 return;
753         }
754         if(event==9) {
755                 copymenu_properties(scene, v3d, ob);
756                 return;
757         }
758         else if(event==10) {
759                 copymenu_logicbricks(scene, v3d, ob);
760                 return;
761         }
762         else if(event==24) {
763                 /* moved to object_link_modifiers */
764                 /* copymenu_modifiers(bmain, scene, v3d, ob); */
765                 return;
766         }
767
768         for(base= FIRSTBASE; base; base= base->next) {
769                 if(base != BASACT) {
770                         if(TESTBASELIB(v3d, base)) {
771                                 base->object->recalc |= OB_RECALC_OB;
772                                 
773                                 if(event==1) {  /* loc */
774                                         copy_v3_v3(base->object->loc, ob->loc);
775                                         copy_v3_v3(base->object->dloc, ob->dloc);
776                                 }
777                                 else if(event==2) {  /* rot */
778                                         copy_v3_v3(base->object->rot, ob->rot);
779                                         copy_v3_v3(base->object->drot, ob->drot);
780
781                                         copy_qt_qt(base->object->quat, ob->quat);
782                                         copy_qt_qt(base->object->dquat, ob->dquat);
783                                 }
784                                 else if(event==3) {  /* size */
785                                         copy_v3_v3(base->object->size, ob->size);
786                                         copy_v3_v3(base->object->dscale, ob->dscale);
787                                 }
788                                 else if(event==4) {  /* drawtype */
789                                         base->object->dt= ob->dt;
790                                         base->object->dtx= ob->dtx;
791                                         base->object->empty_drawtype= ob->empty_drawtype;
792                                         base->object->empty_drawsize= ob->empty_drawsize;
793                                 }
794                                 else if(event==5) {  /* time offs */
795                                         base->object->sf= ob->sf;
796                                 }
797                                 else if(event==6) {  /* dupli */
798                                         base->object->dupon= ob->dupon;
799                                         base->object->dupoff= ob->dupoff;
800                                         base->object->dupsta= ob->dupsta;
801                                         base->object->dupend= ob->dupend;
802                                         
803                                         base->object->transflag &= ~OB_DUPLI;
804                                         base->object->transflag |= (ob->transflag & OB_DUPLI);
805
806                                         base->object->dup_group= ob->dup_group;
807                                         if(ob->dup_group)
808                                                 id_lib_extern(&ob->dup_group->id);
809                                 }
810                                 else if(event==7) {     /* mass */
811                                         base->object->mass= ob->mass;
812                                 }
813                                 else if(event==8) {     /* damping */
814                                         base->object->damping= ob->damping;
815                                         base->object->rdamping= ob->rdamping;
816                                 }
817                                 else if(event==11) {    /* all physical attributes */
818                                         base->object->gameflag = ob->gameflag;
819                                         base->object->inertia = ob->inertia;
820                                         base->object->formfactor = ob->formfactor;
821                                         base->object->damping= ob->damping;
822                                         base->object->rdamping= ob->rdamping;
823                                         base->object->min_vel= ob->min_vel;
824                                         base->object->max_vel= ob->max_vel;
825                                         if (ob->gameflag & OB_BOUNDS) {
826                                                 base->object->collision_boundtype = ob->collision_boundtype;
827                                         }
828                                         base->object->margin= ob->margin;
829                                         base->object->bsoft= copy_bulletsoftbody(ob->bsoft);
830
831                                 }
832                                 else if(event==17) {    /* tex space */
833                                         copy_texture_space(base->object, ob);
834                                 }
835                                 else if(event==18) {    /* font settings */
836                                         
837                                         if(base->object->type==ob->type) {
838                                                 cu= ob->data;
839                                                 cu1= base->object->data;
840                                                 
841                                                 cu1->spacemode= cu->spacemode;
842                                                 cu1->spacing= cu->spacing;
843                                                 cu1->linedist= cu->linedist;
844                                                 cu1->shear= cu->shear;
845                                                 cu1->fsize= cu->fsize;
846                                                 cu1->xof= cu->xof;
847                                                 cu1->yof= cu->yof;
848                                                 cu1->textoncurve= cu->textoncurve;
849                                                 cu1->wordspace= cu->wordspace;
850                                                 cu1->ulpos= cu->ulpos;
851                                                 cu1->ulheight= cu->ulheight;
852                                                 if(cu1->vfont) cu1->vfont->id.us--;
853                                                 cu1->vfont= cu->vfont;
854                                                 id_us_plus((ID *)cu1->vfont);
855                                                 if(cu1->vfontb) cu1->vfontb->id.us--;
856                                                 cu1->vfontb= cu->vfontb;
857                                                 id_us_plus((ID *)cu1->vfontb);
858                                                 if(cu1->vfonti) cu1->vfonti->id.us--;
859                                                 cu1->vfonti= cu->vfonti;
860                                                 id_us_plus((ID *)cu1->vfonti);
861                                                 if(cu1->vfontbi) cu1->vfontbi->id.us--;
862                                                 cu1->vfontbi= cu->vfontbi;
863                                                 id_us_plus((ID *)cu1->vfontbi);                                         
864
865                                                 BKE_text_to_curve(bmain, scene, base->object, 0); /* needed? */
866
867                                                 
868                                                 BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
869                                                 
870                                                 base->object->recalc |= OB_RECALC_DATA;
871                                         }
872                                 }
873                                 else if(event==19) {    /* bevel settings */
874                                         
875                                         if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
876                                                 cu= ob->data;
877                                                 cu1= base->object->data;
878                                                 
879                                                 cu1->bevobj= cu->bevobj;
880                                                 cu1->taperobj= cu->taperobj;
881                                                 cu1->width= cu->width;
882                                                 cu1->bevresol= cu->bevresol;
883                                                 cu1->ext1= cu->ext1;
884                                                 cu1->ext2= cu->ext2;
885                                                 
886                                                 base->object->recalc |= OB_RECALC_DATA;
887                                         }
888                                 }
889                                 else if(event==25) {    /* curve resolution */
890
891                                         if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
892                                                 cu= ob->data;
893                                                 cu1= base->object->data;
894                                                 
895                                                 cu1->resolu= cu->resolu;
896                                                 cu1->resolu_ren= cu->resolu_ren;
897                                                 
898                                                 nu= cu1->nurb.first;
899                                                 
900                                                 while(nu) {
901                                                         nu->resolu= cu1->resolu;
902                                                         nu= nu->next;
903                                                 }
904                                                 
905                                                 base->object->recalc |= OB_RECALC_DATA;
906                                         }
907                                 }
908                                 else if(event==21){
909                                         if (base->object->type==OB_MESH) {
910                                                 ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
911
912                                                 if (md) {
913                                                         ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
914
915                                                         if (!tmd) {
916                                                                 tmd = modifier_new(eModifierType_Subsurf);
917                                                                 BLI_addtail(&base->object->modifiers, tmd);
918                                                         }
919
920                                                         modifier_copyData(md, tmd);
921                                                         base->object->recalc |= OB_RECALC_DATA;
922                                                 }
923                                         }
924                                 }
925                                 else if(event==22) {
926                                         /* Copy the constraint channels over */
927                                         copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
928                                         
929                                         do_scene_sort= 1;
930                                 }
931                                 else if(event==23) {
932                                         base->object->softflag= ob->softflag;
933                                         if(base->object->soft) sbFree(base->object->soft);
934                                         
935                                         base->object->soft= copy_softbody(ob->soft);
936
937                                         if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
938                                                 BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
939                                         }
940                                 }
941                                 else if(event==26) {
942 #if 0 // XXX old animation system
943                                         copy_nlastrips(&base->object->nlastrips, &ob->nlastrips);
944 #endif // XXX old animation system
945                                 }
946                                 else if(event==27) {    /* autosmooth */
947                                         if (base->object->type==OB_MESH) {
948                                                 Mesh *me= ob->data;
949                                                 Mesh *cme= base->object->data;
950                                                 cme->smoothresh= me->smoothresh;
951                                                 if(me->flag & ME_AUTOSMOOTH)
952                                                         cme->flag |= ME_AUTOSMOOTH;
953                                                 else
954                                                         cme->flag &= ~ME_AUTOSMOOTH;
955                                         }
956                                 }
957                                 else if(event==28) { /* UV orco */
958                                         if(ELEM(base->object->type, OB_CURVE, OB_SURF)) {
959                                                 cu= ob->data;
960                                                 cu1= base->object->data;
961                                                 
962                                                 if(cu->flag & CU_UV_ORCO)
963                                                         cu1->flag |= CU_UV_ORCO;
964                                                 else
965                                                         cu1->flag &= ~CU_UV_ORCO;
966                                         }               
967                                 }
968                                 else if(event==29) { /* protected bits */
969                                         base->object->protectflag= ob->protectflag;
970                                 }
971                                 else if(event==30) { /* index object */
972                                         base->object->index= ob->index;
973                                 }
974                                 else if(event==31) { /* object color */
975                                         copy_v4_v4(base->object->col, ob->col);
976                                 }
977                         }
978                 }
979         }
980         
981         if(do_scene_sort)
982                 DAG_scene_sort(bmain, scene);
983
984         DAG_ids_flush_update(bmain, 0);
985 }
986
987 static void UNUSED_FUNCTION(copy_attr_menu)(Main *bmain, Scene *scene, View3D *v3d)
988 {
989         Object *ob;
990         short event;
991         char str[512];
992         
993         if(!(ob=OBACT)) return;
994         
995         if (scene->obedit) { // XXX get from context
996 //              if (ob->type == OB_MESH)
997 // XXX                  mesh_copy_menu();
998                 return;
999         }
1000         
1001         /* Object Mode */
1002         
1003         /* If you change this menu, don't forget to update the menu in header_view3d.c
1004          * view3d_edit_object_copyattrmenu() and in toolbox.c
1005          */
1006         
1007         strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|Time Offset%x5|Dupli%x6|Object Color%x31|%l|Mass%x7|Damping%x8|All Physical Attributes%x11|Properties%x9|Logic Bricks%x10|Protected Transform%x29|%l");
1008         
1009         strcat (str, "|Object Constraints%x22");
1010         strcat (str, "|NLA Strips%x26");
1011         
1012 // XXX  if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
1013 //              strcat(str, "|Texture Space%x17");
1014 //      }       
1015         
1016         if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
1017         if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19|UV Orco%x28");
1018         
1019         if((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
1020                         strcat(str, "|Curve Resolution%x25");
1021         }
1022
1023         if(ob->type==OB_MESH){
1024                 strcat(str, "|Subsurf Settings%x21|AutoSmooth%x27");
1025         }
1026
1027         if(ob->soft) strcat(str, "|Soft Body Settings%x23");
1028         
1029         strcat(str, "|Pass Index%x30");
1030         
1031         if(ob->type==OB_MESH || ob->type==OB_CURVE || ob->type==OB_LATTICE || ob->type==OB_SURF){
1032                 strcat(str, "|Modifiers ...%x24");
1033         }
1034
1035         event= pupmenu(str);
1036         if(event<= 0) return;
1037         
1038         copy_attr(bmain, scene, v3d, event);
1039 }
1040
1041 /* ******************* force field toggle operator ***************** */
1042
1043 static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1044 {
1045         Object *ob = CTX_data_active_object(C);
1046
1047         if(ob->pd == NULL)
1048                 ob->pd = object_add_collision_fields(PFIELD_FORCE);
1049
1050         if(ob->pd->forcefield == 0)
1051                 ob->pd->forcefield = PFIELD_FORCE;
1052         else
1053                 ob->pd->forcefield = 0;
1054         
1055         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
1056
1057         return OPERATOR_FINISHED;
1058 }
1059
1060 void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
1061 {
1062         
1063         /* identifiers */
1064         ot->name= "Toggle Force Field";
1065         ot->description = "Toggle object's force field";
1066         ot->idname= "OBJECT_OT_forcefield_toggle";
1067         
1068         /* api callbacks */
1069         ot->exec= forcefield_toggle_exec;
1070         ot->poll= ED_operator_object_active_editable;
1071         
1072         /* flags */
1073         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1074 }
1075
1076 /* ********************************************** */
1077 /* Motion Paths */
1078
1079 /* For the object with pose/action: update paths for those that have got them
1080  * This should selectively update paths that exist...
1081  *
1082  * To be called from various tools that do incremental updates 
1083  */
1084 void ED_objects_recalculate_paths(bContext *C, Scene *scene)
1085 {
1086         ListBase targets = {NULL, NULL};
1087         
1088         /* loop over objects in scene */
1089         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 
1090         {
1091                 /* set flag to force recalc, then grab the relevant bones to target */
1092                 ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
1093                 animviz_get_object_motionpaths(ob, &targets);
1094         }
1095         CTX_DATA_END;
1096         
1097         /* recalculate paths, then free */
1098         animviz_calc_motionpaths(scene, &targets);
1099         BLI_freelistN(&targets);
1100 }
1101
1102 /* For the object with pose/action: create path curves for selected bones 
1103  * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
1104  */
1105 static int object_calculate_paths_exec (bContext *C, wmOperator *op)
1106 {
1107         Scene *scene= CTX_data_scene(C);
1108         
1109         /* set up path data for bones being calculated */
1110         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)  
1111         {
1112                 /* verify makes sure that the selected bone has a bone with the appropriate settings */
1113                 animviz_verify_motionpaths(op->reports, scene, ob, NULL);
1114         }
1115         CTX_DATA_END;
1116         
1117         /* calculate the bones that now have motionpaths... */
1118         // TODO: only make for the selected bones?
1119         ED_objects_recalculate_paths(C, scene);
1120         
1121         /* notifiers for updates */
1122         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
1123         
1124         return OPERATOR_FINISHED; 
1125 }
1126
1127 void OBJECT_OT_paths_calculate (wmOperatorType *ot)
1128 {
1129         /* identifiers */
1130         ot->name= "Calculate Object Paths";
1131         ot->idname= "OBJECT_OT_paths_calculate";
1132         ot->description= "Calculate paths for the selected bones";
1133         
1134         /* api callbacks */
1135         ot->exec= object_calculate_paths_exec;
1136         ot->poll= ED_operator_object_active_editable;
1137         
1138         /* flags */
1139         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1140 }
1141
1142 /* --------- */
1143
1144 /* for the object with pose/action: clear path curves for selected bones only */
1145 void ED_objects_clear_paths(bContext *C)
1146 {
1147         /* loop over objects in scene */
1148         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 
1149         {
1150                 if (ob->mpath) {
1151                         animviz_free_motionpath(ob->mpath);
1152                         ob->mpath= NULL;
1153                         ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
1154                 }
1155         }
1156         CTX_DATA_END;
1157 }
1158
1159 /* operator callback for this */
1160 static int object_clear_paths_exec (bContext *C, wmOperator *UNUSED(op))
1161 {       
1162         /* use the backend function for this */
1163         ED_objects_clear_paths(C);
1164         
1165         /* notifiers for updates */
1166         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
1167         
1168         return OPERATOR_FINISHED; 
1169 }
1170
1171 void OBJECT_OT_paths_clear (wmOperatorType *ot)
1172 {
1173         /* identifiers */
1174         ot->name= "Clear Object Paths";
1175         ot->idname= "OBJECT_OT_paths_clear";
1176         ot->description= "Clear path caches for selected bones";
1177         
1178         /* api callbacks */
1179         ot->exec= object_clear_paths_exec;
1180         ot->poll= ED_operator_object_active_editable;
1181         
1182         /* flags */
1183         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1184 }
1185
1186
1187 /********************** Smooth/Flat *********************/
1188
1189 static int shade_smooth_exec(bContext *C, wmOperator *op)
1190 {
1191         Curve *cu;
1192         Nurb *nu;
1193         int clear= (strcmp(op->idname, "OBJECT_OT_shade_flat") == 0);
1194         int done= 0;
1195
1196         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1197
1198                 if(ob->type==OB_MESH) {
1199                         mesh_set_smooth_flag(ob, !clear);
1200
1201                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1202                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1203
1204                         done= 1;
1205                 }
1206                 else if ELEM(ob->type, OB_SURF, OB_CURVE) {
1207                         cu= ob->data;
1208
1209                         for(nu=cu->nurb.first; nu; nu=nu->next) {
1210                                 if(!clear) nu->flag |= ME_SMOOTH;
1211                                 else nu->flag &= ~ME_SMOOTH;
1212                         }
1213
1214                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1215                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1216
1217                         done= 1;
1218                 }
1219         }
1220         CTX_DATA_END;
1221
1222         return (done)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
1223 }
1224
1225 static int shade_poll(bContext *C)
1226 {
1227         return (ED_operator_object_active_editable(C) && !ED_operator_editmesh(C));
1228 }
1229
1230 void OBJECT_OT_shade_flat(wmOperatorType *ot)
1231 {
1232         /* identifiers */
1233         ot->name= "Shade Flat";
1234         ot->description= "Display faces 'flat'";
1235         ot->idname= "OBJECT_OT_shade_flat";
1236         
1237         /* api callbacks */
1238         ot->poll= shade_poll;
1239         ot->exec= shade_smooth_exec;
1240
1241         /* flags */
1242         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1243 }
1244
1245 void OBJECT_OT_shade_smooth(wmOperatorType *ot)
1246 {
1247         /* identifiers */
1248         ot->name= "Shade Smooth";
1249         ot->description= "Display faces 'smooth' (using vertex normals)";
1250         ot->idname= "OBJECT_OT_shade_smooth";
1251         
1252         /* api callbacks */
1253         ot->poll= shade_poll;
1254         ot->exec= shade_smooth_exec;
1255         
1256         /* flags */
1257         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1258 }
1259
1260 /* ********************** */
1261
1262 static void UNUSED_FUNCTION(image_aspect)(Scene *scene, View3D *v3d)
1263 {
1264         /* all selected objects with an image map: scale in image aspect */
1265         Base *base;
1266         Object *ob;
1267         Material *ma;
1268         Tex *tex;
1269         float x, y, space;
1270         int a, b, done;
1271         
1272         if(scene->obedit) return; // XXX get from context
1273         if(scene->id.lib) return;
1274         
1275         for(base= FIRSTBASE; base; base= base->next) {
1276                 if(TESTBASELIB(v3d, base)) {
1277                         ob= base->object;
1278                         done= 0;
1279                         
1280                         for(a=1; a<=ob->totcol; a++) {
1281                                 ma= give_current_material(ob, a);
1282                                 if(ma) {
1283                                         for(b=0; b<MAX_MTEX; b++) {
1284                                                 if(ma->mtex[b] && ma->mtex[b]->tex) {
1285                                                         tex= ma->mtex[b]->tex;
1286                                                         if(tex->type==TEX_IMAGE && tex->ima) {
1287                                                                 ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, NULL);
1288                                                                 
1289                                                                 /* texturespace */
1290                                                                 space= 1.0;
1291                                                                 if(ob->type==OB_MESH) {
1292                                                                         float size[3];
1293                                                                         mesh_get_texspace(ob->data, NULL, NULL, size);
1294                                                                         space= size[0]/size[1];
1295                                                                 }
1296                                                                 else if(ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
1297                                                                         Curve *cu= ob->data;
1298                                                                         space= cu->size[0]/cu->size[1];
1299                                                                 }
1300                                                         
1301                                                                 x= ibuf->x/space;
1302                                                                 y= ibuf->y;
1303                                                                 
1304                                                                 if(x>y) ob->size[0]= ob->size[1]*x/y;
1305                                                                 else ob->size[1]= ob->size[0]*y/x;
1306                                                                 
1307                                                                 done= 1;
1308                                                                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);                                                               
1309                                                         }
1310                                                 }
1311                                                 if(done) break;
1312                                         }
1313                                 }
1314                                 if(done) break;
1315                         }
1316                 }
1317         }
1318         
1319 }
1320
1321
1322 static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
1323 {       
1324         EnumPropertyItem *input = object_mode_items;
1325         EnumPropertyItem *item= NULL;
1326         Object *ob;
1327         int totitem= 0;
1328         
1329         if(!C) /* needed for docs */
1330                 return object_mode_items;
1331
1332         ob = CTX_data_active_object(C);
1333         while(ob && input->identifier) {
1334                 if((input->value == OB_MODE_EDIT && ((ob->type == OB_MESH) || (ob->type == OB_ARMATURE) ||
1335                                                         (ob->type == OB_CURVE) || (ob->type == OB_SURF) ||
1336                                                          (ob->type == OB_FONT) || (ob->type == OB_MBALL) || (ob->type == OB_LATTICE))) ||
1337                    (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
1338                    (input->value == OB_MODE_PARTICLE_EDIT && ob->particlesystem.first) ||
1339                    ((input->value == OB_MODE_SCULPT || input->value == OB_MODE_VERTEX_PAINT ||
1340                          input->value == OB_MODE_WEIGHT_PAINT || input->value == OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
1341                    (input->value == OB_MODE_OBJECT))
1342                         RNA_enum_item_add(&item, &totitem, input);
1343                 ++input;
1344         }
1345
1346         RNA_enum_item_end(&item, &totitem);
1347
1348         *free= 1;
1349
1350         return item;
1351 }
1352
1353 static const char *object_mode_op_string(int mode)
1354 {
1355         if(mode & OB_MODE_EDIT)
1356                 return "OBJECT_OT_editmode_toggle";
1357         if(mode == OB_MODE_SCULPT)
1358                 return "SCULPT_OT_sculptmode_toggle";
1359         if(mode == OB_MODE_VERTEX_PAINT)
1360                 return "PAINT_OT_vertex_paint_toggle";
1361         if(mode == OB_MODE_WEIGHT_PAINT)
1362                 return "PAINT_OT_weight_paint_toggle";
1363         if(mode == OB_MODE_TEXTURE_PAINT)
1364                 return "PAINT_OT_texture_paint_toggle";
1365         if(mode == OB_MODE_PARTICLE_EDIT)
1366                 return "PARTICLE_OT_particle_edit_toggle";
1367         if(mode == OB_MODE_POSE)
1368                 return "OBJECT_OT_posemode_toggle";
1369         return NULL;
1370 }
1371
1372 /* checks the mode to be set is compatible with the object
1373  * should be made into a generic function */
1374 static int object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob)
1375 {
1376         ObjectMode mode = RNA_enum_get(op->ptr, "mode");
1377
1378         if(ob) {
1379                 if(mode == OB_MODE_OBJECT)
1380                         return 1;
1381
1382                 switch(ob->type) {
1383                 case OB_MESH:
1384                         if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
1385                                 return 1;
1386                         return 0;
1387                 case OB_CURVE:
1388                 case OB_SURF:
1389                 case OB_FONT:
1390                 case OB_MBALL:
1391                         if(mode & (OB_MODE_EDIT))
1392                                 return 1;
1393                         return 0;
1394                 case OB_LATTICE:
1395                         if(mode & (OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT))
1396                                 return 1;
1397                 case OB_ARMATURE:
1398                         if(mode & (OB_MODE_EDIT|OB_MODE_POSE))
1399                                 return 1;
1400                 }
1401         }
1402
1403         return 0;
1404 }
1405
1406 static int object_mode_set_exec(bContext *C, wmOperator *op)
1407 {
1408         Object *ob= CTX_data_active_object(C);
1409         ObjectMode mode = RNA_enum_get(op->ptr, "mode");
1410         ObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
1411         int toggle = RNA_boolean_get(op->ptr, "toggle");
1412
1413         if(!ob || !object_mode_set_compat(C, op, ob))
1414                 return OPERATOR_PASS_THROUGH;
1415
1416         /* Exit current mode if it's not the mode we're setting */
1417         if(ob->mode != OB_MODE_OBJECT && ob->mode != mode)
1418                 WM_operator_name_call(C, object_mode_op_string(ob->mode), WM_OP_EXEC_REGION_WIN, NULL);
1419
1420         if(mode != OB_MODE_OBJECT) {
1421                 /* Enter new mode */
1422                 if(ob->mode != mode || toggle)
1423                         WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
1424
1425                 if(toggle) {
1426                         if(ob->mode == mode)
1427                                 /* For toggling, store old mode so we know what to go back to */
1428                                 ob->restore_mode = restore_mode;
1429                         else if(ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
1430                                 WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
1431                         }
1432                 }
1433         }
1434
1435         return OPERATOR_FINISHED;
1436 }
1437
1438 void OBJECT_OT_mode_set(wmOperatorType *ot)
1439 {
1440         PropertyRNA *prop;
1441
1442         /* identifiers */
1443         ot->name= "Set Object Mode";
1444         ot->description = "Sets the object interaction mode";
1445         ot->idname= "OBJECT_OT_mode_set";
1446         
1447         /* api callbacks */
1448         ot->exec= object_mode_set_exec;
1449         
1450         ot->poll= ED_operator_object_active_editable;
1451         
1452         /* flags */
1453         ot->flag= 0; /* no register/undo here, leave it to operators being called */
1454         
1455         prop= RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", "");
1456         RNA_def_enum_funcs(prop, object_mode_set_itemsf);
1457
1458         RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
1459 }
1460
1461
1462
1463 void ED_object_toggle_modes(bContext *C, int mode)
1464 {
1465         if(mode & OB_MODE_SCULPT)
1466                 WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1467         if(mode & OB_MODE_VERTEX_PAINT)
1468                 WM_operator_name_call(C, "PAINT_OT_vertex_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1469         if(mode & OB_MODE_WEIGHT_PAINT)
1470                 WM_operator_name_call(C, "PAINT_OT_weight_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1471         if(mode & OB_MODE_TEXTURE_PAINT)
1472                 WM_operator_name_call(C, "PAINT_OT_texture_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1473         if(mode & OB_MODE_PARTICLE_EDIT)
1474                 WM_operator_name_call(C, "PARTICLE_OT_particle_edit_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1475         if(mode & OB_MODE_POSE)
1476                 WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1477         if(mode & OB_MODE_EDIT)
1478                 WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
1479 }
1480
1481 /************************ Game Properties ***********************/
1482
1483 static int game_property_new(bContext *C, wmOperator *op)
1484 {
1485         Object *ob= CTX_data_active_object(C);
1486         bProperty *prop;
1487         char name[MAX_NAME];
1488         int type= RNA_enum_get(op->ptr, "type");
1489
1490         prop= new_property(type);
1491         BLI_addtail(&ob->prop, prop);
1492
1493         RNA_string_get(op->ptr, "name", name);
1494         if (name[0] != '\0') {
1495                 BLI_strncpy(prop->name, name, sizeof(prop->name));
1496         }
1497
1498         unique_property(NULL, prop, 0); // make_unique_prop_names(prop->name);
1499
1500         WM_event_add_notifier(C, NC_LOGIC, NULL);
1501         return OPERATOR_FINISHED;
1502 }
1503
1504
1505 void OBJECT_OT_game_property_new(wmOperatorType *ot)
1506 {
1507         /* identifiers */
1508         ot->name= "New Game Property";
1509         ot->description= "Create a new property available to the game engine";
1510         ot->idname= "OBJECT_OT_game_property_new";
1511
1512         /* api callbacks */
1513         ot->exec= game_property_new;
1514         ot->poll= ED_operator_object_active_editable;
1515
1516         /* flags */
1517         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1518
1519         RNA_def_enum(ot->srna, "type", gameproperty_type_items, GPROP_FLOAT, "Type", "Type of game property to add");
1520         RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the game property to add");
1521 }
1522
1523 static int game_property_remove(bContext *C, wmOperator *op)
1524 {
1525         Object *ob= CTX_data_active_object(C);
1526         bProperty *prop;
1527         int index= RNA_int_get(op->ptr, "index");
1528
1529         if(!ob)
1530                 return OPERATOR_CANCELLED;
1531
1532         prop= BLI_findlink(&ob->prop, index);
1533
1534         if(prop) {
1535                 BLI_remlink(&ob->prop, prop);
1536                 free_property(prop);
1537
1538                 WM_event_add_notifier(C, NC_LOGIC, NULL);
1539                 return OPERATOR_FINISHED;
1540         }
1541         else {
1542                 return OPERATOR_CANCELLED;
1543         }
1544 }
1545
1546 void OBJECT_OT_game_property_remove(wmOperatorType *ot)
1547 {
1548         /* identifiers */
1549         ot->name= "Remove Game Property";
1550         ot->description= "Remove game property";
1551         ot->idname= "OBJECT_OT_game_property_remove";
1552
1553         /* api callbacks */
1554         ot->exec= game_property_remove;
1555         ot->poll= ED_operator_object_active_editable;
1556
1557         /* flags */
1558         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1559
1560         RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX);
1561 }
1562
1563 #define COPY_PROPERTIES_REPLACE 1
1564 #define COPY_PROPERTIES_MERGE   2
1565 #define COPY_PROPERTIES_COPY    3
1566
1567 static EnumPropertyItem game_properties_copy_operations[] ={
1568         {COPY_PROPERTIES_REPLACE, "REPLACE", 0, "Replace Properties", ""},
1569         {COPY_PROPERTIES_MERGE, "MERGE", 0, "Merge Properties", ""},
1570         {COPY_PROPERTIES_COPY, "COPY", 0, "Copy a Property", ""},
1571         {0, NULL, 0, NULL, NULL}};
1572
1573 static EnumPropertyItem gameprops_items[]= {
1574         {0, NULL, 0, NULL, NULL}};
1575
1576 static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
1577 {       
1578         Object *ob= ED_object_active_context(C);
1579         EnumPropertyItem tmp = {0, "", 0, "", ""};
1580         EnumPropertyItem *item= NULL;
1581         bProperty *prop;
1582         int a, totitem= 0;
1583         
1584         if(!ob)
1585                 return gameprops_items;
1586
1587         for(a=1, prop= ob->prop.first; prop; prop=prop->next, a++) {
1588                 tmp.value= a;
1589                 tmp.identifier= prop->name;
1590                 tmp.name= prop->name;
1591                 RNA_enum_item_add(&item, &totitem, &tmp);
1592         }
1593
1594         RNA_enum_item_end(&item, &totitem);
1595         *free= 1;
1596
1597         return item;
1598 }
1599
1600 static int game_property_copy_exec(bContext *C, wmOperator *op)
1601 {
1602         Object *ob=ED_object_active_context(C);
1603         bProperty *prop;
1604         int type = RNA_enum_get(op->ptr, "operation");
1605         int propid= RNA_enum_get(op->ptr, "property");
1606
1607         if(propid > 0) { /* copy */
1608                 prop = BLI_findlink(&ob->prop, propid-1);
1609                 
1610                 if(prop) {
1611                         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
1612                                 if (ob != ob_iter)
1613                                         set_ob_property(ob_iter, prop);
1614                         } CTX_DATA_END;
1615                 }
1616         }
1617
1618         else {
1619                 CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
1620                         if (ob != ob_iter) {
1621                                 if (type == COPY_PROPERTIES_REPLACE)
1622                                         copy_properties(&ob_iter->prop, &ob->prop);
1623
1624                                 /* merge - the default when calling with no argument */
1625                                 else
1626                                         for(prop = ob->prop.first; prop; prop= prop->next)
1627                                                 set_ob_property(ob_iter, prop);
1628                         }
1629                 }
1630                 CTX_DATA_END;
1631         }
1632
1633         return OPERATOR_FINISHED;
1634 }
1635
1636 void OBJECT_OT_game_property_copy(wmOperatorType *ot)
1637 {
1638         PropertyRNA *prop;
1639         /* identifiers */
1640         ot->name= "Copy Game Property";
1641         ot->idname= "OBJECT_OT_game_property_copy";
1642
1643         /* api callbacks */
1644         ot->exec= game_property_copy_exec;
1645         ot->poll= ED_operator_object_active_editable;
1646
1647         /* flags */
1648         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1649
1650         RNA_def_enum(ot->srna, "operation", game_properties_copy_operations, 3, "Operation", "");
1651         prop=RNA_def_enum(ot->srna, "property", gameprops_items, 0, "Property", "Properties to copy");
1652         RNA_def_enum_funcs(prop, gameprops_itemf);
1653         ot->prop=prop;
1654 }
1655
1656 static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op))
1657 {
1658         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
1659                 free_properties(&ob_iter->prop);
1660         }
1661         CTX_DATA_END;
1662
1663         WM_event_add_notifier(C, NC_LOGIC, NULL);
1664         return OPERATOR_FINISHED;
1665 }
1666 void OBJECT_OT_game_property_clear(wmOperatorType *ot)
1667 {
1668         /* identifiers */
1669         ot->name= "Clear Game Property";
1670         ot->idname= "OBJECT_OT_game_property_clear";
1671
1672         /* api callbacks */
1673         ot->exec= game_property_clear_exec;
1674         ot->poll= ED_operator_object_active_editable;
1675
1676         /* flags */
1677         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1678 }
1679
1680 /************************ Copy Logic Bricks ***********************/
1681
1682 static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op))
1683 {
1684         Object *ob=ED_object_active_context(C);
1685
1686         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
1687                 if(ob != ob_iter) {
1688                         /* first: free all logic */
1689                         free_sensors(&ob_iter->sensors);                                
1690                         unlink_controllers(&ob_iter->controllers);
1691                         free_controllers(&ob_iter->controllers);
1692                         unlink_actuators(&ob_iter->actuators);
1693                         free_actuators(&ob_iter->actuators);
1694                 
1695                         /* now copy it, this also works without logicbricks! */
1696                         clear_sca_new_poins_ob(ob);
1697                         copy_sensors(&ob_iter->sensors, &ob->sensors);
1698                         copy_controllers(&ob_iter->controllers, &ob->controllers);
1699                         copy_actuators(&ob_iter->actuators, &ob->actuators);
1700                         set_sca_new_poins_ob(ob_iter);
1701                 
1702                         /* some menu settings */
1703                         ob_iter->scavisflag= ob->scavisflag;
1704                         ob_iter->scaflag= ob->scaflag;
1705                 
1706                         /* set the initial state */
1707                         ob_iter->state= ob->state;
1708                         ob_iter->init_state= ob->init_state;
1709
1710                         if(ob_iter->totcol==ob->totcol) {
1711                                 ob_iter->actcol= ob->actcol;
1712                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob_iter);
1713                         }
1714                 }
1715         }
1716         CTX_DATA_END;
1717
1718         WM_event_add_notifier(C, NC_LOGIC, NULL);
1719
1720         return OPERATOR_FINISHED;
1721 }
1722
1723 void OBJECT_OT_logic_bricks_copy(wmOperatorType *ot)
1724 {
1725         /* identifiers */
1726         ot->name= "Copy Logic Bricks to Selected";
1727         ot->description = "Copy logic bricks to other selected objects";
1728         ot->idname= "OBJECT_OT_logic_bricks_copy";
1729
1730         /* api callbacks */
1731         ot->exec= logicbricks_copy_exec;
1732         ot->poll= ED_operator_object_active_editable;
1733
1734         /* flags */
1735         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1736 }
1737
1738 static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
1739 {
1740         Object *ob=ED_object_active_context(C);
1741         
1742         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
1743                 if(ob != ob_iter) {
1744                         ob_iter->gameflag = ob->gameflag;
1745                         ob_iter->gameflag2 = ob->gameflag2;
1746                         ob_iter->inertia = ob->inertia;
1747                         ob_iter->formfactor = ob->formfactor;;
1748                         ob_iter->damping = ob->damping;
1749                         ob_iter->rdamping = ob->rdamping;
1750                         ob_iter->min_vel = ob->min_vel;
1751                         ob_iter->max_vel = ob->max_vel;
1752                         ob_iter->obstacleRad = ob->obstacleRad;
1753                         ob_iter->mass = ob->mass;
1754                         ob_iter->anisotropicFriction[0] = ob->anisotropicFriction[0];
1755                         ob_iter->anisotropicFriction[1] = ob->anisotropicFriction[1];
1756                         ob_iter->anisotropicFriction[2] = ob->anisotropicFriction[2];
1757                         ob_iter->collision_boundtype = ob->collision_boundtype;                 
1758                         ob_iter->margin = ob->margin;
1759                         ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft);
1760                         if(ob->restrictflag & OB_RESTRICT_RENDER) 
1761                                 ob_iter->restrictflag |= OB_RESTRICT_RENDER;
1762                          else
1763                                 ob_iter->restrictflag &= ~OB_RESTRICT_RENDER;
1764                 }
1765         }
1766         CTX_DATA_END;
1767         
1768         return OPERATOR_FINISHED;
1769 }
1770
1771 void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
1772 {
1773         /* identifiers */
1774         ot->name= "Copy Game Physics Properties to Selected";
1775         ot->description = "Copy game physics properties to other selected objects";
1776         ot->idname= "OBJECT_OT_game_physics_copy";
1777         
1778         /* api callbacks */
1779         ot->exec= game_physics_copy_exec;
1780         ot->poll= ED_operator_object_active_editable;
1781         
1782         /* flags */
1783         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1784 }