// // Copyright (c) 2008-2017 the Urho3D project. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #pragma once #include "../Navigation/CrowdManager.h" #include "../Scene/Component.h" namespace Atomic { enum CrowdAgentRequestedTarget { CA_REQUESTEDTARGET_NONE = 0, CA_REQUESTEDTARGET_POSITION, CA_REQUESTEDTARGET_VELOCITY }; enum CrowdAgentTargetState { CA_TARGET_NONE = 0, CA_TARGET_FAILED, CA_TARGET_VALID, CA_TARGET_REQUESTING, CA_TARGET_WAITINGFORQUEUE, CA_TARGET_WAITINGFORPATH, CA_TARGET_VELOCITY }; enum CrowdAgentState { CA_STATE_INVALID = 0, ///< The agent is not in a valid state. CA_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon. CA_STATE_OFFMESH ///< The agent is traversing an off-mesh connection. }; enum NavigationQuality { NAVIGATIONQUALITY_LOW = 0, NAVIGATIONQUALITY_MEDIUM = 1, NAVIGATIONQUALITY_HIGH = 2 }; enum NavigationPushiness { NAVIGATIONPUSHINESS_LOW = 0, NAVIGATIONPUSHINESS_MEDIUM, NAVIGATIONPUSHINESS_HIGH, NAVIGATIONPUSHINESS_NONE }; /// 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. class ATOMIC_API CrowdAgent : public Component { ATOMIC_OBJECT(CrowdAgent, Component); friend class CrowdManager; friend void CrowdAgentUpdateCallback(dtCrowdAgent* ag, float dt); public: /// Construct. CrowdAgent(Context* context); /// Destruct. virtual ~CrowdAgent(); /// Register object factory. static void RegisterObject(Context* context); /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update. virtual void ApplyAttributes(); /// Handle enabled/disabled state change. virtual void OnSetEnabled(); /// Draw debug geometry. void DrawDebugGeometry(bool depthTest); /// Draw debug feelers. virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest); /// Submit a new target position request for this agent. void SetTargetPosition(const Vector3& position); /// Submit a new target velocity request for this agent. void SetTargetVelocity(const Vector3& velocity); /// 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. void ResetTarget(); /// 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. void SetUpdateNodePosition(bool unodepos); /// Set the agent's max acceleration. void SetMaxAccel(float maxAccel); /// Set the agent's max velocity. void SetMaxSpeed(float maxSpeed); /// Set the agent's radius. void SetRadius(float radius); /// Set the agent's height. void SetHeight(float height); /// Set the agent's query filter type. void SetQueryFilterType(unsigned queryFilterType); /// Set the agent's obstacle avoidance type. void SetObstacleAvoidanceType(unsigned obstacleAvoidanceType); /// Set the agent's navigation quality. void SetNavigationQuality(NavigationQuality val); /// Set the agent's navigation pushiness. void SetNavigationPushiness(NavigationPushiness val); /// Return the agent's position. Vector3 GetPosition() const; /// Return the agent's desired velocity. Vector3 GetDesiredVelocity() const; /// Return the agent's actual velocity. Vector3 GetActualVelocity() const; /// Return the agent's requested target position. const Vector3& GetTargetPosition() const { return targetPosition_; } /// Return the agent's requested target velocity. const Vector3& GetTargetVelocity() const { return targetVelocity_; } /// Return the agent's requested target type, if any. CrowdAgentRequestedTarget GetRequestedTargetType() const { return requestedTargetType_; } /// Return the agent's state. CrowdAgentState GetAgentState() const; /// Return the agent's target state. CrowdAgentTargetState GetTargetState() const; /// Return true when the node's position should be updated by the CrowdManager. bool GetUpdateNodePosition() const { return updateNodePosition_; } /// Return the agent id. int GetAgentCrowdId() const { return agentCrowdId_; } /// Get the agent's max acceleration. float GetMaxAccel() const { return maxAccel_; } /// Get the agent's max velocity. float GetMaxSpeed() const { return maxSpeed_; } /// Get the agent's radius. float GetRadius() const { return radius_; } /// Get the agent's height. float GetHeight() const { return height_; } /// Get the agent's query filter type. unsigned GetQueryFilterType() const { return queryFilterType_; } /// Get the agent's obstacle avoidance type. unsigned GetObstacleAvoidanceType() const { return obstacleAvoidanceType_; } /// Get the agent's navigation quality. NavigationQuality GetNavigationQuality() const { return navQuality_; } /// Get the agent's navigation pushiness. NavigationPushiness GetNavigationPushiness() const { return navPushiness_; } /// Return true when the agent has a target. bool HasRequestedTarget() const { return requestedTargetType_ != CA_REQUESTEDTARGET_NONE; } /// Return true when the agent has arrived at its target. bool HasArrived() const; /// Return true when the agent is in crowd (being managed by a crowd manager). bool IsInCrowd() const; protected: /// Handle crowd agent being updated. It is called by CrowdManager::Update() via callback. virtual void OnCrowdUpdate(dtCrowdAgent* ag, float dt); /// Handle node being assigned. virtual void OnNodeSet(Node* node); /// Handle node being assigned. virtual void OnSceneSet(Scene* scene); /// \todo Handle node transform being dirtied. virtual void OnMarkedDirty(Node* node); /// Get internal Detour crowd agent. const dtCrowdAgent* GetDetourCrowdAgent() const; /// Handle navigation mesh tile added. void HandleNavigationTileAdded(StringHash eventType, VariantMap& eventData); private: /// Update Detour crowd agent parameter. void UpdateParameters(unsigned scope = M_MAX_UNSIGNED); /// Add agent into crowd. int AddAgentToCrowd(bool force = false); /// Remove agent from crowd. void RemoveAgentFromCrowd(); /// Crowd manager. WeakPtr crowdManager_; /// Crowd manager reference to this agent. int agentCrowdId_; /// Requested target position. Vector3 targetPosition_; /// Requested target velocity. Vector3 targetVelocity_; /// Requested target type. CrowdAgentRequestedTarget requestedTargetType_; /// Flag indicating the node's position should be updated by Detour crowd manager. bool updateNodePosition_; /// Agent's max acceleration. float maxAccel_; /// Agent's max Velocity. float maxSpeed_; /// Agent's radius, if 0 the navigation mesh's setting will be used. float radius_; /// Agent's height, if 0 the navigation mesh's setting will be used. float height_; /// Agent's query filter type, it is an index to the query filter buffer configured in Detour crowd manager. unsigned queryFilterType_; /// 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". unsigned obstacleAvoidanceType_; /// Agent's navigation quality. The higher the setting, the higher the CPU usage during crowd simulation. NavigationQuality navQuality_; /// Agent's navigation pushiness. The higher the setting, the stronger the agent pushes its colliding neighbours around. NavigationPushiness navPushiness_; /// Agent's previous position used to check for position changes. Vector3 previousPosition_; /// Agent's previous target state used to check for state changes. CrowdAgentTargetState previousTargetState_; /// Agent's previous agent state used to check for state changes. CrowdAgentState previousAgentState_; /// Internal flag to ignore transform changes because it came from us, used in OnCrowdAgentReposition(). bool ignoreTransformChanges_; }; }