merge with/from trunk at r35190
[blender.git] / source / blender / editors / object / object_edit.c
index 8a0fc56fa874a6f4495508ac88bea1fcd6d87a85..ba336ad388ca7bc15d321555edc6cbf99680d554 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -36,6 +36,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_utildefines.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 #include "BLI_rand.h"
@@ -49,6 +50,7 @@
 #include "DNA_property_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
+#include "DNA_object_force.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_vfont_types.h"
 
@@ -58,6 +60,7 @@
 #include "BKE_constraint.h"
 #include "BKE_context.h"
 #include "BKE_curve.h"
+#include "BKE_effect.h"
 #include "BKE_depsgraph.h"
 #include "BKE_font.h"
 #include "BKE_image.h"
 #include "object_intern.h"     // own include
 
 /* ************* XXX **************** */
-static void error(const char *dummy) {}
-static void waitcursor(int val) {}
-static int pupmenu(const char *msg) {return 0;}
+static void error(const char *UNUSED(arg)) {}
+static void waitcursor(int UNUSED(val)) {}
+static int pupmenu(const char *UNUSED(msg)) {return 0;}
 
 /* port over here */
-static bContext *C;
-static void error_libdata() {}
+static bContext *evil_C;
+static void error_libdata(void) {}
 
 
 /* find the correct active object per context
@@ -121,7 +124,7 @@ Object *ED_object_active_context(bContext *C)
 
 
 /* ********* clear/set restrict view *********/
-static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
+static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Main *bmain= CTX_data_main(C);
        ScrArea *sa= CTX_wm_area(C);
@@ -168,7 +171,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
        Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C);
        short changed = 0;
-       int unselected= RNA_boolean_get(op->ptr, "unselected");
+       const int unselected= RNA_boolean_get(op->ptr, "unselected");
        
        CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
                if(!unselected) {
@@ -220,7 +223,7 @@ void OBJECT_OT_hide_view_set(wmOperatorType *ot)
 }
 
 /* 99% same as above except no need for scene refreshing (TODO, update render preview) */
-static int object_hide_render_clear_exec(bContext *C, wmOperator *op)
+static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
 {
        short changed= 0;
 
@@ -257,7 +260,7 @@ void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
 
 static int object_hide_render_set_exec(bContext *C, wmOperator *op)
 {
-       int unselected= RNA_boolean_get(op->ptr, "unselected");
+       const int unselected= RNA_boolean_get(op->ptr, "unselected");
 
        CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
                if(!unselected) {
@@ -326,11 +329,12 @@ void ED_object_exit_editmode(bContext *C, int flag)
                        MEM_freeN(me->edit_btmesh);
                        me->edit_btmesh= NULL;
                }
-               
+#if 0 //BMESH_TODO             
                if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
                        mesh_octree_table(NULL, NULL, NULL, 'e');
                        mesh_mirrtopo_table(NULL, 'e');
                }
+#endif
        }
        else if (obedit->type==OB_ARMATURE) {   
                ED_armature_from_edit(obedit);
@@ -373,7 +377,7 @@ void ED_object_exit_editmode(bContext *C, int flag)
                BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_DEPSGRAPH);
 
                /* also flush ob recalc, doesn't take much overhead, but used for particles */
-               DAG_id_flush_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
+               DAG_id_tag_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
        
                if(flag & EM_DO_UNDO)
                        ED_undo_push(C, "Editmode");
@@ -435,7 +439,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
        if(ob->type==OB_MESH) {
                Mesh *me= ob->data;
                
-               if(me->pv) mesh_pmv_off(ob, me);
+               if(me->pv) mesh_pmv_off(me);
                ok= 1;
                scene->obedit= ob;      // context sees this
                
@@ -462,7 +466,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
                scene->obedit= ob;
                ED_armature_to_edit(ob);
                /* to ensure all goes in restposition and without striding */
-               DAG_id_flush_update(&ob->id, OB_RECALC_ALL); // XXX: should this be OB_RECALC_DATA?
+               DAG_id_tag_update(&ob->id, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); // XXX: should this be OB_RECALC_DATA?
 
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, scene);
        }
