BGE: dynamic loading patch commited. API and demo files available here: https://projects.blender.org/tracker/?func=detail&aid=19492&group_id=9&atid=127

This commit is contained in:
Benoit Bolsee 2009-11-15 23:58:56 +00:00
parent 349fa813ea
commit b45ab480e0
42 changed files with 1164 additions and 45 deletions

@ -40,6 +40,10 @@
#include "KX_KetsjiEngine.h"
#include "KX_IPhysicsController.h"
#include "BL_Material.h"
#include "KX_BlenderMaterial.h"
#include "KX_PolygonMaterial.h"
#include "SYS_System.h"
#include "DummyPhysicsEnvironment.h"
@ -72,27 +76,48 @@ extern "C"
{
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "BLI_blenlib.h"
#include "MEM_guardedalloc.h"
//XXX #include "BSE_editipo.h"
//XXX #include "BSE_editipo_types.h"
#include "DNA_ipo_types.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_ipo.h" // eval_icu
#include "BKE_material.h" // copy_material
#include "BKE_mesh.h" // copy_mesh
#include "DNA_space_types.h"
}
/* Only for dynamic loading and merging */
#include "RAS_BucketManager.h" // XXX cant stay
#include "KX_BlenderSceneConverter.h"
#include "BL_BlenderDataConversion.h"
#include "KX_MeshProxy.h"
#include "RAS_MeshObject.h"
extern "C" {
#include "BKE_context.h"
#include "BLO_readfile.h"
#include "BKE_report.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h" /* report api */
#include "../../blender/blenlib/BLI_linklist.h"
}
KX_BlenderSceneConverter::KX_BlenderSceneConverter(
struct Main* maggie,
class KX_KetsjiEngine* engine
)
: m_maggie(maggie),
/*m_maggie_dyn(NULL),*/
m_ketsjiEngine(engine),
m_alwaysUseExpandFraming(false),
m_usemat(false),
m_useglslmat(false)
{
tag_main(maggie, 0); /* avoid re-tagging later on */
m_newfilename = "";
}
@ -141,10 +166,15 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
KX_ClearBulletSharedShapes();
#endif
/* free any data that was dynamically loaded */
for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
Main *main= *it;
free_main(main);
}
m_DynamicMaggie.clear();
}
void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
{
m_newfilename = filename;
@ -183,6 +213,14 @@ Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
if (name == (sce->id.name+2))
return sce;
for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
Main *main= *it;
for (sce= (Scene*) main->scene.first; sce; sce= (Scene*) sce->id.next)
if (name == (sce->id.name+2))
return sce;
}
return (Scene*)m_maggie->scene.first;
}
@ -490,7 +528,9 @@ void KX_BlenderSceneConverter::RegisterGameMesh(
RAS_MeshObject *gamemesh,
struct Mesh *for_blendermesh)
{
if(for_blendermesh) { /* dynamically loaded meshes we dont want to keep lookups for */
m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
}
m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
}
@ -925,3 +965,480 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace()
return m_ketsjiEngine->GetPyNamespace();
}
#endif
vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
{
return m_DynamicMaggie;
}
Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
{
for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
if(strcmp((*it)->name, path)==0)
return *it;
return NULL;
}
bool KX_BlenderSceneConverter::LinkBlendFile(const char *path, char *group, KX_Scene *scene_merge, char **err_str)
{
bContext *C;
Main *main_newlib; /* stored as a dynamic 'main' until we free it */
Main *main_tmp= NULL; /* created only for linking, then freed */
LinkNode *names = NULL;
BlendHandle *bpy_openlib = NULL; /* ptr to the open .blend file */
int idcode= BLO_idcode_from_name(group);
short flag= 0; /* dont need any special options */
ReportList reports;
static char err_local[255];
/* only scene and mesh supported right now */
if(idcode!=ID_SCE && idcode!=ID_ME) {
snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
return false;
}
if(GetMainDynamicPath(path)) {
snprintf(err_local, sizeof(err_local), "blend file alredy open \"%s\"\n", path);
*err_str= err_local;
return false;
}
bpy_openlib = BLO_blendhandle_from_file( (char *)path );
if(bpy_openlib==NULL) {
snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
*err_str= err_local;
return false;
}
main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
C= CTX_create();
CTX_data_main_set(C, main_newlib);
BKE_reports_init(&reports, RPT_STORE);
/* here appending/linking starts */
main_tmp = BLO_library_append_begin(C, &bpy_openlib, (char *)path);
names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode);
int i=0;
LinkNode *n= names;
while(n) {
BLO_library_append_named_part(C, main_tmp, &bpy_openlib, (char *)n->link, idcode, 0);
n= (LinkNode *)n->next;
i++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
BLO_library_append_end(C, main_tmp, &bpy_openlib, idcode, flag);
BLO_blendhandle_close(bpy_openlib);
CTX_free(C);
BKE_reports_clear(&reports);
/* done linking */
/* needed for lookups*/
GetMainDynamic().push_back(main_newlib);
strncpy(main_newlib->name, path, sizeof(main_newlib->name));
if(idcode==ID_ME) {
/* Convert all new meshes into BGE meshes */
ID* mesh;
KX_Scene *kx_scene= m_currentScene;
for(mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
}
}
else if(idcode==ID_SCE) {
/* Merge all new linked in scene into the existing one */
ID *scene;
for(scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
printf("SceneName: %s\n", scene->name);
/* merge into the base scene */
KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
scene_merge->MergeScene(other);
// RemoveScene(other); // Dont run this, it frees the entire scene converter data, just delete the scene
delete other;
}
}
return true;
}
/* Note m_map_*** are all ok and dont need to be freed
* most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
{
int maggie_index;
int i=0;
if(maggie==NULL)
return false;
/* tag all false except the one we remove */
for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
Main *main= *it;
if(main != maggie) {
tag_main(main, 0);
}
else {
maggie_index= i;
}
i++;
}
m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
tag_main(maggie, 1);
/* free all tagged objects */
KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
{
KX_Scene* scene = scenes->at(scene_idx);
if(IS_TAGGED(scene->GetBlenderScene())) {
RemoveScene(scene); // XXX - not tested yet
scene_idx--;
numScenes--;
}
else {
/* incase the mesh might be refered to later */
{
GEN_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
for(int i=0; i<mapStringToMeshes.size(); i++)
{
RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
if(meshobj && IS_TAGGED(meshobj->GetMesh()))
{
STR_HashedString mn = meshobj->GetName();
mapStringToMeshes.remove(mn);
i--;
}
}
}
//scene->FreeTagged(); /* removed tagged objects and meshes*/
CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
for(int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
{
CListValue *obs= obj_lists[ob_ls_idx];
RAS_MeshObject* mesh;
for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
{
KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
if(IS_TAGGED(gameobj->GetBlenderObject())) {
int size_before = obs->GetCount();
/* Eventually calls RemoveNodeDestructObject
* frees m_map_gameobject_to_blender from UnregisterGameObject */
scene->RemoveObject(gameobj);
if(size_before != obs->GetCount())
ob_idx--;
else {
printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr());
}
}
else {
/* free the mesh, we could be referecing a linked one! */
int mesh_index= gameobj->GetMeshCount();
while(mesh_index--) {
mesh= gameobj->GetMesh(mesh_index);
if(IS_TAGGED(mesh->GetMesh())) {
gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
break;
}
}
}
}
}
}
}
int size;
// delete the entities of this scene
/* TODO - */
/*
vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
size = m_worldinfos.size();
for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
if ((*worldit).second) {
delete (*worldit).second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
} else {
i++;
worldit++;
}
}*/
/* Worlds dont reference original blender data so we need to make a set from them */
typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
KX_WorldInfoSet worldset;
for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
{
KX_Scene* scene = scenes->at(scene_idx);
if(scene->GetWorldInfo())
worldset.insert( scene->GetWorldInfo() );
}
vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
size = m_worldinfos.size();
for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
delete (*worldit).second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
} else {
i++;
worldit++;
}
}
worldset.clear();
/* done freeing the worlds */
vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
size = m_polymaterials.size();
for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
RAS_IPolyMaterial *mat= (*polymit).second;
Material *bmat= NULL;
/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
if(mat->GetFlag() & RAS_BLENDERMAT) {
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
bmat= bl_mat->GetBlenderMaterial();
} else {
KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
bmat= kx_mat->GetBlenderMaterial();
}
if (IS_TAGGED(bmat)) {
/* only remove from bucket */
((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
}
i++;
polymit++;
}
for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
RAS_IPolyMaterial *mat= (*polymit).second;
Material *bmat= NULL;
/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
if(mat->GetFlag() & RAS_BLENDERMAT) {
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
bmat= bl_mat->GetBlenderMaterial();
} else {
KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
bmat= kx_mat->GetBlenderMaterial();
}
if(bmat) {
//printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
}
else {
//printf("LOST MAT !!!");
}
if (IS_TAGGED(bmat)) {
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
size--;
//printf("tagged !\n");
} else {
i++;
polymit++;
//printf("(un)tagged !\n");
}
}
vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
size = m_materials.size();
for (i=0, matit=m_materials.begin(); i<size; ) {
BL_Material *mat= (*matit).second;
if (IS_TAGGED(mat->material)) {
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
size--;
} else {
i++;
matit++;
}
}
vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
size = m_meshobjects.size();
for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
RAS_MeshObject *me= (*meshit).second;
if (IS_TAGGED(me->GetMesh())) {
delete (*meshit).second;
*meshit = m_meshobjects.back();
m_meshobjects.pop_back();
size--;
} else {
i++;
meshit++;
}
}
free_main(maggie);
return true;
}
bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
{
return FreeBlendFile(GetMainDynamicPath(path));
}
bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
{
{
vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
while (itp != m_worldinfos.end()) {
if ((*itp).first==from)
(*itp).first= to;
itp++;
}
}
{
vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
if ((*itp).first==from) {
(*itp).first= to;
/* also switch internal data */
RAS_IPolyMaterial*mat= (*itp).second;
mat->Replace_IScene(to);
}
itp++;
}
}
{
vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
while (itp != m_meshobjects.end()) {
if ((*itp).first==from)
(*itp).first= to;
itp++;
}
}
{
vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
while (itp != m_materials.end()) {
if ((*itp).first==from)
(*itp).first= to;
itp++;
}
}
return true;
}
/* This function merges a mesh from the current scene into another main
* it does not convert */
RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
{
ID *me;
/* Find a mesh in the current main */
for(me = (ID *)m_maggie->mesh.first; me; me= (ID *)me->next)
if(strcmp(name, me->name+2)==0)
break;
if(me==NULL) {
printf("Could not be found \"%s\"\n", name);
return NULL;
}
/* Watch this!, if its used in the original scene can cause big troubles */
if(me->us > 0) {
printf("Mesh has a user \"%s\"\n", name);
me = (ID*)copy_mesh((Mesh*)me);
me->us--;
}
BLI_remlink(&m_maggie->mesh, me); /* even if we made the copy it needs to be removed */
BLI_addtail(&maggie->mesh, me);
/* Must copy the materials this uses else we cant free them */
{
Mesh *mesh= (Mesh *)me;
/* ensure all materials are tagged */
for(int i=0; i<mesh->totcol; i++)
if(mesh->mat[i])
mesh->mat[i]->id.flag &= ~LIB_DOIT;
for(int i=0; i<mesh->totcol; i++)
{
Material *mat_old= mesh->mat[i];
/* if its tagged its a replaced material */
if(mat_old && (mat_old->id.flag & LIB_DOIT)==0)
{
Material *mat_old= mesh->mat[i];
Material *mat_new= copy_material( mat_old );
mat_new->id.flag |= LIB_DOIT;
mat_old->id.us--;
BLI_remlink(&m_maggie->mat, mat_new);
BLI_addtail(&maggie->mat, mat_new);
mesh->mat[i]= mat_new;
/* the same material may be used twice */
for(int j=i+1; j<mesh->totcol; j++)
{
if(mesh->mat[j]==mat_old)
{
mesh->mat[j]= mat_new;
mat_new->id.us++;
mat_old->id.us--;
}
}
}
}
}
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */
return meshobj;
}

