VPath.cpp
Engine/source/Verve/VPath/VPath.cpp
Public Variables
Public Functions
DefineEngineFunction(getServerPathSet , S32 , () , "( void )" )
DefineEngineMethod(VPath , addNode , void , (TransformF transform, F32 weight, S32 location) , (MatrixF::Identity, 1.0, -1) , "( transform pTransform, float pWeight, [int pLocation] ) - Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> node with the given properties. Nodes represent physical points that attached objects move towards or between, but the PathType determines \"how\" they move between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">them.\n</a>" "@param pTransform The position and rotation of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pWeight The weight of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pLocation The index of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , deleteNode , void , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Delete the node with the given index. If you delete <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> node that an attached object is moving to, or from then the object 's movement will adjust so that it has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> valid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pNodeIndex The index of the node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , detachObject , void , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Detach the object from this path in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">place.\n</a>" "@param pObject The SimObjectID of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">detached.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , getNodeCount , S32 , () , "() - Get the number of nodes in this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" "@return Returns the number of nodes." )
DefineEngineMethod(VPath , getNodeLength , F32 , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the length of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the length of the given node." )
DefineEngineMethod(VPath , getNodeLocalPosition , Point3F , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" " @return Returns the Local Position of the given node." )
DefineEngineMethod(VPath , getNodeLocalRotation , AngAxisF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the Local Rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the Local Rotation of the given node." )
DefineEngineMethod(VPath , getNodeLocalTransform , const char * , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the local transform (local position and rotation) of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the transform of the given node." )
DefineEngineMethod(VPath , getNodeOrientationMode , const char * , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Gets the current orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> string indicating the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> and its properties." )
DefineEngineMethod(VPath , getNodeWeight , F32 , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the weight of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the weight of the given node." )
DefineEngineMethod(VPath , getNodeWorldPosition , Point3F , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Position of the given node." )
DefineEngineMethod(VPath , getNodeWorldRotation , AngAxisF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Rotation of the given node." )
DefineEngineMethod(VPath , getNodeWorldTransform , TransformF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Transform (position and rotation) of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the transform of the given node." )
DefineEngineMethod(VPath , getPathObjectEndNode , S32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the index of the node this object is meant <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> stop upon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reaching.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the node index." )
DefineEngineMethod(VPath , getPathObjectInterp , F32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the current interp position of the path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the current interp position." )
DefineEngineMethod(VPath , getPathObjectNode , S32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Gets the last node of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the node index." )
DefineEngineMethod(VPath , getPathObjectOffset , const char * , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the position offset assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the position offset." )
DefineEngineMethod(VPath , getPathObjectOrientationMode , const char * , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Gets the current orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> string indicating the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> and its properties." )
DefineEngineMethod(VPath , getPathObjectSpeed , F32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the speed this object is traveling along the path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">at.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the speed of the object." )
DefineEngineMethod(VPath , getPathPosition , const char * , (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp) , (0, 0, 1.0) , "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the world position of the path at the interp point between two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pSrcNodeIndex The first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pDstNodeIndex The second <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTimeInterp The time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> interp between the two nodes. <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> is between 0.0 and 1.0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return Returns the world position of the interp time between the two given nodes." )
DefineEngineMethod(VPath , getPathTransform , const char * , (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp) , (0, 0, 1.0) , "( int pSrcNodeIndex, int pDstNodeIndex, float pTimeInterp ) - Get the transform of the path at the interp point between two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pSrcNodeIndex The first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pDstNodeIndex The second <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTimeInterp The time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> interp between the two nodes. <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> is between 0.0 and 1.0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return Returns the transform of the interp time between the two given nodes." )
DefineEngineMethod(VPath , isObjectAttached , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Is the object attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param pObject The SimObjectID of the object you wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">check.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path." )
DefineEngineMethod(VPath , isPathObjectActive , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Is the object actively traveling around this path?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns true of the object is active." )
DefineEngineMethod(VPath , isPathObjectForward , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object is traveling forwards along the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is traveling forwards." )
DefineEngineMethod(VPath , setNodePosition , void , (S32 nodeIndex, Point3F position) , (0, Point3F::Zero) , "( int pNodeIndex, vector pPosition ) - Set the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pPosition The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeRotation , void , (S32 nodeIndex, AngAxisF aa) , (0, AngAxisF()) , "( int pNodeIndex, angAxis pRotation ) - Set the rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pRotation The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> rotation <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeTransform , void , (S32 nodeIndex, TransformF transform) , (0, MatrixF::Identity) , "( int pNodeIndex, matrix pTransform ) - Set the transform of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTransform The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> transform <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeWeight , void , (S32 nodeIndex, F32 nodeWeight) , (0, 1.0) , "( int pNodeIndex, float pWeight ) - Set the weight of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pWeight The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> weight <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectActive , void , (SceneObject *sceneObject, bool isActive) , (nullAsType< SceneObject * >(), true) , "( SimObject pObject, bool pActive ) - Enable or disable the object from traveling around this path. Inactive objects are still attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the path, but are not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">updated.\n</a>" " @param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" " @param pActive The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> status of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , setPathObjectEndNode , void , (SceneObject *sceneObject, S32 nodeIndex) , (nullAsType< SceneObject * >(), 0) , "( SimObject pObject, bool pNodeIndex ) - Set end node of the path object. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of \"-1\" is applied, the object will path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">indefinitely.\n</a>" " @param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" " @param pNodeIndex The index of the node that the object will cease pathing upon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reaching.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , setPathObjectForward , void , (SceneObject *sceneObject, bool forward) , (nullAsType< SceneObject * >(), true) , "( SimObject pObject, bool pForward ) - Set the travel direction of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pForward The direction of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectInterp , void , (SceneObject *sceneObject, F32 timeInterp) , (nullAsType< SceneObject * >(), 1.0) , "( SimObject pObject, float pTimeInterp ) - Set the interp position of the object between its current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pTimeInterp The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> interp position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectNode , void , (SceneObject *sceneObject, S32 nodeIndex) , (nullAsType< SceneObject * >(), 0) , "( SimObject pObject, bool pNodeIndex ) - <a href="/coding/class/structmove/">Move</a> the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the node's position. You may also want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> observe the \"setPathObjectInterp\" method.\n" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pNodeIndex The index of the node that the object will reposition <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectOffset , void , (SceneObject *sceneObject, Point3F offset) , (nullAsType< SceneObject * >(), Point3F::Zero) , "( SimObject pObject, vector pOffset ) - Set the position offset of the object. As the object is moving along the path, its position is offset by this value. Setting the \"Relative\" parameter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> attaching an object will automatically apply an offset <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pOffset The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> position offset of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectSpeed , void , (SceneObject *sceneObject, F32 speed) , (nullAsType< SceneObject * >(), 1.0) , "( SimObject pObject, float pSpeed ) - Set the speed of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pSpeed The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> speed of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathType , void , (String pathType) , ("LINEAR") , "( string pPathType ) - The path type dictates how attached objects move between nodes. There are currently two supported path types, \"BEZIER\" and \"LINEAR\".\n" "@return No return value." )
DefineEngineStringlyVariadicMethod(VPath , attachObject , void , 7 , 8 , "( SimObject pObject, bool pForward, float pSpeed, bool pRelative, int pStartNode, [int pEndNode] ) - Attach an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path with the given properties. If the object is already attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> path, then <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> warning will be displayed and the object will *not *be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pObject The SimObjectID of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">attached.\n</a>" " @param pForward Should the object be moving forward?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param pSpeed The speed that the object will travel around the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pRelative <a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a660d8e8336a58d3d6950e2a638583056">Offset</a> the object based on the difference between the start node and its current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n</a>" " @param pStartNode The index of the node this object starts pathing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" " @param pEndNode The index of the node this object will stop pathing at." " @return No return value." )
DefineEngineStringlyVariadicMethod(VPath , setNodeOrientationMode , void , 4 , 5 , "( int pNodeIndex, string pOrientationType, [vector pPoint] ) - Set the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pOrientationType The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> orientation type of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pPoint If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> POINT, this parameter must be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" " @return No return value." )
DefineEngineStringlyVariadicMethod(VPath , setPathObjectOrientationMode , void , 4 , 5 , "( SimObject pObject, string pOrientationType, [<a href="/coding/class/classsimobject/">SimObject</a> pObject / vector pPoint] ) - Set the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the object. This property affects the rotation of the object. If you wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore the object's rotation altogether, set the <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> \"FREE\".\n" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pOrientationType The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> orientation type of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> OBJECT, this parameter must be the SimObjectID of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @param pPoint If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> POINT, this parameter must be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" " @return No return value." )
getPathTypeEnum(const char * pLabel)
ImplementEnumType(VPathType , "" )
Detailed Description
Public Variables
EndImplementEnumType
F32 gBezierInterpStep
U32 gPathTypeBits
Public Functions
DefineEngineFunction(getServerPathSet , S32 , () , "( void )" )
DefineEngineMethod(VPath , addNode , void , (TransformF transform, F32 weight, S32 location) , (MatrixF::Identity, 1.0, -1) , "( transform pTransform, float pWeight, [int pLocation] ) - Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> node with the given properties. Nodes represent physical points that attached objects move towards or between, but the PathType determines \"how\" they move between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">them.\n</a>" "@param pTransform The position and rotation of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pWeight The weight of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pLocation The index of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , deleteNode , void , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Delete the node with the given index. If you delete <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> node that an attached object is moving to, or from then the object 's movement will adjust so that it has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> valid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pNodeIndex The index of the node <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">deleted.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , detachObject , void , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Detach the object from this path in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">place.\n</a>" "@param pObject The SimObjectID of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">detached.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , getNodeCount , S32 , () , "() - Get the number of nodes in this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" "@return Returns the number of nodes." )
DefineEngineMethod(VPath , getNodeLength , F32 , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the length of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the length of the given node." )
DefineEngineMethod(VPath , getNodeLocalPosition , Point3F , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" " @return Returns the Local Position of the given node." )
DefineEngineMethod(VPath , getNodeLocalRotation , AngAxisF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the Local Rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the Local Rotation of the given node." )
DefineEngineMethod(VPath , getNodeLocalTransform , const char * , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the local transform (local position and rotation) of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the transform of the given node." )
DefineEngineMethod(VPath , getNodeOrientationMode , const char * , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Gets the current orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> string indicating the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> and its properties." )
DefineEngineMethod(VPath , getNodeWeight , F32 , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the weight of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the weight of the given node." )
DefineEngineMethod(VPath , getNodeWorldPosition , Point3F , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Position of the given node." )
DefineEngineMethod(VPath , getNodeWorldRotation , AngAxisF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Rotation of the given node." )
DefineEngineMethod(VPath , getNodeWorldTransform , TransformF , (S32 nodeIndex) , (0) , "( int pNodeIndex ) - Get the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> Transform (position and rotation) of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return Returns the transform of the given node." )
DefineEngineMethod(VPath , getPathObjectEndNode , S32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the index of the node this object is meant <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> stop upon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reaching.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the node index." )
DefineEngineMethod(VPath , getPathObjectInterp , F32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the current interp position of the path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the current interp position." )
DefineEngineMethod(VPath , getPathObjectNode , S32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Gets the last node of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the node index." )
DefineEngineMethod(VPath , getPathObjectOffset , const char * , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the position offset assigned <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the position offset." )
DefineEngineMethod(VPath , getPathObjectOrientationMode , const char * , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Gets the current orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> string indicating the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> and its properties." )
DefineEngineMethod(VPath , getPathObjectSpeed , F32 , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get the speed this object is traveling along the path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">at.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns the speed of the object." )
DefineEngineMethod(VPath , getPathPosition , const char * , (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp) , (0, 0, 1.0) , "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the world position of the path at the interp point between two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pSrcNodeIndex The first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pDstNodeIndex The second <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTimeInterp The time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> interp between the two nodes. <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> is between 0.0 and 1.0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return Returns the world position of the interp time between the two given nodes." )
DefineEngineMethod(VPath , getPathTransform , const char * , (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp) , (0, 0, 1.0) , "( int pSrcNodeIndex, int pDstNodeIndex, float pTimeInterp ) - Get the transform of the path at the interp point between two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pSrcNodeIndex The first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pDstNodeIndex The second <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTimeInterp The time <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> interp between the two nodes. <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> is between 0.0 and 1.0.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return Returns the transform of the interp time between the two given nodes." )
DefineEngineMethod(VPath , isObjectAttached , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Is the object attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param pObject The SimObjectID of the object you wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">check.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path." )
DefineEngineMethod(VPath , isPathObjectActive , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Is the object actively traveling around this path?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns true of the object is active." )
DefineEngineMethod(VPath , isPathObjectForward , bool , (SceneObject *sceneObject) , (nullAsType< SceneObject * >()) , "( SimObject pObject ) - Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> this object is traveling forwards along the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">observed.\n</a>" "@return Returns true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the object is traveling forwards." )
DefineEngineMethod(VPath , setNodePosition , void , (S32 nodeIndex, Point3F position) , (0, Point3F::Zero) , "( int pNodeIndex, vector pPosition ) - Set the position of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pPosition The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> position <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeRotation , void , (S32 nodeIndex, AngAxisF aa) , (0, AngAxisF()) , "( int pNodeIndex, angAxis pRotation ) - Set the rotation of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pRotation The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> rotation <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeTransform , void , (S32 nodeIndex, TransformF transform) , (0, MatrixF::Identity) , "( int pNodeIndex, matrix pTransform ) - Set the transform of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pTransform The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> transform <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setNodeWeight , void , (S32 nodeIndex, F32 nodeWeight) , (0, 1.0) , "( int pNodeIndex, float pWeight ) - Set the weight of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pWeight The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> weight <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be applied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectActive , void , (SceneObject *sceneObject, bool isActive) , (nullAsType< SceneObject * >(), true) , "( SimObject pObject, bool pActive ) - Enable or disable the object from traveling around this path. Inactive objects are still attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the path, but are not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">updated.\n</a>" " @param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" " @param pActive The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> status of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , setPathObjectEndNode , void , (SceneObject *sceneObject, S32 nodeIndex) , (nullAsType< SceneObject * >(), 0) , "( SimObject pObject, bool pNodeIndex ) - Set end node of the path object. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of \"-1\" is applied, the object will path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">indefinitely.\n</a>" " @param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" " @param pNodeIndex The index of the node that the object will cease pathing upon <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">reaching.\n</a>" " @return No return value." )
DefineEngineMethod(VPath , setPathObjectForward , void , (SceneObject *sceneObject, bool forward) , (nullAsType< SceneObject * >(), true) , "( SimObject pObject, bool pForward ) - Set the travel direction of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pForward The direction of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectInterp , void , (SceneObject *sceneObject, F32 timeInterp) , (nullAsType< SceneObject * >(), 1.0) , "( SimObject pObject, float pTimeInterp ) - Set the interp position of the object between its current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pTimeInterp The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> interp position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectNode , void , (SceneObject *sceneObject, S32 nodeIndex) , (nullAsType< SceneObject * >(), 0) , "( SimObject pObject, bool pNodeIndex ) - <a href="/coding/class/structmove/">Move</a> the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the node's position. You may also want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> observe the \"setPathObjectInterp\" method.\n" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pNodeIndex The index of the node that the object will reposition <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectOffset , void , (SceneObject *sceneObject, Point3F offset) , (nullAsType< SceneObject * >(), Point3F::Zero) , "( SimObject pObject, vector pOffset ) - Set the position offset of the object. As the object is moving along the path, its position is offset by this value. Setting the \"Relative\" parameter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> attaching an object will automatically apply an offset <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pOffset The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> position offset of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathObjectSpeed , void , (SceneObject *sceneObject, F32 speed) , (nullAsType< SceneObject * >(), 1.0) , "( SimObject pObject, float pSpeed ) - Set the speed of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pSpeed The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> speed of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@return No return value." )
DefineEngineMethod(VPath , setPathType , void , (String pathType) , ("LINEAR") , "( string pPathType ) - The path type dictates how attached objects move between nodes. There are currently two supported path types, \"BEZIER\" and \"LINEAR\".\n" "@return No return value." )
DefineEngineStringlyVariadicMethod(VPath , attachObject , void , 7 , 8 , "( SimObject pObject, bool pForward, float pSpeed, bool pRelative, int pStartNode, [int pEndNode] ) - Attach an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this path with the given properties. If the object is already attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> path, then <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> warning will be displayed and the object will *not *be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pObject The SimObjectID of the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">attached.\n</a>" " @param pForward Should the object be moving forward?\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param pSpeed The speed that the object will travel around the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">path.\n</a>" " @param pRelative <a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a660d8e8336a58d3d6950e2a638583056">Offset</a> the object based on the difference between the start node and its current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">position.\n</a>" " @param pStartNode The index of the node this object starts pathing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" " @param pEndNode The index of the node this object will stop pathing at." " @return No return value." )
DefineEngineStringlyVariadicMethod(VPath , setNodeOrientationMode , void , 4 , 5 , "( int pNodeIndex, string pOrientationType, [vector pPoint] ) - Set the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pNodeIndex The index of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param pOrientationType The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> orientation type of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pPoint If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> POINT, this parameter must be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" " @return No return value." )
DefineEngineStringlyVariadicMethod(VPath , setPathObjectOrientationMode , void , 4 , 5 , "( SimObject pObject, string pOrientationType, [<a href="/coding/class/classsimobject/">SimObject</a> pObject / vector pPoint] ) - Set the orientation <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> of the object. This property affects the rotation of the object. If you wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> ignore the object's rotation altogether, set the <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> \"FREE\".\n" "@param pObject The SimObjectID of the object being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">altered.\n</a>" "@param pOrientationType The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> orientation type of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param pObject If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> OBJECT, this parameter must be the SimObjectID of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> scene <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" " @param pPoint If the orientation type is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> POINT, this parameter must be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">vector.\n</a>" " @return No return value." )
getPathTypeEnum(const char * pLabel)
IMPLEMENT_CO_NETOBJECT_V1(VPath )
ImplementEnumType(VPathType , "" )
1 2//----------------------------------------------------------------------------- 3// Verve 4// Copyright (C) 2014 - Violent Tulip 5// 6// Permission is hereby granted, free of charge, to any person obtaining a copy 7// of this software and associated documentation files (the "Software"), to 8// deal in the Software without restriction, including without limitation the 9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10// sell copies of the Software, and to permit persons to whom the Software is 11// furnished to do so, subject to the following conditions: 12// 13// The above copyright notice and this permission notice shall be included in 14// all copies or substantial portions of the Software. 15// 16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22// IN THE SOFTWARE. 23//----------------------------------------------------------------------------- 24#include "VPath.h" 25 26#include "console/consoleTypes.h" 27#include "core/iTickable.h" 28#include "core/stream/bitStream.h" 29#include "math/mMathFn.h" 30#include "math/mathIO.h" 31#include "math/mTransform.h" 32 33//----------------------------------------------------------------------------- 34 35// Uncomment this definition to debug the network information. 36//#define VPATH_DEBUG_NET 37 38// Uncomment this definition to debug the time step information 39//#define VPATH_DEBUG_STEP 40 41//----------------------------------------------------------------------------- 42 43SimObjectPtr<SimSet> VPath::gServerSet = NULL; 44 45U32 VPath::gMaxNodeTransmit = 16; 46U32 VPath::gMaxNodeBits = 8; 47U32 VPath::gMaxNodeCount = 1 << gMaxNodeBits; // 256 48 49U32 VPath::gMaxObjectTransmit = 4; 50U32 VPath::gMaxObjectBits = 4; 51U32 VPath::gMaxObjectCount = 1 << gMaxObjectBits; // 16 52 53Point3F VPath::gBezierAxis( 0.f, 1.f, 0.f ); 54Point3F VPath::gBezierUp( 0.f, 0.f, 1.f ); 55 56//----------------------------------------------------------------------------- 57 58static U32 gPathTypeBits = getBinLog2( getNextPow2( VPath::k_PathTypeSize ) ); 59static F32 gBezierInterpStep = 0.0001f; 60 61//----------------------------------------------------------------------------- 62// Path Type Table. 63//----------------------------------------------------------------------------- 64 65// Implement the Path Type enum list. 66ImplementEnumType( VPathType, "" ) 67 { VPath::k_PathBezier, "BEZIER" }, 68 { VPath::k_PathLinear, "LINEAR" }, 69EndImplementEnumType; 70 71static VPath::ePathType getPathTypeEnum( const char *pLabel ) 72{ 73 VPath::ePathType out; 74 if ( !castConsoleTypeFromString( out, pLabel ) ) 75 { 76 // Bah! 77 return VPath::k_PathInvalid; 78 } 79 80 // Return. 81 return out; 82} 83 84//----------------------------------------------------------------------------- 85IMPLEMENT_CO_NETOBJECT_V1( VPath ); 86//----------------------------------------------------------------------------- 87 88VPath::VPath( void ) : 89 mPathType( k_PathBezier ) 90{ 91 // Marker Type. 92 mTypeMask = MarkerObjectType; 93 94 // Ghost & Scope. 95 mNetFlags.set( Ghostable | ScopeAlways ); 96 97 // Process Ticks. 98 setProcessTick( true ); 99 100 VECTOR_SET_ASSOCIATION( mNodeList ); 101 VECTOR_SET_ASSOCIATION( mObjectList ); 102} 103 104VPath::~VPath( void ) 105{ 106 // Void. 107} 108 109bool VPath::onAdd( void ) 110{ 111 if ( !Parent::onAdd() ) 112 { 113 return false; 114 } 115 116 // Add to Scene. 117 addToScene(); 118 119 if ( isServerObject() ) 120 { 121 // Read Fields. 122 readFields(); 123 124 // Add to Set. 125 getServerSet()->addObject( this ); 126 } 127 128 return true; 129} 130 131void VPath::onDeleteNotify( SimObject *pObject ) 132{ 133 // Parent Notify. 134 Parent::onDeleteNotify( pObject ); 135 136 if ( SceneObject *sceneObject = dynamic_cast<SceneObject*>( pObject ) ) 137 { 138 // Detach Object. 139 detachObject( sceneObject ); 140 141 // Exit. 142 return; 143 } 144 145 if ( NetConnection *connection = dynamic_cast<NetConnection*>( pObject ) ) 146 { 147 // Clear Connection References. 148 for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) 149 { 150 // Erase Connection. 151 ( *itr )->clearConnection( connection ); 152 } 153 154 // Exit. 155 return; 156 } 157} 158 159void VPath::onRemove( void ) 160{ 161 // Remove From Scene. 162 removeFromScene(); 163 164 // Clear Everything. 165 clear(); 166 167 Parent::onRemove(); 168} 169 170void VPath::initPersistFields( void ) 171{ 172 Parent::initPersistFields(); 173 174 addProtectedField( "PathType", TYPEID<ePathType>(), Offset( mPathType, VPath ), &setPathType, &defaultProtectedGetFn, "The type of path this is." ); 175} 176 177SimSet *VPath::getServerSet( void ) 178{ 179 if ( !gServerSet ) 180 { 181 gServerSet = new SimSet(); 182 gServerSet->registerObject( "ServerPathSet" ); 183 Sim::getRootGroup()->addObject( gServerSet ); 184 } 185 186 return gServerSet; 187} 188 189DefineEngineFunction( getServerPathSet, S32, (),, "( void )" ) 190{ 191 return VPath::getServerSet()->getId(); 192} 193 194//----------------------------------------------------------------------------- 195// 196// Editor Methods. 197// 198//----------------------------------------------------------------------------- 199 200bool VPath::collideBox( const Point3F &pStart, const Point3F &pEnd, RayInfo* pInfo ) 201{ 202 if ( mObjBox.isContained( pStart ) ) 203 { 204 pInfo->t = 0.f; 205 pInfo->object = this; 206 pInfo->normal = VectorF( 0.f, 0.f, 1.f ); 207 pInfo->material = NULL; 208 209 return true; 210 } 211 212 return Parent::collideBox( pStart, pEnd, pInfo ); 213} 214 215//----------------------------------------------------------------------------- 216// 217// Update Methods. 218// 219//----------------------------------------------------------------------------- 220 221F32 VPath::getUpdatePriority( CameraScopeQuery *pFocusObject, U32 pUpdateMask, S32 pUpdateSkips ) 222{ 223 if ( mObjectList.size() > 0 ) 224 { 225 for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) 226 { 227 // Fetch Object. 228 VPathObject *pathObject = ( *itr ); 229 if ( pathObject->isActive() ) 230 { 231 // High Priority. 232 return 100.f; 233 } 234 } 235 } 236 237 // Normal Priority. 238 return 0.f; 239} 240 241void VPath::updateContainer( void ) 242{ 243 if ( mNodeList.size() == 0 ) 244 { 245 // Sanity!. 246 return; 247 } 248 249 // Init Min / Max. 250 mObjBox.minExtents = ( mNodeList[0]->getLocalPosition() ); 251 mObjBox.maxExtents = mObjBox.minExtents; 252 253 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 254 { 255 // Fetch Node. 256 VPathNode *node = ( *itr ); 257 258 // Node Position. 259 const Point3F &nodeLocalPosition = node->getLocalPosition(); 260 261 // Update Object Box. 262 mObjBox.minExtents.setMin( nodeLocalPosition ); 263 mObjBox.maxExtents.setMax( nodeLocalPosition ); 264 } 265 266 // Adjust. 267 mObjBox.minExtents -= Point3F( 1.f, 1.f, 1.f ); 268 mObjBox.maxExtents += Point3F( 1.f, 1.f, 1.f ); 269 270 // Reset Box. 271 resetWorldBox(); 272 resetRenderWorldBox(); 273} 274 275void VPath::updateNodeTransforms( void ) 276{ 277 // Fetch Transform Details. 278 const MatrixF &pathTransform = getTransform(); 279 const QuatF &pathRotation( pathTransform ); 280 const VectorF &pathScale = getScale(); 281 282 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 283 { 284 // Fetch Node. 285 VPathNode *node = ( *itr ); 286 287 // Fetch Node Spatials. 288 const Point3F &nodePosition = node->getLocalPosition(); 289 const QuatF &nodeRotation = node->getLocalRotation(); 290 291 // Calculate the new Position. 292 Point3F newPosition = nodePosition; 293 newPosition.convolve( pathScale ); 294 pathTransform.mulP( newPosition ); 295 296 // Calculate the new Rotation. 297 QuatF newRotation; 298 newRotation.mul( nodeRotation, pathRotation ); 299 300 // Apply. 301 node->setWorldPosition( newPosition ); 302 node->setWorldRotation( newRotation ); 303 } 304} 305 306void VPath::setTransform( const MatrixF &pMatrix ) 307{ 308 // Parent Call. 309 Parent::setTransform( pMatrix ); 310 311 // Update Nodes. 312 updateNodeTransforms(); 313 314 if ( isServerObject() ) 315 { 316 // Update Path. 317 setMaskBits( PathUpdateMask ); 318 } 319} 320 321void VPath::setScale( const VectorF &pScale ) 322{ 323 // Parent Call. 324 Parent::setScale( pScale ); 325 326 // Update Nodes. 327 updateNodeTransforms(); 328 329 if ( isServerObject() ) 330 { 331 // Update Path. 332 setMaskBits( PathUpdateMask ); 333 } 334} 335 336DefineEngineMethod( VPath, setPathType, void, (String pathType), ("LINEAR"), "( string pPathType ) - The path type dictates how attached objects move between nodes. There are currently two supported path types, \"BEZIER\" and \"LINEAR\".\n" 337 "@return No return value." ) 338{ 339 // Fetch Enum. 340 const VPath::ePathType &type = getPathTypeEnum(pathType); 341 342 // Update. 343 object->setPathType( type ); 344} 345 346void VPath::setPathType( const ePathType &pType ) 347{ 348 // Apply Value. 349 mPathType = pType; 350 351 // Calculate Path. 352 calculatePath(); 353 354 if ( isServerObject() ) 355 { 356 // Update Path. 357 setMaskBits( PathUpdateMask ); 358 } 359} 360 361bool VPath::setPathType( void *pObject, const char *pArray, const char *pData ) 362{ 363 // Apply Type. 364 static_cast<VPath*>( pObject )->setPathType( getPathTypeEnum( pData ) ); 365 return false; 366} 367 368//----------------------------------------------------------------------------- 369// 370// Mounting Methods. 371// 372//----------------------------------------------------------------------------- 373 374bool VPath::isMountIndex( const U32 &pIndex ) 375{ 376 for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) 377 { 378 if ( itr->getMountNode() == pIndex ) 379 { 380 // Yes. 381 return true; 382 } 383 } 384 385 // No. 386 return false; 387} 388 389U32 VPath::getAvailableMountIndex( void ) 390{ 391 U32 i = 0; 392 while( isMountIndex( i ) ) 393 { 394 // Increment. 395 i++; 396 } 397 398 // Return Index. 399 return i; 400} 401 402void VPath::mountObject( SceneObject *pObject, S32 pIndex, const MatrixF &pTransform ) 403{ 404#ifdef VPATH_DEBUG_NET 405 Con::printf( "VPath::mountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), isObjectAttached( pObject ) ); 406#endif 407 408 // Attached? 409 if ( !isObjectAttached( pObject ) ) 410 { 411 if ( isServerObject() ) 412 { 413 // Shouldn't Use this Method. 414 Con::warnf( "VPath::mountObject() - Use 'attachObject' instead." ); 415 } 416 417 // Not Attached. 418 return; 419 } 420 421 // Parent Call. 422 Parent::mountObject( pObject, pIndex, pTransform ); 423 424 // Clear the mounted mask. 425 // Note: This is so that we send the mounting information via the VPath 426 // packets instead of letting T3D handle it. 427 pObject->clearMaskBits( SceneObject::MountedMask ); 428} 429 430void VPath::unmountObject( SceneObject *pObject ) 431{ 432 // Fetch Path Object. 433 VPathObject *pathObject = getPathObject( pObject ); 434 435#ifdef VPATH_DEBUG_NET 436 Con::printf( "VPath::unmountObject() %d | %d, IsAttached %d", isServerObject(), pObject->getId(), pathObject != NULL ); 437#endif 438 439 // Valid? 440 if ( !pathObject || pObject->getObjectMount() != this ) 441 { 442 // Warn. 443 Con::warnf( "VPath::unmountObject() - Object is not attached to this Path. %d", pObject->getId() ); 444 // Not Mounted Here! 445 return; 446 } 447 448 // Parent Call. 449 Parent::unmountObject( pObject ); 450 451 // Clear the mounted mask. 452 // Note: This is so that we send the mounting information via the VPath 453 // packets instead of letting T3D handle it. 454 pObject->clearMaskBits( SceneObject::MountedMask ); 455} 456 457void VPath::getMountTransform( S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) 458{ 459 // Fetch the Scene Object. 460 VPathObject *pathObject = NULL; 461 for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) 462 { 463 if ( itr->getMountNode() == pIndex ) 464 { 465 pathObject = getPathObject( itr ); 466 break; 467 } 468 } 469 470 if ( !pathObject ) 471 { 472 // Reset Transform. 473 *pTransform = pInTransform; 474 // Sanity! 475 return; 476 } 477 478 // Advance the Object. 479 advanceObject( pathObject, TickSec ); 480 481 // Apply Transform. 482 *pTransform = pathObject->getTransform(); 483} 484 485void VPath::getRenderMountTransform( F32 pDelta, S32 pIndex, const MatrixF &pInTransform, MatrixF *pTransform ) 486{ 487 // Fetch the Scene Object. 488 VPathObject *pathObject = NULL; 489 for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) 490 { 491 if ( itr->getMountNode() == pIndex ) 492 { 493 pathObject = getPathObject( itr ); 494 break; 495 } 496 } 497 498 if ( !pathObject ) 499 { 500 // Reset Transform. 501 *pTransform = pInTransform; 502 // Sanity! 503 return; 504 } 505 506 // Apply Transform. 507 *pTransform = pathObject->getRenderTransform( pDelta ); 508} 509 510VectorF VPath::getMountVelocity( const U32 &pIndex ) 511{ 512 // Fetch the Scene Object. 513 VPathObject *pathObject = NULL; 514 for ( SceneObject *itr = getMountList(); itr != NULL; itr = itr->getMountLink() ) 515 { 516 if ( itr->getMountNode() == pIndex ) 517 { 518 pathObject = getPathObject( itr ); 519 break; 520 } 521 } 522 523 if ( !pathObject ) 524 { 525 // Sanity! 526 return VectorF::Zero; 527 } 528 529 // Determine Velocity. 530 return ( pathObject->getOrientation() * pathObject->getSpeed() ); 531} 532 533//----------------------------------------------------------------------------- 534// 535// Persistence Methods. 536// 537//----------------------------------------------------------------------------- 538 539void VPath::readFields( void ) 540{ 541 const char *nodeData = ""; 542 for ( S32 nodeIndex = 0; String::compare( nodeData = getDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL ), "" ) != 0; nodeIndex++ ) 543 { 544 // Create Node. 545 VPathNode *node = createNode(); 546 // Deserialize the Node. 547 node->fromString( nodeData ); 548 // Add the Node. 549 addNode( node ); 550 551 // Clear Field. 552 setDataField( StringTable->insert( avar( "Node%d", nodeIndex ) ), NULL, "" ); 553 } 554 555 // Update Transforms. 556 updateNodeTransforms(); 557 558 // Update Size. 559 updateContainer(); 560 561 // Calculate Path. 562 calculatePath(); 563} 564 565void VPath::writeFields( Stream &pStream, U32 pTabStop ) 566{ 567 // Field Name. 568 StringTableEntry fieldName = StringTable->insert( "node" ); 569 570 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 571 { 572 // Set Field. 573 setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), ( *itr )->toString().c_str() ); 574 } 575 576 // Write Fields. 577 Parent::writeFields( pStream, pTabStop ); 578 579 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 580 { 581 // Clear Field. 582 setDataField( fieldName, avar( "%d" , ( itr - mNodeList.begin() ) ), "" ); 583 } 584} 585 586U32 VPath::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream ) 587{ 588 U32 retMask = Parent::packUpdate( pConnection, pMask, pStream ); 589 590 if ( pMask & InitialUpdateMask ) 591 { 592 // Delete Notify. 593 deleteNotify( pConnection ); 594 } 595 596 if ( pStream->writeFlag( pMask & PathUpdateMask ) ) 597 { 598 // Write Path Type. 599 pStream->writeInt( mPathType, gPathTypeBits ); 600 601 // Write Transform. 602 mathWrite( *pStream, mObjToWorld ); 603 // Write Scale. 604 mathWrite( *pStream, mObjScale ); 605 } 606 607 if ( pStream->writeFlag( pMask & NodeUpdateMask ) ) 608 { 609 // Path needs recalculating? 610 bool needsCalculating = false; 611 612 // Delete Vector. 613 Vector<U32> deleteVector; 614 // Update Vector. 615 Vector<U32> updateVector; 616 617 for ( U32 i = 0; i < mNodeList.size(); i++ ) 618 { 619 // Fetch Node. 620 VPathNode *node = mNodeList[i]; 621 622 // Already In Map? 623 if ( !node->isConnection( pConnection ) ) 624 { 625 // Insert. 626 node->addConnection( pConnection ); 627 } 628 629 // Fetch State. 630 VNetStateInfo *state = node->getState( pConnection ); 631 632 // Delete new node? 633 if ( state->Mask & VPathNode::k_StateDelete 634 && state->Mask & VPathNode::k_StateCreate ) 635 { 636 // Remove Node. 637 removeNode( i-- ); 638 // Flag true. 639 needsCalculating = true; 640 } 641 642 // Delete? 643 else if ( state->Mask & VPathNode::k_StateDelete ) 644 { 645 // Add To List. 646 deleteVector.push_front( i ); 647 } 648 649 // Update? 650 else if ( state->Mask & VPathNode::k_StateUpdate ) 651 { 652 if ( updateVector.size() < gMaxNodeTransmit ) 653 { 654 // Add To List. 655 updateVector.push_back( i ); 656 } 657 } 658 } 659 660 // More Updates? 661 if ( updateVector.size() == gMaxNodeTransmit ) 662 { 663 // More Updates. 664 retMask |= NodeUpdateMask; 665 } 666 667 // Write Count. 668 pStream->writeInt( updateVector.size(), gMaxNodeBits + 1 ); 669 670 for ( Vector<U32>::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) 671 { 672 // Fetch Index. 673 const U32 index = ( *itr ); 674 675 // Write Index. 676 pStream->writeInt( index, gMaxNodeBits ); 677 // Pack Update. 678 retMask |= mNodeList[index]->packNode( pConnection, pStream ); 679 } 680 681 // Write Count. 682 pStream->writeInt( deleteVector.size(), gMaxNodeBits + 1 ); 683 684 if ( deleteVector.size() > 0 ) 685 { 686 for ( Vector<U32>::iterator itr = deleteVector.begin(); itr != deleteVector.end(); itr++ ) 687 { 688 // Fetch Index. 689 const U32 index = ( *itr ); 690 691 // Write Index. 692 pStream->writeInt( index, gMaxNodeBits ); 693 // Remove Node. 694 removeNode( index ); 695 } 696 697 // Flag true. 698 needsCalculating = true; 699 // Clear Vector. 700 deleteVector.clear(); 701 } 702 703 // Recalculate path? 704 if ( needsCalculating ) 705 { 706 // Update Size. 707 updateContainer(); 708 // Calculate Path. 709 calculatePath(); 710 } 711 } 712 713 if ( pStream->writeFlag( pMask & ObjectUpdateMask ) ) 714 { 715 // Detach Vector. 716 Vector<U32> detachVector; 717 // Update Vector. 718 Vector<U32> updateVector; 719 720 for ( U32 i = 0; i < mObjectList.size(); i++ ) 721 { 722 // Fetch Node. 723 VPathObject *pathObject = mObjectList[i]; 724 725 // Already In Map? 726 if ( !pathObject->isConnection( pConnection ) ) 727 { 728 // Insert. 729 pathObject->addConnection( pConnection ); 730 } 731 732 // Fetch State. 733 VNetStateInfo *state = pathObject->getState( pConnection ); 734 735 // Detach newly attached object? 736 if ( state->Mask & VPathObject::k_StateAttach 737 && state->Mask & VPathObject::k_StateDetach ) 738 { 739 // Process Detach. 740 onDetachObject( pathObject ); 741 // Decrease index. 742 i -= 1; 743 744 // Skip. 745 continue; 746 } 747 748 // Update? 749 if ( state->Mask & VPathObject::k_StateUpdate ) 750 { 751 if ( updateVector.size() < gMaxObjectTransmit ) 752 { 753 // Add To List. 754 updateVector.push_back( i ); 755 } 756 } 757 758 // Detach? 759 if ( state->Mask & VPathObject::k_StateDetach ) 760 { 761 // Add To List. 762 detachVector.push_front( i ); 763 } 764 } 765 766 // More Updates? 767 if ( updateVector.size() == gMaxObjectTransmit ) 768 { 769 // More Updates. 770 retMask |= ObjectUpdateMask; 771 } 772 773 // Write Count. 774 pStream->writeInt( updateVector.size(), gMaxObjectBits + 1 ); 775 776 for ( Vector<U32>::iterator itr = updateVector.begin(); itr != updateVector.end(); itr++ ) 777 { 778 // Fetch Index. 779 const U32 index = ( *itr ); 780 781 // Write Index. 782 pStream->writeInt( index, gMaxObjectBits ); 783 784 // Fetch the object. 785 VPathObject *pathObject = mObjectList[index]; 786 // Fetch State. 787 VNetStateInfo *state = pathObject->getState( pConnection ); 788 789 // Was the Object Attached? 790 if ( pStream->writeFlag( state->Mask & VPathObject::k_StateAttach ) ) 791 { 792#ifdef VPATH_DEBUG_NET 793 Con::printf( "VPath::packUpdate() - Attached - %d | %d", isServerObject(), index ); 794#endif 795 796 // Clear Update. 797 state->Mask &= ~<a href="/coding/class/structvpathobject/">VPathObject</a>::k_StateAttach; 798 } 799 800 // Pack Object. 801 retMask |= mObjectList[index]->packUpdate( pConnection, pStream ); 802 } 803 804 // Write Count. 805 pStream->writeInt( detachVector.size(), gMaxObjectBits + 1 ); 806 807 if ( detachVector.size() > 0 ) 808 { 809 for ( Vector<U32>::iterator itr = detachVector.begin(); itr != detachVector.end(); itr++ ) 810 { 811 // Fetch Index. 812 const U32 index = ( *itr ); 813 // Write Index. 814 pStream->writeInt( index, gMaxObjectBits ); 815 // Process Detach. 816 onDetachObject( mObjectList[index] ); 817 } 818 819 // Clear Vector. 820 detachVector.clear(); 821 } 822 } 823 824 // Return. 825 return retMask; 826} 827 828void VPath::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) 829{ 830 Parent::unpackUpdate( pConnection, pStream ); 831 832 // Update Path? 833 if ( pStream->readFlag() ) 834 { 835 // Read Path Type. 836 mPathType = pStream->readInt( gPathTypeBits ); 837 838 // Read Transform. 839 mathRead( *pStream, &mObjToWorld ); 840 // Read Scale. 841 mathRead( *pStream, &mObjScale ); 842 843 // Update Nodes. 844 updateNodeTransforms(); 845 // Calculate Path. 846 calculatePath(); 847 } 848 849 // Update Nodes? 850 if ( pStream->readFlag() ) 851 { 852 // Number To Update. 853 const U32 updateCount = pStream->readInt( gMaxNodeBits + 1 ); 854 855 for ( U32 i = 0; i < updateCount; i++ ) 856 { 857 // Read Index. 858 const U32 nodeIndex = pStream->readInt( gMaxNodeBits ); 859 860 // Was the Node Created? 861 if ( pStream->readFlag() ) 862 { 863 // Create Node. 864 VPathNode *node = createNode(); 865 // Add the Node. 866 addNode( node, nodeIndex ); 867 } 868 869 // Reference Node. 870 VPathNode *node = mNodeList[nodeIndex]; 871 // Apply Update. 872 node->unpackNode( pConnection, pStream ); 873 } 874 875 // Number To Delete. 876 const U32 deleteCount = pStream->readInt( gMaxNodeBits + 1 ); 877 878 for ( U32 i = 0; i < deleteCount; i++ ) 879 { 880 // Remove Node. 881 removeNode( pStream->readInt( gMaxNodeBits ) ); 882 } 883 884 // Update Size. 885 updateContainer(); 886 // Calculate Path. 887 calculatePath(); 888 } 889 890 // Update Objects? 891 if ( pStream->readFlag() ) 892 { 893 // Number To Update. 894 const U32 updateCount = pStream->readInt( gMaxObjectBits + 1 ); 895 896 for ( U32 i = 0; i < updateCount; i++ ) 897 { 898 // Read Index. 899 const U32 objectIndex = pStream->readInt( gMaxObjectBits ); 900 901 // Read Attached. 902 // Note: The editor handles the both the server and client side attachment calls. 903 // This is dangerous because there could be a mix up in indices, but it is 904 // needed to ensure the editor runs smoothly :( 905 const bool wasAttached = pStream->readFlag(); 906 if ( wasAttached && objectIndex >= mObjectList.size() ) 907 { 908#ifdef VPATH_DEBUG_NET 909 Con::printf( "VPath::unpackUpdate() - WasAttached - %d | %d", isServerObject(), objectIndex ); 910#endif 911 912 // Create & Add to the List. 913 attachObject( new VPathObject() ); 914 } 915 916 // Reference Node. 917 VPathObject *pathObject = mObjectList[objectIndex]; 918 919 // Unpack Update. 920 pathObject->unpackUpdate( pConnection, pStream ); 921 922 // Object Attached this Unpack? 923 if ( wasAttached ) 924 { 925 // Reset. 926 setPathObjectInterp( pathObject, pathObject->getTimeInterp() ); 927 } 928 } 929 930 // Number To Detach. 931 const U32 detachCount = pStream->readInt( gMaxObjectBits + 1 ); 932 933 for ( U32 i = 0; i < detachCount; i++ ) 934 { 935 // Fetch the path object. 936 VPathObject *pathObject = mObjectList[pStream->readInt( gMaxObjectBits )]; 937 // Detach callback. 938 onDetachObject( pathObject ); 939 } 940 } 941} 942 943//----------------------------------------------------------------------------- 944// 945// Node Methods. 946// 947//----------------------------------------------------------------------------- 948 949VPathNode *VPath::createNode( void ) 950{ 951 return new VPathNode(); 952} 953 954void VPath::deleteNode( VPathNode *pNode ) 955{ 956 delete pNode; 957} 958 959void VPath::clear( void ) 960{ 961 for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) 962 { 963 VPathObject *pathObject = ( *itr ); 964 965 // Fetch the attached object. 966 SceneObject *refObject = pathObject->getObject(); 967 // Unmount Object. 968 unmountObject( refObject ); 969 970 // Delete the Path Object. 971 delete pathObject; 972 } 973 974 // Clear Object List. 975 mObjectList.clear(); 976 977 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 978 { 979 deleteNode( ( *itr ) ); 980 } 981 982 // Clear Node List. 983 mNodeList.clear(); 984 985 if ( isServerObject() ) 986 { 987 // Update. 988 setMaskBits( NodeUpdateMask ); 989 } 990} 991 992VPathNode *VPath::getNode( const S32 &pNodeIndex ) 993{ 994 // Sanity! 995 AssertFatal( pNodeIndex >= 0 && pNodeIndex < mNodeList.size(), "VPath::getNode() - Invalid Index" ); 996 997 // Return Node. 998 return mNodeList[pNodeIndex]; 999} 1000 1001DefineEngineMethod( VPath, addNode, void, (TransformF transform, F32 weight, S32 location), (MatrixF::Identity, 1.0, -1), 1002 "( transform pTransform, float pWeight, [int pLocation] ) - Add a node with the given properties. Nodes represent physical points that attached objects move towards or between, but the PathType determines \"how\" they move between them.\n" 1003 "@param pTransform The position and rotation of the new node.\n" 1004 "@param pWeight The weight of the new node.\n" 1005 "@param pLocation The index of the new node.\n" 1006 "@return No return value.") 1007{ 1008 // Fetch Invers Path Transform. 1009 MatrixF pathTransformInv = object->getTransform(); 1010 pathTransformInv.setPosition( Point3F::Zero ); 1011 pathTransformInv.inverse(); 1012 1013 Point3F pos; 1014 QuatF rot; 1015 AngAxisF aa; 1016 1017 pos = transform.mPosition; 1018 aa = transform.mOrientation; 1019 1020 // Set Rotation. 1021 rot.set( aa ); 1022 1023 // World to Local Position. 1024 Point3F nodePosition = ( pos - object->getPosition() ); 1025 pathTransformInv.mulP( nodePosition ); 1026 1027 // World to Local Rotation. 1028 MatrixF nodeRotationMat; 1029 rot.setMatrix( &nodeRotationMat ); 1030 pathTransformInv.mul( nodeRotationMat ); 1031 1032 // Set Quat. 1033 QuatF nodeRotation; 1034 nodeRotation.set( nodeRotationMat ); 1035 1036 // Add Node. 1037 VPathNode *node = object->addNode( nodePosition, nodeRotation, weight, location ); 1038 1039 // Valid Node? 1040 if ( node ) 1041 { 1042 // Update Size. 1043 object->updateContainer(); 1044 1045 // Calculate Path. 1046 object->calculatePath(); 1047 } 1048} 1049 1050VPathNode *VPath::addNode( const Point3F &pPosition, const QuatF &pRotation, const F32 &pWeight, const S32 &pLocation ) 1051{ 1052 // Reference Object. 1053 VPathNode *pathNode = createNode(); 1054 1055 // Store Properties. 1056 pathNode->setLocalPosition( pPosition ); 1057 pathNode->setLocalRotation( pRotation ); 1058 pathNode->setWeight( pWeight ); 1059 1060 // Add Node. 1061 return addNode( pathNode, pLocation ); 1062} 1063 1064VPathNode *VPath::addNode( VPathNode *pNode, const S32 &pLocation ) 1065{ 1066 if ( pNode->getPath() ) 1067 { 1068 // Error. 1069 Con::errorf( "VPath::addNode() - Node already belongs to a Path, '%d'", pNode->getPath()->getId() ); 1070 1071 return NULL; 1072 } 1073 else if ( mNodeList.size() == gMaxNodeCount ) 1074 { 1075 // Error. 1076 Con::errorf( "VPath::addNode() - Reached Max Nodes (%d)", gMaxNodeCount ); 1077 1078 // Delete Node. 1079 deleteNode( pNode ); 1080 1081 return NULL; 1082 } 1083 1084 // Set Path. 1085 pNode->setPath( this ); 1086 1087 // Update World Data. 1088 pNode->updateWorldData(); 1089 1090 if ( pLocation < 0 ) 1091 { 1092 // Push Back. 1093 mNodeList.push_back( pNode ); 1094 } 1095 else 1096 { 1097 // Fetch Size. 1098 const S32 nodeCount = mNodeList.size(); 1099 1100 if ( pLocation >= nodeCount ) 1101 { 1102 // Push Back. 1103 mNodeList.push_back( pNode ); 1104 } 1105 else 1106 { 1107 // Insert. 1108 mNodeList.insert( ( mNodeList.address() + pLocation ), pNode ); 1109 } 1110 } 1111 1112 if ( isServerObject() ) 1113 { 1114 // Update. 1115 setMaskBits( NodeUpdateMask ); 1116 } 1117 1118 // Return Node. 1119 return pNode; 1120} 1121 1122DefineEngineMethod( VPath, deleteNode, void, (S32 nodeIndex), (0), "( int pNodeIndex ) - Delete the node with the given index. If you delete a node that an attached object is moving to, or from then the object's movement will adjust so that it has a valid path.\n" 1123 "@param pNodeIndex The index of the node to be deleted.\n" 1124 "@return No return value." ) 1125{ 1126 // Apply Update. 1127 object->deleteNode( nodeIndex ); 1128} 1129 1130void VPath::deleteNode( const S32 &pNodeIndex ) 1131{ 1132 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 1133 { 1134 // Woops! 1135 Con::warnf( "VPath::deleteNode() - Invalid Index Specified (%d).", pNodeIndex ); 1136 return; 1137 } 1138 1139 // Fetch Node. 1140 VPathNode *node = mNodeList[pNodeIndex]; 1141 1142 // Remove Node References. 1143 for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) 1144 { 1145 // Fetch Object. 1146 VPathObject *pathObject = ( *itr ); 1147 1148 if ( ( pathObject->getSourceNode() >= pNodeIndex ) || ( pathObject->getDestinationNode() >= pNodeIndex ) ) 1149 { 1150 S32 srcNode = pathObject->getSourceNode(); 1151 S32 dstNode = pathObject->getDestinationNode(); 1152 1153 if ( pathObject->isForward() ) 1154 { 1155 if ( srcNode >= pNodeIndex ) 1156 { 1157 srcNode -= 1; 1158 } 1159 1160 if ( dstNode > pNodeIndex ) 1161 { 1162 dstNode -= 1; 1163 } 1164 } 1165 else 1166 { 1167 if ( srcNode > pNodeIndex ) 1168 { 1169 srcNode -= 1; 1170 } 1171 1172 if ( dstNode >= pNodeIndex ) 1173 { 1174 dstNode -= 1; 1175 } 1176 } 1177 1178 // Normalize indices. 1179 normalizeNodeIndex( srcNode, ( mNodeList.size() - 1 ) ); 1180 normalizeNodeIndex( dstNode, ( mNodeList.size() - 1 ) ); 1181 1182 // Apply Update. 1183 pathObject->setNode( srcNode, dstNode ); 1184 1185 if ( isServerObject() ) 1186 { 1187 // Update Objects. 1188 setMaskBits( ObjectUpdateMask ); 1189 } 1190 } 1191 } 1192 1193 if ( isServerObject() ) 1194 { 1195 // Network Flags. 1196 setMaskBits( NodeUpdateMask ); 1197 1198 // Flag for Deletion. 1199 node->setMaskBits( VPathNode::k_StateDelete ); 1200 } 1201} 1202 1203void VPath::removeNode( const S32 &pNodeIndex ) 1204{ 1205 // Fetch the node. 1206 VPathNode *node = getNode( pNodeIndex ); 1207 if ( !node ) 1208 { 1209 // Quit. 1210 return; 1211 } 1212 1213 // Delete Node. 1214 deleteNode( node ); 1215 // Erase Node. 1216 mNodeList.erase( pNodeIndex ); 1217} 1218 1219S32 VPath::normalizeNodeIndex( S32 &pNodeIndex ) 1220{ 1221 const S32 nodeCount = mNodeList.size(); 1222 if ( nodeCount == 0 ) 1223 { 1224 // No Nodex. 1225 pNodeIndex = 0; 1226 } 1227 else 1228 { 1229 while ( pNodeIndex < 0 ) 1230 { 1231 // Wrap Backwards. 1232 pNodeIndex += nodeCount; 1233 } 1234 1235 // Wrap Forwards. 1236 pNodeIndex %= nodeCount; 1237 } 1238 1239 // Return Index. 1240 return pNodeIndex; 1241} 1242 1243S32 VPath::normalizeNodeIndex( const S32 &pNodeIndex ) 1244{ 1245 // Temp. 1246 S32 nodeIndex = pNodeIndex; 1247 1248 // Return Index. 1249 return normalizeNodeIndex( nodeIndex ); 1250} 1251 1252S32 VPath::normalizeNodeIndex( S32 &pNodeIndex, const S32 &pNodeCount ) 1253{ 1254 if ( pNodeCount == 0 ) 1255 { 1256 // No Nodex. 1257 pNodeIndex = 0; 1258 } 1259 else 1260 { 1261 while ( pNodeIndex < 0 ) 1262 { 1263 // Wrap Backwards. 1264 pNodeIndex += pNodeCount; 1265 } 1266 1267 // Wrap Forwards. 1268 pNodeIndex %= pNodeCount; 1269 } 1270 1271 // Return Index. 1272 return pNodeIndex; 1273} 1274 1275//----------------------------------------------------------------------------- 1276// 1277// Object Methods. 1278// 1279//----------------------------------------------------------------------------- 1280 1281DefineEngineMethod( VPath, isObjectAttached, bool, (SceneObject* sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Is the object attached to this path?\n" 1282 "@param pObject The SimObjectID of the object you wish to check.\n" 1283 "@return Returns true if the object is attached to this path." ) 1284{ 1285 if (sceneObject== nullptr) 1286 { 1287 Con::errorf( "VPath::isObjectAttached() - Invalid Target Object." ); 1288 return false; 1289 } 1290 1291 // Attached? 1292 return object->isObjectAttached( sceneObject ); 1293} 1294 1295bool VPath::isObjectAttached( SceneObject *pObject ) 1296{ 1297 // Valid Object? 1298 return ( getPathObject( pObject ) != NULL ); 1299} 1300 1301VPathObject *VPath::getPathObject( SceneObject *pObject ) 1302{ 1303 for ( VPathObjectIterator itr = mObjectList.begin(); itr != mObjectList.end(); itr++ ) 1304 { 1305 // Correct Object? 1306 if ( ( *itr )->getObject() == pObject ) 1307 { 1308 // Yes. 1309 return ( *itr ); 1310 } 1311 } 1312 1313 return NULL; 1314} 1315 1316DefineEngineStringlyVariadicMethod( VPath, attachObject, void, 7, 8, "( SimObject pObject, bool pForward, float pSpeed, bool pRelative, int pStartNode, [int pEndNode] ) - Attach an object to this path with the given properties. If the object is already attached to a path, then a warning will be displayed and the object will *not* be attached to this path.\n" 1317 "@param pObject The SimObjectID of the object to be attached.\n" 1318 "@param pForward Should the object be moving forward?\n" 1319 "@param pSpeed The speed that the object will travel around the path.\n" 1320 "@param pRelative Offset the object based on the difference between the start node and its current position.\n" 1321 "@param pStartNode The index of the node this object starts pathing from.\n" 1322 "@param pEndNode The index of the node this object will stop pathing at." 1323 "@return No return value." ) 1324{ 1325 // Fetch Object. 1326 SceneObject *sceneObject; 1327 if ( !Sim::findObject( argv[2], sceneObject ) ) 1328 { 1329 Con::errorf( "VPath::attachObject() - Invalid Target Object." ); 1330 return; 1331 } 1332 1333 // Fetch Direction. 1334 const bool forward = dAtob( argv[3] ); 1335 // Fetch Speed. 1336 const F32 speed = dAtof( argv[4] ); 1337 // Fetch Relativity. 1338 const bool relative = dAtob( argv[5] ); 1339 // Fetch Start Node. 1340 const S32 startNode = dAtoi( argv[6] ); 1341 // Fetch End Node. 1342 const S32 endNode = ( argc >= 8 ) ? dAtoi( argv[7] ) : -1; 1343 1344 // Attach Object. 1345 object->attachObject( sceneObject, forward, speed, relative, startNode, endNode ); 1346} 1347 1348void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode ) 1349{ 1350 attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, VPathObject::k_OrientationToPath, NULL ); 1351} 1352 1353void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode ) 1354{ 1355 attachObject( pObject, pForward, pSpeed, pRelative, pStartNode, pEndNode, pOrientationMode, NULL ); 1356} 1357 1358void VPath::attachObject( SceneObject *pObject, const bool &pForward, const F32 &pSpeed, const bool &pRelative, const S32 &pStartNode, const S32 &pEndNode, const VPathObject::eOrientationType &pOrientationMode, void *pOrientationData ) 1359{ 1360 // Already Pathing? 1361 if ( isObjectAttached( pObject ) ) 1362 { 1363 Con::warnf( "VPath::attachObject() - Object Already Attached to a Path." ); 1364 return; 1365 } 1366 1367 // Determine Target Nodes. 1368 const S32 srcNode = normalizeNodeIndex( pStartNode ); 1369 const S32 dstNode = normalizeNodeIndex( ( pForward ) ? pStartNode + 1 : pStartNode - 1 ); 1370 const S32 endNode = ( pEndNode == -1 ) ? pEndNode : normalizeNodeIndex( pEndNode ); 1371 1372 // Valid Source Node? 1373 if ( getNodeCount() == 0 || !getNode( srcNode ) ) 1374 { 1375 Con::warnf( "VPath::attachObject() - Invalid Start Node." ); 1376 return; 1377 } 1378 1379 VPathObject *pathObject = new VPathObject(); 1380 1381 // Init Properties. 1382 pathObject->setActive( true ); 1383 pathObject->setObject( pObject ); 1384 1385 pathObject->setForward( pForward ); 1386 1387 pathObject->setTimeInterp( 0.f ); 1388 pathObject->setPathInterp( 0.f ); 1389 pathObject->setOffset( Point3F::Zero ); 1390 pathObject->setSpeed( pSpeed ); 1391 1392 switch( pOrientationMode ) 1393 { 1394 case VPathObject::k_OrientationFree : 1395 case VPathObject::k_OrientationInterpolate : 1396 case VPathObject::k_OrientationToPath : 1397 { 1398 pathObject->setOrientationMode( pOrientationMode ); 1399 1400 } break; 1401 1402 case VPathObject::k_OrientationToObject : 1403 { 1404 pathObject->setOrientationMode( pOrientationMode, (SceneObject*)pOrientationData ); 1405 1406 } break; 1407 1408 case VPathObject::k_OrientationToPoint : 1409 { 1410 pathObject->setOrientationMode( pOrientationMode, ( *(Point3F*)pOrientationData ) ); 1411 1412 } break; 1413 } 1414 1415 pathObject->setNode( srcNode, dstNode ); 1416 pathObject->setStartNode( srcNode ); 1417 pathObject->setEndNode( endNode ); 1418 1419 // Fetch Init Node. 1420 VPathNode *node = mNodeList[srcNode]; 1421 1422 // Relative Position? 1423 if ( pRelative ) 1424 { 1425 // Set Position Offset. 1426 pathObject->setOffset( pObject->getPosition() - node->getWorldPosition() ); 1427 } 1428 1429 // Set info. 1430 setPathObjectInterp( pathObject, 0.f ); 1431 1432 // Attach. 1433 attachObject( pathObject ); 1434} 1435 1436void VPath::attachObject( VPathObject *pPathObject ) 1437{ 1438#ifdef VPATH_DEBUG_NET 1439 Con::printf( "VPath::attachObject() - %d", isServerObject() ); 1440#endif 1441 1442 if ( mObjectList.size() == gMaxObjectCount ) 1443 { 1444 Con::errorf( "VPath::attachObject() - Reached Max Objects (%d)", gMaxObjectCount ); 1445 return; 1446 } 1447 1448 // Add to List. 1449 mObjectList.push_back( pPathObject ); 1450 1451 // Callback. 1452 onAttachObject( pPathObject ); 1453 1454 if ( isServerObject() ) 1455 { 1456 // Update. 1457 setMaskBits( ObjectUpdateMask ); 1458 } 1459} 1460 1461void VPath::onAttachObject( VPathObject *pPathObject ) 1462{ 1463 // Valid Object? 1464 SceneObject *refObject = pPathObject->getObject(); 1465 if ( !refObject ) 1466 { 1467 return; 1468 } 1469 1470#ifdef VPATH_DEBUG_NET 1471 Con::printf( "VPath::onAttachObject() - %d | %d", isServerObject(), refObject->getId() ); 1472#endif 1473 1474 // Delete Notify. 1475 deleteNotify( refObject ); 1476 1477 if ( isServerObject() ) 1478 { 1479 // Fetch the Available Mount Index. 1480 U32 mountIndex = getAvailableMountIndex(); 1481 // Mount the Object to this Path. 1482 mountObject( refObject, mountIndex ); 1483 1484 // Return Buffer. 1485 char buffer[1][32]; 1486 dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); 1487 1488 // Callback. 1489 // VPath::onAttachObject( %object ); 1490 Con::executef( this, "onAttachObject", buffer[0] ); 1491 } 1492} 1493 1494DefineEngineMethod( VPath, detachObject, void, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Detach the object from this path in place.\n" 1495 "@param pObject The SimObjectID of the object to be detached.\n" 1496 "@return No return value." ) 1497{ 1498 // Fetch Object. 1499 if (sceneObject == nullptr) 1500 { 1501 Con::errorf( "VPath::detachObject() - Invalid Target Object." ); 1502 return; 1503 } 1504 1505 // Detach Object. 1506 object->detachObject( sceneObject ); 1507} 1508 1509void VPath::detachObject( SceneObject *pObject ) 1510{ 1511 VPathObject *pathObject = getPathObject( pObject ); 1512 if ( !pathObject ) 1513 { 1514 Con::warnf( "VPath::detachObject() - Object (%d) Not Attached to Path.", pObject->getId() ); 1515 return; 1516 } 1517 1518 // Detach. 1519 detachObject( pathObject ); 1520} 1521 1522void VPath::detachObject( VPathObject *pPathObject ) 1523{ 1524#ifdef VPATH_DEBUG_NET 1525 Con::printf( "VPath::detachObject() - %d", isServerObject() ); 1526#endif 1527 1528 if ( isServerObject() ) 1529 { 1530 // Update Objects. 1531 setMaskBits( ObjectUpdateMask ); 1532 1533 // Detach. 1534 pPathObject->setMaskBits( VPathObject::k_StateDetach ); 1535 } 1536 1537 /* 1538 // Valid Object? 1539 SceneObject *refObject = pPathObject->getObject(); 1540 if ( refObject ) 1541 { 1542 // Unmount Object. 1543 unmountObject( refObject ); 1544 } 1545 */ 1546} 1547 1548void VPath::onDetachObject( VPathObject *pPathObject ) 1549{ 1550 // Valid Object? 1551 SceneObject *refObject = pPathObject->getObject(); 1552 if ( !refObject ) 1553 { 1554 return; 1555 } 1556 1557#ifdef VPATH_DEBUG_NET 1558 Con::printf( "VPath::onDetachObject() - %d | %d", isServerObject(), refObject->getId() ); 1559#endif 1560 1561 // Reset. 1562 setPathObjectInterp( pPathObject, pPathObject->getTimeInterp() ); 1563 // Unmount Object. 1564 unmountObject( refObject ); 1565 1566 // Delete the Path Object. 1567 delete pPathObject; 1568 // Remove from the Set. 1569 mObjectList.erase( mObjectList.find_next( pPathObject ) ); 1570 1571 // Clear Delete Notify. 1572 clearNotify( refObject ); 1573 1574 if ( isServerObject() ) 1575 { 1576 // Return Buffer. 1577 char buffer[1][32]; 1578 dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); 1579 1580 // Callback. 1581 // VPath::onDetachObject( %object ); 1582 Con::executef( this, "onDetachObject", buffer[0] ); 1583 } 1584} 1585 1586void VPath::processTick( const Move *pMove ) 1587{ 1588} 1589 1590void VPath::advanceObject( VPathObject *pPathObject, const F32 &pDelta ) 1591{ 1592 SceneObject *refObject = pPathObject->getObject(); 1593 if ( !refObject || mIsZero( pDelta ) ) 1594 { 1595 // Ignore. 1596 return; 1597 } 1598 1599 // Spatial Delta. 1600 pPathObject->popDelta(); 1601 1602 // Active and Moving? 1603 if ( !pPathObject->isActive() || mIsZero( pPathObject->getSpeed() ) ) 1604 { 1605 // Update Delta. 1606 pPathObject->pushDelta( refObject->getPosition(), refObject->getTransform().getForwardVector() ); 1607 // Skip. 1608 return; 1609 } 1610 1611 // Fetch Nodes. 1612 VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; 1613 VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; 1614 VPathNode *lenNode = ( pPathObject->isForward() ) ? srcNode : dstNode; 1615 1616 // Calculate Interp Delta. 1617 const F32 stepDistance = ( pPathObject->getSpeed() * pDelta ); 1618 const F32 speedMod = ( pPathObject->getSpeed() / lenNode->getLength() ); 1619 F32 timeInterp = pPathObject->getTimeInterp(); 1620 F32 timeInterpDelta = ( speedMod * pDelta ); 1621 F32 pathInterp = pPathObject->getPathInterp(); 1622 F32 pathInterpDelta = 0.f; 1623 1624 // Fetch the old position. 1625 const Point3F oldPosition = pPathObject->getPosition(); 1626 // Calculate the new position and path delta. 1627 Point3F newPosition = getAdvancedPathPosition( pPathObject, stepDistance, pathInterpDelta ); 1628 1629 // Finished? 1630 if ( ( timeInterp + timeInterpDelta ) >= 1.f ) 1631 { 1632 // Finished? 1633 if ( pPathObject->getDestinationNode() == pPathObject->getEndNode() ) 1634 { 1635 // Stop Updates. 1636 pPathObject->setActive( false ); 1637 } 1638 else 1639 { 1640 // Update Nodes. 1641 const S32 srcNodeIndex = pPathObject->getDestinationNode(); 1642 const S32 dstNodeIndex = normalizeNodeIndex( ( pPathObject->isForward() ) ? srcNodeIndex + 1 : srcNodeIndex - 1 ); 1643 1644#ifdef VPATH_DEBUG_STEP 1645 if ( isServerObject() ) 1646 Con::errorf( "Change Node:\n Source, %d\n Destination, %d", srcNodeIndex, dstNodeIndex ); 1647#endif 1648 1649 // Apply Changes. 1650 pPathObject->setNode( srcNodeIndex, dstNodeIndex ); 1651 pPathObject->setTimeInterp( 0.f ); 1652 pPathObject->setPathInterp( 0.f ); 1653 pPathObject->setPosition( newPosition ); 1654 1655 // Reset local interp information. 1656 timeInterp = 0.f; 1657 timeInterpDelta = 0.f; 1658 pathInterp = 0.f; 1659 pathInterpDelta = 0.f; 1660 1661 // Fetch the distance we've travelled. 1662 const F32 &advanceDistance = ( newPosition - oldPosition ).len(); 1663 // Any remaining distance? 1664 if ( ( stepDistance - advanceDistance ) > 0.0001f ) 1665 { 1666 // Determine how much more we need to move. 1667 Point3F newPosition0 = newPosition; 1668 newPosition = getAdvancedPathPosition( pPathObject, ( stepDistance - advanceDistance ), pathInterpDelta ); 1669 1670#ifdef VPATH_DEBUG_STEP 1671 if ( isServerObject() ) 1672 Con::errorf( "Transition Step: %f\nTransition Distance: %f + %f = %f", pathInterpDelta, advanceDistance, ( newPosition - newPosition0 ).len(), advanceDistance + ( newPosition - newPosition0 ).len() ); 1673#endif 1674 } 1675 } 1676 1677 if ( isServerObject() ) 1678 { 1679 // Return Buffer. 1680 char buffer[3][32]; 1681 dSprintf( buffer[0], sizeof( buffer[0] ), "%d", refObject->getId() ); 1682 dSprintf( buffer[1], sizeof( buffer[1] ), "%d", pPathObject->isActive() ? pPathObject->getSourceNode() : pPathObject->getDestinationNode() ); 1683 dSprintf( buffer[2], sizeof( buffer[2] ), "%d", !pPathObject->isActive() ); 1684 1685 // Callback. 1686 // VPath::onReachNode( %object, %node, %finished ); 1687 Con::executef( this, "onReachNode", buffer[0], buffer[1], buffer[2] ); 1688 } 1689 } 1690 1691 // Update Object Interp. 1692 timeInterp = mClampF( timeInterp + timeInterpDelta, 0.f, 1.f ); 1693 pathInterp = mClampF( pathInterp + pathInterpDelta, 0.f, 1.f ); 1694 1695 // Apply Changes. 1696 pPathObject->setTimeInterp( timeInterp ); 1697 pPathObject->setPathInterp( pathInterp ); 1698 pPathObject->setPosition( newPosition ); 1699 1700#ifdef VPATH_DEBUG_STEP 1701 if ( isServerObject() ) 1702 Con::printf( "Time / Distance: %f %f / %f %f", timeInterp, pathInterp, stepDistance, ( newPosition - oldPosition ).len() ); 1703#endif 1704 1705 switch ( pPathObject->getOrientationMode().Type ) 1706 { 1707 case VPathObject::k_OrientationInterpolate : 1708 case VPathObject::k_OrientationToObject : 1709 case VPathObject::k_OrientationToPoint : 1710 { 1711 // Update Orientation. 1712 updateOrientation( pPathObject ); 1713 1714 } break; 1715 1716 case VPathObject::k_OrientationToPath : 1717 { 1718 // Determine the path orientation. 1719 VectorF pathOrientation = ( newPosition - oldPosition ); 1720 pathOrientation.normalize(); 1721 1722 // Update Orientation. 1723 updateOrientation( pPathObject, pathOrientation ); 1724 1725 } break; 1726 } 1727 1728 // Update Delta. 1729 pPathObject->pushDelta( pPathObject->getPosition(), pPathObject->getOrientation() ); 1730 1731 if ( isServerObject() ) 1732 { 1733 // Update Objects. 1734 setMaskBits( ObjectUpdateMask ); 1735 1736 // Update This Object. 1737 pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); 1738 } 1739} 1740 1741void VPath::updatePosition( VPathObject *pPathObject ) 1742{ 1743 // Fetch Nodes. 1744 VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); 1745 VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); 1746 1747 // Fetch Position. 1748 F32 pathInterp = 0.f; 1749 const Point3F newPosition = getPathPosition( srcNode, dstNode, pPathObject->getTimeInterp(), pPathObject->isForward(), pathInterp ); 1750 1751 // Apply Position. 1752 pPathObject->setPosition( newPosition ); 1753 pPathObject->setPathInterp( pathInterp ); 1754} 1755 1756void VPath::updateOrientation( VPathObject *pPathObject ) 1757{ 1758 // Update Orientation? 1759 if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) 1760 { 1761 // Skip. 1762 return; 1763 } 1764 1765 // Fetch Nodes. 1766 VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); 1767 VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); 1768 1769 // Determine Path Orientation. 1770 VectorF pathOrientation; 1771 switch ( pPathObject->getOrientationMode().Type ) 1772 { 1773 case VPathObject::k_OrientationInterpolate : 1774 { 1775 // Interpolate Between Transforms. 1776 QuatF rot; 1777 rot.interpolate( srcNode->getWorldRotation(), dstNode->getWorldRotation(), pPathObject->getPathInterp() ); 1778 1779 // Set Matrix. 1780 MatrixF mat; 1781 rot.setMatrix( &mat ); 1782 1783 // Fetch Orientation. 1784 pathOrientation = mat.getColumn3F( 1 ); 1785 1786 } break; 1787 1788 case VPathObject::k_OrientationToObject : 1789 { 1790 // Fetch Orientation. 1791 pathOrientation = ( pPathObject->getOrientationMode().Object->getPosition() - pPathObject->getWorldPosition() ); 1792 pathOrientation.normalizeSafe(); 1793 1794 } break; 1795 1796 case VPathObject::k_OrientationToPoint : 1797 { 1798 // Fetch Orientation. 1799 pathOrientation = ( pPathObject->getOrientationMode().Point - pPathObject->getWorldPosition() ); 1800 pathOrientation.normalizeSafe(); 1801 1802 } break; 1803 1804 case VPathObject::k_OrientationToPath : 1805 { 1806 // Fetch Orientation. 1807 pathOrientation = getPathOrientation( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward() ); 1808 1809 } break; 1810 } 1811 1812 // Update. 1813 updateOrientation( pPathObject, pathOrientation ); 1814} 1815 1816void VPath::updateOrientation( VPathObject *pPathObject, const Point3F &pPathOrientation ) 1817{ 1818 // Update Orientation? 1819 if ( pPathObject->getOrientationMode().Type == VPathObject::k_OrientationFree ) 1820 { 1821 // Skip. 1822 return; 1823 } 1824 1825 // Fetch Nodes. 1826 VPathNode *srcNode = getNode( pPathObject->getSourceNode() ); 1827 VPathNode *dstNode = getNode( pPathObject->getDestinationNode() ); 1828 1829 // Determine Source Orientation. 1830 VectorF srcOrientation; 1831 switch ( srcNode->getOrientationMode().Type ) 1832 { 1833 case VPathNode::k_OrientationToPoint : 1834 { 1835 // Fetch Orientation. 1836 srcOrientation = ( srcNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); 1837 srcOrientation.normalize(); 1838 1839 } break; 1840 1841 default : 1842 { 1843 // Use Path Orientation. 1844 srcOrientation = pPathOrientation; 1845 1846 } break; 1847 } 1848 1849 // Determine Destination Orientation. 1850 VectorF dstOrientation; 1851 switch ( dstNode->getOrientationMode().Type ) 1852 { 1853 case VPathNode::k_OrientationToPoint : 1854 { 1855 // Fetch Orientation. 1856 dstOrientation = ( dstNode->getOrientationMode().Point - pPathObject->getWorldPosition() ); 1857 dstOrientation.normalize(); 1858 1859 } break; 1860 1861 default : 1862 { 1863 // Use Path Orientation. 1864 dstOrientation = pPathOrientation; 1865 1866 } break; 1867 } 1868 1869 // Determine Actual Orientation. 1870 VectorF orientation; 1871 orientation.interpolate( srcOrientation, dstOrientation, pPathObject->getTimeInterp() ); 1872 1873 // Apply. 1874 pPathObject->setOrientation( orientation ); 1875} 1876 1877//----------------------------------------------------------------------------- 1878// 1879// Path Methods. 1880// 1881//----------------------------------------------------------------------------- 1882 1883void VPath::calculatePath( void ) 1884{ 1885 if ( mNodeList.size() < 2 ) 1886 { 1887 // No Path. 1888 return; 1889 } 1890 1891 switch ( mPathType ) 1892 { 1893 case k_PathLinear : 1894 { 1895 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 1896 { 1897 if ( itr == ( mNodeList.end() - 1 ) ) 1898 { 1899 // Head, Front. 1900 calculateLinearPath( ( *itr ), ( *( mNodeList.begin() ) ) ); 1901 } 1902 else 1903 { 1904 // Head, Next. 1905 calculateLinearPath( ( *itr ), ( *( itr + 1 ) ) ); 1906 } 1907 } 1908 1909 } break; 1910 1911 case k_PathBezier : 1912 { 1913 for ( VPathNodeIterator itr = mNodeList.begin(); itr != mNodeList.end(); itr++ ) 1914 { 1915 if ( itr == ( mNodeList.end() - 1 ) ) 1916 { 1917 // Head, Prev, Front. 1918 calculateBezierPath( ( *itr ), ( *( mNodeList.begin() ) ) ); 1919 } 1920 else 1921 { 1922 // Head, Prev, Next. 1923 calculateBezierPath( ( *itr ), ( *( itr + 1 ) ) ); 1924 } 1925 } 1926 1927 } break; 1928 } 1929} 1930 1931Point3F VPath::getAdvancedPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) 1932{ 1933 switch( mPathType ) 1934 { 1935 case k_PathLinear : 1936 { 1937 return getAdvancedLinearPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); 1938 1939 } break; 1940 1941 case k_PathBezier : 1942 { 1943 return getAdvancedBezierPathPosition( pPathObject, pTargetDistance, pPathInterpDelta ); 1944 1945 } break; 1946 } 1947 1948 // Sanity! 1949 AssertFatal( false, "Invalid path type!" ); 1950 return Point3F::Zero; 1951} 1952 1953DefineEngineMethod( VPath, getPathTransform, const char *, (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp), (0,0,1.0), "( int pSrcNodeIndex, int pDstNodeIndex, float pTimeInterp ) - Get the transform of the path at the interp point between two nodes.\n" 1954 "@param pSrcNodeIndex The first node.\n" 1955 "@param pDstNodeIndex The second node.\n" 1956 "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" 1957 "@return Returns the transform of the interp time between the two given nodes." ) 1958{ 1959 // Fetch Nodes. 1960 VPathNode *srcNode = object->getNode(srcNodeIndex); 1961 VPathNode *dstNode = object->getNode(dstNodeIndex); 1962 1963 // Interp Time. 1964 const F32 &interp = timeInterp; 1965 1966 // Fetch Position & Orientation. 1967 const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); 1968 const VectorF orientation = object->getPathOrientation( srcNode, dstNode, interp, true ); 1969 1970 // Y-Axis. 1971 VectorF yVec = orientation; 1972 yVec.normalize(); 1973 1974 // X-Axis. 1975 VectorF xVec = mCross( yVec, VPath::gBezierUp ); 1976 xVec.normalize(); 1977 1978 // Z-Axis. 1979 VectorF zVec = mCross( xVec, yVec ); 1980 zVec.normalize(); 1981 1982 // Setup Object Transform. 1983 MatrixF mat( true ); 1984 mat.setColumn( 0, xVec ); 1985 mat.setColumn( 1, yVec ); 1986 mat.setColumn( 2, zVec ); 1987 1988 // AngAxis. 1989 AngAxisF aa( mat ); 1990 1991 // Return Buffer; 1992 char *buffer = Con::getReturnBuffer( 256 ); 1993 dSprintf( buffer, 256, "%g %g %g %g %g %g %g", position.x, position.y, position.z, 1994 aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); 1995 1996 // Return. 1997 return buffer; 1998} 1999 2000DefineEngineMethod( VPath, getPathPosition, const char *, (S32 srcNodeIndex, S32 dstNodeIndex, F32 timeInterp), (0, 0, 1.0), "( int pSrcNodeIndex, int pDstNodeIndex, int pTimeInterp ) - Get the world position of the path at the interp point between two nodes.\n" 2001 "@param pSrcNodeIndex The first node.\n" 2002 "@param pDstNodeIndex The second node.\n" 2003 "@param pTimeInterp The time to interp between the two nodes. Value is between 0.0 and 1.0.\n" 2004 "@return Returns the world position of the interp time between the two given nodes." ) 2005{ 2006 // Fetch Nodes. 2007 VPathNode *srcNode = object->getNode(srcNodeIndex); 2008 VPathNode *dstNode = object->getNode(dstNodeIndex); 2009 2010 // Interp Time. 2011 const F32 &interp = timeInterp; 2012 2013 // Find Position. 2014 const Point3F position = object->getPathPosition( srcNode, dstNode, interp, true ); 2015 2016 // Return Buffer; 2017 char *buffer = Con::getReturnBuffer( 128 ); 2018 dSprintf( buffer, 128, "%g %g %g", position.x, position.y, position.z ); 2019 2020 // Return. 2021 return buffer; 2022} 2023 2024Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) 2025{ 2026 F32 pathInterp = 0.f; 2027 return getPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pathInterp ); 2028} 2029 2030Point3F VPath::getPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) 2031{ 2032 switch( mPathType ) 2033 { 2034 case k_PathBezier : 2035 { 2036 return getBezierPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); 2037 2038 } break; 2039 2040 case k_PathLinear : 2041 { 2042 return getLinearPathPosition( pSourceNode, pDestinationNode, pTimeInterp, pForward, pPathInterp ); 2043 2044 } break; 2045 } 2046 2047 // NULL. 2048 return Point3F::Zero; 2049} 2050 2051VectorF VPath::getPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) 2052{ 2053 switch( mPathType ) 2054 { 2055 case k_PathBezier : 2056 { 2057 return getBezierPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); 2058 2059 } break; 2060 2061 case k_PathLinear : 2062 { 2063 return getLinearPathOrientation( pSourceNode, pDestinationNode, pTimeInterp, pForward ); 2064 2065 } break; 2066 } 2067 2068 // NULL. 2069 return VectorF::Zero; 2070} 2071 2072//----------------------------------------------------------------------------- 2073// 2074// Linear Path Methods. 2075// 2076//----------------------------------------------------------------------------- 2077 2078void VPath::calculateLinearPath( VPathNode *pNode, VPathNode *pNextNode ) 2079{ 2080 // Calculate Segment Length. 2081 pNode->setLength( ( pNextNode->getWorldPosition() - pNode->getWorldPosition() ).len() ); 2082} 2083 2084Point3F VPath::getAdvancedLinearPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) 2085{ 2086 // Fetch Nodes. 2087 VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; 2088 VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; 2089 2090 // Fetch the length of the segment. 2091 const F32 length = ( pPathObject->isForward() ) ? srcNode->getLength() : dstNode->getLength(); 2092 2093 // Set the interp delta. 2094 pPathInterpDelta = ( pTargetDistance / length ); 2095 2096 // Return the position. 2097 F32 pathInterp = 0.f; 2098 return getLinearPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->isForward(), pathInterp ); 2099} 2100 2101Point3F VPath::getLinearPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) 2102{ 2103 // Set path interp to the time interp. 2104 pPathInterp = pTimeInterp; 2105 2106 if ( pTimeInterp <= 0.f ) 2107 { 2108 // Source Node. 2109 return pSourceNode->getWorldPosition(); 2110 } 2111 else if ( pTimeInterp >= 1.f ) 2112 { 2113 // Destination Node. 2114 return pDestinationNode->getWorldPosition(); 2115 } 2116 2117 // Calculate Position. 2118 Point3F position; 2119 position.interpolate( pSourceNode->getWorldPosition(), pDestinationNode->getWorldPosition(), pTimeInterp ); 2120 2121 // Return. 2122 return position; 2123} 2124 2125VectorF VPath::getLinearPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) 2126{ 2127 // Calculate Orientation. 2128 VectorF newOrientation = ( pDestinationNode->getWorldPosition() - pSourceNode->getWorldPosition() ); 2129 newOrientation.normalizeSafe(); 2130 2131 // Return. 2132 return newOrientation; 2133} 2134 2135//----------------------------------------------------------------------------- 2136// 2137// Bezier Path Methods. 2138// 2139//----------------------------------------------------------------------------- 2140 2141void VPath::calculateBezierPath( VPathNode *pNode, VPathNode *pNextNode ) 2142{ 2143 // Reset Length. 2144 F32 segmentLength = 0.f; 2145 2146 // Positions. 2147 const Point3F &pt0 = pNode->getWorldPosition(); 2148 const Point3F &pt3 = pNextNode->getWorldPosition(); 2149 2150 // Fetch Node Rotation Matrices. 2151 MatrixF mat0, mat1; 2152 pNode->getWorldRotation().setMatrix( &mat0 ); 2153 pNextNode->getWorldRotation().setMatrix( &mat1 ); 2154 2155 // Determine Tangent Axis. 2156 Point3F pt1( gBezierAxis * pNode->getWeight() ); 2157 Point3F pt2( -gBezierAxis * pNextNode->getWeight() ); 2158 2159 // Rotate Axis. 2160 mat0.mulP( pt1 ); 2161 mat1.mulP( pt2 ); 2162 2163 // Offset Points. 2164 pt1 += pt0; 2165 pt2 += pt3; 2166 2167 // Initial Position. 2168 Point3F ptA = pt0; 2169 const F32 i = gBezierInterpStep; 2170 for ( F32 t = 0.f, it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) 2171 { 2172 // Calculate Position. 2173 Point3F ptB = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); 2174 2175 // Add Segment. 2176 segmentLength += ( ptB - ptA ).len(); 2177 2178 // Store Position. 2179 ptA = ptB; 2180 } 2181 2182 // Apply Update. 2183 pNode->setLength( segmentLength ); 2184} 2185 2186Point3F VPath::getAdvancedBezierPathPosition( VPathObject *pPathObject, const F32 &pTargetDistance, F32 &pPathInterpDelta ) 2187{ 2188 // Fetch Nodes. 2189 VPathNode *srcNode = mNodeList[pPathObject->getSourceNode()]; 2190 VPathNode *dstNode = mNodeList[pPathObject->getDestinationNode()]; 2191 2192 // Fetch the delta position. 2193 return getBezierPathPosition( srcNode, dstNode, pPathObject->getPathInterp(), pPathObject->getPosition(), pTargetDistance, pPathObject->isForward(), true, pPathInterpDelta ); 2194} 2195 2196Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward, F32 &pPathInterp ) 2197{ 2198 // Fetch the length of the segment. 2199 const F32 length = ( pForward ) ? pSourceNode->getLength() : pDestinationNode->getLength(); 2200 2201 // Determine the real interp time for the distance fraction. 2202 return getBezierPathPosition( pSourceNode, pDestinationNode, 0.f, pSourceNode->getWorldPosition(), ( length * pTimeInterp ), pForward, false, pPathInterp ); 2203} 2204 2205Point3F VPath::getBezierPathPosition( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const Point3F &pReferencePosition, const F32 &pTargetDistance, const bool &pForward, const bool &pRelativeToReference, F32 &pPathInterpDelta ) 2206{ 2207 // Positions. 2208 const Point3F &pt0 = pSourceNode->getWorldPosition(); 2209 const Point3F &pt3 = pDestinationNode->getWorldPosition(); 2210 2211 // Fetch Node Rotation Matrices. 2212 MatrixF mat0, mat1; 2213 pSourceNode->getWorldRotation().setMatrix( &mat0 ); 2214 pDestinationNode->getWorldRotation().setMatrix( &mat1 ); 2215 2216 // Determine Tangent Axis. 2217 Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); 2218 Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); 2219 2220 if ( !pForward ) 2221 { 2222 pt1 *= -1.f; 2223 pt2 *= -1.f; 2224 } 2225 2226 // Rotate Axis. 2227 mat0.mulP( pt1 ); 2228 mat1.mulP( pt2 ); 2229 2230 // Offset Points. 2231 pt1 += pt0; 2232 pt2 += pt3; 2233 2234 // Move Position. 2235 Point3F movePosition = pReferencePosition; 2236 // Movement Distance. 2237 F32 moveDistance = 0.f; 2238 2239 // Determine the Real Delta. 2240 const F32 i = gBezierInterpStep; 2241 for ( F32 t = ( pTimeInterp + i ), it = ( 1.f - t ); t <= 1.f; t += i, it = ( 1.f - t ) ) 2242 { 2243 // Calculate Step. 2244 const Point3F stepPosition = ( pt0 * it * it * it ) + ( 3 * pt1 * it * it * t ) + ( 3 * pt2 * it * t * t ) + ( pt3 * t * t * t ); 2245 // Step Length. 2246 const F32 &stepDistance = ( stepPosition - movePosition ).len(); 2247 2248 if ( pRelativeToReference ) 2249 { 2250 // Calculate Distance. 2251 moveDistance = ( pReferencePosition - stepPosition ).len(); 2252 2253 // Moved Target Distance? 2254 if ( moveDistance >= pTargetDistance ) 2255 { 2256 // Interpolate Step. 2257 const F32 stepInterp = ( moveDistance - pTargetDistance ) / moveDistance; 2258 // Store Interp Delta. 2259 pPathInterpDelta = ( t - pTimeInterp ) * ( 1.f - stepInterp ); 2260 2261 // Interpolate the step. 2262 Point3F outPosition; 2263 outPosition.interpolate( pReferencePosition, stepPosition, ( 1.f - stepInterp ) ); 2264 // Return the position. 2265 return outPosition; 2266 } 2267 } 2268 else 2269 { 2270 // Calculate Distance. 2271 moveDistance += stepDistance; 2272 2273 // Moved Target Distance? 2274 if ( moveDistance >= pTargetDistance ) 2275 { 2276 // Interpolate Step. 2277 const F32 stepInterp = ( moveDistance - pTargetDistance ) / stepDistance; 2278 // Store Interp Delta. 2279 pPathInterpDelta = ( t - pTimeInterp ) - ( stepInterp * i ); 2280 2281 // Interpolate the step. 2282 Point3F outPosition; 2283 outPosition.interpolate( movePosition, stepPosition, ( 1.f - stepInterp ) ); 2284 // Return the position. 2285 return outPosition; 2286 } 2287 } 2288 2289 // Apply New Position. 2290 movePosition = stepPosition; 2291 } 2292 2293 // Update. 2294 pPathInterpDelta = ( 1.f - pTimeInterp ); 2295 // At the destination node? 2296 return pt3; 2297} 2298 2299VectorF VPath::getBezierPathOrientation( VPathNode *pSourceNode, VPathNode *pDestinationNode, const F32 &pTimeInterp, const bool &pForward ) 2300{ 2301 // Positions. 2302 const Point3F &pt0 = pSourceNode->getWorldPosition(); 2303 const Point3F &pt3 = pDestinationNode->getWorldPosition(); 2304 2305 // Fetch Node Rotation Matrices. 2306 MatrixF mat0, mat1; 2307 pSourceNode->getWorldRotation().setMatrix( &mat0 ); 2308 pDestinationNode->getWorldRotation().setMatrix( &mat1 ); 2309 2310 // Determine Tangent Axis. 2311 Point3F pt1( gBezierAxis * pSourceNode->getWeight() ); 2312 Point3F pt2( -gBezierAxis * pDestinationNode->getWeight() ); 2313 2314 if ( !pForward ) 2315 { 2316 pt1 *= -1.f; 2317 pt2 *= -1.f; 2318 } 2319 2320 // Rotate Axis. 2321 mat0.mulP( pt1 ); 2322 mat1.mulP( pt2 ); 2323 2324 const F32 halfStep = ( gBezierInterpStep / 2.f ); 2325 if ( ( pTimeInterp - halfStep ) <= 0.f ) 2326 { 2327 // Orientation From Node Tangent. 2328 pt1.normalize(); 2329 2330 // Return. 2331 return pt1; 2332 } 2333 else if ( ( pTimeInterp + halfStep ) >= 1.f ) 2334 { 2335 // Orientation From Node Tangent. 2336 pt2.normalize(); 2337 2338 // Return. 2339 return -pt2; 2340 } 2341 2342 // Offset Points. 2343 pt1 += pt0; 2344 pt2 += pt3; 2345 2346 // Interp Times. 2347 const F32 t0 = ( pTimeInterp - halfStep ); 2348 const F32 it0 = ( 1.f - t0 ); 2349 2350 const F32 t1 = ( pTimeInterp + halfStep ); 2351 const F32 it1 = ( 1.f - t1 ); 2352 2353 // Calculate Position. 2354 Point3F d0 = ( pt0 * it0 * it0 * it0 ) + ( 3 * pt1 * it0 * it0 * t0 ) + ( 3 * pt2 * it0 * t0 * t0 ) + ( pt3 * t0 * t0 * t0 ); 2355 Point3F d1 = ( pt0 * it1 * it1 * it1 ) + ( 3 * pt1 * it1 * it1 * t1 ) + ( 3 * pt2 * it1 * t1 * t1 ) + ( pt3 * t1 * t1 * t1 ); 2356 2357 // Set Orientation. 2358 Point3F orientation = ( d1 - d0 ); 2359 orientation.normalizeSafe(); 2360 2361 // Return. 2362 return orientation; 2363} 2364 2365//----------------------------------------------------------------------------- 2366// 2367// Path Node Property Methods. 2368// 2369//----------------------------------------------------------------------------- 2370 2371DefineEngineMethod( VPath, getNodeCount, S32, (),, "() - Get the number of nodes in this path.\n" 2372 "@return Returns the number of nodes." ) 2373{ 2374 // Return Count. 2375 return object->getNodeCount(); 2376} 2377 2378S32 VPath::getNodeCount( void ) 2379{ 2380 // Return the Size of the Node List. 2381 return mNodeList.size(); 2382} 2383 2384DefineEngineMethod( VPath, getNodeLocalTransform, const char *, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the local transform (local position and rotation) of the given node.\n" 2385 "@param pNodeIndex The index of the node.\n" 2386 "@return Returns the transform of the given node." ) 2387{ 2388 // Fetch Position. 2389 const Point3F &position = object->getNodeLocalPosition(nodeIndex); 2390 2391 // Fetch Rotation. 2392 const QuatF &rotation = object->getNodeLocalRotation(nodeIndex); 2393 2394 // Angle & Axis. 2395 AngAxisF aa( rotation ); 2396 2397 // Return Buffer. 2398 char *buffer = Con::getReturnBuffer( 256 ); 2399 dSprintf( buffer, 128, "%.3g %.3g %.3g %.3g %.3g %.3g %.3g", position.x, position.y, position.z, aa.axis.x, aa.axis.y, aa.axis.z, aa.angle ); 2400 2401 return buffer; 2402} 2403 2404DefineEngineMethod( VPath, getNodeLocalPosition, Point3F, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the position of the given node.\n" 2405 "@param pNodeIndex The index of the node.\n" 2406 " @return Returns the Local Position of the given node." ) 2407{ 2408 // Fetch Position. 2409 const Point3F &position = object->getNodeLocalPosition(nodeIndex); 2410 2411 return position; 2412} 2413 2414Point3F VPath::getNodeLocalPosition( const S32 &pNodeIndex ) 2415{ 2416 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2417 { 2418 // Woops! 2419 Con::warnf( "VPath::getNodeLocalPosition() - Invalid Index Specified (%d).", pNodeIndex ); 2420 return Point3F::Zero; 2421 } 2422 2423 return mNodeList[pNodeIndex]->getLocalPosition(); 2424} 2425 2426DefineEngineMethod( VPath, getNodeLocalRotation, AngAxisF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the Local Rotation of the given node.\n" 2427 "@param pNodeIndex The index of the node.\n" 2428 "@return Returns the Local Rotation of the given node." ) 2429{ 2430 // Fetch Rotation. 2431 const QuatF &rotation = object->getNodeLocalRotation(nodeIndex); 2432 2433 // Angle & Axis. 2434 AngAxisF aa( rotation ); 2435 2436 return aa; 2437} 2438 2439QuatF VPath::getNodeLocalRotation( const S32 &pNodeIndex ) 2440{ 2441 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2442 { 2443 // Woops! 2444 Con::warnf( "VPath::getNodeLocalRotation() - Invalid Index Specified (%d).", pNodeIndex ); 2445 return QuatF( Point3F::Zero, 0.f ); 2446 } 2447 2448 return mNodeList[pNodeIndex]->getLocalRotation(); 2449} 2450 2451DefineEngineMethod( VPath, getNodeWorldTransform, TransformF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the World Transform (position and rotation) of the given node.\n" 2452 "@param pNodeIndex The index of the node.\n" 2453 "@return Returns the transform of the given node." ) 2454{ 2455 // Fetch Position. 2456 const Point3F &position = object->getNodeWorldPosition(nodeIndex); 2457 2458 // Fetch Rotation. 2459 const QuatF &rotation = object->getNodeWorldRotation(nodeIndex); 2460 2461 // Angle & Axis. 2462 AngAxisF aa( rotation ); 2463 2464 TransformF trans; 2465 trans.mPosition = position; 2466 trans.mOrientation = aa; 2467 2468 return trans; 2469} 2470 2471DefineEngineMethod( VPath, getNodeWorldPosition, Point3F, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the position of the given node.\n" 2472 "@param pNodeIndex The index of the node.\n" 2473 "@return Returns the World Position of the given node." ) 2474{ 2475 // Fetch Position. 2476 const Point3F &position = object->getNodeWorldPosition(nodeIndex); 2477 2478 return position; 2479} 2480 2481Point3F VPath::getNodeWorldPosition( const S32 &pNodeIndex ) 2482{ 2483 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2484 { 2485 // Woops! 2486 Con::warnf( "VPath::getNodeWorldPosition() - Invalid Index Specified (%d).", pNodeIndex ); 2487 return Point3F::Zero; 2488 } 2489 2490 return mNodeList[pNodeIndex]->getWorldPosition(); 2491} 2492 2493DefineEngineMethod( VPath, getNodeWorldRotation, AngAxisF, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the World Rotation of the given node.\n" 2494 "@param pNodeIndex The index of the node.\n" 2495 "@return Returns the World Rotation of the given node." ) 2496{ 2497 // Fetch Rotation. 2498 const QuatF &rotation = object->getNodeWorldRotation(nodeIndex); 2499 2500 // Angle & Axis. 2501 AngAxisF aa( rotation ); 2502 2503 return aa; 2504} 2505 2506QuatF VPath::getNodeWorldRotation( const S32 &pNodeIndex ) 2507{ 2508 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2509 { 2510 // Woops! 2511 Con::warnf( "VPath::getNodeWorldRotation() - Invalid Index Specified (%d).", pNodeIndex ); 2512 return QuatF( Point3F::Zero, 0.f ); 2513 } 2514 2515 return mNodeList[pNodeIndex]->getWorldRotation(); 2516} 2517 2518DefineEngineMethod( VPath, getNodeWeight, F32, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the weight of the given node.\n" 2519 "@param pNodeIndex The index of the node.\n" 2520 "@return Returns the weight of the given node." ) 2521{ 2522 // Fetch Weight. 2523 return object->getNodeWeight(nodeIndex); 2524} 2525 2526F32 VPath::getNodeWeight( const S32 &pNodeIndex ) 2527{ 2528 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2529 { 2530 // Woops! 2531 Con::warnf( "VPath::getNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); 2532 return 0.f; 2533 } 2534 2535 return mNodeList[pNodeIndex]->getWeight(); 2536} 2537 2538DefineEngineMethod( VPath, getNodeLength, F32, (S32 nodeIndex), (0), "( int pNodeIndex ) - Get the length of the given node.\n" 2539 "@param pNodeIndex The index of the node.\n" 2540 "@return Returns the length of the given node." ) 2541{ 2542 // Fetch Length. 2543 return object->getNodeLength( nodeIndex ); 2544} 2545 2546F32 VPath::getNodeLength( const S32 &pNodeIndex ) 2547{ 2548 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2549 { 2550 // Woops! 2551 Con::warnf( "VPath::getNodeLength() - Invalid Index Specified (%d).", pNodeIndex ); 2552 return 0.f; 2553 } 2554 2555 return mNodeList[pNodeIndex]->getLength(); 2556} 2557 2558DefineEngineMethod( VPath, setNodeTransform, void, (S32 nodeIndex, TransformF transform), (0, MatrixF::Identity), "( int pNodeIndex, matrix pTransform ) - Set the transform of the given node.\n" 2559 "@param pNodeIndex The index of the node.\n" 2560 "@param pTransform The new transform to be applied to the node.\n" 2561 "@return No return value." ) 2562{ 2563 // Fetch Position & Rotation. 2564 Point3F position = transform.mPosition; 2565 AngAxisF aa = transform.mOrientation; 2566 QuatF rotation; 2567 2568 // Set Rotation. 2569 rotation.set( aa ); 2570 2571 // Apply Update. 2572 object->setNodePosition( nodeIndex, position ); 2573 object->setNodeRotation( nodeIndex, rotation ); 2574} 2575 2576DefineEngineMethod( VPath, setNodePosition, void, (S32 nodeIndex, Point3F position), (0, Point3F::Zero), "( int pNodeIndex, vector pPosition ) - Set the position of the given node.\n" 2577 "@param pNodeIndex The index of the node.\n" 2578 "@param pPosition The new position to be applied to the node.\n" 2579 "@return No return value." ) 2580{ 2581 // Apply Update. 2582 object->setNodePosition( nodeIndex, position ); 2583} 2584 2585void VPath::setNodePosition( const S32 &pNodeIndex, const Point3F &pPosition ) 2586{ 2587 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2588 { 2589 // Woops! 2590 Con::warnf( "VPath::setNodePosition() - Invalid Index Specified (%d).", pNodeIndex ); 2591 return; 2592 } 2593 2594 // Fetch Node. 2595 VPathNode *node = mNodeList[pNodeIndex]; 2596 2597 // Apply Update. 2598 node->setLocalPosition( pPosition ); 2599 2600 // Update Size. 2601 updateContainer(); 2602 2603 // Calculate Path. 2604 calculatePath(); 2605 2606 if ( isServerObject() ) 2607 { 2608 // Network Flags. 2609 setMaskBits( NodeUpdateMask ); 2610 } 2611} 2612 2613DefineEngineMethod( VPath, setNodeRotation, void, (S32 nodeIndex, AngAxisF aa), (0, AngAxisF()), "( int pNodeIndex, angAxis pRotation ) - Set the rotation of the given node.\n" 2614 "@param pNodeIndex The index of the node.\n" 2615 "@param pRotation The new rotation to be applied to the node.\n" 2616 "@return No return value." ) 2617{ 2618 QuatF rotation; 2619 2620 // Set Rotation. 2621 rotation.set( aa ); 2622 2623 // Apply Update. 2624 object->setNodeRotation( nodeIndex, rotation ); 2625} 2626 2627void VPath::setNodeRotation( const S32 &pNodeIndex, const QuatF &pRotation ) 2628{ 2629 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2630 { 2631 // Woops! 2632 Con::warnf( "VPath::setNodeRotation() - Invalid Index Specified (%d).", pNodeIndex ); 2633 return; 2634 } 2635 2636 // Fetch Node. 2637 VPathNode *node = mNodeList[pNodeIndex]; 2638 2639 // Apply Update. 2640 node->setLocalRotation( pRotation ); 2641 2642 // Calculate Path. 2643 calculatePath(); 2644 2645 if ( isServerObject() ) 2646 { 2647 // Network Flags. 2648 setMaskBits( NodeUpdateMask ); 2649 } 2650} 2651 2652DefineEngineMethod( VPath, setNodeWeight, void, (S32 nodeIndex, F32 nodeWeight), (0, 1.0), "( int pNodeIndex, float pWeight ) - Set the weight of the given node.\n" 2653 "@param pNodeIndex The index of the node.\n" 2654 "@param pWeight The new weight to be applied to the node.\n" 2655 "@return No return value." ) 2656{ 2657 // Apply Update. 2658 object->setNodeWeight( nodeIndex, nodeWeight ); 2659} 2660 2661void VPath::setNodeWeight( const S32 &pNodeIndex, const F32 &pWeight ) 2662{ 2663 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2664 { 2665 // Woops! 2666 Con::warnf( "VPath::setNodeWeight() - Invalid Index Specified (%d).", pNodeIndex ); 2667 return; 2668 } 2669 2670 // Fetch Node. 2671 VPathNode *node = mNodeList[pNodeIndex]; 2672 2673 // Apply Update. 2674 node->setWeight( pWeight ); 2675 2676 // Calculate Path. 2677 calculatePath(); 2678 2679 if ( isServerObject() ) 2680 { 2681 // Network Flags. 2682 setMaskBits( NodeUpdateMask ); 2683 } 2684} 2685 2686DefineEngineMethod( VPath, getNodeOrientationMode, const char *, (S32 nodeIndex), (0), "( int pNodeIndex ) - Gets the current orientation mode of the node.\n" 2687 "@param pNodeIndex The index of the node.\n" 2688 "@return Returns a string indicating the orientation mode and its properties." ) 2689{ 2690 if ( nodeIndex < 0 || nodeIndex >= object->getNodeCount() ) 2691 { 2692 // Woops! 2693 Con::warnf( "VPath::getNodeOrientationMode() - Invalid Index Specified (%d).", nodeIndex ); 2694 return ""; 2695 } 2696 2697 // Fetch Object 2698 VPathNode *node = object->getNode( nodeIndex ); 2699 2700 // Fetch Orientation Mode. 2701 const VPathNode::sOrientation &orientation = node->getOrientationMode(); 2702 2703 // Determine the Type. 2704 StringTableEntry type = VPathNode::getOrientationTypeLabel( orientation.Type ); 2705 2706 // Buffer. 2707 char *buffer = Con::getReturnBuffer( 128 ); 2708 2709 switch( orientation.Type ) 2710 { 2711 case VPathNode::k_OrientationFree : 2712 { 2713 // Buffer String. 2714 dSprintf( buffer, 128, "%s", type ); 2715 2716 } break; 2717 2718 case VPathNode::k_OrientationToPoint: 2719 { 2720 // Fetch Point. 2721 const Point3F &lookAtPoint = orientation.Point; 2722 // Buffer String. 2723 dSprintf( buffer, 128, "%s\t%.2f %.2f %.2f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); 2724 2725 } break; 2726 } 2727 2728 // Return Buffer. 2729 return buffer; 2730} 2731 2732DefineEngineStringlyVariadicMethod( VPath, setNodeOrientationMode, void, 4, 5, "( int pNodeIndex, string pOrientationType, [vector pPoint] ) - Set the orientation mode of the node.\n" 2733 "@param pNodeIndex The index of the node.\n" 2734 "@param pOrientationType The new orientation type of the object.\n" 2735 "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" 2736 "@return No return value." ) 2737{ 2738 // Fetch Index. 2739 const S32 nodeIndex = dAtoi( argv[2] ); 2740 2741 // Orient? 2742 const VPathNode::eOrientationType type = VPathNode::getOrientationTypeEnum( argv[3] ); 2743 2744 switch ( type ) 2745 { 2746 case VPathNode::k_OrientationFree : 2747 { 2748 // Apply Mode. 2749 object->setNodeOrientationMode( nodeIndex, type ); 2750 2751 } break; 2752 2753 case VPathNode::k_OrientationToPoint: 2754 { 2755 // Fetch Point. 2756 Point3F lookAtPoint( 0.f, 0.f, 0.f ); 2757 dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); 2758 2759 // Apply Mode. 2760 object->setNodeOrientationMode( nodeIndex, type, lookAtPoint ); 2761 2762 } break; 2763 2764 default : 2765 { 2766 AssertFatal( false, "VPath::setNodeOrientationMode() - Invalid Orientation Mode Specified." ); 2767 2768 } break; 2769 } 2770} 2771 2772void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType ) 2773{ 2774 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2775 { 2776 // Woops! 2777 Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); 2778 return; 2779 } 2780 2781 // Fetch Node. 2782 VPathNode *node = mNodeList[pNodeIndex]; 2783 2784 // Apply. 2785 node->setOrientationMode( pType ); 2786 2787 // Network Flags. 2788 setMaskBits( NodeUpdateMask ); 2789} 2790 2791void VPath::setNodeOrientationMode( const S32 &pNodeIndex, const VPathNode::eOrientationType &pType, const Point3F pPoint ) 2792{ 2793 if ( pNodeIndex < 0 || pNodeIndex >= mNodeList.size() ) 2794 { 2795 // Woops! 2796 Con::warnf( "VPath::setNodeOrientationMode() - Invalid Index Specified (%d).", pNodeIndex ); 2797 return; 2798 } 2799 2800 // Fetch Node. 2801 VPathNode *node = mNodeList[pNodeIndex]; 2802 2803 // Apply. 2804 node->setOrientationMode( pType, pPoint ); 2805 2806 // Network Flags. 2807 setMaskBits( NodeUpdateMask ); 2808} 2809 2810//----------------------------------------------------------------------------- 2811// 2812// Path Object Property Methods. 2813// 2814//----------------------------------------------------------------------------- 2815 2816DefineEngineMethod( VPath, isPathObjectActive, bool, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Is the object actively traveling around this path?\n" 2817 "@param pObject The SimObjectID of the object being observed.\n" 2818 "@return Returns true of the object is active." ) 2819{ 2820 // Fetch Object. 2821 if (sceneObject == nullptr) 2822 { 2823 Con::errorf( "VPath::isPathObjectActive() - Invalid Target Object." ); 2824 return false; 2825 } 2826 2827 // Fetch Object 2828 VPathObject *pathObject = object->getPathObject( sceneObject ); 2829 2830 // Return. 2831 return pathObject->isActive(); 2832} 2833 2834DefineEngineMethod( VPath, setPathObjectActive, void, (SceneObject *sceneObject, bool isActive), (nullAsType<SceneObject*>(), true), "( SimObject pObject, bool pActive ) - Enable or disable the object from traveling around this path. Inactive objects are still attached to the path, but are not updated.\n" 2835 "@param pObject The SimObjectID of the object being altered.\n" 2836 "@param pActive The new status of the object.\n" 2837 "@return No return value." ) 2838{ 2839 // Fetch Object. 2840 if (sceneObject == nullptr) 2841 { 2842 Con::errorf( "VPath::setPathObjectActive() - Invalid Target Object." ); 2843 return; 2844 } 2845 2846 // Apply. 2847 object->setPathObjectActive( sceneObject, isActive); 2848} 2849 2850void VPath::setPathObjectActive( SceneObject *pObject, const bool &pActive ) 2851{ 2852 VPathObject *pathObject = getPathObject( pObject ); 2853 if ( !pathObject ) 2854 { 2855 Con::warnf( "VPath::setPathObjectActive() - Object (%d) Not Attached to Path.", pObject->getId() ); 2856 return; 2857 } 2858 2859 // Apply. 2860 pathObject->setActive( pActive ); 2861 2862 // Network Flags. 2863 setMaskBits( ObjectUpdateMask ); 2864} 2865 2866DefineEngineMethod( VPath, getPathObjectInterp, F32, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Get the current interp position of the path object.\n" 2867 "@param pObject The SimObjectID of the object being observed.\n" 2868 "@return Returns the current interp position." ) 2869{ 2870 // Fetch Object. 2871 if (sceneObject == nullptr) 2872 { 2873 Con::errorf( "VPath::getPathObjectInterp() - Invalid Target Object." ); 2874 return false; 2875 } 2876 2877 // Fetch Object 2878 VPathObject *pathObject = object->getPathObject( sceneObject ); 2879 2880 // Return. 2881 return pathObject->getTimeInterp(); 2882} 2883 2884DefineEngineMethod( VPath, setPathObjectInterp, void, (SceneObject *sceneObject, F32 timeInterp), (nullAsType<SceneObject*>(), 1.0), "( SimObject pObject, float pTimeInterp ) - Set the interp position of the object between its current nodes.\n" 2885 "@param pObject The SimObjectID of the object being altered.\n" 2886 "@param pTimeInterp The new interp position of the object.\n" 2887 "@return No return value." ) 2888{ 2889 // Fetch Object. 2890 if (sceneObject == nullptr) 2891 { 2892 Con::errorf( "VPath::setPathObjectInterp() - Invalid Target Object." ); 2893 return; 2894 } 2895 2896 // Apply. 2897 object->setPathObjectInterp( sceneObject, timeInterp); 2898} 2899 2900void VPath::setPathObjectInterp( SceneObject *pObject, const F32 &pTimeInterp ) 2901{ 2902 VPathObject *pathObject = getPathObject( pObject ); 2903 if ( !pathObject ) 2904 { 2905 Con::warnf( "VPath::setPathObjectInterp() - Object (%d) Not Attached to Path.", pObject->getId() ); 2906 return; 2907 } 2908 2909 // Update. 2910 setPathObjectInterp( pathObject, pTimeInterp ); 2911} 2912 2913void VPath::setPathObjectInterp( VPathObject *pPathObject, const F32 &pTimeInterp ) 2914{ 2915 // Set Interp Time. 2916 pPathObject->setTimeInterp( pTimeInterp ); 2917 2918 // Update Position. 2919 updatePosition( pPathObject ); 2920 // Update Orientation. 2921 updateOrientation( pPathObject ); 2922 // Reset the delta. 2923 pPathObject->resetDelta(); 2924 2925 // Set the object transform. 2926 pPathObject->getObject()->setTransform( pPathObject->getTransform() ); 2927 2928 if ( isServerObject() ) 2929 { 2930 // Update Objects. 2931 setMaskBits( ObjectUpdateMask ); 2932 2933 // Update This Object. 2934 pPathObject->setMaskBits( VPathObject::k_StateUpdatePosition ); 2935 } 2936} 2937 2938DefineEngineMethod( VPath, getPathObjectOffset, const char *, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Get the position offset assigned to this object.\n" 2939 "@param pObject The SimObjectID of the object being observed.\n" 2940 "@return Returns the position offset." ) 2941{ 2942 // Fetch Object. 2943 if (sceneObject == nullptr) 2944 { 2945 Con::errorf( "VPath::getPathObjectOffset() - Invalid Target Object." ); 2946 return ""; 2947 } 2948 2949 // Fetch Object 2950 VPathObject *pathObject = object->getPathObject( sceneObject ); 2951 2952 // Fetch Offset. 2953 const Point3F &offset = pathObject->getOffset(); 2954 2955 // Buffer. 2956 char *buffer = Con::getReturnBuffer( 64 ); 2957 dSprintf( buffer, 64, "%f %f %f", offset.x, offset.y, offset.z ); 2958 return buffer; 2959} 2960 2961DefineEngineMethod( VPath, setPathObjectOffset, void, (SceneObject *sceneObject, Point3F offset), (nullAsType<SceneObject*>(), Point3F::Zero), "( SimObject pObject, vector pOffset ) - Set the position offset of the object. As the object is moving along the path, its position is offset by this value. Setting the \"Relative\" parameter while attaching an object will automatically apply an offset value.\n" 2962 "@param pObject The SimObjectID of the object being altered.\n" 2963 "@param pOffset The new position offset of the object.\n" 2964 "@return No return value." ) 2965{ 2966 // Fetch Object. 2967 if (sceneObject == nullptr) 2968 { 2969 Con::errorf( "VPath::setPathObjectOffset() - Invalid Target Object." ); 2970 return; 2971 } 2972 2973 // Apply. 2974 object->setPathObjectOffset( sceneObject, offset ); 2975} 2976 2977void VPath::setPathObjectOffset( SceneObject *pObject, const Point3F &pOffset ) 2978{ 2979 VPathObject *pathObject = getPathObject( pObject ); 2980 if ( !pathObject ) 2981 { 2982 Con::warnf( "VPath::setPathObjectOffset() - Object (%d) Not Attached to Path.", pObject->getId() ); 2983 return; 2984 } 2985 2986 // Apply. 2987 pathObject->setOffset( pOffset ); 2988 2989 // Network Flags. 2990 setMaskBits( ObjectUpdateMask ); 2991} 2992 2993DefineEngineMethod( VPath, getPathObjectSpeed, F32, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Get the speed this object is traveling along the path at.\n" 2994 "@param pObject The SimObjectID of the object being observed.\n" 2995 "@return Returns the speed of the object." ) 2996{ 2997 // Fetch Object. 2998 if (sceneObject == nullptr) 2999 { 3000 Con::errorf( "VPath::getPathObjectSpeed() - Invalid Target Object." ); 3001 return false; 3002 } 3003 3004 // Fetch Object 3005 VPathObject *pathObject = object->getPathObject( sceneObject ); 3006 3007 // Return. 3008 return pathObject->getSpeed(); 3009} 3010 3011DefineEngineMethod( VPath, setPathObjectSpeed, void, (SceneObject *sceneObject, F32 speed), (nullAsType<SceneObject*>(), 1.0), "( SimObject pObject, float pSpeed ) - Set the speed of the object.\n" 3012 "@param pObject The SimObjectID of the object being altered.\n" 3013 "@param pSpeed The new speed of the object.\n" 3014 "@return No return value." ) 3015{ 3016 // Fetch Object. 3017 if (sceneObject == nullptr) 3018 { 3019 Con::errorf( "VPath::setPathObjectSpeed() - Invalid Target Object." ); 3020 return; 3021 } 3022 3023 // Apply. 3024 object->setPathObjectSpeed( sceneObject, speed ); 3025} 3026 3027void VPath::setPathObjectSpeed( SceneObject *pObject, const F32 &pSpeed ) 3028{ 3029 VPathObject *pathObject = getPathObject( pObject ); 3030 if ( !pathObject ) 3031 { 3032 Con::warnf( "VPath::setPathObjectSpeed() - Object (%d) Not Attached to Path.", pObject->getId() ); 3033 return; 3034 } 3035 3036 // Apply. 3037 pathObject->setSpeed( mFabs( pSpeed ) ); 3038 3039 // Network Flags. 3040 setMaskBits( ObjectUpdateMask ); 3041} 3042 3043DefineEngineMethod( VPath, getPathObjectOrientationMode, const char *, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Gets the current orientation mode of the object.\n" 3044 "@param pObject The SimObjectID of the object being observed.\n" 3045 "@return Returns a string indicating the orientation mode and its properties." ) 3046{ 3047 // Fetch Object. 3048 if (sceneObject == nullptr) 3049 { 3050 Con::errorf( "VPath::getPathObjectOrientationMode() - Invalid Target Object." ); 3051 return ""; 3052 } 3053 3054 // Fetch Object 3055 VPathObject *pathObject = object->getPathObject( sceneObject ); 3056 3057 // Fetch Orientation Mode. 3058 const VPathObject::sOrientation &orientation = pathObject->getOrientationMode(); 3059 3060 // Determine the Type. 3061 StringTableEntry type = VPathObject::getOrientationTypeLabel( orientation.Type ); 3062 3063 // Buffer. 3064 char *buffer = Con::getReturnBuffer( 128 ); 3065 3066 switch( orientation.Type ) 3067 { 3068 case VPathObject::k_OrientationFree : 3069 case VPathObject::k_OrientationInterpolate : 3070 case VPathObject::k_OrientationToPath : 3071 { 3072 // Buffer String. 3073 dSprintf( buffer, 128, "%s", type ); 3074 3075 } break; 3076 3077 case VPathObject::k_OrientationToObject : 3078 { 3079 // Fetch the Object ID. 3080 const S32 objId = ( ( orientation.Object ) ? orientation.Object->getId() : 0 ); 3081 // Buffer String. 3082 dSprintf( buffer, 128, "%s %d", type, objId ); 3083 3084 } break; 3085 3086 case VPathObject::k_OrientationToPoint: 3087 { 3088 // Fetch Point. 3089 const Point3F &lookAtPoint = orientation.Point; 3090 // Buffer String. 3091 dSprintf( buffer, 128, "%s %f %f %f", type, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); 3092 3093 } break; 3094 } 3095 3096 // Return Buffer. 3097 return buffer; 3098} 3099 3100DefineEngineStringlyVariadicMethod( VPath, setPathObjectOrientationMode, void, 4, 5, "( SimObject pObject, string pOrientationType, [SimObject pObject / vector pPoint] ) - Set the orientation mode of the object. This property affects the rotation of the object. If you wish to ignore the object's rotation altogether, set the mode to \"FREE\".\n" 3101 "@param pObject The SimObjectID of the object being altered.\n" 3102 "@param pOrientationType The new orientation type of the object.\n" 3103 "@param pObject If the orientation type is set to OBJECT, this parameter must be the SimObjectID of a scene object.\n" 3104 "@param pPoint If the orientation type is set to POINT, this parameter must be a vector.\n" 3105 "@return No return value." ) 3106{ 3107 // Fetch Object. 3108 SceneObject *sceneObject; 3109 if ( !Sim::findObject( argv[2], sceneObject ) ) 3110 { 3111 Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid Target Object." ); 3112 return; 3113 } 3114 3115 // Orient? 3116 const VPathObject::eOrientationType type = VPathObject::getOrientationTypeEnum( argv[3] ); 3117 3118 switch ( type ) 3119 { 3120 case VPathObject::k_OrientationFree : 3121 case VPathObject::k_OrientationInterpolate : 3122 case VPathObject::k_OrientationToPath : 3123 { 3124 // Apply Mode. 3125 object->setPathObjectOrientationMode( sceneObject, type ); 3126 3127 } break; 3128 3129 case VPathObject::k_OrientationToObject : 3130 { 3131 // Fetch Object. 3132 SceneObject *lookAtObject = dynamic_cast<SceneObject*>( Sim::findObject( argv[4] ) ); 3133 if ( !lookAtObject ) 3134 { 3135 Con::errorf( "VPath::setPathObjectOrientationMode() - Invalid LookAt Object." ); 3136 return; 3137 } 3138 3139 // Apply Mode. 3140 object->setPathObjectOrientationMode( sceneObject, type, lookAtObject ); 3141 3142 } break; 3143 3144 case VPathObject::k_OrientationToPoint: 3145 { 3146 // Fetch Point. 3147 Point3F lookAtPoint( 0.f, 0.f, 0.f ); 3148 dSscanf( argv[4], "%g %g %g", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); 3149 3150 // Apply Mode. 3151 object->setPathObjectOrientationMode( sceneObject, type, lookAtPoint ); 3152 3153 } break; 3154 3155 default : 3156 { 3157 AssertFatal( false, "VPath::setPathObjectOrientationMode() - Invalid Orientation Mode Specified." ); 3158 3159 } break; 3160 } 3161} 3162 3163void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType ) 3164{ 3165 VPathObject *pathObject = getPathObject( pObject ); 3166 if ( !pathObject ) 3167 { 3168 Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); 3169 return; 3170 } 3171 3172 // Apply. 3173 pathObject->setOrientationMode( pType ); 3174 3175 // Network Flags. 3176 setMaskBits( ObjectUpdateMask ); 3177} 3178 3179void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, SceneObject *pLookAtObject ) 3180{ 3181 VPathObject *pathObject = getPathObject( pObject ); 3182 if ( !pathObject ) 3183 { 3184 Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); 3185 return; 3186 } 3187 3188 // Apply. 3189 pathObject->setOrientationMode( pType, pLookAtObject ); 3190 3191 // Network Flags. 3192 setMaskBits( ObjectUpdateMask ); 3193} 3194 3195void VPath::setPathObjectOrientationMode( SceneObject *pObject, const VPathObject::eOrientationType &pType, const Point3F pPoint ) 3196{ 3197 VPathObject *pathObject = getPathObject( pObject ); 3198 if ( !pathObject ) 3199 { 3200 Con::warnf( "VPath::setPathObjectOrientationMode() - Object (%d) Not Attached to Path.", pObject->getId() ); 3201 return; 3202 } 3203 3204 // Apply. 3205 pathObject->setOrientationMode( pType, pPoint ); 3206 3207 // Network Flags. 3208 setMaskBits( ObjectUpdateMask ); 3209} 3210 3211DefineEngineMethod( VPath, isPathObjectForward, bool, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Get if this object is traveling forwards along the path.\n" 3212 "@param pObject The SimObjectID of the object being observed.\n" 3213 "@return Returns true if the object is traveling forwards." ) 3214{ 3215 // Fetch Object. 3216 if (sceneObject == nullptr) 3217 { 3218 Con::errorf( "VPath::isPathObjectForward() - Invalid Target Object." ); 3219 return false; 3220 } 3221 3222 // Fetch Object 3223 VPathObject *pathObject = object->getPathObject( sceneObject ); 3224 3225 // Return. 3226 return pathObject->isForward(); 3227} 3228 3229DefineEngineMethod( VPath, setPathObjectForward, void, (SceneObject *sceneObject, bool forward), (nullAsType<SceneObject*>(), true), "( SimObject pObject, bool pForward ) - Set the travel direction of the object.\n" 3230 "@param pObject The SimObjectID of the object being altered.\n" 3231 "@param pForward The direction of the object.\n" 3232 "@return No return value." ) 3233{ 3234 // Fetch Object. 3235 if (sceneObject == nullptr) 3236 { 3237 Con::errorf( "VPath::setPathObjectForward() - Invalid Target Object." ); 3238 return; 3239 } 3240 3241 // Apply. 3242 object->setPathObjectForward( sceneObject, forward); 3243} 3244 3245void VPath::setPathObjectForward( SceneObject *pObject, const bool &pForward ) 3246{ 3247 VPathObject *pathObject = getPathObject( pObject ); 3248 if ( !pathObject ) 3249 { 3250 Con::warnf( "VPath::setPathObjectForward() - Object (%d) Not Attached to Path.", pObject->getId() ); 3251 return; 3252 } 3253 3254 // Apply. 3255 pathObject->setForward( pForward ); 3256 3257 // Network Flags. 3258 setMaskBits( ObjectUpdateMask ); 3259} 3260 3261DefineEngineMethod( VPath, getPathObjectNode, S32, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Gets the last node of the object.\n" 3262 "@param pObject The SimObjectID of the object being observed.\n" 3263 "@return Returns the node index." ) 3264{ 3265 // Fetch Object. 3266 if (sceneObject == nullptr) 3267 { 3268 Con::errorf( "VPath::getPathObjectNode() - Invalid Target Object." ); 3269 return false; 3270 } 3271 3272 // Fetch Object 3273 VPathObject *pathObject = object->getPathObject( sceneObject ); 3274 3275 // Return. 3276 return pathObject->getSourceNode(); 3277} 3278 3279DefineEngineMethod( VPath, setPathObjectNode, void, (SceneObject *sceneObject, S32 nodeIndex), (nullAsType<SceneObject*>(), 0), "( SimObject pObject, bool pNodeIndex ) - Move the object to the node's position. You may also want to observe the \"setPathObjectInterp\" method.\n" 3280 "@param pObject The SimObjectID of the object being altered.\n" 3281 "@param pNodeIndex The index of the node that the object will reposition to.\n" 3282 "@return No return value." ) 3283{ 3284 // Fetch Object. 3285 if (sceneObject == nullptr) 3286 { 3287 Con::errorf( "VPath::setPathObjectNode() - Invalid Target Object." ); 3288 return; 3289 } 3290 3291 // Apply. 3292 object->setPathObjectNode( sceneObject, nodeIndex); 3293} 3294 3295void VPath::setPathObjectNode( SceneObject *pObject, const S32 &pNodeIndex ) 3296{ 3297 VPathObject *pathObject = getPathObject( pObject ); 3298 if ( !pathObject ) 3299 { 3300 Con::warnf( "VPath::setPathObjectNode() - Object (%d) Not Attached to Path.", pObject->getId() ); 3301 return; 3302 } 3303 3304 // Source & Destination Nodes. 3305 const S32 srcNode = pNodeIndex; 3306 const S32 dstNode = ( pathObject->isForward() ) ? ( pNodeIndex + 1 ) : ( pNodeIndex - 1 ); 3307 3308 // Set Current Node. 3309 pathObject->setNode( normalizeNodeIndex( srcNode ), normalizeNodeIndex( dstNode ) ); 3310 3311 // Reset Interp. 3312 pathObject->setTimeInterp( 0.f ); 3313 pathObject->setPathInterp( 0.f ); 3314 3315 // Network Flags. 3316 setMaskBits( ObjectUpdateMask ); 3317} 3318 3319DefineEngineMethod( VPath, getPathObjectEndNode, S32, (SceneObject *sceneObject), (nullAsType<SceneObject*>()), "( SimObject pObject ) - Get the index of the node this object is meant to stop upon reaching.\n" 3320 "@param pObject The SimObjectID of the object being observed.\n" 3321 "@return Returns the node index." ) 3322{ 3323 // Fetch Object. 3324 if (sceneObject == nullptr) 3325 { 3326 Con::errorf( "VPath::getPathObjectEndNode() - Invalid Target Object." ); 3327 return false; 3328 } 3329 3330 // Fetch Object 3331 VPathObject *pathObject = object->getPathObject( sceneObject ); 3332 3333 // Return. 3334 return pathObject->getEndNode(); 3335} 3336 3337DefineEngineMethod( VPath, setPathObjectEndNode, void, (SceneObject *sceneObject, S32 nodeIndex), (nullAsType<SceneObject*>(), 0), "( SimObject pObject, bool pNodeIndex ) - Set end node of the path object. If a value of \"-1\" is applied, the object will path indefinitely.\n" 3338 "@param pObject The SimObjectID of the object being altered.\n" 3339 "@param pNodeIndex The index of the node that the object will cease pathing upon reaching.\n" 3340 "@return No return value." ) 3341{ 3342 // Fetch Object. 3343 if (sceneObject == nullptr) 3344 { 3345 Con::errorf( "VPath::setPathObjectEndNode() - Invalid Target Object." ); 3346 return; 3347 } 3348 3349 // Apply. 3350 object->setPathObjectEndNode( sceneObject, nodeIndex); 3351} 3352 3353void VPath::setPathObjectEndNode( SceneObject *pObject, const S32 &pNodeIndex ) 3354{ 3355 VPathObject *pathObject = getPathObject( pObject ); 3356 if ( !pathObject ) 3357 { 3358 Con::warnf( "VPath::setPathObjectEndNode() - Object (%d) Not Attached to Path.", pObject->getId() ); 3359 return; 3360 } 3361 3362 // Set index. 3363 S32 index = pNodeIndex; 3364 3365 if ( index != -1 ) 3366 { 3367 // Normalize index. 3368 normalizeNodeIndex( index ); 3369 } 3370 3371 // Apply. 3372 pathObject->setEndNode( index ); 3373 3374 // Network Flags. 3375 setMaskBits( ObjectUpdateMask ); 3376} 3377