@@ -496,7 +500,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
        }
        
        if(ok) {
-               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
        else {
                scene->obedit= NULL; // XXX for context
@@ -508,12 +512,12 @@ void ED_object_enter_editmode(bContext *C, int flag)
        if(flag & EM_WAITCURSOR) waitcursor(0);
 }
 
-static int editmode_toggle_exec(bContext *C, wmOperator *op)
+static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 {
        if(!CTX_data_edit_object(C))
                ED_object_enter_editmode(C, EM_WAITCURSOR);
        else
-               ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO);
+               ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
        
        return OPERATOR_FINISHED;
 }
@@ -526,7 +530,10 @@ static int editmode_toggle_poll(bContext *C)
        if(ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib)
                return 0;
 
-       return ob && (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
+       if (ob->restrictflag & OB_RESTRICT_VIEW)
+               return 0;
+
+       return (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
                          ob->type == OB_FONT || ob->type == OB_MBALL ||
                          ob->type == OB_LATTICE || ob->type == OB_SURF ||
                          ob->type == OB_CURVE);
@@ -551,7 +558,7 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
 
 /* *************************** */
 
-static int posemode_exec(bContext *C, wmOperator *op)
+static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Base *base= CTX_data_active_base(C);
        
@@ -583,20 +590,11 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
        ot->poll= ED_operator_object_active_editable;
        
        /* flag */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* *********************** */
 
-void check_editmode(int type)
-{
-       Object *obedit= NULL; // XXX
-       
-       if (obedit==NULL || obedit->type==type) return;
-
-// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO); /* freedata, and undo */
-}
-
 #if 0
 // XXX should be in view3d?
 
@@ -721,7 +719,7 @@ static void spot_interactive(Object *ob, int mode)
 }
 #endif
 
-void special_editmenu(Scene *scene, View3D *v3d)
+static void special_editmenu(Scene *scene, View3D *v3d)
 {
 // XXX static short numcuts= 2;
        Object *ob= OBACT;
@@ -740,9 +738,9 @@ void special_editmenu(Scene *scene, View3D *v3d)
                        MTFace *tface;
                        MFace *mface;
                        int a;
-                       
-                       if(me==0 || me->mtface==0) return;
-                       
+
+                       if(me==NULL || me->mtface==NULL) return;
+
                        nr= pupmenu("Specials%t|Set     Tex%x1|         Shared%x2|         Light%x3|         Invisible%x4|         Collision%x5|         TwoSide%x6|Clr     Tex%x7|         Shared%x8|         Light%x9|         Invisible%x10|         Collision%x11|         TwoSide%x12");
                        
                        tface= me->mtface;
@@ -764,7 +762,7 @@ void special_editmenu(Scene *scene, View3D *v3d)
                                                tface->mode |= TF_TWOSIDE; break;
                                        case 7:
                                                tface->mode &= ~TF_TEX;
-                                               tface->tpage= 0;
+                                               tface->tpage= NULL;
                                                break;
                                        case 8:
                                                tface->mode &= ~TF_SHAREDCOL; break;
@@ -779,19 +777,19 @@ void special_editmenu(Scene *scene, View3D *v3d)
                                        }
                                }
                        }
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
                else if(ob->mode & OB_MODE_VERTEX_PAINT) {
                        Mesh *me= get_mesh(ob);
                        
-                       if(me==0 || (me->mcol==NULL && me->mtface==NULL) ) return;
+                       if(me==NULL || (me->mcol==NULL && me->mtface==NULL) ) return;
                        
                        nr= pupmenu("Specials%t|Shared VertexCol%x1");
                        if(nr==1) {
                                
 // XXX                         do_shared_vertexcol(me);
                                
-                               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        }
                }
                else if(ob->mode & OB_MODE_WEIGHT_PAINT) {
@@ -838,7 +836,7 @@ void special_editmenu(Scene *scene, View3D *v3d)
                                break;
                        }
                        
-                       DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
                        
                        if(nr>0) waitcursor(0);
 #endif