@ -64,6 +64,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
GEN_Map<CHashedPtr,BL_InterpolatorList*> m_map_blender_to_gameAdtList;
Main* m_maggie;
vector<struct Main*> m_DynamicMaggie;
STR_String m_newfilename;
class KX_KetsjiEngine* m_ketsjiEngine;
@ -140,7 +141,39 @@ public:
struct Scene* GetBlenderSceneForName(const STR_String& name);
struct Main* GetMain() { return m_maggie; };
// struct Main* GetMain() { return m_maggie; };
struct Main* GetMainDynamicPath(const char *path);
vector<struct Main*> &GetMainDynamic();
bool LinkBlendFile(const char *path, char *group, KX_Scene *scene_merge, char **err_str);
bool MergeScene(KX_Scene *to, KX_Scene *from);
RAS_MeshObject *ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name);
bool FreeBlendFile(struct Main *maggie);
bool FreeBlendFile(const char *path);
void PrintStats() {
printf("BGE STATS!\n");
printf("\nAssets...\n");
printf("\t m_worldinfos: %d\n", m_worldinfos.size());
printf("\t m_polymaterials: %d\n", m_polymaterials.size());
printf("\t m_meshobjects: %d\n", m_meshobjects.size());
printf("\t m_materials: %d\n", m_materials.size());
printf("\nMappings...\n");
printf("\t m_map_blender_to_gameobject: %d\n", m_map_blender_to_gameobject.size());
printf("\t m_map_mesh_to_gamemesh: %d\n", m_map_mesh_to_gamemesh.size());
printf("\t m_map_blender_to_gameactuator: %d\n", m_map_blender_to_gameactuator.size());
printf("\t m_map_blender_to_gamecontroller: %d\n", m_map_blender_to_gamecontroller.size());
printf("\t m_map_blender_to_gameAdtList: %d\n", m_map_blender_to_gameAdtList.size());
#ifdef WITH_CXX_GUARDEDALLOC
MEM_printmemlist_pydict();
#endif
// /printf("\t m_ketsjiEngine->m_scenes: %d\n", m_ketsjiEngine->CurrentScenes()->size());
}
#ifndef DISABLE_PYTHON
PyObject *GetPyNamespace();

