// this function is called at broad phase stage to check if the two controller // need to interact at all. It is used for Near/Radar sensor that don't need to // check collision with object not included in filter bool KX_NearSensor::BroadPhaseFilterCollision(void*obj1,void*obj2) { KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); // need the mapping from PHY_IPhysicsController to gameobjects now assert(obj1==m_physCtrl && obj2); KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo*>((static_cast<PHY_IPhysicsController*>(obj2))->GetNewClientInfo()); KX_GameObject* gameobj = ( client_info ? client_info->m_gameobject : NULL); if (gameobj && (gameobj != parent)) { // only take valid colliders if (client_info->m_type == KX_ClientObjectInfo::ACTOR) { if ((m_touchedpropname.size() == 0) || (gameobj->GetProperty(m_touchedpropname))) { return true; } } } return false; }
/* 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 }
bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; bool bFound = false; if (m_propertyname.Length() == 0) { bFound = true; } else { if (m_bFindMaterial) { if (client->m_auxilary_info) { bFound = (m_propertyname== ((char*)client->m_auxilary_info)); } } else { bFound = hitKXObj->GetProperty(m_propertyname) != NULL; } } if (bFound) { m_rayHit = true; m_hitObject = hitKXObj; m_hitPosition[0] = result->m_hitPoint[0]; m_hitPosition[1] = result->m_hitPoint[1]; m_hitPosition[2] = result->m_hitPoint[2]; m_hitNormal[0] = result->m_hitNormal[0]; m_hitNormal[1] = result->m_hitNormal[1]; m_hitNormal[2] = result->m_hitNormal[2]; m_hitMaterial = (client->m_auxilary_info ? (char*)client->m_auxilary_info : ""); } // no multi-hit search yet return true; }
// 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; }
bool BL_ActionActuator::Update(double curtime, bool frame) { bool bNegativeEvent = false; bool bPositiveEvent = false; bool bUseContinue = false; KX_GameObject *obj = (KX_GameObject*)GetParent(); short playtype = BL_Action::ACT_MODE_PLAY; float start = m_startframe; float end = m_endframe; // If we don't have an action, we can't do anything if (!m_action) return false; // Convert our playtype to one that BL_Action likes switch(m_playtype) { case ACT_ACTION_LOOP_END: case ACT_ACTION_LOOP_STOP: playtype = BL_Action::ACT_MODE_LOOP; break; case ACT_ACTION_PINGPONG: // We handle ping pong ourselves to increase compabitility // with files made prior to animation changes from GSoC 2011. playtype = BL_Action::ACT_MODE_PLAY; if (m_flag & ACT_FLAG_REVERSE) { start = m_endframe; end = m_startframe; } break; case ACT_ACTION_FROM_PROP: CValue* prop = GetParent()->GetProperty(m_propname); // If we don't have a property, we can't do anything, so just bail if (!prop) return false; playtype = BL_Action::ACT_MODE_PLAY; start = end = prop->GetNumber(); break; } if (m_flag & ACT_FLAG_CONTINUE) bUseContinue = true; // Handle events if (frame) { bNegativeEvent = m_negevent; bPositiveEvent = m_posevent; RemoveAllEvents(); } // "Active" actions need to keep updating their current frame if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE)) m_localtime = obj->GetActionFrame(m_layer); if (m_flag & ACT_FLAG_ATTEMPT_PLAY) SetLocalTime(curtime); else ResetStartTime(curtime); // Handle a frame property if it's defined if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0) { CValue* oldprop = obj->GetProperty(m_framepropname); CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer)); if (oldprop) oldprop->SetValue(newval); else obj->SetProperty(m_framepropname, newval); newval->Release(); } // Handle a finished animation if ((m_flag & ACT_FLAG_PLAY_END) && (m_flag & ACT_FLAG_ACTIVE) && obj->IsActionDone(m_layer)) { m_flag &= ~ACT_FLAG_ACTIVE; m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; if (m_playtype == ACT_ACTION_PINGPONG) m_flag ^= ACT_FLAG_REVERSE; return false; } // If a different action is playing, we've been overruled and are no longer active if (obj->GetCurrentAction(m_layer) != m_action && !obj->IsActionDone(m_layer)) m_flag &= ~ACT_FLAG_ACTIVE; if (bPositiveEvent || (m_flag & ACT_FLAG_ATTEMPT_PLAY && !(m_flag & ACT_FLAG_ACTIVE))) { if (bPositiveEvent && m_playtype == ACT_ACTION_PLAY) { if (obj->IsActionDone(m_layer)) m_localtime = start; ResetStartTime(curtime); } if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags)) { m_flag |= ACT_FLAG_ACTIVE; if (bUseContinue) obj->SetActionFrame(m_layer, m_localtime); if (m_playtype == ACT_ACTION_PLAY || m_playtype == ACT_ACTION_PINGPONG) m_flag |= ACT_FLAG_PLAY_END; else m_flag &= ~ACT_FLAG_PLAY_END; } m_flag |= ACT_FLAG_ATTEMPT_PLAY; } else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent) { m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; m_localtime = obj->GetActionFrame(m_layer); bAction *curr_action = obj->GetCurrentAction(m_layer); if (curr_action && curr_action != m_action) { // Someone changed the action on us, so we wont mess with it // Hopefully there wont be too many problems with two actuators using // the same action... m_flag &= ~ACT_FLAG_ACTIVE; return false; } switch(m_playtype) { case ACT_ACTION_LOOP_STOP: obj->StopAction(m_layer); // Stop the action after getting the frame // We're done m_flag &= ~ACT_FLAG_ACTIVE; return false; case ACT_ACTION_LOOP_END: // Convert into a play and let it finish obj->SetPlayMode(m_layer, BL_Action::ACT_MODE_PLAY); m_flag |= ACT_FLAG_PLAY_END; break; case ACT_ACTION_FLIPPER: // Convert into a play action and play back to the beginning end = start; start = obj->GetActionFrame(m_layer); obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags); m_flag |= ACT_FLAG_PLAY_END; break; } } return m_flag & ACT_FLAG_ACTIVE; }