|
|
@@ -59,7 +59,8 @@ CrowdManager::CrowdManager(Context* context) :
|
|
|
Component(context),
|
|
|
crowd_(0),
|
|
|
maxAgents_(DEFAULT_MAX_AGENTS),
|
|
|
- maxAgentRadius_(DEFAULT_MAX_AGENT_RADIUS)
|
|
|
+ maxAgentRadius_(DEFAULT_MAX_AGENT_RADIUS),
|
|
|
+ navigationMeshId_(0)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
@@ -75,7 +76,8 @@ void CrowdManager::RegisterObject(Context* context)
|
|
|
|
|
|
ATTRIBUTE("Max Agents", unsigned, maxAgents_, DEFAULT_MAX_AGENTS, AM_DEFAULT);
|
|
|
ATTRIBUTE("Max Agent Radius", float, maxAgentRadius_, DEFAULT_MAX_AGENT_RADIUS, AM_DEFAULT);
|
|
|
- //TODO: add attribute for navmesh
|
|
|
+ ATTRIBUTE("Navigation Mesh", unsigned, navigationMeshId_, 0, AM_DEFAULT | AM_COMPONENTID);
|
|
|
+ // TODO: add attributes for crowd filter type and avoidance parameters configuration
|
|
|
}
|
|
|
|
|
|
void CrowdManager::ApplyAttributes()
|
|
|
@@ -84,8 +86,18 @@ void CrowdManager::ApplyAttributes()
|
|
|
maxAgents_ = Max(1, maxAgents_);
|
|
|
maxAgentRadius_ = Max(0.f, maxAgentRadius_);
|
|
|
|
|
|
+ Scene* scene = GetScene();
|
|
|
+ if (scene && navigationMeshId_)
|
|
|
+ {
|
|
|
+ NavigationMesh* navMesh = dynamic_cast<NavigationMesh*>(scene->GetComponent(navigationMeshId_));
|
|
|
+ if (navMesh)
|
|
|
+ navigationMesh_ = navMesh;
|
|
|
+ }
|
|
|
+ navigationMeshId_ = navigationMesh_ ? navigationMesh_->GetID() : 0;
|
|
|
+
|
|
|
+ // If the Detour crowd initialization parameters have changed then recreate it
|
|
|
if (crowd_ && (crowd_->getAgentCount() != maxAgents_ || crowd_->getMaxAgentRadius() != (maxAgentRadius_ > 0.f ? maxAgentRadius_ : navigationMesh_->GetAgentRadius())))
|
|
|
- CreateCrowd(true);
|
|
|
+ CreateCrowd();
|
|
|
}
|
|
|
|
|
|
void CrowdManager::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
|
|
|
@@ -158,8 +170,9 @@ void CrowdManager::SetCrowdTarget(const Vector3& position, Node* node)
|
|
|
Vector3 moveTarget(position);
|
|
|
for (unsigned i = 0; i < agents.Size(); ++i)
|
|
|
{
|
|
|
- CrowdAgent* agent = agents[i];
|
|
|
// Give application a chance to determine the desired crowd formation when they reach the target position
|
|
|
+ CrowdAgent* agent = agents[i];
|
|
|
+
|
|
|
using namespace CrowdAgentFormation;
|
|
|
|
|
|
VariantMap& map = GetEventDataMap();
|
|
|
@@ -201,7 +214,7 @@ void CrowdManager::SetMaxAgents(unsigned maxAgents)
|
|
|
if (maxAgents != maxAgents_ && maxAgents > 0)
|
|
|
{
|
|
|
maxAgents_ = maxAgents;
|
|
|
- CreateCrowd(true);
|
|
|
+ CreateCrowd();
|
|
|
MarkNetworkUpdate();
|
|
|
}
|
|
|
}
|
|
|
@@ -211,7 +224,7 @@ void CrowdManager::SetMaxAgentRadius(float maxAgentRadius)
|
|
|
if (maxAgentRadius != maxAgentRadius_ && maxAgentRadius > 0.f)
|
|
|
{
|
|
|
maxAgentRadius_ = maxAgentRadius;
|
|
|
- CreateCrowd(true);
|
|
|
+ CreateCrowd();
|
|
|
MarkNetworkUpdate();
|
|
|
}
|
|
|
}
|
|
|
@@ -221,7 +234,8 @@ void CrowdManager::SetNavigationMesh(NavigationMesh* navMesh)
|
|
|
if (navMesh != navigationMesh_ && navMesh)
|
|
|
{
|
|
|
navigationMesh_ = navMesh;
|
|
|
- CreateCrowd(true);
|
|
|
+ navigationMeshId_ = navMesh->GetID();
|
|
|
+ CreateCrowd();
|
|
|
MarkNetworkUpdate();
|
|
|
}
|
|
|
}
|
|
|
@@ -393,6 +407,32 @@ void CrowdManager::RemoveAgent(CrowdAgent* agent)
|
|
|
crowd_->removeAgent(agent->GetAgentCrowdId());
|
|
|
}
|
|
|
|
|
|
+void DetourCrowdManager::OnSceneSet(Scene* scene)
|
|
|
+{
|
|
|
+ // Subscribe to the scene subsystem update, which will trigger the crowd update step, and grab a reference
|
|
|
+ // to the scene's NavigationMesh
|
|
|
+ if (scene)
|
|
|
+ {
|
|
|
+ SubscribeToEvent(scene, E_SCENESUBSYSTEMUPDATE, HANDLER(CrowdManager, HandleSceneSubsystemUpdate));
|
|
|
+ NavigationMesh* mesh = GetScene()->GetDerivedComponent<NavigationMesh>();
|
|
|
+ if (mesh)
|
|
|
+ {
|
|
|
+ SubscribeToEvent(mesh, E_NAVIGATION_MESH_REBUILT, HANDLER(CrowdManager, HandleNavMeshFullRebuild));
|
|
|
+ navigationMesh_ = navMesh;
|
|
|
+ navigationMeshId_ = navMesh->GetID();
|
|
|
+ CreateCrowd(false);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ LOGERROR("CrowdManager requires an existing navigation mesh");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ UnsubscribeFromEvent(E_SCENESUBSYSTEMUPDATE);
|
|
|
+ UnsubscribeFromEvent(E_NAVIGATION_MESH_REBUILT);
|
|
|
+ navigationMesh_.Reset();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void CrowdManager::Update(float delta)
|
|
|
{
|
|
|
if (!crowd_ || !navigationMesh_)
|
|
|
@@ -422,28 +462,4 @@ void CrowdManager::HandleNavMeshFullRebuild(StringHash eventType, VariantMap& ev
|
|
|
SetNavigationMesh(static_cast<NavigationMesh*>(eventData[P_MESH].GetPtr()));
|
|
|
}
|
|
|
|
|
|
-void DetourCrowdManager::OnSceneSet(Scene* scene)
|
|
|
-{
|
|
|
- // Subscribe to the scene subsystem update, which will trigger the crowd update step, and grab a reference
|
|
|
- // to the scene's NavigationMesh
|
|
|
- if (scene)
|
|
|
- {
|
|
|
- SubscribeToEvent(scene, E_SCENESUBSYSTEMUPDATE, HANDLER(CrowdManager, HandleSceneSubsystemUpdate));
|
|
|
- NavigationMesh* mesh = GetScene()->GetDerivedComponent<NavigationMesh>();
|
|
|
- if (mesh)
|
|
|
- {
|
|
|
- SubscribeToEvent(mesh, E_NAVIGATION_MESH_REBUILT, HANDLER(CrowdManager, HandleNavMeshFullRebuild));
|
|
|
- SetNavigationMesh(mesh);
|
|
|
- }
|
|
|
- else
|
|
|
- LOGERROR("CrowdManager requires an existing navigation mesh");
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- UnsubscribeFromEvent(E_SCENESUBSYSTEMUPDATE);
|
|
|
- UnsubscribeFromEvent(E_NAVIGATION_MESH_REBUILT);
|
|
|
- navigationMesh_.Reset();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
}
|