@ -70,6 +70,11 @@ public:
virtual void EndFrame();
virtual void RegisterSensor(class SCA_ISensor* sensor);
int GetType();
//SG_DList &GetSensors() { return m_sensors; }
void Replace_LogicManager(SCA_LogicManager* logicmgr) { m_logicmgr= logicmgr; }
virtual void Replace_PhysicsScene(class PHY_IPhysicsEnvironment* env) { } /* only for event managers that use one */
protected:
EVENT_MANAGER_TYPE m_mgrtype;

@ -35,6 +35,9 @@
#include "GEN_Map.h"
#include "GEN_HashedPtr.h"
class NG_NetworkScene;
class SCA_IScene;
class SCA_ILogicBrick : public CValue
{
Py_Header;
@ -122,9 +125,14 @@ public:
virtual bool LessComparedTo(SCA_ILogicBrick* other);
/* runtime variable, set when Triggering the python controller */
static class SCA_LogicManager* m_sCurrentLogicManager;
/* for moving logic bricks between scenes */
virtual void Replace_IScene(SCA_IScene *val) {};
virtual void Replace_NetworkScene(NG_NetworkScene *val) {};
#ifndef DISABLE_PYTHON
// python methods

@ -160,6 +160,19 @@ void SCA_ISensor::RegisterToManager()
m_eventmgr->RegisterSensor(this);
}
void SCA_ISensor::Replace_EventManager(class SCA_LogicManager* logicmgr)
{
if(m_links) { /* true if we're used currently */
m_eventmgr->RemoveSensor(this);
m_eventmgr= logicmgr->FindEventManager(m_eventmgr->GetType());
m_eventmgr->RegisterSensor(this);
}
else {
m_eventmgr= logicmgr->FindEventManager(m_eventmgr->GetType());
}
}
void SCA_ISensor::LinkToController(SCA_IController* controller)
{
m_linkedcontrollers.push_back(controller);

@ -133,6 +133,7 @@ public:
virtual void RegisterToManager();
virtual void UnregisterToManager();
void Replace_EventManager(class SCA_LogicManager* logicmgr);
void ReserveController(int num)
{
m_linkedcontrollers.reserve(num);

@ -282,6 +282,11 @@ void SCA_LogicManager::RegisterMeshName(const STR_String& meshname,void* mesh)
m_mapStringToMeshes.insert(mn,mesh);
}
void SCA_LogicManager::UnregisterMeshName(const STR_String& meshname,void* mesh)
{
STR_HashedString mn = meshname;
m_mapStringToMeshes.remove(mn);
}
void SCA_LogicManager::RegisterActionName(const STR_String& actname,void* action)

@ -66,6 +66,7 @@ typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t;
#include "SCA_ILogicBrick.h"
#include "SCA_IActuator.h"
#include "SCA_EventManager.h"
class SCA_LogicManager
@ -110,6 +111,7 @@ public:
void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor);
SCA_EventManager* FindEventManager(int eventmgrtype);
vector<class SCA_EventManager*> GetEventManagers() { return m_eventmanagers; }
void RemoveGameObject(const STR_String& gameobjname);
@ -123,6 +125,9 @@ public:
// for the scripting... needs a FactoryManager later (if we would have time... ;)
void RegisterMeshName(const STR_String& meshname,void* mesh);
void UnregisterMeshName(const STR_String& meshname,void* mesh);
GEN_Map<STR_HashedString,void*>& GetMeshMap() { return m_mapStringToMeshes; };
void RegisterActionName(const STR_String& actname,void* action);
void* GetActionByName (const STR_String& actname);

