Reserved some Bullet 2.x constraint data.
authorErwin Coumans <blender@erwincoumans.com>
Thu, 30 Nov 2006 00:19:27 +0000 (00:19 +0000)
committerErwin Coumans <blender@erwincoumans.com>
Thu, 30 Nov 2006 00:19:27 +0000 (00:19 +0000)
Although we will delay the main Rigid Body user interface after 2.43 release early 2007, I need some constraint data/UI to make progress with COLLADA Physics.
Added RigidBody constraint UI
LR_ALTKEY+LR_CTRLKEY+LR_SHIFTKEY+ P will bake rigidbody
Contribution by RCRuiz, Ramon Carlos.

15 files changed:
source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/src/buttons_object.c
source/blender/src/space.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.h
source/gameengine/GamePlayer/ghost/GPG_Application.cpp
source/gameengine/Ketsji/KX_ISceneConverter.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_KetsjiEngine.h

index d299acb..d471e9c 100644 (file)
@@ -723,7 +723,40 @@ void *new_constraint_data (short type)
                        result = data;
                }
                break;
-       default:
+    case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+               {
+                       bRigidBodyJointConstraint *data;
+                       int i;
+                       Base *base_iter;
+
+                       data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
+                       base_iter = G.scene->base.first;
+            while( base_iter && !data->tar ) {
+                if( ( ( base_iter->flag & SELECT ) &&
+//                    ( base_iter->lay & G.vd->lay ) ) &&
+                    ( base_iter != G.scene->basact ) )
+                    )
+                        data->tar=base_iter->object;
+                base_iter = base_iter->next;
+            }
+            data->type=1;
+            data->pivX=0.0;
+            data->pivY=0.0;
+            data->pivZ=0.0;
+            data->axX=0.0;
+            data->axY=0.0;
+            data->axZ=1.0;
+                       for (i=0;i<6;i++)
+                       {
+                               data->minLimit[i]=0.0;
+                               data->maxLimit[i]=0.0;
+                       }
+            data->extraFz=0.0;
+                       result = data;
+               }
+               break;
+  
+       default:
                result = NULL;
                break;
        }
@@ -2014,6 +2047,12 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                        VecMulf(ob->obmat[2], size[2]/obsize[2]);
                }
                break;
+       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+        {
+
+
+        }
+        break;         
        default:
                printf ("Error: Unknown constraint type\n");
                break;
index c78ad8d..d33fa63 100644 (file)
@@ -1690,6 +1690,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data= ((bSizeLimitConstraint*)con->data);
                        };
                        break;
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+                       {
+                               bRigidBodyJointConstraint *data;
+                               data= ((bRigidBodyJointConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       };
+                       break;
 
                case CONSTRAINT_TYPE_NULL:
                        break;
@@ -6589,6 +6596,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                                break;
                        }
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+                       {
+                               bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                               break;
+                       }
                case CONSTRAINT_TYPE_NULL:
                        break;
                default:
index fa45428..3ca85ee 100644 (file)
@@ -741,6 +741,9 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
                case CONSTRAINT_TYPE_SIZELIMIT:
                        writestruct(wd, DATA, "bSizeLimitConstraint", 1, con->data);
                        break;
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+                       writestruct(wd, DATA, "bRigidBodyJointConstraint", 1, con->data);
+                       break;
                default:
                        break;
                }
index 46c6d7b..44432c4 100644 (file)
@@ -639,6 +639,7 @@ enum {
        B_CONSTRAINT_ADD_LOCLIMIT,
        B_CONSTRAINT_ADD_ROTLIMIT,
        B_CONSTRAINT_ADD_SIZELIMIT,
+       B_CONSTRAINT_ADD_RIGIDBODYJOINT,
        B_CONSTRAINT_INF
 };
 
index fcfbe57..5e220e4 100644 (file)
@@ -194,6 +194,26 @@ typedef struct bSizeLimitConstraint{
        short           pad1;
 } bSizeLimitConstraint;
 
+/* Rigid Body constraint */
+typedef struct bRigidBodyJointConstraint{
+       Object          *tar;
+       Object          *child;
+       int         type;
+       float       pivX;
+       float       pivY;
+       float       pivZ;
+       float       axX;
+       float       axY;
+       float       axZ;
+       float       minLimit[6];
+       float       maxLimit[6];
+       float       extraFz;
+       short           flag;
+       short           pad;
+       short           pad1;
+       short           pad2;
+} bRigidBodyJointConstraint;
+
 /* bConstraint.type */
 #define CONSTRAINT_TYPE_NULL           0
 #define CONSTRAINT_TYPE_CHILDOF                1       /* Unimplemented */
