Blender V2.61 - r43446

object_edit.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation, 2002-2008 full recode
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <math.h>
00033 #include <time.h>
00034 #include <float.h>
00035 #include <ctype.h>
00036 #include <stddef.h> //for offsetof
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "BLI_blenlib.h"
00041 #include "BLI_math.h"
00042 #include "BLI_utildefines.h"
00043 #include "BLI_editVert.h"
00044 #include "BLI_ghash.h"
00045 #include "BLI_rand.h"
00046 
00047 #include "DNA_armature_types.h"
00048 #include "DNA_curve_types.h"
00049 #include "DNA_group_types.h"
00050 #include "DNA_lattice_types.h"
00051 #include "DNA_material_types.h"
00052 #include "DNA_meta_types.h"
00053 #include "DNA_property_types.h"
00054 #include "DNA_scene_types.h"
00055 #include "DNA_object_types.h"
00056 #include "DNA_object_force.h"
00057 #include "DNA_meshdata_types.h"
00058 #include "DNA_vfont_types.h"
00059 
00060 #include "IMB_imbuf_types.h"
00061 
00062 #include "BKE_anim.h"
00063 #include "BKE_constraint.h"
00064 #include "BKE_context.h"
00065 #include "BKE_curve.h"
00066 #include "BKE_effect.h"
00067 #include "BKE_depsgraph.h"
00068 #include "BKE_font.h"
00069 #include "BKE_image.h"
00070 #include "BKE_library.h"
00071 #include "BKE_main.h"
00072 #include "BKE_material.h"
00073 #include "BKE_mball.h"
00074 #include "BKE_mesh.h"
00075 #include "BKE_object.h"
00076 #include "BKE_paint.h"
00077 #include "BKE_pointcache.h"
00078 #include "BKE_property.h"
00079 #include "BKE_sca.h"
00080 #include "BKE_softbody.h"
00081 #include "BKE_modifier.h"
00082 
00083 #include "ED_armature.h"
00084 #include "ED_curve.h"
00085 #include "ED_mesh.h"
00086 #include "ED_mball.h"
00087 #include "ED_lattice.h"
00088 #include "ED_object.h"
00089 #include "ED_screen.h"
00090 #include "ED_util.h"
00091 
00092 
00093 #include "RNA_access.h"
00094 #include "RNA_define.h"
00095 #include "RNA_enum_types.h"
00096 
00097 /* for menu/popup icons etc etc*/
00098 
00099 #include "UI_interface.h"
00100 #include "WM_api.h"
00101 #include "WM_types.h"
00102 
00103 #include "object_intern.h"  // own include
00104 
00105 /* ************* XXX **************** */
00106 static void error(const char *UNUSED(arg)) {}
00107 static void waitcursor(int UNUSED(val)) {}
00108 static int pupmenu(const char *UNUSED(msg)) {return 0;}
00109 
00110 /* port over here */
00111 static void error_libdata(void) {}
00112 
00113 Object *ED_object_context(bContext *C)
00114 {
00115     return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
00116 }
00117 
00118 /* find the correct active object per context
00119  * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
00120 Object *ED_object_active_context(bContext *C)
00121 {
00122     Object *ob= NULL;
00123     if(C) {
00124         ob= ED_object_context(C);
00125         if (!ob) ob= CTX_data_active_object(C);
00126     }
00127     return ob;
00128 }
00129 
00130 
00131 /* ********* clear/set restrict view *********/
00132 static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
00133 {
00134     Main *bmain= CTX_data_main(C);
00135     ScrArea *sa= CTX_wm_area(C);
00136     View3D *v3d= sa->spacedata.first;
00137     Scene *scene= CTX_data_scene(C);
00138     Base *base;
00139     int changed = 0;
00140     
00141     /* XXX need a context loop to handle such cases */
00142     for(base = FIRSTBASE; base; base=base->next){
00143         if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
00144             base->flag |= SELECT;
00145             base->object->flag = base->flag;
00146             base->object->restrictflag &= ~OB_RESTRICT_VIEW; 
00147             changed = 1;
00148         }
00149     }
00150     if (changed) {
00151         DAG_id_type_tag(bmain, ID_OB);
00152         DAG_scene_sort(bmain, scene);
00153         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
00154     }
00155 
00156     return OPERATOR_FINISHED;
00157 }
00158 
00159 void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
00160 {
00161     
00162     /* identifiers */
00163     ot->name= "Clear Restrict View";
00164     ot->description = "Reveal the object by setting the hide flag";
00165     ot->idname= "OBJECT_OT_hide_view_clear";
00166     
00167     /* api callbacks */
00168     ot->exec= object_hide_view_clear_exec;
00169     ot->poll= ED_operator_view3d_active;
00170     
00171     /* flags */
00172     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00173 }
00174 
00175 static int object_hide_view_set_exec(bContext *C, wmOperator *op)
00176 {
00177     Main *bmain= CTX_data_main(C);
00178     Scene *scene= CTX_data_scene(C);
00179     short changed = 0;
00180     const int unselected= RNA_boolean_get(op->ptr, "unselected");
00181     
00182     CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
00183         if(!unselected) {
00184             if (base->flag & SELECT){
00185                 base->flag &= ~SELECT;
00186                 base->object->flag = base->flag;
00187                 base->object->restrictflag |= OB_RESTRICT_VIEW;
00188                 changed = 1;
00189                 if (base==BASACT) {
00190                     ED_base_object_activate(C, NULL);
00191                 }
00192             }
00193         }
00194         else {
00195             if (!(base->flag & SELECT)){
00196                 base->object->restrictflag |= OB_RESTRICT_VIEW;
00197                 changed = 1;
00198             }
00199         }   
00200     }
00201     CTX_DATA_END;
00202 
00203     if (changed) {
00204         DAG_id_type_tag(bmain, ID_OB);
00205         DAG_scene_sort(bmain, scene);
00206         
00207         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
00208         
00209     }
00210 
00211     return OPERATOR_FINISHED;
00212 }
00213 
00214 void OBJECT_OT_hide_view_set(wmOperatorType *ot)
00215 {
00216     /* identifiers */
00217     ot->name= "Set Restrict View";
00218     ot->description = "Hide the object by setting the hide flag";
00219     ot->idname= "OBJECT_OT_hide_view_set";
00220     
00221     /* api callbacks */
00222     ot->exec= object_hide_view_set_exec;
00223     ot->poll= ED_operator_view3d_active;
00224     
00225     /* flags */
00226     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00227     
00228     RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
00229     
00230 }
00231 
00232 /* 99% same as above except no need for scene refreshing (TODO, update render preview) */
00233 static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
00234 {
00235     short changed= 0;
00236 
00237     /* XXX need a context loop to handle such cases */
00238     CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
00239         if(ob->restrictflag & OB_RESTRICT_RENDER) {
00240             ob->restrictflag &= ~OB_RESTRICT_RENDER;
00241             changed= 1;
00242         }
00243     }
00244     CTX_DATA_END;
00245 
00246     if(changed)
00247         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_OUTLINER, NULL);
00248 
00249     return OPERATOR_FINISHED;
00250 }
00251 
00252 void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
00253 {
00254 
00255     /* identifiers */
00256     ot->name= "Clear Restrict Render";
00257     ot->description = "Reveal the render object by setting the hide render flag";
00258     ot->idname= "OBJECT_OT_hide_render_clear";
00259 
00260     /* api callbacks */
00261     ot->exec= object_hide_render_clear_exec;
00262     ot->poll= ED_operator_view3d_active;
00263 
00264     /* flags */
00265     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00266 }
00267 
00268 static int object_hide_render_set_exec(bContext *C, wmOperator *op)
00269 {
00270     const int unselected= RNA_boolean_get(op->ptr, "unselected");
00271 
00272     CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
00273         if(!unselected) {
00274             if (base->flag & SELECT){
00275                 base->object->restrictflag |= OB_RESTRICT_RENDER;
00276             }
00277         }
00278         else {
00279             if (!(base->flag & SELECT)){
00280                 base->object->restrictflag |= OB_RESTRICT_RENDER;
00281             }
00282         }
00283     }
00284     CTX_DATA_END;
00285     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_OUTLINER, NULL);
00286     return OPERATOR_FINISHED;
00287 }
00288 
00289 void OBJECT_OT_hide_render_set(wmOperatorType *ot)
00290 {
00291     /* identifiers */
00292     ot->name= "Set Restrict Render";
00293     ot->description = "Hide the render object by setting the hide render flag";
00294     ot->idname= "OBJECT_OT_hide_render_set";
00295 
00296     /* api callbacks */
00297     ot->exec= object_hide_render_set_exec;
00298     ot->poll= ED_operator_view3d_active;
00299 
00300     /* flags */
00301     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00302 
00303     RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
00304 }
00305 
00306 /* ******************* toggle editmode operator  ***************** */
00307 
00308 void ED_object_exit_editmode(bContext *C, int flag)
00309 {
00310     /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
00311 
00312     Scene *scene= CTX_data_scene(C);
00313     Object *obedit= CTX_data_edit_object(C);
00314     int freedata = flag & EM_FREEDATA;
00315     
00316     if(obedit==NULL) return;
00317     
00318     if(flag & EM_WAITCURSOR) waitcursor(1);
00319     if(obedit->type==OB_MESH) {
00320         Mesh *me= obedit->data;
00321         
00322 //      if(EM_texFaceCheck())
00323         
00324         if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
00325             error("Too many vertices");
00326             return;
00327         }
00328         load_editMesh(scene, obedit);
00329         
00330         if(freedata) {
00331             free_editMesh(me->edit_mesh);
00332             MEM_freeN(me->edit_mesh);
00333             me->edit_mesh= NULL;
00334         }
00335         
00336         if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
00337             mesh_octree_table(NULL, NULL, NULL, 'e');
00338             mesh_mirrtopo_table(NULL, 'e');
00339         }
00340     }
00341     else if (obedit->type==OB_ARMATURE) {   
00342         ED_armature_from_edit(obedit);
00343         if(freedata)
00344             ED_armature_edit_free(obedit);
00345     }
00346     else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
00347         load_editNurb(obedit);
00348         if(freedata) free_editNurb(obedit);
00349     }
00350     else if(obedit->type==OB_FONT && freedata) {
00351         load_editText(obedit);
00352         if(freedata) free_editText(obedit);
00353     }
00354     else if(obedit->type==OB_LATTICE) {
00355         load_editLatt(obedit);
00356         if(freedata) free_editLatt(obedit);
00357     }
00358     else if(obedit->type==OB_MBALL) {
00359         load_editMball(obedit);
00360         if(freedata) free_editMball(obedit);
00361     }
00362 
00363     /* freedata only 0 now on file saves and render */
00364     if(freedata) {
00365         ListBase pidlist;
00366         PTCacheID *pid;
00367 
00368         /* for example; displist make is different in editmode */
00369         scene->obedit= NULL; // XXX for context
00370 
00371         /* flag object caches as outdated */
00372         BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0);
00373         for(pid=pidlist.first; pid; pid=pid->next) {
00374             if(pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
00375                 pid->cache->flag |= PTCACHE_OUTDATED;
00376         }
00377         BLI_freelistN(&pidlist);
00378         
00379         BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
00380 
00381         /* also flush ob recalc, doesn't take much overhead, but used for particles */
00382         DAG_id_tag_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
00383     
00384         if(flag & EM_DO_UNDO)
00385             ED_undo_push(C, "Editmode");
00386     
00387         if(flag & EM_WAITCURSOR) waitcursor(0);
00388     
00389         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
00390 
00391         obedit->mode &= ~OB_MODE_EDIT;
00392     }
00393 }
00394 
00395 
00396 void ED_object_enter_editmode(bContext *C, int flag)
00397 {
00398     Scene *scene= CTX_data_scene(C);
00399     Base *base= NULL;
00400     Object *ob;
00401     ScrArea *sa= CTX_wm_area(C);
00402     View3D *v3d= NULL;
00403     int ok= 0;
00404     
00405     if(scene->id.lib) return;
00406     
00407     if(sa && sa->spacetype==SPACE_VIEW3D)
00408         v3d= sa->spacedata.first;
00409     
00410     if((flag & EM_IGNORE_LAYER)==0) {
00411         base= CTX_data_active_base(C); /* active layer checked here for view3d */
00412 
00413         if(base==NULL) return;
00414         else if(v3d && (base->lay & v3d->lay)==0) return;
00415         else if(!v3d && (base->lay & scene->lay)==0) return;
00416     }
00417     else {
00418         base= scene->basact;
00419     }
00420 
00421     if (ELEM3(NULL, base, base->object, base->object->data)) return;
00422 
00423     ob = base->object;
00424     
00425     if (object_data_is_libdata(ob)) {
00426         error_libdata();
00427         return;
00428     }
00429     
00430     if(flag & EM_WAITCURSOR) waitcursor(1);
00431 
00432     ob->restore_mode = ob->mode;
00433 
00434     /* note, when switching scenes the object can have editmode data but
00435      * not be scene->obedit: bug 22954, this avoids calling self eternally */
00436     if((ob->restore_mode & OB_MODE_EDIT)==0)
00437         ED_object_toggle_modes(C, ob->mode);
00438 
00439     ob->mode= OB_MODE_EDIT;
00440     
00441     if(ob->type==OB_MESH) {
00442         ok= 1;
00443         scene->obedit= ob;  // context sees this
00444         
00445         make_editMesh(scene, ob);
00446 
00447         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
00448     }
00449     else if (ob->type==OB_ARMATURE){
00450         bArmature *arm= base->object->data;
00451         if (!arm) return;
00452         /*
00453          * The function object_data_is_libdata make a problem here, the
00454          * check for ob->proxy return 0 and let blender enter to edit mode
00455          * this causa a crash when you try leave the edit mode.
00456          * The problem is that i can't remove the ob->proxy check from
00457          * object_data_is_libdata that prevent the bugfix #6614, so
00458          * i add this little hack here.
00459          */
00460         if(arm->id.lib) {
00461             error_libdata();
00462             return;
00463         }
00464         ok=1;
00465         scene->obedit= ob;
00466         ED_armature_to_edit(ob);
00467         /* to ensure all goes in restposition and without striding */
00468         DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX: should this be OB_RECALC_DATA?
00469 
00470         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, scene);
00471     }
00472     else if(ob->type==OB_FONT) {
00473         scene->obedit= ob; // XXX for context
00474         ok= 1;
00475         make_editText(ob);
00476 
00477         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_TEXT, scene);
00478     }
00479     else if(ob->type==OB_MBALL) {
00480         scene->obedit= ob; // XXX for context
00481         ok= 1;
00482         make_editMball(ob);
00483 
00484         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MBALL, scene);
00485     }
00486     else if(ob->type==OB_LATTICE) {
00487         scene->obedit= ob; // XXX for context
00488         ok= 1;
00489         make_editLatt(ob);
00490         
00491         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_LATTICE, scene);
00492     }
00493     else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
00494         ok= 1;
00495         scene->obedit= ob; // XXX for context
00496         make_editNurb(ob);
00497         
00498         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_CURVE, scene);
00499     }
00500     
00501     if(ok) {
00502         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00503     }
00504     else {
00505         scene->obedit= NULL; // XXX for context
00506         ob->mode &= ~OB_MODE_EDIT;
00507         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
00508     }
00509     
00510     if(flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
00511     if(flag & EM_WAITCURSOR) waitcursor(0);
00512 }
00513 
00514 static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
00515 {
00516     if(!CTX_data_edit_object(C))
00517         ED_object_enter_editmode(C, EM_WAITCURSOR);
00518     else
00519         ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
00520     
00521     return OPERATOR_FINISHED;
00522 }
00523 
00524 static int editmode_toggle_poll(bContext *C)
00525 {
00526     Object *ob = CTX_data_active_object(C);
00527 
00528     /* covers proxies too */
00529     if(ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib)
00530         return 0;
00531 
00532     if (ob->restrictflag & OB_RESTRICT_VIEW)
00533         return 0;
00534 
00535     return (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
00536             ob->type == OB_FONT || ob->type == OB_MBALL ||
00537             ob->type == OB_LATTICE || ob->type == OB_SURF ||
00538             ob->type == OB_CURVE);
00539 }
00540 
00541 void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
00542 {
00543     
00544     /* identifiers */
00545     ot->name= "Toggle Editmode";
00546     ot->description = "Toggle object's editmode";
00547     ot->idname= "OBJECT_OT_editmode_toggle";
00548     
00549     /* api callbacks */
00550     ot->exec= editmode_toggle_exec;
00551     
00552     ot->poll= editmode_toggle_poll;
00553     
00554     /* flags */
00555     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00556 }
00557 
00558 /* *************************** */
00559 
00560 static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
00561 {
00562     Base *base= CTX_data_active_base(C);
00563     
00564     if(base->object->type==OB_ARMATURE) {
00565         if(base->object==CTX_data_edit_object(C)) {
00566             ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
00567             ED_armature_enter_posemode(C, base);
00568         }
00569         else if(base->object->mode & OB_MODE_POSE)
00570             ED_armature_exit_posemode(C, base);
00571         else
00572             ED_armature_enter_posemode(C, base);
00573         
00574         return OPERATOR_FINISHED;
00575     }
00576     
00577     return OPERATOR_PASS_THROUGH;
00578 }
00579 
00580 void OBJECT_OT_posemode_toggle(wmOperatorType *ot) 
00581 {
00582     /* identifiers */
00583     ot->name= "Toggle Pose Mode";
00584     ot->idname= "OBJECT_OT_posemode_toggle";
00585     ot->description= "Enable or disable posing/selecting bones";
00586     
00587     /* api callbacks */
00588     ot->exec= posemode_exec;
00589     ot->poll= ED_operator_object_active_editable;
00590     
00591     /* flag */
00592     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00593 }
00594 
00595 static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
00596 {   
00597 //XXX no longer used - to be removed - replaced by game_properties_copy_exec
00598     bProperty *prop;
00599     Base *base;
00600     int nr, tot=0;
00601     char *str;
00602     
00603     prop= ob->prop.first;
00604     while(prop) {
00605         tot++;
00606         prop= prop->next;
00607     }
00608     
00609     str= MEM_callocN(50 + 33*tot, "copymenu prop");
00610     
00611     if (tot)
00612         strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
00613     else
00614         strcpy(str, "Copy Property %t|Clear All (no properties on active)");
00615     
00616     tot= 0; 
00617     prop= ob->prop.first;
00618     while(prop) {
00619         tot++;
00620         strcat(str, "|");
00621         strcat(str, prop->name);
00622         prop= prop->next;
00623     }
00624 
00625     nr= pupmenu(str);
00626     
00627     if ( nr==1 || nr==2 ) {
00628         for(base= FIRSTBASE; base; base= base->next) {
00629             if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
00630                 if (nr==1) { /* replace */
00631                     copy_properties( &base->object->prop, &ob->prop );
00632                 } else {
00633                     for(prop = ob->prop.first; prop; prop= prop->next ) {
00634                         set_ob_property(base->object, prop);
00635                     }
00636                 }
00637             }
00638         }
00639     } else if(nr>0) {
00640         prop = BLI_findlink(&ob->prop, nr-4); /* account for first 3 menu items & menu index starting at 1*/
00641         
00642         if(prop) {
00643             for(base= FIRSTBASE; base; base= base->next) {
00644                 if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
00645                     set_ob_property(base->object, prop);
00646                 }
00647             }
00648         }
00649     }
00650     MEM_freeN(str);
00651     
00652 }
00653 
00654 static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
00655 {
00656 //XXX no longer used - to be removed - replaced by logicbricks_copy_exec
00657     Base *base;
00658     
00659     for(base= FIRSTBASE; base; base= base->next) {
00660         if(base->object != ob) {
00661             if(TESTBASELIB(v3d, base)) {
00662                 
00663                 /* first: free all logic */
00664                 free_sensors(&base->object->sensors);               
00665                 unlink_controllers(&base->object->controllers);
00666                 free_controllers(&base->object->controllers);
00667                 unlink_actuators(&base->object->actuators);
00668                 free_actuators(&base->object->actuators);
00669                 
00670                 /* now copy it, this also works without logicbricks! */
00671                 clear_sca_new_poins_ob(ob);
00672                 copy_sensors(&base->object->sensors, &ob->sensors);
00673                 copy_controllers(&base->object->controllers, &ob->controllers);
00674                 copy_actuators(&base->object->actuators, &ob->actuators);
00675                 set_sca_new_poins_ob(base->object);
00676                 
00677                 /* some menu settings */
00678                 base->object->scavisflag= ob->scavisflag;
00679                 base->object->scaflag= ob->scaflag;
00680                 
00681                 /* set the initial state */
00682                 base->object->state= ob->state;
00683                 base->object->init_state= ob->init_state;
00684             }
00685         }
00686     }
00687 }
00688 
00689 /* both pointers should exist */
00690 static void copy_texture_space(Object *to, Object *ob)
00691 {
00692     float *poin1= NULL, *poin2= NULL;
00693     short texflag= 0;
00694     
00695     if(ob->type==OB_MESH) {
00696         texflag= ((Mesh *)ob->data)->texflag;
00697         poin2= ((Mesh *)ob->data)->loc;
00698     }
00699     else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
00700         texflag= ((Curve *)ob->data)->texflag;
00701         poin2= ((Curve *)ob->data)->loc;
00702     }
00703     else if(ob->type==OB_MBALL) {
00704         texflag= ((MetaBall *)ob->data)->texflag;
00705         poin2= ((MetaBall *)ob->data)->loc;
00706     }
00707     else
00708         return;
00709         
00710     if(to->type==OB_MESH) {
00711         ((Mesh *)to->data)->texflag= texflag;
00712         poin1= ((Mesh *)to->data)->loc;
00713     }
00714     else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
00715         ((Curve *)to->data)->texflag= texflag;
00716         poin1= ((Curve *)to->data)->loc;
00717     }
00718     else if(to->type==OB_MBALL) {
00719         ((MetaBall *)to->data)->texflag= texflag;
00720         poin1= ((MetaBall *)to->data)->loc;
00721     }
00722     else
00723         return;
00724     
00725     memcpy(poin1, poin2, 9*sizeof(float));  /* this was noted in DNA_mesh, curve, mball */
00726     
00727     if(to->type==OB_MESH) ;
00728     else if(to->type==OB_MBALL) tex_space_mball(to);
00729     else tex_space_curve(to->data);
00730     
00731 }
00732 
00733 /* UNUSED, keep incase we want to copy functionality for use elsewhere */
00734 static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
00735 {
00736     Object *ob;
00737     Base *base;
00738     Curve *cu, *cu1;
00739     Nurb *nu;
00740     int do_scene_sort= 0;
00741     
00742     if(scene->id.lib) return;
00743 
00744     if(!(ob=OBACT)) return;
00745     
00746     if(scene->obedit) { // XXX get from context
00747         /* obedit_copymenu(); */
00748         return;
00749     }
00750     if(event==9) {
00751         copymenu_properties(scene, v3d, ob);
00752         return;
00753     }
00754     else if(event==10) {
00755         copymenu_logicbricks(scene, v3d, ob);
00756         return;
00757     }
00758     else if(event==24) {
00759         /* moved to object_link_modifiers */
00760         /* copymenu_modifiers(bmain, scene, v3d, ob); */
00761         return;
00762     }
00763 
00764     for(base= FIRSTBASE; base; base= base->next) {
00765         if(base != BASACT) {
00766             if(TESTBASELIB(v3d, base)) {
00767                 base->object->recalc |= OB_RECALC_OB;
00768                 
00769                 if(event==1) {  /* loc */
00770                     copy_v3_v3(base->object->loc, ob->loc);
00771                     copy_v3_v3(base->object->dloc, ob->dloc);
00772                 }
00773                 else if(event==2) {  /* rot */
00774                     copy_v3_v3(base->object->rot, ob->rot);
00775                     copy_v3_v3(base->object->drot, ob->drot);
00776 
00777                     copy_qt_qt(base->object->quat, ob->quat);
00778                     copy_qt_qt(base->object->dquat, ob->dquat);
00779                 }
00780                 else if(event==3) {  /* size */
00781                     copy_v3_v3(base->object->size, ob->size);
00782                     copy_v3_v3(base->object->dscale, ob->dscale);
00783                 }
00784                 else if(event==4) {  /* drawtype */
00785                     base->object->dt= ob->dt;
00786                     base->object->dtx= ob->dtx;
00787                     base->object->empty_drawtype= ob->empty_drawtype;
00788                     base->object->empty_drawsize= ob->empty_drawsize;
00789                 }
00790                 else if(event==5) {  /* time offs */
00791                     base->object->sf= ob->sf;
00792                 }
00793                 else if(event==6) {  /* dupli */
00794                     base->object->dupon= ob->dupon;
00795                     base->object->dupoff= ob->dupoff;
00796                     base->object->dupsta= ob->dupsta;
00797                     base->object->dupend= ob->dupend;
00798                     
00799                     base->object->transflag &= ~OB_DUPLI;
00800                     base->object->transflag |= (ob->transflag & OB_DUPLI);
00801 
00802                     base->object->dup_group= ob->dup_group;
00803                     if(ob->dup_group)
00804                         id_lib_extern(&ob->dup_group->id);
00805                 }
00806                 else if(event==7) { /* mass */
00807                     base->object->mass= ob->mass;
00808                 }
00809                 else if(event==8) { /* damping */
00810                     base->object->damping= ob->damping;
00811                     base->object->rdamping= ob->rdamping;
00812                 }
00813                 else if(event==11) {    /* all physical attributes */
00814                     base->object->gameflag = ob->gameflag;
00815                     base->object->inertia = ob->inertia;
00816                     base->object->formfactor = ob->formfactor;
00817                     base->object->damping= ob->damping;
00818                     base->object->rdamping= ob->rdamping;
00819                     base->object->min_vel= ob->min_vel;
00820                     base->object->max_vel= ob->max_vel;
00821                     if (ob->gameflag & OB_BOUNDS) {
00822                         base->object->collision_boundtype = ob->collision_boundtype;
00823                     }
00824                     base->object->margin= ob->margin;
00825                     base->object->bsoft= copy_bulletsoftbody(ob->bsoft);
00826 
00827                 }
00828                 else if(event==17) {    /* tex space */
00829                     copy_texture_space(base->object, ob);
00830                 }
00831                 else if(event==18) {    /* font settings */
00832                     
00833                     if(base->object->type==ob->type) {
00834                         cu= ob->data;
00835                         cu1= base->object->data;
00836                         
00837                         cu1->spacemode= cu->spacemode;
00838                         cu1->spacing= cu->spacing;
00839                         cu1->linedist= cu->linedist;
00840                         cu1->shear= cu->shear;
00841                         cu1->fsize= cu->fsize;
00842                         cu1->xof= cu->xof;
00843                         cu1->yof= cu->yof;
00844                         cu1->textoncurve= cu->textoncurve;
00845                         cu1->wordspace= cu->wordspace;
00846                         cu1->ulpos= cu->ulpos;
00847                         cu1->ulheight= cu->ulheight;
00848                         if(cu1->vfont) cu1->vfont->id.us--;
00849                         cu1->vfont= cu->vfont;
00850                         id_us_plus((ID *)cu1->vfont);
00851                         if(cu1->vfontb) cu1->vfontb->id.us--;
00852                         cu1->vfontb= cu->vfontb;
00853                         id_us_plus((ID *)cu1->vfontb);
00854                         if(cu1->vfonti) cu1->vfonti->id.us--;
00855                         cu1->vfonti= cu->vfonti;
00856                         id_us_plus((ID *)cu1->vfonti);
00857                         if(cu1->vfontbi) cu1->vfontbi->id.us--;
00858                         cu1->vfontbi= cu->vfontbi;
00859                         id_us_plus((ID *)cu1->vfontbi);                     
00860 
00861                         BKE_text_to_curve(bmain, scene, base->object, 0); /* needed? */
00862 
00863                         
00864                         BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
00865                         
00866                         base->object->recalc |= OB_RECALC_DATA;
00867                     }
00868                 }
00869                 else if(event==19) {    /* bevel settings */
00870                     
00871                     if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
00872                         cu= ob->data;
00873                         cu1= base->object->data;
00874                         
00875                         cu1->bevobj= cu->bevobj;
00876                         cu1->taperobj= cu->taperobj;
00877                         cu1->width= cu->width;
00878                         cu1->bevresol= cu->bevresol;
00879                         cu1->ext1= cu->ext1;
00880                         cu1->ext2= cu->ext2;
00881                         
00882                         base->object->recalc |= OB_RECALC_DATA;
00883                     }
00884                 }
00885                 else if(event==25) {    /* curve resolution */
00886 
00887                     if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
00888                         cu= ob->data;
00889                         cu1= base->object->data;
00890                         
00891                         cu1->resolu= cu->resolu;
00892                         cu1->resolu_ren= cu->resolu_ren;
00893                         
00894                         nu= cu1->nurb.first;
00895                         
00896                         while(nu) {
00897                             nu->resolu= cu1->resolu;
00898                             nu= nu->next;
00899                         }
00900                         
00901                         base->object->recalc |= OB_RECALC_DATA;
00902                     }
00903                 }
00904                 else if(event==21){
00905                     if (base->object->type==OB_MESH) {
00906                         ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
00907 
00908                         if (md) {
00909                             ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
00910 
00911                             if (!tmd) {
00912                                 tmd = modifier_new(eModifierType_Subsurf);
00913                                 BLI_addtail(&base->object->modifiers, tmd);
00914                             }
00915 
00916                             modifier_copyData(md, tmd);
00917                             base->object->recalc |= OB_RECALC_DATA;
00918                         }
00919                     }
00920                 }
00921                 else if(event==22) {
00922                     /* Copy the constraint channels over */
00923                     copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
00924                     
00925                     do_scene_sort= 1;
00926                 }
00927                 else if(event==23) {
00928                     base->object->softflag= ob->softflag;
00929                     if(base->object->soft) sbFree(base->object->soft);
00930                     
00931                     base->object->soft= copy_softbody(ob->soft);
00932 
00933                     if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
00934                         BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
00935                     }
00936                 }
00937                 else if(event==26) {
00938 #if 0 // XXX old animation system
00939                     copy_nlastrips(&base->object->nlastrips, &ob->nlastrips);
00940 #endif // XXX old animation system
00941                 }
00942                 else if(event==27) {    /* autosmooth */
00943                     if (base->object->type==OB_MESH) {
00944                         Mesh *me= ob->data;
00945                         Mesh *cme= base->object->data;
00946                         cme->smoothresh= me->smoothresh;
00947                         if(me->flag & ME_AUTOSMOOTH)
00948                             cme->flag |= ME_AUTOSMOOTH;
00949                         else
00950                             cme->flag &= ~ME_AUTOSMOOTH;
00951                     }
00952                 }
00953                 else if(event==28) { /* UV orco */
00954                     if(ELEM(base->object->type, OB_CURVE, OB_SURF)) {
00955                         cu= ob->data;
00956                         cu1= base->object->data;
00957                         
00958                         if(cu->flag & CU_UV_ORCO)
00959                             cu1->flag |= CU_UV_ORCO;
00960                         else
00961                             cu1->flag &= ~CU_UV_ORCO;
00962                     }       
00963                 }
00964                 else if(event==29) { /* protected bits */
00965                     base->object->protectflag= ob->protectflag;
00966                 }
00967                 else if(event==30) { /* index object */
00968                     base->object->index= ob->index;
00969                 }
00970                 else if(event==31) { /* object color */
00971                     copy_v4_v4(base->object->col, ob->col);
00972                 }
00973             }
00974         }
00975     }
00976     
00977     if(do_scene_sort)
00978         DAG_scene_sort(bmain, scene);
00979 
00980     DAG_ids_flush_update(bmain, 0);
00981 }
00982 
00983 static void UNUSED_FUNCTION(copy_attr_menu)(Main *bmain, Scene *scene, View3D *v3d)
00984 {
00985     Object *ob;
00986     short event;
00987     char str[512];
00988     
00989     if(!(ob=OBACT)) return;
00990     
00991     if (scene->obedit) { // XXX get from context
00992 //      if (ob->type == OB_MESH)
00993 // XXX          mesh_copy_menu();
00994         return;
00995     }
00996     
00997     /* Object Mode */
00998     
00999     /* If you change this menu, don't forget to update the menu in header_view3d.c
01000      * view3d_edit_object_copyattrmenu() and in toolbox.c
01001      */
01002     
01003     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");
01004     
01005     strcat (str, "|Object Constraints%x22");
01006     strcat (str, "|NLA Strips%x26");
01007     
01008 // XXX  if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
01009 //      strcat(str, "|Texture Space%x17");
01010 //  }   
01011     
01012     if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
01013     if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19|UV Orco%x28");
01014     
01015     if((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
01016             strcat(str, "|Curve Resolution%x25");
01017     }
01018 
01019     if(ob->type==OB_MESH){
01020         strcat(str, "|Subsurf Settings%x21|AutoSmooth%x27");
01021     }
01022 
01023     if(ob->soft) strcat(str, "|Soft Body Settings%x23");
01024     
01025     strcat(str, "|Pass Index%x30");
01026     
01027     if(ob->type==OB_MESH || ob->type==OB_CURVE || ob->type==OB_LATTICE || ob->type==OB_SURF){
01028         strcat(str, "|Modifiers ...%x24");
01029     }
01030 
01031     event= pupmenu(str);
01032     if(event<= 0) return;
01033     
01034     copy_attr(bmain, scene, v3d, event);
01035 }
01036 
01037 /* ******************* force field toggle operator ***************** */
01038 
01039 static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
01040 {
01041     Object *ob = CTX_data_active_object(C);
01042 
01043     if(ob->pd == NULL)
01044         ob->pd = object_add_collision_fields(PFIELD_FORCE);
01045 
01046     if(ob->pd->forcefield == 0)
01047         ob->pd->forcefield = PFIELD_FORCE;
01048     else
01049         ob->pd->forcefield = 0;
01050     
01051     WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
01052 
01053     return OPERATOR_FINISHED;
01054 }
01055 
01056 void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
01057 {
01058     
01059     /* identifiers */
01060     ot->name= "Toggle Force Field";
01061     ot->description = "Toggle object's force field";
01062     ot->idname= "OBJECT_OT_forcefield_toggle";
01063     
01064     /* api callbacks */
01065     ot->exec= forcefield_toggle_exec;
01066     ot->poll= ED_operator_object_active_editable;
01067     
01068     /* flags */
01069     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01070 }
01071 
01072 /* ********************************************** */
01073 /* Motion Paths */
01074 
01075 /* For the object with pose/action: update paths for those that have got them
01076  * This should selectively update paths that exist...
01077  *
01078  * To be called from various tools that do incremental updates 
01079  */
01080 void ED_objects_recalculate_paths(bContext *C, Scene *scene)
01081 {
01082     ListBase targets = {NULL, NULL};
01083     
01084     /* loop over objects in scene */
01085     CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 
01086     {
01087         /* set flag to force recalc, then grab the relevant bones to target */
01088         ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
01089         animviz_get_object_motionpaths(ob, &targets);
01090     }
01091     CTX_DATA_END;
01092     
01093     /* recalculate paths, then free */
01094     animviz_calc_motionpaths(scene, &targets);
01095     BLI_freelistN(&targets);
01096 }
01097 
01098 /* For the object with pose/action: create path curves for selected bones 
01099  * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
01100  */
01101 static int object_calculate_paths_exec (bContext *C, wmOperator *op)
01102 {
01103     Scene *scene= CTX_data_scene(C);
01104     
01105     /* set up path data for bones being calculated */
01106     CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)  
01107     {
01108         /* verify makes sure that the selected bone has a bone with the appropriate settings */
01109         animviz_verify_motionpaths(op->reports, scene, ob, NULL);
01110     }
01111     CTX_DATA_END;
01112     
01113     /* calculate the bones that now have motionpaths... */
01114     // TODO: only make for the selected bones?
01115     ED_objects_recalculate_paths(C, scene);
01116     
01117     /* notifiers for updates */
01118     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
01119     
01120     return OPERATOR_FINISHED; 
01121 }
01122 
01123 void OBJECT_OT_paths_calculate (wmOperatorType *ot)
01124 {
01125     /* identifiers */
01126     ot->name= "Calculate Object Paths";
01127     ot->idname= "OBJECT_OT_paths_calculate";
01128     ot->description= "Calculate paths for the selected bones";
01129     
01130     /* api callbacks */
01131     ot->exec= object_calculate_paths_exec;
01132     ot->poll= ED_operator_object_active_editable;
01133     
01134     /* flags */
01135     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01136 }
01137 
01138 /* --------- */
01139 
01140 /* for the object with pose/action: clear path curves for selected bones only */
01141 void ED_objects_clear_paths(bContext *C)
01142 {
01143     /* loop over objects in scene */
01144     CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 
01145     {
01146         if (ob->mpath) {
01147             animviz_free_motionpath(ob->mpath);
01148             ob->mpath= NULL;
01149             ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
01150         }
01151     }
01152     CTX_DATA_END;
01153 }
01154 
01155 /* operator callback for this */
01156 static int object_clear_paths_exec (bContext *C, wmOperator *UNUSED(op))
01157 {   
01158     /* use the backend function for this */
01159     ED_objects_clear_paths(C);
01160     
01161     /* notifiers for updates */
01162     WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
01163     
01164     return OPERATOR_FINISHED; 
01165 }
01166 
01167 void OBJECT_OT_paths_clear (wmOperatorType *ot)
01168 {
01169     /* identifiers */
01170     ot->name= "Clear Object Paths";
01171     ot->idname= "OBJECT_OT_paths_clear";
01172     ot->description= "Clear path caches for selected bones";
01173     
01174     /* api callbacks */
01175     ot->exec= object_clear_paths_exec;
01176     ot->poll= ED_operator_object_active_editable;
01177     
01178     /* flags */
01179     ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
01180 }
01181 
01182 
01183 /********************** Smooth/Flat *********************/
01184 
01185 static int shade_smooth_exec(bContext *C, wmOperator *op)
01186 {
01187     Curve *cu;
01188     Nurb *nu;
01189     int clear= (strcmp(op->idname, "OBJECT_OT_shade_flat") == 0);
01190     int done= 0;
01191 
01192     CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
01193 
01194         if(ob->type==OB_MESH) {
01195             mesh_set_smooth_flag(ob, !clear);
01196 
01197             DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01198             WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
01199 
01200             done= 1;
01201         }
01202         else if ELEM(ob->type, OB_SURF, OB_CURVE) {
01203             cu= ob->data;
01204 
01205             for(nu=cu->nurb.first; nu; nu=nu->next) {
01206                 if(!clear) nu->flag |= ME_SMOOTH;
01207                 else nu->flag &= ~ME_SMOOTH;
01208             }
01209 
01210             DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01211             WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
01212 
01213             done= 1;
01214         }
01215     }
01216     CTX_DATA_END;
01217 
01218     return (done)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
01219 }
01220 
01221 static int shade_poll(bContext *C)
01222 {
01223     return (ED_operator_object_active_editable(C) && !ED_operator_editmesh(C));
01224 }
01225 
01226 void OBJECT_OT_shade_flat(wmOperatorType *ot)
01227 {
01228     /* identifiers */
01229     ot->name= "Shade Flat";
01230     ot->description= "Display faces 'flat'";
01231     ot->idname= "OBJECT_OT_shade_flat";
01232     
01233     /* api callbacks */
01234     ot->poll= shade_poll;
01235     ot->exec= shade_smooth_exec;
01236 
01237     /* flags */
01238     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01239 }
01240 
01241 void OBJECT_OT_shade_smooth(wmOperatorType *ot)
01242 {
01243     /* identifiers */
01244     ot->name= "Shade Smooth";
01245     ot->description= "Display faces 'smooth' (using vertex normals)";
01246     ot->idname= "OBJECT_OT_shade_smooth";
01247     
01248     /* api callbacks */
01249     ot->poll= shade_poll;
01250     ot->exec= shade_smooth_exec;
01251     
01252     /* flags */
01253     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01254 }
01255 
01256 /* ********************** */
01257 
01258 static void UNUSED_FUNCTION(image_aspect)(Scene *scene, View3D *v3d)
01259 {
01260     /* all selected objects with an image map: scale in image aspect */
01261     Base *base;
01262     Object *ob;
01263     Material *ma;
01264     Tex *tex;
01265     float x, y, space;
01266     int a, b, done;
01267     
01268     if(scene->obedit) return; // XXX get from context
01269     if(scene->id.lib) return;
01270     
01271     for(base= FIRSTBASE; base; base= base->next) {
01272         if(TESTBASELIB(v3d, base)) {
01273             ob= base->object;
01274             done= 0;
01275             
01276             for(a=1; a<=ob->totcol; a++) {
01277                 ma= give_current_material(ob, a);
01278                 if(ma) {
01279                     for(b=0; b<MAX_MTEX; b++) {
01280                         if(ma->mtex[b] && ma->mtex[b]->tex) {
01281                             tex= ma->mtex[b]->tex;
01282                             if(tex->type==TEX_IMAGE && tex->ima) {
01283                                 ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, NULL);
01284                                 
01285                                 /* texturespace */
01286                                 space= 1.0;
01287                                 if(ob->type==OB_MESH) {
01288                                     float size[3];
01289                                     mesh_get_texspace(ob->data, NULL, NULL, size);
01290                                     space= size[0]/size[1];
01291                                 }
01292                                 else if(ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
01293                                     Curve *cu= ob->data;
01294                                     space= cu->size[0]/cu->size[1];
01295                                 }
01296                             
01297                                 x= ibuf->x/space;
01298                                 y= ibuf->y;
01299                                 
01300                                 if(x>y) ob->size[0]= ob->size[1]*x/y;
01301                                 else ob->size[1]= ob->size[0]*y/x;
01302                                 
01303                                 done= 1;
01304                                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);                               
01305                             }
01306                         }
01307                         if(done) break;
01308                     }
01309                 }
01310                 if(done) break;
01311             }
01312         }
01313     }
01314     
01315 }
01316 
01317 
01318 static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
01319 {   
01320     EnumPropertyItem *input = object_mode_items;
01321     EnumPropertyItem *item= NULL;
01322     Object *ob;
01323     int totitem= 0;
01324     
01325     if(!C) /* needed for docs */
01326         return object_mode_items;
01327 
01328     ob = CTX_data_active_object(C);
01329     while(ob && input->identifier) {
01330         if((input->value == OB_MODE_EDIT && ((ob->type == OB_MESH) || (ob->type == OB_ARMATURE) ||
01331                             (ob->type == OB_CURVE) || (ob->type == OB_SURF) ||
01332                              (ob->type == OB_FONT) || (ob->type == OB_MBALL) || (ob->type == OB_LATTICE))) ||
01333            (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
01334            (input->value == OB_MODE_PARTICLE_EDIT && ob->particlesystem.first) ||
01335            ((input->value == OB_MODE_SCULPT || input->value == OB_MODE_VERTEX_PAINT ||
01336              input->value == OB_MODE_WEIGHT_PAINT || input->value == OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
01337            (input->value == OB_MODE_OBJECT))
01338             RNA_enum_item_add(&item, &totitem, input);
01339         ++input;
01340     }
01341 
01342     RNA_enum_item_end(&item, &totitem);
01343 
01344     *free= 1;
01345 
01346     return item;
01347 }
01348 
01349 static const char *object_mode_op_string(int mode)
01350 {
01351     if(mode & OB_MODE_EDIT)
01352         return "OBJECT_OT_editmode_toggle";
01353     if(mode == OB_MODE_SCULPT)
01354         return "SCULPT_OT_sculptmode_toggle";
01355     if(mode == OB_MODE_VERTEX_PAINT)
01356         return "PAINT_OT_vertex_paint_toggle";
01357     if(mode == OB_MODE_WEIGHT_PAINT)
01358         return "PAINT_OT_weight_paint_toggle";
01359     if(mode == OB_MODE_TEXTURE_PAINT)
01360         return "PAINT_OT_texture_paint_toggle";
01361     if(mode == OB_MODE_PARTICLE_EDIT)
01362         return "PARTICLE_OT_particle_edit_toggle";
01363     if(mode == OB_MODE_POSE)
01364         return "OBJECT_OT_posemode_toggle";
01365     return NULL;
01366 }
01367 
01368 /* checks the mode to be set is compatible with the object
01369  * should be made into a generic function */
01370 static int object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob)
01371 {
01372     ObjectMode mode = RNA_enum_get(op->ptr, "mode");
01373 
01374     if(ob) {
01375         if(mode == OB_MODE_OBJECT)
01376             return 1;
01377 
01378         switch(ob->type) {
01379         case OB_MESH:
01380             if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT))
01381                 return 1;
01382             return 0;
01383         case OB_CURVE:
01384         case OB_SURF:
01385         case OB_FONT:
01386         case OB_MBALL:
01387             if(mode & (OB_MODE_EDIT))
01388                 return 1;
01389             return 0;
01390         case OB_LATTICE:
01391             if(mode & (OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT))
01392                 return 1;
01393         case OB_ARMATURE:
01394             if(mode & (OB_MODE_EDIT|OB_MODE_POSE))
01395                 return 1;
01396         }
01397     }
01398 
01399     return 0;
01400 }
01401 
01402 static int object_mode_set_exec(bContext *C, wmOperator *op)
01403 {
01404     Object *ob= CTX_data_active_object(C);
01405     ObjectMode mode = RNA_enum_get(op->ptr, "mode");
01406     ObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
01407     int toggle = RNA_boolean_get(op->ptr, "toggle");
01408 
01409     if(!ob || !object_mode_set_compat(C, op, ob))
01410         return OPERATOR_PASS_THROUGH;
01411 
01412     /* Exit current mode if it's not the mode we're setting */
01413     if(ob->mode != OB_MODE_OBJECT && ob->mode != mode)
01414         WM_operator_name_call(C, object_mode_op_string(ob->mode), WM_OP_EXEC_REGION_WIN, NULL);
01415 
01416     if(mode != OB_MODE_OBJECT) {
01417         /* Enter new mode */
01418         if(ob->mode != mode || toggle)
01419             WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
01420 
01421         if(toggle) {
01422             if(ob->mode == mode)
01423                 /* For toggling, store old mode so we know what to go back to */
01424                 ob->restore_mode = restore_mode;
01425             else if(ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
01426                 WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
01427             }
01428         }
01429     }
01430 
01431     return OPERATOR_FINISHED;
01432 }
01433 
01434 void OBJECT_OT_mode_set(wmOperatorType *ot)
01435 {
01436     PropertyRNA *prop;
01437 
01438     /* identifiers */
01439     ot->name= "Set Object Mode";
01440     ot->description = "Sets the object interaction mode";
01441     ot->idname= "OBJECT_OT_mode_set";
01442     
01443     /* api callbacks */
01444     ot->exec= object_mode_set_exec;
01445     
01446     ot->poll= ED_operator_object_active_editable;
01447     
01448     /* flags */
01449     ot->flag= 0; /* no register/undo here, leave it to operators being called */
01450     
01451     prop= RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", "");
01452     RNA_def_enum_funcs(prop, object_mode_set_itemsf);
01453 
01454     RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
01455 }
01456 
01457 
01458 
01459 void ED_object_toggle_modes(bContext *C, int mode)
01460 {
01461     if(mode & OB_MODE_SCULPT)
01462         WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01463     if(mode & OB_MODE_VERTEX_PAINT)
01464         WM_operator_name_call(C, "PAINT_OT_vertex_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01465     if(mode & OB_MODE_WEIGHT_PAINT)
01466         WM_operator_name_call(C, "PAINT_OT_weight_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01467     if(mode & OB_MODE_TEXTURE_PAINT)
01468         WM_operator_name_call(C, "PAINT_OT_texture_paint_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01469     if(mode & OB_MODE_PARTICLE_EDIT)
01470         WM_operator_name_call(C, "PARTICLE_OT_particle_edit_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01471     if(mode & OB_MODE_POSE)
01472         WM_operator_name_call(C, "OBJECT_OT_posemode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01473     if(mode & OB_MODE_EDIT)
01474         WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
01475 }
01476 
01477 /************************ Game Properties ***********************/
01478 
01479 static int game_property_new(bContext *C, wmOperator *op)
01480 {
01481     Object *ob= CTX_data_active_object(C);
01482     bProperty *prop;
01483     char name[MAX_NAME];
01484     int type= RNA_enum_get(op->ptr, "type");
01485 
01486     prop= new_property(type);
01487     BLI_addtail(&ob->prop, prop);
01488 
01489     RNA_string_get(op->ptr, "name", name);
01490     if (name[0] != '\0') {
01491         BLI_strncpy(prop->name, name, sizeof(prop->name));
01492     }
01493 
01494     unique_property(NULL, prop, 0); // make_unique_prop_names(prop->name);
01495 
01496     WM_event_add_notifier(C, NC_LOGIC, NULL);
01497     return OPERATOR_FINISHED;
01498 }
01499 
01500 
01501 void OBJECT_OT_game_property_new(wmOperatorType *ot)
01502 {
01503     /* identifiers */
01504     ot->name= "New Game Property";
01505     ot->description= "Create a new property available to the game engine";
01506     ot->idname= "OBJECT_OT_game_property_new";
01507 
01508     /* api callbacks */
01509     ot->exec= game_property_new;
01510     ot->poll= ED_operator_object_active_editable;
01511 
01512     /* flags */
01513     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01514 
01515     RNA_def_enum(ot->srna, "type", gameproperty_type_items, 2, "Type", "Type of game property to add");
01516     RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the game property to add");
01517 }
01518 
01519 static int game_property_remove(bContext *C, wmOperator *op)
01520 {
01521     Object *ob= CTX_data_active_object(C);
01522     bProperty *prop;
01523     int index= RNA_int_get(op->ptr, "index");
01524 
01525     if(!ob)
01526         return OPERATOR_CANCELLED;
01527 
01528     prop= BLI_findlink(&ob->prop, index);
01529 
01530     if(prop) {
01531         BLI_remlink(&ob->prop, prop);
01532         free_property(prop);
01533 
01534         WM_event_add_notifier(C, NC_LOGIC, NULL);
01535         return OPERATOR_FINISHED;
01536     }
01537     else {
01538         return OPERATOR_CANCELLED;
01539     }
01540 }
01541 
01542 void OBJECT_OT_game_property_remove(wmOperatorType *ot)
01543 {
01544     /* identifiers */
01545     ot->name= "Remove Game Property";
01546     ot->description= "Remove game property";
01547     ot->idname= "OBJECT_OT_game_property_remove";
01548 
01549     /* api callbacks */
01550     ot->exec= game_property_remove;
01551     ot->poll= ED_operator_object_active_editable;
01552 
01553     /* flags */
01554     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01555 
01556     RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX);
01557 }
01558 
01559 #define COPY_PROPERTIES_REPLACE 1
01560 #define COPY_PROPERTIES_MERGE   2
01561 #define COPY_PROPERTIES_COPY    3
01562 
01563 static EnumPropertyItem game_properties_copy_operations[] ={
01564     {COPY_PROPERTIES_REPLACE, "REPLACE", 0, "Replace Properties", ""},
01565     {COPY_PROPERTIES_MERGE, "MERGE", 0, "Merge Properties", ""},
01566     {COPY_PROPERTIES_COPY, "COPY", 0, "Copy a Property", ""},
01567     {0, NULL, 0, NULL, NULL}};
01568 
01569 static EnumPropertyItem gameprops_items[]= {
01570     {0, NULL, 0, NULL, NULL}};
01571 
01572 static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
01573 {   
01574     Object *ob= ED_object_active_context(C);
01575     EnumPropertyItem tmp = {0, "", 0, "", ""};
01576     EnumPropertyItem *item= NULL;
01577     bProperty *prop;
01578     int a, totitem= 0;
01579     
01580     if(!ob)
01581         return gameprops_items;
01582 
01583     for(a=1, prop= ob->prop.first; prop; prop=prop->next, a++) {
01584         tmp.value= a;
01585         tmp.identifier= prop->name;
01586         tmp.name= prop->name;
01587         RNA_enum_item_add(&item, &totitem, &tmp);
01588     }
01589 
01590     RNA_enum_item_end(&item, &totitem);
01591     *free= 1;
01592 
01593     return item;
01594 }
01595 
01596 static int game_property_copy_exec(bContext *C, wmOperator *op)
01597 {
01598     Object *ob=ED_object_active_context(C);
01599     bProperty *prop;
01600     int type = RNA_enum_get(op->ptr, "operation");
01601     int propid= RNA_enum_get(op->ptr, "property");
01602 
01603     if(propid > 0) { /* copy */
01604         prop = BLI_findlink(&ob->prop, propid-1);
01605         
01606         if(prop) {
01607             CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
01608                 if (ob != ob_iter)
01609                     set_ob_property(ob_iter, prop);
01610             } CTX_DATA_END;
01611         }
01612     }
01613 
01614     else {
01615         CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
01616             if (ob != ob_iter) {
01617                 if (type == COPY_PROPERTIES_REPLACE)
01618                     copy_properties(&ob_iter->prop, &ob->prop);
01619 
01620                 /* merge - the default when calling with no argument */
01621                 else
01622                     for(prop = ob->prop.first; prop; prop= prop->next)
01623                         set_ob_property(ob_iter, prop);
01624             }
01625         }
01626         CTX_DATA_END;
01627     }
01628 
01629     return OPERATOR_FINISHED;
01630 }
01631 
01632 void OBJECT_OT_game_property_copy(wmOperatorType *ot)
01633 {
01634     PropertyRNA *prop;
01635     /* identifiers */
01636     ot->name= "Copy Game Property";
01637     ot->idname= "OBJECT_OT_game_property_copy";
01638 
01639     /* api callbacks */
01640     ot->exec= game_property_copy_exec;
01641     ot->poll= ED_operator_object_active_editable;
01642 
01643     /* flags */
01644     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01645 
01646     RNA_def_enum(ot->srna, "operation", game_properties_copy_operations, 3, "Operation", "");
01647     prop=RNA_def_enum(ot->srna, "property", gameprops_items, 0, "Property", "Properties to copy");
01648     RNA_def_enum_funcs(prop, gameprops_itemf);
01649     ot->prop=prop;
01650 }
01651 
01652 static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op))
01653 {
01654     CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
01655         free_properties(&ob_iter->prop);
01656     }
01657     CTX_DATA_END;
01658 
01659     WM_event_add_notifier(C, NC_LOGIC, NULL);
01660     return OPERATOR_FINISHED;
01661 }
01662 void OBJECT_OT_game_property_clear(wmOperatorType *ot)
01663 {
01664     /* identifiers */
01665     ot->name= "Clear Game Property";
01666     ot->idname= "OBJECT_OT_game_property_clear";
01667 
01668     /* api callbacks */
01669     ot->exec= game_property_clear_exec;
01670     ot->poll= ED_operator_object_active_editable;
01671 
01672     /* flags */
01673     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01674 }
01675 
01676 /************************ Copy Logic Bricks ***********************/
01677 
01678 static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op))
01679 {
01680     Object *ob=ED_object_active_context(C);
01681 
01682     CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
01683         if(ob != ob_iter) {
01684             /* first: free all logic */
01685             free_sensors(&ob_iter->sensors);                
01686             unlink_controllers(&ob_iter->controllers);
01687             free_controllers(&ob_iter->controllers);
01688             unlink_actuators(&ob_iter->actuators);
01689             free_actuators(&ob_iter->actuators);
01690         
01691             /* now copy it, this also works without logicbricks! */
01692             clear_sca_new_poins_ob(ob);
01693             copy_sensors(&ob_iter->sensors, &ob->sensors);
01694             copy_controllers(&ob_iter->controllers, &ob->controllers);
01695             copy_actuators(&ob_iter->actuators, &ob->actuators);
01696             set_sca_new_poins_ob(ob_iter);
01697         
01698             /* some menu settings */
01699             ob_iter->scavisflag= ob->scavisflag;
01700             ob_iter->scaflag= ob->scaflag;
01701         
01702             /* set the initial state */
01703             ob_iter->state= ob->state;
01704             ob_iter->init_state= ob->init_state;
01705 
01706             if(ob_iter->totcol==ob->totcol) {
01707                 ob_iter->actcol= ob->actcol;
01708                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob_iter);
01709             }
01710         }
01711     }
01712     CTX_DATA_END;
01713 
01714     WM_event_add_notifier(C, NC_LOGIC, NULL);
01715 
01716     return OPERATOR_FINISHED;
01717 }
01718 
01719 void OBJECT_OT_logic_bricks_copy(wmOperatorType *ot)
01720 {
01721     /* identifiers */
01722     ot->name= "Copy Logic Bricks to Selected";
01723     ot->description = "Copy logic bricks to other selected objects";
01724     ot->idname= "OBJECT_OT_logic_bricks_copy";
01725 
01726     /* api callbacks */
01727     ot->exec= logicbricks_copy_exec;
01728     ot->poll= ED_operator_object_active_editable;
01729 
01730     /* flags */
01731     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01732 }
01733 
01734 static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
01735 {
01736     Object *ob=ED_object_active_context(C);
01737     
01738     CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
01739         if(ob != ob_iter) {
01740             ob_iter->gameflag = ob->gameflag;
01741             ob_iter->gameflag2 = ob->gameflag2;
01742             ob_iter->inertia = ob->inertia;
01743             ob_iter->formfactor = ob->formfactor;;
01744             ob_iter->damping = ob->damping;
01745             ob_iter->rdamping = ob->rdamping;
01746             ob_iter->min_vel = ob->min_vel;
01747             ob_iter->max_vel = ob->max_vel;
01748             ob_iter->obstacleRad = ob->obstacleRad;
01749             ob_iter->mass = ob->mass;
01750             ob_iter->anisotropicFriction[0] = ob->anisotropicFriction[0];
01751             ob_iter->anisotropicFriction[1] = ob->anisotropicFriction[1];
01752             ob_iter->anisotropicFriction[2] = ob->anisotropicFriction[2];
01753             ob_iter->collision_boundtype = ob->collision_boundtype;         
01754             ob_iter->margin = ob->margin;
01755             ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft);
01756             if(ob->restrictflag & OB_RESTRICT_RENDER) 
01757                 ob_iter->restrictflag |= OB_RESTRICT_RENDER;
01758              else
01759                 ob_iter->restrictflag &= ~OB_RESTRICT_RENDER;
01760         }
01761     }
01762     CTX_DATA_END;
01763     
01764     return OPERATOR_FINISHED;
01765 }
01766 
01767 void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
01768 {
01769     /* identifiers */
01770     ot->name= "Copy Game Physics Properties to Selected";
01771     ot->description = "Copy game physics properties to other selected objects";
01772     ot->idname= "OBJECT_OT_game_physics_copy";
01773     
01774     /* api callbacks */
01775     ot->exec= game_physics_copy_exec;
01776     ot->poll= ED_operator_object_active_editable;
01777     
01778     /* flags */
01779     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01780 }