@ -55,6 +55,10 @@ public:
virtual bool Update();
virtual CValue* GetReplica();
virtual void Replace_NetworkScene(NG_NetworkScene *val)
{
m_networkscene= val;
};
/* ------------------------------------------------------------ */
/* Python interface ------------------------------------------- */

@ -66,6 +66,11 @@ public:
virtual void Init();
void EndFrame();
virtual void Replace_NetworkScene(NG_NetworkScene *val)
{
m_NetworkScene= val;
};
#ifndef DISABLE_PYTHON
/* ------------------------------------------------------------- */

@ -19,6 +19,9 @@
#include "MEM_guardedalloc.h"
#endif
#include "SCA_IScene.h" /* only for Replace_IScene */
#include "KX_Scene.h"
struct MTFace;
class KX_Scene;
@ -68,6 +71,7 @@ public:
TCachingInfo& cachingInfo
)const;
Material* GetBlenderMaterial() const;
MTFace* GetMTFace(void) const;
unsigned int* GetMCol(void) const;
BL_Texture * getTex (unsigned int idx) {
@ -83,6 +87,11 @@ public:
MT_Scalar ref, MT_Scalar emit, MT_Scalar alpha
);
virtual void Replace_IScene(SCA_IScene *val)
{
mScene= static_cast<KX_Scene *>(val);
};
#ifndef DISABLE_PYTHON
// --------------------------------
virtual PyObject* py_repr(void) { return PyUnicode_FromString(mMaterial->matname.ReadPtr()); }
@ -119,7 +128,6 @@ private:
bool UsesLighting(RAS_IRasterizer *rasty) const;
void GetMaterialRGBAColor(unsigned char *rgba) const;
Material* GetBlenderMaterial() const;
Scene* GetBlenderScene() const;
void ReleaseMaterial();

@ -51,7 +51,7 @@ KX_GameActuator::KX_GameActuator(SCA_IObject *gameobj,
int mode,
const STR_String& filename,
const STR_String& loadinganimationname,
KX_Scene* scene,
SCA_IScene* scene,
KX_KetsjiEngine* ketsjiengine)
: SCA_IActuator(gameobj, KX_ACT_GAME)
{

@ -35,6 +35,9 @@
#include "SCA_IActuator.h"
#include "SCA_IScene.h" /* Replace_IScene only */
#include "KX_Scene.h" /* Replace_IScene only */
class KX_GameActuator : public SCA_IActuator
{
Py_Header;
@ -43,7 +46,7 @@ protected:
bool m_restart;
STR_String m_filename;
STR_String m_loadinganimationname;
class KX_Scene* m_scene;
class SCA_IScene* m_scene;
class KX_KetsjiEngine* m_ketsjiengine;
public:
@ -64,7 +67,7 @@ protected:
int mode,
const STR_String& filename,
const STR_String& loadinganimationname,
KX_Scene* scene,
SCA_IScene* scene,
KX_KetsjiEngine* ketsjiEngine);
virtual ~KX_GameActuator();
@ -72,6 +75,11 @@ protected:
virtual bool Update();
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= val;
};
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */

@ -1606,15 +1606,12 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
}
}
KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
{
Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
m_mousedevice,
m_networkdevice,
scenename,
scene->id.name+2,
scene);
m_sceneconverter->ConvertScene(tmpscene,
@ -1624,7 +1621,11 @@ KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
return tmpscene;
}
KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
{
Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
return CreateScene(scene);
}
void KX_KetsjiEngine::AddScheduledScenes()
{

@ -381,6 +381,9 @@ public:
*/
void GetOverrideFrameColor(float& r, float& g, float& b) const;
KX_Scene* CreateScene(const STR_String& scenename);
KX_Scene* CreateScene(Scene *scene);
protected:
/**
* Processes all scheduled scene activity.
@ -399,7 +402,6 @@ protected:
void AddScheduledScenes(void);
void ReplaceScheduledScenes(void);
void PostProcessScene(class KX_Scene* scene);
KX_Scene* CreateScene(const STR_String& scenename);
bool BeginFrame();
void ClearFrame();

@ -66,6 +66,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
replica->ProcessReplica();
return replica;
};
virtual void Replace_IScene(SCA_IScene *val)
{
m_kxscene= static_cast<KX_Scene *>(val);
};
/**
* @attention Overrides default evaluate.
*/

@ -102,6 +102,11 @@ public:
void DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const;
virtual bool Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const;
Material *GetBlenderMaterial() const
{
return m_material;
}
/**
* Returns the Blender texture face structure that is used for this material.
* @return The material's texture face.

@ -30,9 +30,6 @@
#include "GL/glew.h"
// directory header for py function getBlendFileList
#include <stdlib.h>
#ifdef WIN32
#pragma warning (disable : 4786)
#endif //WIN32
@ -50,6 +47,16 @@ extern "C" {
#endif
#include "KX_PythonInit.h"
// directory header for py function getBlendFileList
#ifndef WIN32
#include <dirent.h>
#include <stdlib.h>
#else
#include <io.h>
#include "BLI_winstuff.h"
#endif
//python physics binding
#include "KX_PyConstraintBinding.h"
@ -82,6 +89,8 @@ extern "C" {
#include "InputParser.h"
#include "KX_Scene.h"
#include "NG_NetworkScene.h" //Needed for sendMessage()
#include "BL_Shader.h"
#include "KX_PyMath.h"
@ -100,12 +109,16 @@ extern "C" {
#include "BKE_global.h"
#include "BLI_blenlib.h"
#include "GPU_material.h"
#include "MEM_guardedalloc.h"
/* for converting new scenes */
#include "KX_BlenderSceneConverter.h"
#include "KX_MeshProxy.h" /* for creating a new library of mesh objects */
extern "C" {
#include "BLO_readfile.h"
}
#ifndef WIN32
#include <dirent.h>
#else
#include "BLI_winstuff.h"
#endif
#include "NG_NetworkScene.h" //Needed for sendMessage()
static void setSandbox(TPythonSecurityLevel level);
@ -513,6 +526,12 @@ static PyObject* gPyGetSceneList(PyObject* self)
return list;
}
static PyObject *pyPrintStats(PyObject *,PyObject *,PyObject *)
{
gp_KetsjiScene->GetSceneConverter()->PrintStats();
Py_RETURN_NONE;
}
static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
{
#define pprint(x) std::cout << x << std::endl;
@ -584,6 +603,116 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
Py_RETURN_NONE;
}
static PyObject *gLibLoad(PyObject*, PyObject* args)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
char *group;
char *err_str= NULL;
if (!PyArg_ParseTuple(args,"ss:LibLoad",&path, &group))
return NULL;
if(kx_scene->GetSceneConverter()->LinkBlendFile(path, group, kx_scene, &err_str)) {
Py_RETURN_TRUE;
}
if(err_str) {
PyErr_SetString(PyExc_ValueError, err_str);
return NULL;
}
Py_RETURN_FALSE;
}
static PyObject *gLibNew(PyObject*, PyObject* args)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
char *group;
char *name;
PyObject *names;
int idcode;
if (!PyArg_ParseTuple(args,"ssO!:LibNew",&path, &group, &PyList_Type, &names))
return NULL;
if(kx_scene->GetSceneConverter()->GetMainDynamicPath(path))
{
PyErr_SetString(PyExc_KeyError, "the name of the path given exists");
return NULL;
}
idcode= BLO_idcode_from_name(group);
if(idcode==0) {
PyErr_Format(PyExc_ValueError, "invalid group given \"%s\"", group);
return NULL;
}
Main *maggie= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
kx_scene->GetSceneConverter()->GetMainDynamic().push_back(maggie);
strncpy(maggie->name, path, sizeof(maggie->name)-1);
/* Copy the object into main */
if(idcode==ID_ME) {
PyObject *ret= PyList_New(0);
PyObject *item;
for(int i= 0; i < PyList_GET_SIZE(names); i++) {
name= _PyUnicode_AsString(PyList_GET_ITEM(names, i));
if(name) {
RAS_MeshObject *meshobj= kx_scene->GetSceneConverter()->ConvertMeshSpecial(kx_scene, maggie, name);
if(meshobj) {
KX_MeshProxy* meshproxy = new KX_MeshProxy(meshobj);
item= meshproxy->NewProxy(true);
PyList_Append(ret, item);
Py_DECREF(item);
}
}
else {
PyErr_Clear(); /* wasnt a string, ignore for now */
}
}
return ret;
}
else {
PyErr_Format(PyExc_ValueError, "only \"Mesh\" group currently supported");
return NULL;
}
Py_RETURN_NONE;
}
static PyObject *gLibFree(PyObject*, PyObject* args)
{
KX_Scene *kx_scene= gp_KetsjiScene;
char *path;
if (!PyArg_ParseTuple(args,"s:LibFree",&path))
return NULL;
if (kx_scene->GetSceneConverter()->FreeBlendFile(path))
{
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
static PyObject *gLibList(PyObject*, PyObject* args)
{
vector<Main*> &dynMaggie = gp_KetsjiScene->GetSceneConverter()->GetMainDynamic();
int i= 0;
PyObject *list= PyList_New(dynMaggie.size());
for (vector<Main*>::iterator it=dynMaggie.begin(); !(it==dynMaggie.end()); it++)
{
PyList_SET_ITEM(list, i++, PyUnicode_FromString( (*it)->name) );
}
return list;
}
static struct PyMethodDef game_methods[] = {
{"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (const char *)gPyExpandPath_doc},
@ -616,6 +745,14 @@ static struct PyMethodDef game_methods[] = {
{"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"},
{"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (const char *)"Gets a list of blend files in the same directory as the current blend file"},
{"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"},
{"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine stastics"},
/* library functions */
{"LibLoad", (PyCFunction)gLibLoad, METH_VARARGS, (const char *)""},
{"LibNew", (PyCFunction)gLibNew, METH_VARARGS, (const char *)""},
{"LibFree", (PyCFunction)gLibFree, METH_VARARGS, (const char *)""},
{"LibList", (PyCFunction)gLibList, METH_VARARGS, (const char *)""},
{NULL, (PyCFunction) NULL, 0, NULL }
};

@ -34,6 +34,8 @@
#include "SCA_ISensor.h"
#include "MT_Point3.h"
#include "SCA_IScene.h" /* only for scene replace */
#include "KX_Scene.h" /* only for scene replace */
struct KX_ClientObjectInfo;
class KX_RayCast;
@ -73,6 +75,10 @@ public:
bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
bool NeedRayCast(KX_ClientObjectInfo* client);
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= static_cast<KX_Scene *>(val);
}
//Python Interface
enum RayAxis {

@ -43,6 +43,8 @@
#include "MT_Vector3.h"
class SCA_IScene;
class KX_SCA_AddObjectActuator : public SCA_IActuator
@ -100,6 +102,11 @@ public:
virtual void
ProcessReplica();
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= val;
};
virtual bool
UnlinkObject(SCA_IObject* clientobj);

@ -59,6 +59,11 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator
virtual bool
Update();
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= val;
};
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */

@ -80,6 +80,11 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= val;
};
static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);

@ -273,6 +273,10 @@ RAS_BucketManager* KX_Scene::GetBucketManager()
}
CListValue* KX_Scene::GetTempObjectList()
{
return m_tempObjectList;
}
CListValue* KX_Scene::GetObjectList()
{
@ -280,7 +284,6 @@ CListValue* KX_Scene::GetObjectList()
}
CListValue* KX_Scene::GetRootParentList()
{
return m_parentlist;
@ -1043,7 +1046,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
newobj->SetDeformer(NULL);
}
if (mesh->IsDeformed())
if (mesh->IsDeformed()) /* checks GetMesh() isnt NULL */
{
// we must create a new deformer but which one?
KX_GameObject* parentobj = newobj->GetParent();
@ -1588,10 +1591,10 @@ void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter)
void KX_Scene::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv)
{
m_physicsEnvironment = physEnv;
if(m_physicsEnvironment) {
KX_TouchEventManager* touchmgr = new KX_TouchEventManager(m_logicmgr, physEnv);
m_logicmgr->RegisterEventManager(touchmgr);
return;
}
}
void KX_Scene::setSuspendedTime(double suspendedtime)
@ -1613,6 +1616,182 @@ double KX_Scene::getSuspendedDelta()
#ifndef DISABLE_PYTHON
#include "KX_BulletPhysicsController.h"
static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
{
SCA_LogicManager *logicmgr= to->GetLogicManager();
brick->Replace_IScene(to);
brick->Replace_NetworkScene(to->GetNetworkScene());
SCA_ISensor *sensor= dynamic_cast<class SCA_ISensor *>(brick);
if(sensor) {
sensor->Replace_EventManager(logicmgr);
}
/* near sensors have physics controllers */
KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick);
if(touch_sensor) {
touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
}
}
#include "CcdGraphicController.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
#include "CcdPhysicsEnvironment.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
#include "KX_BulletPhysicsController.h"
static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene *from)
{
{
SCA_ActuatorList& actuators= gameobj->GetActuators();
SCA_ActuatorList::iterator ita;
for (ita = actuators.begin(); !(ita==actuators.end()); ++ita)
{
MergeScene_LogicBrick(*ita, to);
}
}
{
SCA_SensorList& sensors= gameobj->GetSensors();
SCA_SensorList::iterator its;
for (its = sensors.begin(); !(its==sensors.end()); ++its)
{
MergeScene_LogicBrick(*its, to);
}
}
{
SCA_ControllerList& controllers= gameobj->GetControllers();
SCA_ControllerList::iterator itc;
for (itc = controllers.begin(); !(itc==controllers.end()); ++itc)
{
SCA_IController *cont= *itc;
MergeScene_LogicBrick(cont, to);
vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) {
MergeScene_LogicBrick(*ita, to);
}
for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) {
MergeScene_LogicBrick(*its, to);
}
}
}
/* graphics controller */
PHY_IGraphicController *ctrl = gameobj->GetGraphicController();
if(ctrl) {
/* SHOULD update the m_cullingTree */
ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
}
/* SG_Node can hold a scene reference */
SG_Node *sg= gameobj->GetSGNode();
if(sg) {
if(sg->GetSGClientInfo() == from) {
sg->SetSGClientInfo(to);
}
SGControllerList::iterator contit;
SGControllerList& controllers = sg->GetSGControllerList();
for (contit = controllers.begin();contit!=controllers.end();++contit)
{
KX_BulletPhysicsController *phys_ctrl= dynamic_cast<KX_BulletPhysicsController *>(*contit);
if (phys_ctrl)
phys_ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
}
}
}
bool KX_Scene::MergeScene(KX_Scene *other)
{
CcdPhysicsEnvironment *env= dynamic_cast<CcdPhysicsEnvironment *>(this->GetPhysicsEnvironment());
CcdPhysicsEnvironment *env_other= dynamic_cast<CcdPhysicsEnvironment *>(other->GetPhysicsEnvironment());
if((env==NULL) != (env_other==NULL)) /* TODO - even when both scenes have NONE physics, the other is loaded with bullet enabled, ??? */
{
printf("KX_Scene::MergeScene: physics scenes type differ, aborting\n");
printf("\tsource %d, terget %d\n", (int)(env!=NULL), (int)(env_other!=NULL));
return false;
}
if(GetSceneConverter() != other->GetSceneConverter()) {
printf("KX_Scene::MergeScene: converters differ, aborting\n");
return false;
}
GetBucketManager()->MergeBucketManager(other->GetBucketManager());
/* move materials across, assume they both use the same scene-converters */
GetSceneConverter()->MergeScene(this, other);
/* active + inactive == all ??? - lets hope so */
for (int i = 0; i < other->GetObjectList()->GetCount(); i++)
{
KX_GameObject* gameobj = (KX_GameObject*)other->GetObjectList()->GetValue(i);
MergeScene_GameObject(gameobj, this, other);
gameobj->UpdateBuckets(false); /* only for active objects */
}
for (int i = 0; i < other->GetInactiveList()->GetCount(); i++)
{
KX_GameObject* gameobj = (KX_GameObject*)other->GetInactiveList()->GetValue(i);
MergeScene_GameObject(gameobj, this, other);
}
GetTempObjectList()->MergeList(other->GetTempObjectList());
other->GetTempObjectList()->ReleaseAndRemoveAll();
GetObjectList()->MergeList(other->GetObjectList());
other->GetObjectList()->ReleaseAndRemoveAll();
GetInactiveList()->MergeList(other->GetInactiveList());
other->GetInactiveList()->ReleaseAndRemoveAll();
GetRootParentList()->MergeList(other->GetRootParentList());
other->GetRootParentList()->ReleaseAndRemoveAll();
GetLightList()->MergeList(other->GetLightList());
other->GetLightList()->ReleaseAndRemoveAll();
if(env) /* bullet scene? - dummy scenes dont need touching */
env->MergeEnvironment(env_other);
/* merge logic */
{
SCA_LogicManager *logicmgr= GetLogicManager();
SCA_LogicManager *logicmgr_other= other->GetLogicManager();
vector<class SCA_EventManager*>evtmgrs= logicmgr->GetEventManagers();
//vector<class SCA_EventManager*>evtmgrs_others= logicmgr_other->GetEventManagers();
//SCA_EventManager *evtmgr;
SCA_EventManager *evtmgr_other;
for(int i= 0; i < evtmgrs.size(); i++) {
evtmgr_other= logicmgr_other->FindEventManager(evtmgrs[i]->GetType());
if(evtmgr_other) /* unlikely but possible one scene has a joystick and not the other */
evtmgr_other->Replace_LogicManager(logicmgr);
/* when merging objects sensors are moved across into the new manager, dont need to do this here */
}
}
return true;
}
//----------------------------------------------------------------------------
//Python