@@ -212,7 +232,7 @@ typedef struct bSizeLimitConstraint{
 #define CONSTRAINT_TYPE_DISTANCELIMIT  14 
 #define CONSTRAINT_TYPE_STRETCHTO      15  /* claiming this to be mine :) is in tuhopuu bjornmose */ 
 #define CONSTRAINT_TYPE_MINMAX      16  /* floor constraint */
-
+#define CONSTRAINT_TYPE_RIGIDBODYJOINT 17 /* rigidbody constraint */
 
 /* bConstraint.flag */
                /* expand for UI */
@@ -298,5 +318,10 @@ typedef struct bSizeLimitConstraint{
 
 #define LIMIT_NOPARENT 0x01
 
+#define CONSTRAINT_RB_BALL             1
+#define CONSTRAINT_RB_HINGE            2
+#define CONSTRAINT_RB_GENERIC6DOF 3
+#define CONSTRAINT_RB_VEHICLE  11
+
 #endif
 
index 39ca370..7733824 100644 (file)
@@ -368,6 +368,9 @@ void get_constraint_typestring (char *str, void *con_v)
        case CONSTRAINT_TYPE_SIZELIMIT:
                strcpy (str, "Limit Scale");
                return;
+       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+               strcpy (str, "Rigid Body");
+               return;
        default:
                strcpy (str, "Unknown");
                return;
@@ -405,6 +408,8 @@ static int get_constraint_col(bConstraint *con)
                return TH_BUT_POPUP;
        case CONSTRAINT_TYPE_SIZELIMIT:
                return TH_BUT_POPUP;
+       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+               return TH_BUT_SETTING;
        default:
                return TH_REDALERT;
        }
@@ -1126,6 +1131,97 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                uiBlockEndAlign(block);
                        }
                        break;
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
+                       {
+                               bRigidBodyJointConstraint *data = con->data;
+                               int togButWidth = 70;
+                               int offsetY = 150;
+                               float extremeLin = 1000.f;
+                               float extremeAngX = 180.f;
+                               float extremeAngY = 45.f;
+                               float extremeAngZ = 45.f;
+
+                               int textButWidth = ((width/2)-togButWidth);
+
+                               uiDefButS(block, MENU, B_SWITCHRENDER, "Joint Types%t|Ball%x1|Hinge%x2|Generic6DOF%x3",//|Extra Force%x6",
+                                                                                               *xco, *yco-25, 150, 18, &data->type, 0, 0, 0, 0, "Choose the joint type");
+                height = 310;
+                               
+                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+                               {
+                                   //uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+                    uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "Child:", *xco, *yco-50, 130, 18, &data->tar, "Child Object");
+                    //if (data->tar)
+                    //    uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "Child:", *xco+135, *yco-50, 130, 18, &data->child, "Child2 Object (if this exist then this object will be the pivot Only)");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot X:", *xco, *yco-75, 130, 18, &data->pivX, -10000, 10000, 100.0, 0.0, "Offset Joint");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot Y:", *xco, *yco-100, 130, 18, &data->pivY, -10000, 10000, 100.0, 0.0, "Offset Joint");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot Z:", *xco, *yco-125, 130, 18, &data->pivZ, -10000, 10000, 100.0, 0.0, "Offset Joint");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Ax X:", *xco+135, *yco-75, 130, 18, &data->axX, -10000, 10000, 100.0, 0.0, "Offset Joint");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Ax Y:", *xco+135, *yco-100, 130, 18, &data->axY, -10000, 10000, 100.0, 0.0, "Offset Joint");
+                    uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Ax Z:", *xco+135, *yco-125, 130, 18, &data->axZ, -10000, 10000, 100.0, 0.0, "Offset Joint");
+
+                                       /* Draw Pairs of LimitToggle+LimitValue */
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "LinMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"min x limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "LinMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"max x limit"); 
+                               uiBlockEndAlign(block); 
+                               offsetY += 20;
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_YMIN, B_CONSTRAINT_TEST, "LinMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"min y limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_YMIN, B_CONSTRAINT_TEST, "LinMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"max y limit"); 
+                               uiBlockEndAlign(block); 
+                               offsetY += 20;
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_ZMIN, B_CONSTRAINT_TEST, "LinMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"min z limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_ZMIN, B_CONSTRAINT_TEST, "LinMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"max z limit"); 
+                               uiBlockEndAlign(block);
+                               offsetY += 20;
+                               
+                                       /* Draw Pairs of LimitToggle+LimitValue */
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_XMAX, B_CONSTRAINT_TEST, "AngMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"min x limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_XMAX, B_CONSTRAINT_TEST, "AngMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"max x limit"); 
+                               uiBlockEndAlign(block); 
+                               offsetY += 20;
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_YMAX, B_CONSTRAINT_TEST, "AngMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"min y limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_YMAX, B_CONSTRAINT_TEST, "AngMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"max y limit"); 
+                               uiBlockEndAlign(block); 
+                               offsetY += 20;
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_ZMAX, B_CONSTRAINT_TEST, "AngMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"min z limit"); 
+                               uiBlockEndAlign(block); 
+                               uiBlockBeginAlign(block); 
+                               uiDefButBitS(block, TOG, LIMIT_ZMAX, B_CONSTRAINT_TEST, "AngMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth-5), 18, &(data->maxLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"max z limit"); 
+                               uiBlockEndAlign(block);
+
+
+                }
+                               
+                       }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        {
                                height = 17;
@@ -1141,7 +1237,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                (*yco)-=(24+height);
        }
 
-       if (con->type!=CONSTRAINT_TYPE_NULL) {
+       if ((con->type!=CONSTRAINT_TYPE_NULL)&&(con->type!=CONSTRAINT_TYPE_RIGIDBODYJOINT)) {
                uiBlockBeginAlign(block);
                uiDefButF(block, NUMSLI, B_CONSTRAINT_INF, "Influence ", *xco, *yco, 197, 20, &(con->enforce), 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
                but = uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Show", *xco+200, *yco, 45, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show constraint's ipo in the Ipo window, adds a channel if not there");
@@ -1190,6 +1286,8 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO,"Stretch To",          0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
 
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_RIGIDBODYJOINT,"Rigid Body Joint", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");//rcruiz
+
        if (ob->flag & OB_POSEMODE) {
                uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
                
@@ -1362,6 +1460,15 @@ void do_constraintbuts(unsigned short event)
                        BIF_undo_push("Add constraint");
                }
                break;
+       case B_CONSTRAINT_ADD_RIGIDBODYJOINT:
+               {
+                       bConstraint *con;
+                       con = add_new_constraint(CONSTRAINT_TYPE_RIGIDBODYJOINT);
+                       add_constraint_to_active(ob, con);
+
+                       BIF_undo_push("Add constraint");
+               }
+               break;
 
        default:
                break;
index b9bce7b..d6307c7 100644 (file)
 
 
 extern void StartKetsjiShell(ScrArea *area, char* startscenename, struct Main* maggie, struct SpaceIpo* sipo,int always_use_expand_framing);
+extern void StartKetsjiShellSimulation(ScrArea *area, char* startscenename, struct Main* maggie, struct SpaceIpo* sipo,int always_use_expand_framing);//rcruiz
 
 /**
  * When the mipmap setting changes, we want to redraw the view right
@@ -541,6 +542,78 @@ void start_game(void)
 #endif
 }
 
+void start_RBSimulation(void)
+{
+#if GAMEBLENDER == 1
+#ifndef NO_KETSJI
+       Scene *sc, *startscene = G.scene;
+       LinkNode *scene_cfra_store;
+
+               /* XXX, silly code -  the game engine can
+                * access any scene through logic, so we try
+                * to make sure each scene has a valid camera,
+                * just in case the game engine tries to use it.
+                *
+                * Better would be to make a better routine
+                * in the game engine for finding the camera.
+                *  - zr
+                * Note: yes, this is all very badly hacked! (ton)
+                */
+       for (sc= G.main->scene.first; sc; sc= sc->id.next) {
+               if (!sc->camera) {
+                       Base *base;
+
+                       for (base= sc->base.first; base; base= base->next)
+                               if (base->object->type==OB_CAMERA)
+                                       break;
+
+                       sc->camera= base?base->object:NULL;
+               }
+       }
+
+       /* these two lines make sure front and backbuffer are equal. for swapbuffers */
+       markdirty_all();
+       screen_swapbuffers();
+
+       /* can start from header */
+       mywinset(curarea->win);
+
+       scene_cfra_store= save_and_reset_all_scene_cfra();
+
+
+       /* game engine will do its own sounds. */
+       sound_stop_all_sounds();
+       sound_exit_audio();
+
+       /* Before jumping into Ketsji, we configure some settings. */
+       space_set_commmandline_options();
+
+       SaveState();
+       StartKetsjiShellSimulation(curarea, startscene->id.name+2, G.main,G.sipo, 1);
+       RestoreState();
+       /* Restart BPY - unload the game engine modules. */
+       BPY_end_python();
+       BPY_start_python(0, NULL); /* argc, argv stored there already */
+       BPY_post_start_python(); /* userpref path and menus init */
+
+       restore_all_scene_cfra(scene_cfra_store);
+       set_scene_bg(startscene);
+       scene_update_for_newframe(G.scene, G.scene->lay);
+
+       if (G.flags & G_FILE_AUTOPLAY)
+               exit_usiblender();
+
+               /* groups could have changed ipo */
+       allqueue(REDRAWNLA, 0);
+       allqueue(REDRAWACTION, 0);
+       allspace(REMAKEIPO, 0);
+       allqueue(REDRAWIPO, 0);
+#endif
+#else
+       notice("YOU NEED GAME ENGIEN TO RUN THE SIMULATION!");
+#endif
+}
+
 static void changeview3dspace(ScrArea *sa, void *spacedata)
 {
        setwinmatrixview3d(sa->winx, sa->winy, NULL);   /* 0= no pick rect */
@@ -1771,6 +1844,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        clear_parent();
                                else if(G.qual==(LR_ALTKEY|LR_CTRLKEY))
                                        make_proxy();
+                               else if(G.qual==(LR_ALTKEY|LR_CTRLKEY|LR_SHIFTKEY)) {
+                       start_RBSimulation();
+                               }
                                else if((G.qual==0) && (OBACT) && (OBACT->type==OB_ARMATURE) && (OBACT->flag & OB_POSEMODE))
                                        select_bone_parent();
                                else if((G.qual==0)) {
index a270b73..b886e4f 100644 (file)
@@ -348,7 +348,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
                                rasterizer->Init();
                                
                                // start the engine
-                               ketsjiengine->StartEngine();
+                               ketsjiengine->StartEngine(true);
                                
                                // the mainloop
                                while (!exitrequested)
@@ -449,3 +449,349 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
 
        if (bfd) BLO_blendfiledata_free(bfd);
 }
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "BSE_headerbuttons.h"
+void update_for_newframe();
+#ifdef __cplusplus
+}
+#endif
+
+extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
+                                                                char* scenename,
+                                                                struct Main* maggie,
+                                                                struct SpaceIpo *sipo,
+                                                                int always_use_expand_framing)
+{
+    int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
+
+       Main* blenderdata = maggie;
+
+       char* startscenename = scenename;
+       char pathname[160];
+       strcpy (pathname, maggie->name);
+       STR_String exitstring = "";
+       BlendFileData *bfd= NULL;
+
+       bgl::InitExtensions(1);
+
+       do
+       {
+//             View3D *v3d= (View3D*) area->spacedata.first;
+
+               // get some preferences
+               SYS_SystemHandle syshandle = SYS_GetSystem();
+               bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
+               bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
+               bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
+               bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
+               bool game2ipo = true;//(SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0);
+               bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
+               bool usemat = false;
+
+/*             #ifdef GL_ARB_multitexture
+               if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) {
+                       usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0);
+                       int unitmax=0;
+                       glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax);
+                       bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX;
+                       //std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl;
+               } else {
+                       bgl::max_texture_units = 0;
+               }
+               #endif
+
+*/
+               // create the canvas, rasterizer and rendertools
+               RAS_ICanvas* canvas = new KX_BlenderCanvas(area);
+               //canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
+               RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
+               RAS_IRasterizer* rasterizer = NULL;
+
+               // let's see if we want to use vertexarrays or not
+               int usevta = SYS_GetCommandLineInt(syshandle,"vertexarrays",1);
+               bool useVertexArrays = (usevta > 0);
+
+               bool lock_arrays = (displaylists && useVertexArrays);
+
+               if(displaylists && !useVertexArrays)
+                       rasterizer = new RAS_ListRasterizer(canvas);
+               else if (useVertexArrays && bgl::QueryVersion(1, 1))
+                       rasterizer = new RAS_VAOpenGLRasterizer(canvas, lock_arrays);
+               else
+                       rasterizer = new RAS_OpenGLRasterizer(canvas);
+
+               // create the inputdevices
+               KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
+               KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
+
+               // create a networkdevice
+               NG_NetworkDeviceInterface* networkdevice = new
+                       NG_LoopBackNetworkDeviceInterface();
+
+               // get an audiodevice
+               SND_DeviceManager::Subscribe();
+               SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
+               audiodevice->UseCD();
+
+               // create a ketsji/blendersystem (only needed for timing and stuff)
+               KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
+
+               // create the ketsjiengine
+               KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
+
+/*             // set the devices
+               ketsjiengine->SetKeyboardDevice(keyboarddevice);
+               ketsjiengine->SetMouseDevice(mousedevice);
+               ketsjiengine->SetNetworkDevice(networkdevice);
+               ketsjiengine->SetCanvas(canvas);
+               ketsjiengine->SetRenderTools(rendertools);
+               ketsjiengine->SetRasterizer(rasterizer);
+               ketsjiengine->SetNetworkDevice(networkdevice);
+               ketsjiengine->SetAudioDevice(audiodevice);
+               ketsjiengine->SetUseFixedTime(usefixed);
+               ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
+
+*/
+
+               // some blender stuff
+               MT_CmMatrix4x4 projmat;
+               MT_CmMatrix4x4 viewmat;
+               int i;
+
+/*             for (i = 0; i < 16; i++)
+               {
+                       float *viewmat_linear= (float*) v3d->viewmat;
+                       viewmat.setElem(i, viewmat_linear[i]);
+               }
+               for (i = 0; i < 16; i++)
+               {
+                       float *projmat_linear = (float*) area->winmat;
+                       projmat.setElem(i, projmat_linear[i]);
+               }
+*/
+/*             float camzoom = (1.41421 + (v3d->camzoom / 50.0));
+               camzoom *= camzoom;
+               camzoom = 4.0 / camzoom;
+*/
+//             ketsjiengine->SetDrawType(v3d->drawtype);
+//             ketsjiengine->SetCameraZoom(camzoom);
+/*
+               // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
+               if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
+               {
+                       exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
+                       if (bfd) BLO_blendfiledata_free(bfd);
+
+                       char basedpath[160];
+                       // base the actuator filename with respect
+                       // to the original file working directory
+                       if (exitstring != "")
+                               strcpy(basedpath, exitstring.Ptr());
+
+                       BLI_convertstringcode(basedpath, pathname, 0);
+                       bfd = load_game_data(basedpath);
+
+                       // if it wasn't loaded, try it forced relative
+                       if (!bfd)
+                       {
+                               // just add "//" in front of it
+                               char temppath[162];
+                               strcpy(temppath, "//");
+                               strcat(temppath, basedpath);
+
+                               BLI_convertstringcode(temppath, pathname, 0);
+                               bfd = load_game_data(temppath);
+                       }
+
+                       // if we got a loaded blendfile, proceed
+                       if (bfd)
+                       {
+                               blenderdata = bfd->main;
+                               startscenename = bfd->curscene->id.name + 2;
+                       }
+                       // else forget it, we can't find it
+                       else
+                       {
+                               exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
+                       }
+               }
+*/
+               Scene *blscene = NULL;
+               if (!bfd)
+               {
+                       blscene = (Scene*) maggie->scene.first;
+                       for (Scene *sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
+                       {
+                               if (startscenename == (sce->id.name+2))
+                               {
+                                       blscene = sce;
+                                       break;
+                               }
+                       }
+               } else {
+                       blscene = bfd->curscene;
+               }
+        int cframe,startFrame;
+               if (blscene)
+               {
+                       cframe=blscene->r.cfra;
+                       startFrame = blscene->r.sfra;
+                       blscene->r.cfra=startFrame;
+                       update_for_newframe();
+                       ketsjiengine->SetGame2IpoMode(game2ipo,startFrame);
+               }
+
+               // Quad buffered needs a special window.
+               if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
+                       rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode);
+
+               if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
+               {
+                       /*if (v3d->persp != 2)
+                       {
+                               ketsjiengine->EnableCameraOverride(startscenename);
+                               ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == 0));
+                               ketsjiengine->SetCameraOverrideProjectionMatrix(projmat);
+                               ketsjiengine->SetCameraOverrideViewMatrix(viewmat);
+                       }*/
+
+                       // create a scene converter, create and convert the startingscene
+                       KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(maggie,sipo, ketsjiengine);
+                       ketsjiengine->SetSceneConverter(sceneconverter);
+
+                       if (always_use_expand_framing)
+                               sceneconverter->SetAlwaysUseExpandFraming(true);
+
+                       if(usemat)
+                               sceneconverter->SetMaterials(true);
+
+                       KX_Scene* startscene = new KX_Scene(keyboarddevice,
+                               mousedevice,
+                               networkdevice,
+                               audiodevice,
+                               startscenename);
+
+                       // some python things
+                       PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
+                       ketsjiengine->SetPythonDictionary(dictionaryobject);
+                       initRasterizer(rasterizer, canvas);
+                       PyObject *gameLogic = initGameLogic(startscene);
+                       initGameKeys();
+                       initPythonConstraintBinding();
+
+                       if (sceneconverter)
+                       {
+                               // convert and add scene
+                               sceneconverter->ConvertScene(
+                                       startscenename,
+                                       startscene,
+                                       dictionaryobject,
+                                       keyboarddevice,
+                                       rendertools,
+                                       canvas);
+                               ketsjiengine->AddScene(startscene);
+
+                               // init the rasterizer
+                               //rasterizer->Init();
+
+                               // start the engine
+                               ketsjiengine->StartEngine(false);
+
+                               // the mainloop
+                               while ((blscene->r.cfra<=blscene->r.efra)&&(!exitrequested))
+                               {
+                    printf("frame %i\n",blscene->r.cfra);
+                    // first check if we want to exit
+                                       exitrequested = ketsjiengine->GetExitCode();
+
+                                       // kick the engine
+                                       ketsjiengine->NextFrame();
+                                   blscene->r.cfra=blscene->r.cfra+1;
+                                   update_for_newframe();
+                                       // render the frame
+                                       //ketsjiengine->Render();
+
+                                       // test for the ESC key
+                                       /*while (qtest())
+                                       {
+                                               short val;
+                                               unsigned short event = extern_qread(&val);
+
+                                               if (keyboarddevice->ConvertBlenderEvent(event,val))
+                                                       exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
+
+                                               if (event==MOUSEX) {
+                                                       val = val - scrarea_get_win_x(area);
+                                               } else if (event==MOUSEY) {
+                                                       val = scrarea_get_win_height(area) - (val - scrarea_get_win_y(area)) - 1;
+                                               }
+
+                                               mousedevice->ConvertBlenderEvent(event,val);
+                                       }*/
+                               }
+                               exitstring = ketsjiengine->GetExitString();
+                               // when exiting the mainloop
+                               //dictionaryClearByHand(gameLogic);
+                               //ketsjiengine->StopEngine();
+                               //exitGamePythonScripting();
+                               //networkdevice->Disconnect();
+                       }
+                       if (sceneconverter)
+                       {
+                               delete sceneconverter;
+                               sceneconverter = NULL;
+                       }
+               }
+               blscene->r.cfra=cframe;
+               // set the cursor back to normal
+               canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+
+               // clean up some stuff
+               audiodevice->StopCD();
+               if (ketsjiengine)
+               {
+                       delete ketsjiengine;
+                       ketsjiengine = NULL;
+               }
+               if (kxsystem)
+               {
+                       delete kxsystem;
+                       kxsystem = NULL;
+               }
+               if (networkdevice)
+               {
+                       delete networkdevice;
+                       networkdevice = NULL;
+               }
+               if (keyboarddevice)
+               {
+                       delete keyboarddevice;
+                       keyboarddevice = NULL;
+               }
+               if (mousedevice)
+               {
+                       delete mousedevice;
+                       mousedevice = NULL;
+               }
+               /*if (rasterizer)
+               {
+                       delete rasterizer;
+                       rasterizer = NULL;
+               }
+               if (rendertools)
+               {
+                       delete rendertools;
+                       rendertools = NULL;
+               }
+               if (canvas)
+               {
+                       delete canvas;
+                       canvas = NULL;
+               }*/
+               SND_DeviceManager::Unsubscribe();
+
+       } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
+       if (bfd) BLO_blendfiledata_free(bfd);
+}
\ No newline at end of file
index b0986ae..de20789 100644 (file)
@@ -1515,6 +1515,84 @@ static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scen
        return (Scene*) maggie->scene.first;
 }
 
