Exemple #1
0
bool KX_CollisionSensor::NewHandleCollision(void *object1, void *object2, const PHY_CollData *colldata)
{
	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.empty();
		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 = (m_touchedpropname == std::string(meshObj->GetMaterialName(j), 2));
						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_bCollisionPulse) {
					m_bColliderHash += (uint_ptr)(static_cast<void *>(&gameobj));
				}
			}
			m_bTriggered = true;
			m_hitObject = gameobj;
			m_hitMaterial = hitMaterial;
		}

	}
	return 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
}
Exemple #3
0
// 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(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;
}