@ -73,7 +73,6 @@ class KX_Camera;
class KX_GameObject;
class KX_LightObject;
class RAS_BucketManager;
class RAS_BucketManager;
class RAS_MaterialBucket;
class RAS_IPolyMaterial;
class RAS_IRasterizer;
@ -83,6 +82,9 @@ class btCollisionShape;
class KX_BlenderSceneConverter;
struct KX_ClientObjectInfo;
/* for ID freeing */
#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT))
/**
* The KX_Scene holds all data for an independent scene. It relates
* KX_Objects to the specific objects in the modules.
@ -100,6 +102,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
CullingInfo(int layer) : m_layer(layer) {}
};
protected:
RAS_BucketManager* m_bucketmanager;
CListValue* m_tempObjectList;
@ -318,6 +321,10 @@ public:
void
LogicEndFrame(
);
CListValue*
GetTempObjectList(
);
CListValue*
@ -471,6 +478,7 @@ public:
KX_Camera* GetpCamera();
NG_NetworkDeviceInterface* GetNetworkDeviceInterface();
NG_NetworkScene* GetNetworkScene();
KX_BlenderSceneConverter *GetSceneConverter() { return m_sceneConverter; }
/**
* Replicate the logic bricks associated to this object.
@ -567,6 +575,15 @@ public:
* Returns the Blender scene this was made from
*/
struct Scene *GetBlenderScene() { return m_blenderScene; }
bool MergeScene(KX_Scene *other);
//void PrintStats(int verbose_level) {
// m_bucketmanager->PrintStats(verbose_level)
//}
};
typedef std::vector<KX_Scene*> KX_SceneList;