+#include "DNA_constraint_types.h"
+#include "BIF_editconstraint.h"
+
+bPoseChannel *get_active_posechannel2 (Object *ob)
+{
+       bArmature *arm= (bArmature*)ob->data;
+       bPoseChannel *pchan;
+       
+       /* find active */
+       for(pchan= (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+               if(pchan->bone && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer))
+                       return pchan;
+       }
+       
+       return NULL;
+}
+
+ListBase *get_active_constraints2(Object *ob)
+{
+       if (!ob)
+               return NULL;
+
+       if (ob->flag & OB_POSEMODE) {
+               bPoseChannel *pchan;
+
+               pchan = get_active_posechannel2(ob);
+               if (pchan)
+                       return &pchan->constraints;
+       }
+       else 
+               return &ob->constraints;
+
+       return NULL;
+}
+
+
+void RBJconstraints(Object *ob)//not used
+{
+       ListBase *conlist;
+       bConstraint *curcon;
+
+       conlist = get_active_constraints2(ob);
+
+       if (conlist) {
+               for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
+
+                       printf("%i\n",curcon->type);
+               }
+
+
+       }
+}
+
+#include "PHY_IPhysicsEnvironment.h"
+#include "KX_IPhysicsController.h"
+#include "PHY_DynamicTypes.h"
+
+KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc){//not used
+
+    for (int j=0;j<sumolist->GetCount();j++)
+       {
+           KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j);
+           if (gameobje->GetName()==busc)
+            return gameobje->GetPhysicsController();
+       }
+
+}
+
+KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){
+
+    for (int j=0;j<sumolist->GetCount();j++)
+       {
+           KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j);
+           if (gameobje->GetName()==busc)
+            return gameobje;
+       }
+
+}
 
 // convert blender objects into ketsji gameobjects
 void BL_ConvertBlenderObjects(struct Main* maggie,
@@ -1812,6 +1890,77 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
 
        }
        
