1 // 2 // Copyright (c) 2008-2017 the Urho3D project. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 // 22 23 #pragma once 24 25 #include "../Navigation/CrowdManager.h" 26 #include "../Scene/Component.h" 27 28 namespace Urho3D 29 { 30 31 enum CrowdAgentRequestedTarget 32 { 33 CA_REQUESTEDTARGET_NONE = 0, 34 CA_REQUESTEDTARGET_POSITION, 35 CA_REQUESTEDTARGET_VELOCITY 36 }; 37 38 enum CrowdAgentTargetState 39 { 40 CA_TARGET_NONE = 0, 41 CA_TARGET_FAILED, 42 CA_TARGET_VALID, 43 CA_TARGET_REQUESTING, 44 CA_TARGET_WAITINGFORQUEUE, 45 CA_TARGET_WAITINGFORPATH, 46 CA_TARGET_VELOCITY 47 }; 48 49 enum CrowdAgentState 50 { 51 CA_STATE_INVALID = 0, ///< The agent is not in a valid state. 52 CA_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon. 53 CA_STATE_OFFMESH ///< The agent is traversing an off-mesh connection. 54 }; 55 56 enum NavigationQuality 57 { 58 NAVIGATIONQUALITY_LOW = 0, 59 NAVIGATIONQUALITY_MEDIUM = 1, 60 NAVIGATIONQUALITY_HIGH = 2 61 }; 62 63 enum NavigationPushiness 64 { 65 NAVIGATIONPUSHINESS_LOW = 0, 66 NAVIGATIONPUSHINESS_MEDIUM, 67 NAVIGATIONPUSHINESS_HIGH, 68 NAVIGATIONPUSHINESS_NONE 69 }; 70 71 /// Crowd agent component, requires a CrowdManager component in the scene. When not set explicitly, agent's radius and height are defaulted to navigation mesh's agent radius and height, respectively. 72 class URHO3D_API CrowdAgent : public Component 73 { 74 URHO3D_OBJECT(CrowdAgent, Component); 75 76 friend class CrowdManager; 77 friend void CrowdAgentUpdateCallback(dtCrowdAgent* ag, float dt); 78 79 public: 80 /// Construct. 81 CrowdAgent(Context* context); 82 /// Destruct. 83 virtual ~CrowdAgent(); 84 /// Register object factory. 85 static void RegisterObject(Context* context); 86 /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update. 87 virtual void ApplyAttributes(); 88 89 /// Handle enabled/disabled state change. 90 virtual void OnSetEnabled(); 91 /// Draw debug geometry. 92 void DrawDebugGeometry(bool depthTest); 93 /// Draw debug feelers. 94 virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest); 95 96 /// Submit a new target position request for this agent. 97 void SetTargetPosition(const Vector3& position); 98 /// Submit a new target velocity request for this agent. 99 void SetTargetVelocity(const Vector3& velocity); 100 /// Reset any target request for the specified agent. Note that the agent will continue to move into the current direction; set a zero target velocity to actually stop. 101 void ResetTarget(); 102 /// Update the node position. When set to false, the node position should be updated by other means (e.g. using Physics) in response to the E_CROWD_AGENT_REPOSITION event. 103 void SetUpdateNodePosition(bool unodepos); 104 /// Set the agent's max acceleration. 105 void SetMaxAccel(float maxAccel); 106 /// Set the agent's max velocity. 107 void SetMaxSpeed(float maxSpeed); 108 /// Set the agent's radius. 109 void SetRadius(float radius); 110 /// Set the agent's height. 111 void SetHeight(float height); 112 /// Set the agent's query filter type. 113 void SetQueryFilterType(unsigned queryFilterType); 114 /// Set the agent's obstacle avoidance type. 115 void SetObstacleAvoidanceType(unsigned obstacleAvoidanceType); 116 /// Set the agent's navigation quality. 117 void SetNavigationQuality(NavigationQuality val); 118 /// Set the agent's navigation pushiness. 119 void SetNavigationPushiness(NavigationPushiness val); 120 121 /// Return the agent's position. 122 Vector3 GetPosition() const; 123 /// Return the agent's desired velocity. 124 Vector3 GetDesiredVelocity() const; 125 /// Return the agent's actual velocity. 126 Vector3 GetActualVelocity() const; 127 128 /// Return the agent's requested target position. GetTargetPosition()129 const Vector3& GetTargetPosition() const { return targetPosition_; } 130 131 /// Return the agent's requested target velocity. GetTargetVelocity()132 const Vector3& GetTargetVelocity() const { return targetVelocity_; } 133 134 /// Return the agent's requested target type, if any. GetRequestedTargetType()135 CrowdAgentRequestedTarget GetRequestedTargetType() const { return requestedTargetType_; } 136 137 /// Return the agent's state. 138 CrowdAgentState GetAgentState() const; 139 /// Return the agent's target state. 140 CrowdAgentTargetState GetTargetState() const; 141 142 /// Return true when the node's position should be updated by the CrowdManager. GetUpdateNodePosition()143 bool GetUpdateNodePosition() const { return updateNodePosition_; } 144 145 /// Return the agent id. GetAgentCrowdId()146 int GetAgentCrowdId() const { return agentCrowdId_; } 147 148 /// Get the agent's max acceleration. GetMaxAccel()149 float GetMaxAccel() const { return maxAccel_; } 150 151 /// Get the agent's max velocity. GetMaxSpeed()152 float GetMaxSpeed() const { return maxSpeed_; } 153 154 /// Get the agent's radius. GetRadius()155 float GetRadius() const { return radius_; } 156 157 /// Get the agent's height. GetHeight()158 float GetHeight() const { return height_; } 159 160 /// Get the agent's query filter type. GetQueryFilterType()161 unsigned GetQueryFilterType() const { return queryFilterType_; } 162 163 /// Get the agent's obstacle avoidance type. GetObstacleAvoidanceType()164 unsigned GetObstacleAvoidanceType() const { return obstacleAvoidanceType_; } 165 166 /// Get the agent's navigation quality. GetNavigationQuality()167 NavigationQuality GetNavigationQuality() const { return navQuality_; } 168 169 /// Get the agent's navigation pushiness. GetNavigationPushiness()170 NavigationPushiness GetNavigationPushiness() const { return navPushiness_; } 171 172 /// Return true when the agent has a target. HasRequestedTarget()173 bool HasRequestedTarget() const { return requestedTargetType_ != CA_REQUESTEDTARGET_NONE; } 174 175 /// Return true when the agent has arrived at its target. 176 bool HasArrived() const; 177 /// Return true when the agent is in crowd (being managed by a crowd manager). 178 bool IsInCrowd() const; 179 180 protected: 181 /// Handle crowd agent being updated. It is called by CrowdManager::Update() via callback. 182 virtual void OnCrowdUpdate(dtCrowdAgent* ag, float dt); 183 /// Handle node being assigned. 184 virtual void OnNodeSet(Node* node); 185 /// Handle node being assigned. 186 virtual void OnSceneSet(Scene* scene); 187 /// \todo Handle node transform being dirtied. 188 virtual void OnMarkedDirty(Node* node); 189 /// Get internal Detour crowd agent. 190 const dtCrowdAgent* GetDetourCrowdAgent() const; 191 /// Handle navigation mesh tile added. 192 void HandleNavigationTileAdded(StringHash eventType, VariantMap& eventData); 193 194 private: 195 /// Update Detour crowd agent parameter. 196 void UpdateParameters(unsigned scope = M_MAX_UNSIGNED); 197 /// Add agent into crowd. 198 int AddAgentToCrowd(bool force = false); 199 /// Remove agent from crowd. 200 void RemoveAgentFromCrowd(); 201 /// Crowd manager. 202 WeakPtr<CrowdManager> crowdManager_; 203 /// Crowd manager reference to this agent. 204 int agentCrowdId_; 205 /// Requested target position. 206 Vector3 targetPosition_; 207 /// Requested target velocity. 208 Vector3 targetVelocity_; 209 /// Requested target type. 210 CrowdAgentRequestedTarget requestedTargetType_; 211 /// Flag indicating the node's position should be updated by Detour crowd manager. 212 bool updateNodePosition_; 213 /// Agent's max acceleration. 214 float maxAccel_; 215 /// Agent's max Velocity. 216 float maxSpeed_; 217 /// Agent's radius, if 0 the navigation mesh's setting will be used. 218 float radius_; 219 /// Agent's height, if 0 the navigation mesh's setting will be used. 220 float height_; 221 /// Agent's query filter type, it is an index to the query filter buffer configured in Detour crowd manager. 222 unsigned queryFilterType_; 223 /// Agent's obstacle avoidance type, it is an index to the obstacle avoidance array configured in Detour crowd manager. It is ignored when agent's navigation quality is not set to "NAVIGATIONQUALITY_HIGH". 224 unsigned obstacleAvoidanceType_; 225 /// Agent's navigation quality. The higher the setting, the higher the CPU usage during crowd simulation. 226 NavigationQuality navQuality_; 227 /// Agent's navigation pushiness. The higher the setting, the stronger the agent pushes its colliding neighbours around. 228 NavigationPushiness navPushiness_; 229 /// Agent's previous position used to check for position changes. 230 Vector3 previousPosition_; 231 /// Agent's previous target state used to check for state changes. 232 CrowdAgentTargetState previousTargetState_; 233 /// Agent's previous agent state used to check for state changes. 234 CrowdAgentState previousAgentState_; 235 /// Internal flag to ignore transform changes because it came from us, used in OnCrowdAgentReposition(). 236 bool ignoreTransformChanges_; 237 }; 238 239 } 240