@ -34,6 +34,8 @@
#define __KX_SCENEACTUATOR
#include "SCA_IActuator.h"
#include "SCA_IScene.h" /* Replace_IScene only */
#include "KX_Scene.h" /* Replace_IScene only */
class KX_SceneActuator : public SCA_IActuator
{
@ -89,6 +91,11 @@ class KX_SceneActuator : public SCA_IActuator
#ifndef DISABLE_PYTHON
virtual void Replace_IScene(SCA_IScene *val)
{
m_scene= static_cast<KX_Scene *>(val);
};
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */

@ -74,6 +74,7 @@ public:
virtual void RemoveSensor(SCA_ISensor* sensor);
SCA_LogicManager* GetLogicManager() { return m_logicmgr;}
PHY_IPhysicsEnvironment *GetPhysicsEnvironment() { return m_physEnv; }
virtual void Replace_PhysicsScene(PHY_IPhysicsEnvironment* env) { m_physEnv= env; }
#ifdef WITH_CXX_GUARDEDALLOC

@ -111,9 +111,11 @@ public:
return result;
}
virtual void EndFrame();
class PHY_IPhysicsController* GetPhysicsController() { return m_physCtrl; }
// todo: put some info for collision maybe
#ifndef DISABLE_PYTHON

@ -124,6 +124,21 @@ PHY_IGraphicController* CcdGraphicController::GetReplica(class PHY_IMotionState*
return replica;
}
void CcdGraphicController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* env)
{
CcdPhysicsEnvironment* phyEnv = static_cast<CcdPhysicsEnvironment*>(env);
/* Updates the m_phyEnv's m_cullingTree & m_cullingCache */
if(getBroadphaseHandle()) {
/* insert into the new physics scene */
Activate(false);
m_phyEnv= phyEnv;
Activate(true);
}
else {
m_phyEnv= phyEnv;
}
}
void CcdGraphicController::Activate(bool active)
{
if (active)

@ -47,6 +47,8 @@ public:
virtual void setBroadphaseHandle(btBroadphaseProxy* handle) { m_handle = handle; }
virtual btBroadphaseProxy* getBroadphaseHandle() { return m_handle; }
virtual void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* env);
////////////////////////////////////
// PHY_IGraphicController interface
////////////////////////////////////

@ -804,6 +804,23 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
}
void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env)
{
// can safely assume CCD environment
CcdPhysicsEnvironment *physicsEnv = static_cast<CcdPhysicsEnvironment*>(env);
if (m_cci.m_physicsEnv != physicsEnv)
{
// since the environment is changing, we must also move the controler to the
// new environement. Note that we don't handle sensor explicitely: this
// function can be called on sensor but only when they are not registered
if (m_cci.m_physicsEnv->removeCcdPhysicsController(this))
{
physicsEnv->addCcdPhysicsController(this);
}
m_cci.m_physicsEnv = physicsEnv;
}
}
void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform)
{

@ -432,6 +432,7 @@ protected:
// controller replication
virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl);
virtual void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env);
// kinematic methods
virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);

@ -420,7 +420,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
bool CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
{
//also remove constraint
btRigidBody* body = ctrl->GetRigidBody();
@ -445,13 +445,13 @@ void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctr
m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
}
}
m_controllers.erase(ctrl);
if (ctrl->m_registerCount != 0)
printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
//remove it from the triggers
m_triggerControllers.erase(ctrl);
return (m_controllers.erase(ctrl) != 0);
}
void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
@ -1736,10 +1736,19 @@ btDispatcher* CcdPhysicsEnvironment::getDispatcher()
return m_dynamicsWorld->getDispatcher();
}
void CcdPhysicsEnvironment::MergeEnvironment(CcdPhysicsEnvironment *other)
{
std::set<CcdPhysicsController*>::iterator it;
while (other->m_controllers.begin() != other->m_controllers.end())
{
it= other->m_controllers.begin();
CcdPhysicsController* ctrl= (*it);
other->removeCcdPhysicsController(ctrl);
this->addCcdPhysicsController(ctrl);
}
}
CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
{

@ -199,7 +199,7 @@ protected:
void addCcdPhysicsController(CcdPhysicsController* ctrl);
void removeCcdPhysicsController(CcdPhysicsController* ctrl);
bool removeCcdPhysicsController(CcdPhysicsController* ctrl);
void updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask);
@ -242,13 +242,13 @@ protected:
class btConstraintSolver* GetConstraintSolver();
void MergeEnvironment(CcdPhysicsEnvironment *other);
protected:
std::set<CcdPhysicsController*> m_controllers;
std::set<CcdPhysicsController*> m_triggerControllers;
PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE];