+               // create physics joints
+       for (i=0;i<sumolist->GetCount();i++)
+       {
+               KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
+               struct Object* blenderobject = converter->FindBlenderObject(gameobj);
+               int nummeshes = gameobj->GetMeshCount();
+               RAS_MeshObject* meshobj = 0;
+        ListBase *conlist;
+        bConstraint *curcon;
+        conlist = get_active_constraints2(blenderobject);
+        if (conlist) {
+            for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
+                if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT){
+                    bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data;
+                    if (dat->tar)
+                        if (!dat->child){
+                            KX_GameObject *gotar=getGameOb(dat->tar->id.name,sumolist);
+                            PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) (int)gameobj->GetPhysicsController()->GetUserData();
+                            PHY_IPhysicsController* physctr2 = (PHY_IPhysicsController*) (int)gotar->GetPhysicsController()->GetUserData();
+                            kxscene->GetPhysicsEnvironment()->createConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX,(float)dat->pivY,(float)dat->pivZ,(float)dat->axX,(float)dat->axY,(float)dat->axZ);
+                            /*switch(dat->type){
+                                case CONSTRAINT_RB_BALL:
+                                    KX_GameObject *gotar=getGameOb(dat->tar->id.name,sumolist);
+                                    PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) (int)gameobj->GetPhysicsController()->GetUserData();
+                                    PHY_IPhysicsController* physctr2 = (PHY_IPhysicsController*) (int)gotar->GetPhysicsController()->GetUserData();
+                                    kxscene->GetPhysicsEnvironment()->createConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX,(float)dat->pivY,(float)dat->pivZ,(float)dat->axX,(float)dat->axY,(float)dat->axZ);
+                                    break;
+                                case CONSTRAINT_RB_HINGE:
+                                    KX_GameObject *gotar=getGameOb(dat->tar->id.name,sumolist);
+                                    PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) (int)gameobj->GetPhysicsController()->GetUserData();
+                                    PHY_IPhysicsController* physctr2 = (PHY_IPhysicsController*) (int)gotar->GetPhysicsController()->GetUserData();
+                                    kxscene->GetPhysicsEnvironment()->createConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX,(float)dat->pivY,(float)dat->pivZ,(float)dat->axX,(float)dat->axY,(float)dat->axZ);
+                                    break;
+                            }*/
+                        }
+                }
+            }
+        }
+
+       }
+
+    //Intento de actualizar posicion
+       /*for (i=0;i<sumolist->GetCount();i++)
+       {
+               KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
+               struct Object* blenderobject = converter->FindBlenderObject(gameobj);
+
+               MT_Point3 pos = MT_Point3(
+                               blenderobject->loc[0]+blenderobject->dloc[0],
+                               blenderobject->loc[1]+blenderobject->dloc[1],
+                               blenderobject->loc[2]+blenderobject->dloc[2]
+                       );
+               MT_Vector3 eulxyz = MT_Vector3(
+                               blenderobject->rot[0],
+                               blenderobject->rot[1],
+                               blenderobject->rot[2]
+                       );
+               MT_Vector3 scale = MT_Vector3(
+                               blenderobject->size[0],
+                               blenderobject->size[1],
+                               blenderobject->size[2]
+                       );
+
+               gameobj->NodeSetLocalPosition(pos);
+               gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
+               gameobj->NodeSetLocalScale(scale);
+               gameobj->NodeUpdateGS(0,true);
+       }*/
+    //rcruiz>
+
+       
        templist->Release();
        sumolist->Release();    
 
