/* this function is used to pre-filter the object before casting the ray on them. * This is useful for "X-Ray" option when we want to see "through" unwanted object. */ bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client) { KX_GameObject *hitKXObj = client->m_gameobject; if (client->m_type > KX_ClientObjectInfo::ACTOR) { // Unknown type of object, skip it. // Should not occur as the sensor objects are filtered in RayTest() printf("Invalid client type %d found ray casting\n", client->m_type); return false; } if (m_bXRay && m_propertyname.Length() != 0) { if (m_bFindMaterial) { bool found = false; for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; if (found) break; } } if (!found) return false; } else { if (hitKXObj->GetProperty(m_propertyname) == NULL) return false; } } return true; }
bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata) { // KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr; KX_GameObject* parent = (KX_GameObject*)GetParent(); // need the mapping from PHY_IPhysicsController to gameobjects now KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo*> (object1 == m_physCtrl? ((PHY_IPhysicsController*)object2)->GetNewClientInfo(): ((PHY_IPhysicsController*)object1)->GetNewClientInfo()); KX_GameObject* gameobj = ( client_info ? client_info->m_gameobject : NULL); // add the same check as in SCA_ISensor::Activate(), // we don't want to record collision when the sensor is not active. if (m_links && !m_suspended && gameobj && (gameobj != parent) && client_info->isActor()) { bool found = m_touchedpropname.IsEmpty(); bool hitMaterial = false; if (!found) { if (m_bFindMaterial) { for (unsigned int i = 0; i < gameobj->GetMeshCount(); ++i) { RAS_MeshObject *meshObj = gameobj->GetMesh(i); for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; if (found) { hitMaterial = true; break; } } } } else { found = (gameobj->GetProperty(m_touchedpropname) != NULL); } } if (found) { if (!m_colliders->SearchValue(gameobj)) { m_colliders->Add(gameobj->AddRef()); if (m_bTouchPulse) m_bColliderHash += (uint_ptr)(static_cast<void *>(&gameobj)); } m_bTriggered = true; m_hitObject = gameobj; m_hitMaterial = hitMaterial; //printf("KX_TouchSensor::HandleCollision\n"); } } return false; // was DT_CONTINUE but this was defined in sumo as false. }
bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *result, void * const data) { KX_GameObject* hitKXObj = client_info->m_gameobject; /* Is this me? In the ray test, there are a lot of extra checks * for aliasing artifacts from self-hits. That doesn't happen * here, so a simple test suffices. Or does the camera also get * self-hits? (No, and the raysensor shouldn't do it either, since * self-hits are excluded by setting the correct ignore-object.) * Hitspots now become valid. */ KX_GameObject* thisObj = (KX_GameObject*) GetParent(); bool bFound = false; if ((m_focusmode == 2) || hitKXObj == thisObj) { if (m_propertyname.Length() == 0) { bFound = true; } else { if (m_bFindMaterial) { for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; if (bFound) break; } } } else { bFound = hitKXObj->GetProperty(m_propertyname) != NULL; } } if (bFound) { m_hitObject = hitKXObj; m_hitPosition = result->m_hitPoint; m_hitNormal = result->m_hitNormal; m_hitUV = result->m_hitUV; return true; } } return true; // object must be visible to trigger //return false; // occluded objects can trigger }
// get pointer to material RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID) { // if object is available if (obj != NULL) { // get pointer to texture image KX_GameObject * gameObj = gameObjectType.checkType(obj); if (gameObj != NULL && gameObj->GetMeshCount() > 0) { // get material from mesh RAS_MeshObject * mesh = gameObj->GetMesh(0); RAS_MeshMaterial *meshMat = mesh->GetMeshMaterial(matID); if (meshMat != NULL && meshMat->m_bucket != NULL) // return pointer to polygon or blender material return meshMat->m_bucket->GetPolyMaterial(); } } // otherwise material was not found return NULL; }
// this function is called only for sensor objects // return true if the controller can collide with the object bool KX_CollisionSensor::BroadPhaseSensorFilterCollision(void *obj1, void *obj2) { BLI_assert(obj1 == m_physCtrl && obj2); KX_GameObject *myobj = (KX_GameObject *)GetParent(); KX_GameObject *myparent = myobj->GetParent(); KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(((PHY_IPhysicsController *)obj2)->GetNewClientInfo()); KX_ClientObjectInfo *my_client_info = static_cast<KX_ClientObjectInfo *>(m_physCtrl->GetNewClientInfo()); KX_GameObject *otherobj = (client_info ? client_info->m_gameobject : NULL); // we can only check on persistent characteristic: m_link and m_suspended are not // good candidate because they are transient. That must be handled at another level if (!otherobj || otherobj == myparent || // don't interact with our parent (my_client_info->m_type == KX_ClientObjectInfo::OBACTORSENSOR && client_info->m_type != KX_ClientObjectInfo::ACTOR)) // only with actor objects { return false; } bool found = m_touchedpropname.empty(); if (!found) { if (m_bFindMaterial) { for (unsigned int i = 0; i < otherobj->GetMeshCount(); ++i) { RAS_MeshObject *meshObj = otherobj->GetMesh(i); for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { found = (m_touchedpropname == std::string(meshObj->GetMaterialName(j), 2)); if (found) { break; } } } } else { found = (otherobj->GetProperty(m_touchedpropname) != NULL); } } return found; }
/* Note m_map_*** are all ok and don't 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= -1; 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++; } /* should never happen but just to be safe */ if (maggie_index == -1) return false; 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 { /* in case the mesh might be refered to later */ { CTR_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); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); i--; } } } /* Now unregister actions */ { CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); for (int i=0; i<mapStringToActions.size(); i++) { ID *action= (ID*) *mapStringToActions.at(i); if (IS_TAGGED(action)) { STR_HashedString an = action->name+2; mapStringToActions.remove(an); 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; } } /* make sure action actuators are not referencing tagged actions */ for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++) { if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } } } } } } } int size; // delete the entities of this scene /* TODO - */ #if 0 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++; } } #endif /* Worlds don't 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; }
/* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { int maggie_index = -1; int i = 0; if (maggie == NULL) return false; // If the given library is currently in loading, we do nothing. if (m_status_map.count(maggie->name)) { BLI_mutex_lock(&m_threadinfo->m_mutex); const bool finished = m_status_map[maggie->name]->IsFinished(); BLI_mutex_unlock(&m_threadinfo->m_mutex); if (!finished) { printf("Library (%s) is currently being loaded asynchronously, and cannot be freed until this process is done\n", maggie->name); 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) { BKE_main_id_tag_all(main, LIB_TAG_DOIT, false); } else { maggie_index = i; } i++; } /* should never happen but just to be safe */ if (maggie_index == -1) return false; m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, LIB_TAG_DOIT, true); /* 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())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); m_polymat_cache.erase(scene); scene_idx--; numScenes--; } else { /* in case the mesh might be refered to later */ { CTR_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); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); i--; } } } /* Now unregister actions */ { CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); for (int i = 0; i < mapStringToActions.size(); i++) { ID *action = (ID*) *mapStringToActions.at(i); if (IS_TAGGED(action)) { STR_HashedString an = action->name + 2; mapStringToActions.remove(an); m_map_blender_to_gameAdtList.remove(CHashedPtr(action)); 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 { gameobj->RemoveTaggedActions(); /* 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; } else { /* also free the mesh if it's using a tagged material */ int mat_index = mesh->NumMaterials(); while (mat_index--) { if (IS_TAGGED(mesh->GetMeshMaterial(mat_index)->m_bucket->GetPolyMaterial()->GetBlenderMaterial())) { gameobj->RemoveMeshes(); /* XXX - slack, same as above */ break; } } } } /* make sure action actuators are not referencing tagged actions */ for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } } } } } } } int size; // delete the entities of this scene /* TODO - */ #if 0 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++; } } #endif /* Worlds don't 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; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); bmat = bl_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; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { // Remove the poly material coresponding to this Blender Material. m_polymat_cache[polymit->first].erase(bmat); delete polymit->second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; } else { i++; polymit++; } } 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)) { // Remove the bl material coresponding to this Blender Material. m_mat_cache[matit->first].erase(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; RAS_BucketManager::BucketList::iterator bit; list<RAS_MeshSlot>::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); for (i = 0, meshit = m_meshobjects.begin(); i < size;) { RAS_MeshObject *me = meshit->second; if (IS_TAGGED(me->GetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { if (msit->m_mesh == meshit->second) (*bit)->RemoveMesh(&(*msit++)); else msit++; } } // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { if (msit->m_mesh == meshit->second) (*bit)->RemoveMesh(&(*msit++)); else msit++; } } // Now it should be safe to delete delete meshit->second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; } else { i++; meshit++; } } #ifdef WITH_PYTHON /* make sure this maggie is removed from the import list if it's there * (this operation is safe if it isn't in the list) */ removeImportMain(maggie); #endif delete m_status_map[maggie->name]; m_status_map.erase(maggie->name); BKE_main_free(maggie); return true; }