@@ -1054,7 +1052,7 @@ static void copymenu_modifiers(Main *bmain, Scene *scene, View3D *v3d, Object *o
        Base *base;
        int i, event;
        char str[512];
-       char *errorstr= NULL;
+       const char *errorstr= NULL;
 
        strcpy(str, "Copy Modifiers %t");
 
@@ -1080,13 +1078,13 @@ static void copymenu_modifiers(Main *bmain, Scene *scene, View3D *v3d, Object *o
        for (base= FIRSTBASE; base; base= base->next) {
                if(base->object != ob) {
                        if(TESTBASELIB(v3d, base)) {
-                               ModifierData *md;
 
                                base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
 
                                if (base->object->type==ob->type) {
                                        /* copy all */
                                        if (event==NUM_MODIFIER_TYPES) {
+                                               ModifierData *md;
                                                object_free_modifiers(base->object);
 
                                                for (md=ob->modifiers.first; md; md=md->next) {
@@ -1196,7 +1194,7 @@ static void copy_texture_space(Object *to, Object *ob)
        
 }
 
-void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
+static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
 {
        Object *ob;
        Base *base;
@@ -1237,9 +1235,9 @@ void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
                                else if(event==2) {  /* rot */
                                        VECCOPY(base->object->rot, ob->rot);
                                        VECCOPY(base->object->drot, ob->drot);
-                                       /* Quats arnt used yet */
-                                       /*VECCOPY(base->object->quat, ob->quat);
-                                       VECCOPY(base->object->dquat, ob->dquat);*/
+
+                                       QUATCOPY(base->object->quat, ob->quat);
+                                       QUATCOPY(base->object->dquat, ob->dquat);
                                }
                                else if(event==3) {  /* size */
                                        VECCOPY(base->object->size, ob->size);
@@ -1325,7 +1323,7 @@ void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
                                                BKE_text_to_curve(scene, base->object, 0);              /* needed? */
 
                                                
-                                               strcpy(cu1->family, cu->family);
+                                               BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
                                                
                                                base->object->recalc |= OB_RECALC_DATA;
                                        }
@@ -1444,7 +1442,7 @@ void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
        DAG_ids_flush_update(bmain, 0);
 }
 
-void copy_attr_menu(Main *bmain, Scene *scene, View3D *v3d)
+static void copy_attr_menu(Main *bmain, Scene *scene, View3D *v3d)
 {
        Object *ob;
        short event;
@@ -1498,6 +1496,39 @@ void copy_attr_menu(Main *bmain, Scene *scene, View3D *v3d)
        copy_attr(bmain, scene, v3d, event);
 }
 
+/* ******************* force field toggle operator ***************** */
+
+static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Object *ob = CTX_data_active_object(C);
+
+       if(ob->pd == NULL)
+               ob->pd = object_add_collision_fields(PFIELD_FORCE);
+
+       if(ob->pd->forcefield == 0)
+               ob->pd->forcefield = PFIELD_FORCE;
+       else
+               ob->pd->forcefield = 0;
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Toggle Force Field";
+       ot->description = "Toggle object's force field";
+       ot->idname= "OBJECT_OT_forcefield_toggle";
+       
+       /* api callbacks */
+       ot->exec= forcefield_toggle_exec;
+       ot->poll= ED_operator_object_active_editable;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /* ********************************************** */
 /* Motion Paths */
 
@@ -1527,7 +1558,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
 /* For the object with pose/action: create path curves for selected bones 
  * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
  */
-static int object_calculate_paths_exec (bContext *C, wmOperator *op)
+static int object_calculate_paths_exec (bContext *C, wmOperator *UNUSED(op))
 {
        Scene *scene= CTX_data_scene(C);
        
@@ -1567,7 +1598,7 @@ void OBJECT_OT_paths_calculate (wmOperatorType *ot)
 /* --------- */
 
 /* for the object with pose/action: clear path curves for selected bones only */
-void ED_objects_clear_paths(bContext *C, Scene *scene)
+void ED_objects_clear_paths(bContext *C)
 {
        /* loop over objects in scene */
        CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 
@@ -1582,12 +1613,10 @@ void ED_objects_clear_paths(bContext *C, Scene *scene)
 }
 
 /* operator callback for this */
-static int object_clear_paths_exec (bContext *C, wmOperator *op)
-{
-       Scene *scene= CTX_data_scene(C);
-       
+static int object_clear_paths_exec (bContext *C, wmOperator *UNUSED(op))
+{      
        /* use the backend function for this */
-       ED_objects_clear_paths(C, scene);
+       ED_objects_clear_paths(C);
        
        /* notifiers for updates */
        WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
@@ -1625,7 +1654,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
                if(ob->type==OB_MESH) {
                        mesh_set_smooth_flag(ob, !clear);
 
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
 
                        done= 1;
@@ -1638,7 +1667,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
                                else nu->flag &= ~ME_SMOOTH;
                        }
 
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
 
                        done= 1;
@@ -1684,7 +1713,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
 
 /* ********************** */
 
-void image_aspect(Scene *scene, View3D *v3d)
+static void image_aspect(Scene *scene, View3D *v3d)
 {
        /* all selected objects with an image map: scale in image aspect */
        Base *base;
@@ -1730,7 +1759,7 @@ void image_aspect(Scene *scene, View3D *v3d)
                                                                else ob->size[1]= ob->size[0]*y/x;
                                                                
                                                                done= 1;
-                                                               DAG_id_flush_update(&ob->id, OB_RECALC_OB);                                                             
+                                                               DAG_id_tag_update(&ob->id, OB_RECALC_OB);                                                               
                                                        }
                                                }
                                                if(done) break;
@@ -1743,7 +1772,7 @@ void image_aspect(Scene *scene, View3D *v3d)
        
 }
 
-int vergbaseco(const void *a1, const void *a2)
+static int vergbaseco(const void *a1, const void *a2)
 {
        Base **x1, **x2;
        
@@ -1759,7 +1788,7 @@ int vergbaseco(const void *a1, const void *a2)
 }
 
 
-void auto_timeoffs(Scene *scene, View3D *v3d)
+static void auto_timeoffs(Scene *scene, View3D *v3d)
 {
        Base *base, **basesort, **bs;
        float start, delta;
@@ -1800,7 +1829,7 @@ void auto_timeoffs(Scene *scene, View3D *v3d)
 
 }
 
-void ofs_timeoffs(Scene *scene, View3D *v3d)
+static void ofs_timeoffs(Scene *scene, View3D *v3d)
 {
        float offset=0.0f;
 
@@ -1809,7 +1838,7 @@ void ofs_timeoffs(Scene *scene, View3D *v3d)
 // XXX if(fbutton(&offset, -10000.0f, 10000.0f, 10, 10, "Offset")==0) return;
 
        /* make array of all bases, xco yco (screen) */
-       CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+       CTX_DATA_BEGIN(evil_C, Object*, ob, selected_editable_objects) {
                ob->sf += offset;
                if (ob->sf < -MAXFRAMEF)                ob->sf = -MAXFRAMEF;
                else if (ob->sf > MAXFRAMEF)    ob->sf = MAXFRAMEF;
@@ -1819,20 +1848,20 @@ void ofs_timeoffs(Scene *scene, View3D *v3d)
 }
 
 
-void rand_timeoffs(Scene *scene, View3D *v3d)
+static void rand_timeoffs(Scene *scene, View3D *v3d)
 {
        Base *base;
-       float rand=0.0f;
+       float rand_ofs=0.0f;
 
        if(BASACT==0 || v3d==NULL) return;
        
-// XXX if(fbutton(&rand, 0.0f, 10000.0f, 10, 10, "Randomize")==0) return;
+// XXX if(fbutton(&rand_ofs, 0.0f, 10000.0f, 10, 10, "Randomize")==0) return;
        
-       rand *= 2;
+       rand_ofs *= 2;
        
        for(base= FIRSTBASE; base; base= base->next) {
                if(TESTBASELIB(v3d, base)) {
-                       base->object->sf += (BLI_drand()-0.5) * rand;
+                       base->object->sf += (BLI_drand()-0.5) * rand_ofs;
                        if (base->object->sf < -MAXFRAMEF)              base->object->sf = -MAXFRAMEF;
                        else if (base->object->sf > MAXFRAMEF)  base->object->sf = MAXFRAMEF;
                }
@@ -1840,7 +1869,7 @@ void rand_timeoffs(Scene *scene, View3D *v3d)
 
 }
 
-static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *ptr, int *free)
+static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), int *free)
 {      
        EnumPropertyItem *input = object_mode_items;
        EnumPropertyItem *item= NULL;
@@ -1892,7 +1921,7 @@ static const char *object_mode_op_string(int mode)
 
 /* checks the mode to be set is compatible with the object
  * should be made into a generic function */
-static int object_mode_set_compat(bContext *C, wmOperator *op, Object *ob)
+static int object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob)
 {
        ObjectMode mode = RNA_enum_get(op->ptr, "mode");
 
@@ -2006,7 +2035,7 @@ void ED_object_toggle_modes(bContext *C, int mode)
 
 /************************ Game Properties ***********************/
 
-static int game_property_new(bContext *C, wmOperator *op)
+static int game_property_new(bContext *C, wmOperator *UNUSED(op))
 {
        Object *ob= CTX_data_active_object(C);
        bProperty *prop;
@@ -2089,7 +2118,7 @@ static EnumPropertyItem game_properties_copy_operations[] ={
 static EnumPropertyItem gameprops_items[]= {
        {0, NULL, 0, NULL, NULL}};
 
-static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *ptr, int *free)
+static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), int *free)
 {      
        Object *ob= ED_object_active_context(C);
        EnumPropertyItem tmp = {0, "", 0, "", ""};
@@ -2171,7 +2200,7 @@ void OBJECT_OT_game_property_copy(wmOperatorType *ot)
        ot->prop=prop;
 }
 
-static int game_property_clear_exec(bContext *C, wmOperator *op)
+static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op))
 {
        CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
                free_properties(&ob_iter->prop);
@@ -2197,35 +2226,34 @@ void OBJECT_OT_game_property_clear(wmOperatorType *ot)
 
 /************************ Copy Logic Bricks ***********************/
 
-static int logicbricks_copy_exec(bContext *C, wmOperator *op)
+static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Object *ob=ED_object_active_context(C);
 
        CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
                if(ob != ob_iter) {
-                       if (ob->data != ob_iter->data){
-                               /* first: free all logic */
-                               free_sensors(&ob_iter->sensors);                                
-                               unlink_controllers(&ob_iter->controllers);
-                               free_controllers(&ob_iter->controllers);
-                               unlink_actuators(&ob_iter->actuators);
-                               free_actuators(&ob_iter->actuators);
-                       
-                               /* now copy it, this also works without logicbricks! */
-                               clear_sca_new_poins_ob(ob);
-                               copy_sensors(&ob_iter->sensors, &ob->sensors);
-                               copy_controllers(&ob_iter->controllers, &ob->controllers);
-                               copy_actuators(&ob_iter->actuators, &ob->actuators);
-                               set_sca_new_poins_ob(ob_iter);
-                       
-                               /* some menu settings */
-                               ob_iter->scavisflag= ob->scavisflag;
-                               ob_iter->scaflag= ob->scaflag;
-                       
-                               /* set the initial state */
-                               ob_iter->state= ob->state;
-                               ob_iter->init_state= ob->init_state;
-                       }                       
+                       /* first: free all logic */
+                       free_sensors(&ob_iter->sensors);                                
+                       unlink_controllers(&ob_iter->controllers);
+                       free_controllers(&ob_iter->controllers);
+                       unlink_actuators(&ob_iter->actuators);
+                       free_actuators(&ob_iter->actuators);
+               
+                       /* now copy it, this also works without logicbricks! */
+                       clear_sca_new_poins_ob(ob);
+                       copy_sensors(&ob_iter->sensors, &ob->sensors);
+                       copy_controllers(&ob_iter->controllers, &ob->controllers);
+                       copy_actuators(&ob_iter->actuators, &ob->actuators);
+                       set_sca_new_poins_ob(ob_iter);
+               
+                       /* some menu settings */
+                       ob_iter->scavisflag= ob->scavisflag;
+                       ob_iter->scaflag= ob->scaflag;
+               
+                       /* set the initial state */
+                       ob_iter->state= ob->state;
+                       ob_iter->init_state= ob->init_state;
+
                        if(ob_iter->totcol==ob->totcol) {
                                ob_iter->actcol= ob->actcol;
                                WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob_iter);