index 83b2a11..10f3ea3 100644 (file)
@@ -576,7 +576,7 @@ Ipo* KX_BlenderSceneConverter::findIpoForName(char* objName)
 }
 
 
-void   KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo()
+void   KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
 {
 
        KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
@@ -604,6 +604,7 @@ void        KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo()
                                        if (ipo)
                                        {
                                                //clear the curve data
+                                               if (clearIpo){
                                                IpoCurve *icu1;
                                                int numCurves = 0;
                                                for( icu1 = (IpoCurve*)ipo->curve.first; icu1;  ) {
@@ -618,6 +619,7 @@ void        KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo()
                                                        MEM_freeN( tmpicu );
                                                        localDel_ipoCurve( tmpicu ,m_sipo);
                                                }
+                                         }
                                        } else
                                        {
                                                ipo = add_ipo(blenderObject->id.name+2, ID_OB);
index db2090a..c4447c5 100644 (file)
@@ -130,7 +130,7 @@ public:
 
        void RegisterWorldInfo(KX_WorldInfo *worldinfo);
 
-       virtual void    ResetPhysicsObjectsAnimationIpo();
+       virtual void    ResetPhysicsObjectsAnimationIpo(bool clearIpo);
 
        ///this generates ipo curves for position, rotation, allowing to use game physics in animation
        virtual void    WritePhysicsObjectToAnimationIpo(int frameNumber);
index 8554b7c..fd47df7 100644 (file)
@@ -673,7 +673,7 @@ bool GPG_Application::startEngine(void)
                        m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
                }
                m_rasterizer->Init();
-               m_ketsjiengine->StartEngine();
+               m_ketsjiengine->StartEngine(true);
                m_engineRunning = true;
                
        }