@ -31,6 +31,8 @@
#include "PHY_DynamicTypes.h"
class PHY_IPhysicsEnvironment;
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
@ -47,6 +49,7 @@ class PHY_IController
// clientinfo for raycasts for example
virtual void* getNewClientInfo()=0;
virtual void setNewClientInfo(void* clientinfo)=0;
virtual void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env)=0;
#ifdef WITH_CXX_GUARDEDALLOC

@ -32,7 +32,6 @@
#include "PHY_IController.h"
/**
PHY_IPhysicsController is the abstract simplified Interface to a physical object.
It contains the IMotionState and IDeformableMesh Interfaces.
@ -51,7 +50,6 @@ class PHY_IGraphicController : public PHY_IController
virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate) {return 0;}
#ifdef WITH_CXX_GUARDEDALLOC
void *operator new( unsigned int num_bytes) { return MEM_mallocN(num_bytes, "GE:PHY_IController"); }
void operator delete( void *mem ) { MEM_freeN(mem); }

@ -32,6 +32,7 @@
#include "PHY_IController.h"
class PHY_IMotionState;
class PHY_IPhysicsEnvironment;
/**
PHY_IPhysicsController is the abstract simplified Interface to a physical object.

@ -317,3 +317,44 @@ void RAS_BucketManager::ReleaseMaterials(RAS_IPolyMaterial * mat)
}
}
/* frees the bucket, only used when freeing scenes */
void RAS_BucketManager::RemoveMaterial(RAS_IPolyMaterial * mat)
{
BucketList::iterator bit, bitp;
list<RAS_MeshSlot>::iterator mit;
int i;
for(i=0; i<m_SolidBuckets.size(); i++) {
RAS_MaterialBucket *bucket = m_SolidBuckets[i];
if (mat == bucket->GetPolyMaterial()) {
m_SolidBuckets.erase(m_SolidBuckets.begin()+i);
delete bucket;
i--;
}
}
for(int i=0; i<m_AlphaBuckets.size(); i++) {
RAS_MaterialBucket *bucket = m_AlphaBuckets[i];
if (mat == bucket->GetPolyMaterial()) {
m_AlphaBuckets.erase(m_AlphaBuckets.begin()+i);
delete bucket;
i--;
}
}
}
//#include <stdio.h>
void RAS_BucketManager::MergeBucketManager(RAS_BucketManager *other)
{
/* concatinate lists */
// printf("BEFORE %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
GetSolidBuckets().insert( GetSolidBuckets().end(), other->GetSolidBuckets().begin(), other->GetSolidBuckets().end() );
other->GetSolidBuckets().clear();
GetAlphaBuckets().insert( GetAlphaBuckets().end(), other->GetAlphaBuckets().begin(), other->GetAlphaBuckets().end() );
other->GetAlphaBuckets().clear();
//printf("AFTER %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
}

@ -60,6 +60,21 @@ public:
void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL);
void ReleaseMaterials(RAS_IPolyMaterial * material = NULL);
void RemoveMaterial(RAS_IPolyMaterial * mat); // freeing scenes only
/* for merging */
void MergeBucketManager(RAS_BucketManager *other);
BucketList & GetSolidBuckets() {return m_SolidBuckets;};
BucketList & GetAlphaBuckets() {return m_AlphaBuckets;};
/*void PrintStats(int verbose_level) {
printf("\nMappings...\n");
printf("\t m_SolidBuckets: %d\n", m_SolidBuckets.size());
printf("\t\t m_SolidBuckets: %d\n", m_SolidBuckets.size());
printf("\t m_AlphaBuckets: %d\n", m_AlphaBuckets.size());
}*/
private:
void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha);

@ -46,6 +46,7 @@ class RAS_IRasterizer;
struct MTFace;
struct Material;
struct Scene;
class SCA_IScene;
enum MaterialProps
{
@ -164,6 +165,9 @@ public:
virtual void GetMaterialRGBAColor(unsigned char *rgba) const;
virtual bool UsesLighting(RAS_IRasterizer *rasty) const;
virtual bool UsesObjectColor() const;
virtual void Replace_IScene(SCA_IScene *val) {}; /* overridden by KX_BlenderMaterial */
/*
* PreCalculate texture gen
*/

@ -104,6 +104,10 @@ RAS_MeshObject::~RAS_MeshObject()
for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++)
delete (*it);
m_sharedvertex_map.clear();
m_Polygons.clear();
m_materials.clear();
}
bool RAS_MeshObject::MeshModified()

@ -80,7 +80,7 @@ public:
virtual ~RAS_MeshObject();
bool IsDeformed() { return m_bDeformed; }
bool IsDeformed() { return (m_bDeformed && m_mesh); }
/* materials */
int NumMaterials();

@ -241,6 +241,22 @@ public:
m_SGclientObject = clientObject;
}
/* needed for scene switching */
inline const void* GetSGClientInfo() const
{
return m_SGclientInfo;
}
inline void* GetSGClientInfo()
{
return m_SGclientInfo;
}
void SetSGClientInfo(void* clientInfo)
{
m_SGclientInfo = clientInfo;
}
/**
* Set the current simulation time for this node.
* The implementation of this function runs through