index 52a6579..8693eb3 100644 (file)
@@ -61,7 +61,7 @@ public:
        virtual bool    TryAndLoadNewFile() = 0;
 
 
-       virtual void    ResetPhysicsObjectsAnimationIpo() = 0;
+       virtual void    ResetPhysicsObjectsAnimationIpo(bool clearIpo) = 0;
 
        ///this generates ipo curves for position, rotation, allowing to use game physics in animation
        virtual void    WritePhysicsObjectToAnimationIpo(int frameNumber) = 0;
index 4d6b70a..6a54c61 100644 (file)
@@ -254,7 +254,7 @@ void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
  * Blender into Ketsji native (realtime) format also sets up the
  * graphics context
  */
-void KX_KetsjiEngine::StartEngine()
+void KX_KetsjiEngine::StartEngine(bool clearIpo)
 {
        m_clockTime = m_kxsystem->GetTimeInSeconds();
        m_frameTime = m_kxsystem->GetTimeInSeconds();
@@ -266,7 +266,7 @@ void KX_KetsjiEngine::StartEngine()
        
        if (m_game2ipo)
        {
-               m_sceneconverter->ResetPhysicsObjectsAnimationIpo();
+               m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
                m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
        }
 
index d78ad95..ae33e8d 100644 (file)
@@ -205,7 +205,7 @@ public:
        void                    NextFrame();
        void                    Render();
        
-       void                    StartEngine();
+       void                    StartEngine(bool clearIpo);
        void                    StopEngine();
        void                    Export(const STR_String& filename);