ScenePresenceAnimator.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Threading;
  29. using System.Collections.Generic;
  30. using System.Reflection;
  31. using log4net;
  32. using OpenMetaverse;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Framework.Interfaces;
  35. using OpenSim.Region.Framework.Scenes;
  36. using OpenSim.Region.Physics.Manager;
  37. namespace OpenSim.Region.Framework.Scenes.Animation
  38. {
  39. /// <summary>
  40. /// Handle all animation duties for a scene presence
  41. /// </summary>
  42. public class ScenePresenceAnimator
  43. {
  44. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  45. public AnimationSet Animations
  46. {
  47. get { return m_animations; }
  48. }
  49. protected AnimationSet m_animations = new AnimationSet();
  50. /// <value>
  51. /// The current movement animation
  52. /// </value>
  53. public string CurrentMovementAnimation { get; private set; }
  54. private int m_animTickFall;
  55. public int m_animTickJump; // ScenePresence has to see this to control +Z force
  56. public bool m_jumping = false;
  57. public float m_jumpVelocity = 0f;
  58. // private int m_landing = 0;
  59. /// <summary>
  60. /// Is the avatar falling?
  61. /// </summary>
  62. public bool Falling { get; private set; }
  63. private float m_fallHeight;
  64. /// <value>
  65. /// The scene presence that this animator applies to
  66. /// </value>
  67. protected ScenePresence m_scenePresence;
  68. public ScenePresenceAnimator(ScenePresence sp)
  69. {
  70. m_scenePresence = sp;
  71. CurrentMovementAnimation = "CROUCH";
  72. }
  73. public void AddAnimation(UUID animID, UUID objectID)
  74. {
  75. if (m_scenePresence.IsChildAgent)
  76. return;
  77. // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
  78. if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
  79. SendAnimPack();
  80. }
  81. // Called from scripts
  82. public void AddAnimation(string name, UUID objectID)
  83. {
  84. if (m_scenePresence.IsChildAgent)
  85. return;
  86. UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
  87. if (animID == UUID.Zero)
  88. return;
  89. // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name);
  90. AddAnimation(animID, objectID);
  91. }
  92. public void RemoveAnimation(UUID animID)
  93. {
  94. if (m_scenePresence.IsChildAgent)
  95. return;
  96. if (m_animations.Remove(animID))
  97. SendAnimPack();
  98. }
  99. // Called from scripts
  100. public void RemoveAnimation(string name)
  101. {
  102. if (m_scenePresence.IsChildAgent)
  103. return;
  104. UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
  105. if (animID == UUID.Zero)
  106. return;
  107. RemoveAnimation(animID);
  108. }
  109. public void ResetAnimations()
  110. {
  111. // m_log.DebugFormat(
  112. // "[SCENE PRESENCE ANIMATOR]: Resetting animations for {0} in {1}",
  113. // m_scenePresence.Name, m_scenePresence.Scene.RegionInfo.RegionName);
  114. m_animations.Clear();
  115. }
  116. /// <summary>
  117. /// The movement animation is reserved for "main" animations
  118. /// that are mutually exclusive, e.g. flying and sitting.
  119. /// </summary>
  120. public void TrySetMovementAnimation(string anim)
  121. {
  122. if (!m_scenePresence.IsChildAgent)
  123. {
  124. // m_log.DebugFormat(
  125. // "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
  126. // anim, m_scenePresence.Name);
  127. if (m_animations.TrySetDefaultAnimation(
  128. anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
  129. {
  130. // m_log.DebugFormat(
  131. // "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
  132. // anim, m_scenePresence.Name);
  133. // 16384 is CHANGED_ANIMATION
  134. m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
  135. SendAnimPack();
  136. }
  137. }
  138. else
  139. {
  140. m_log.WarnFormat(
  141. "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
  142. anim, m_scenePresence.Name);
  143. }
  144. }
  145. /// <summary>
  146. /// This method determines the proper movement related animation
  147. /// </summary>
  148. private string DetermineMovementAnimation()
  149. {
  150. const float FALL_DELAY = 800f;
  151. const float PREJUMP_DELAY = 200f;
  152. const float JUMP_PERIOD = 800f;
  153. #region Inputs
  154. AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
  155. PhysicsActor actor = m_scenePresence.PhysicsActor;
  156. // Create forward and left vectors from the current avatar rotation
  157. Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
  158. Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
  159. Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
  160. // Check control flags
  161. bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
  162. bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
  163. bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
  164. bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
  165. bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
  166. bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
  167. bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
  168. bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
  169. //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
  170. //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
  171. if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown)
  172. {
  173. heldTurnLeft = false;
  174. heldTurnRight = false;
  175. }
  176. // Direction in which the avatar is trying to move
  177. Vector3 move = Vector3.Zero;
  178. if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
  179. if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
  180. if (heldLeft) { move.X += left.X; move.Y += left.Y; }
  181. if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
  182. if (heldUp) { move.Z += 1; }
  183. if (heldDown) { move.Z -= 1; }
  184. // Is the avatar trying to move?
  185. // bool moving = (move != Vector3.Zero);
  186. #endregion Inputs
  187. #region Flying
  188. if (actor != null && actor.Flying)
  189. {
  190. m_animTickFall = 0;
  191. m_animTickJump = 0;
  192. m_jumping = false;
  193. Falling = false;
  194. m_jumpVelocity = 0f;
  195. actor.Selected = false;
  196. m_fallHeight = actor.Position.Z; // save latest flying height
  197. if (move.X != 0f || move.Y != 0f)
  198. {
  199. return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
  200. }
  201. else if (move.Z > 0f)
  202. {
  203. return "HOVER_UP";
  204. }
  205. else if (move.Z < 0f)
  206. {
  207. if (actor != null && actor.IsColliding)
  208. return "LAND";
  209. else
  210. return "HOVER_DOWN";
  211. }
  212. else
  213. {
  214. return "HOVER";
  215. }
  216. }
  217. #endregion Flying
  218. #region Falling/Floating/Landing
  219. if ((actor == null || !actor.IsColliding) && !m_jumping)
  220. {
  221. float fallElapsed = (float)(Environment.TickCount - m_animTickFall);
  222. float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
  223. if (!m_jumping && (fallVelocity < -3.0f))
  224. Falling = true;
  225. if (m_animTickFall == 0 || (fallVelocity >= 0.0f))
  226. {
  227. // not falling yet, or going up
  228. // reset start of fall time
  229. m_animTickFall = Environment.TickCount;
  230. }
  231. else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying))
  232. {
  233. // Falling long enough to trigger the animation
  234. return "FALLDOWN";
  235. }
  236. return CurrentMovementAnimation;
  237. }
  238. #endregion Falling/Floating/Landing
  239. #region Jumping // section added for jumping...
  240. int jumptime;
  241. jumptime = Environment.TickCount - m_animTickJump;
  242. if ((move.Z > 0f) && (!m_jumping))
  243. {
  244. // Start jumping, prejump
  245. m_animTickFall = 0;
  246. m_jumping = true;
  247. Falling = false;
  248. actor.Selected = true; // borrowed for jumping flag
  249. m_animTickJump = Environment.TickCount;
  250. m_jumpVelocity = 0.35f;
  251. return "PREJUMP";
  252. }
  253. if (m_jumping)
  254. {
  255. if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
  256. {
  257. // end jumping
  258. m_jumping = false;
  259. Falling = false;
  260. actor.Selected = false; // borrowed for jumping flag
  261. m_jumpVelocity = 0f;
  262. m_animTickFall = Environment.TickCount;
  263. return "LAND";
  264. }
  265. else if (jumptime > JUMP_PERIOD)
  266. {
  267. // jump down
  268. m_jumpVelocity = 0f;
  269. return "JUMP";
  270. }
  271. else if (jumptime > PREJUMP_DELAY)
  272. {
  273. // jump up
  274. m_jumping = true;
  275. m_jumpVelocity = 10f;
  276. return "JUMP";
  277. }
  278. }
  279. #endregion Jumping
  280. #region Ground Movement
  281. if (CurrentMovementAnimation == "FALLDOWN")
  282. {
  283. Falling = false;
  284. m_animTickFall = Environment.TickCount;
  285. // TODO: SOFT_LAND support
  286. float fallHeight = m_fallHeight - actor.Position.Z;
  287. if (fallHeight > 15.0f)
  288. return "STANDUP";
  289. else if (fallHeight > 8.0f)
  290. return "SOFT_LAND";
  291. else
  292. return "LAND";
  293. }
  294. else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP"))
  295. {
  296. int landElapsed = Environment.TickCount - m_animTickFall;
  297. int limit = 1000;
  298. if (CurrentMovementAnimation == "LAND")
  299. limit = 350;
  300. // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
  301. if ((m_animTickFall != 0) && (landElapsed <= limit))
  302. {
  303. return CurrentMovementAnimation;
  304. }
  305. else
  306. {
  307. m_fallHeight = actor.Position.Z; // save latest flying height
  308. return "STAND";
  309. }
  310. }
  311. // next section moved outside paren. and realigned for jumping
  312. if (move.X != 0f || move.Y != 0f)
  313. {
  314. m_fallHeight = actor.Position.Z; // save latest flying height
  315. Falling = false;
  316. // Walking / crouchwalking / running
  317. if (move.Z < 0f)
  318. return "CROUCHWALK";
  319. else if (m_scenePresence.SetAlwaysRun)
  320. return "RUN";
  321. else
  322. return "WALK";
  323. }
  324. else if (!m_jumping)
  325. {
  326. Falling = false;
  327. // Not walking
  328. if (move.Z < 0)
  329. return "CROUCH";
  330. else if (heldTurnLeft)
  331. return "TURNLEFT";
  332. else if (heldTurnRight)
  333. return "TURNRIGHT";
  334. else
  335. return "STAND";
  336. }
  337. #endregion Ground Movement
  338. Falling = false;
  339. return CurrentMovementAnimation;
  340. }
  341. /// <summary>
  342. /// Update the movement animation of this avatar according to its current state
  343. /// </summary>
  344. public void UpdateMovementAnimations()
  345. {
  346. CurrentMovementAnimation = DetermineMovementAnimation();
  347. // m_log.DebugFormat(
  348. // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
  349. // CurrentMovementAnimation, m_scenePresence.Name);
  350. TrySetMovementAnimation(CurrentMovementAnimation);
  351. }
  352. public UUID[] GetAnimationArray()
  353. {
  354. UUID[] animIDs;
  355. int[] sequenceNums;
  356. UUID[] objectIDs;
  357. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  358. return animIDs;
  359. }
  360. public BinBVHAnimation GenerateRandomAnimation()
  361. {
  362. int rnditerations = 3;
  363. BinBVHAnimation anim = new BinBVHAnimation();
  364. List<string> parts = new List<string>();
  365. parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso");
  366. parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft");
  367. parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck");
  368. parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight");
  369. parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight");
  370. parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight");
  371. parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft");
  372. anim.HandPose = 1;
  373. anim.InPoint = 0;
  374. anim.OutPoint = (rnditerations * .10f);
  375. anim.Priority = 7;
  376. anim.Loop = false;
  377. anim.Length = (rnditerations * .10f);
  378. anim.ExpressionName = "afraid";
  379. anim.EaseInTime = 0;
  380. anim.EaseOutTime = 0;
  381. string[] strjoints = parts.ToArray();
  382. anim.Joints = new binBVHJoint[strjoints.Length];
  383. for (int j = 0; j < strjoints.Length; j++)
  384. {
  385. anim.Joints[j] = new binBVHJoint();
  386. anim.Joints[j].Name = strjoints[j];
  387. anim.Joints[j].Priority = 7;
  388. anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations];
  389. anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations];
  390. Random rnd = new Random();
  391. for (int i = 0; i < rnditerations; i++)
  392. {
  393. anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
  394. anim.Joints[j].rotationkeys[i].time = (i*.10f);
  395. anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1);
  396. anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1);
  397. anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1);
  398. anim.Joints[j].positionkeys[i] = new binBVHJointKey();
  399. anim.Joints[j].positionkeys[i].time = (i*.10f);
  400. anim.Joints[j].positionkeys[i].key_element.X = 0;
  401. anim.Joints[j].positionkeys[i].key_element.Y = 0;
  402. anim.Joints[j].positionkeys[i].key_element.Z = 0;
  403. }
  404. }
  405. AssetBase Animasset = new AssetBase(UUID.Random(), "Random Animation", (sbyte)AssetType.Animation, m_scenePresence.UUID.ToString());
  406. Animasset.Data = anim.ToBytes();
  407. Animasset.Temporary = true;
  408. Animasset.Local = true;
  409. Animasset.Description = "dance";
  410. //BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data);
  411. m_scenePresence.Scene.AssetService.Store(Animasset);
  412. AddAnimation(Animasset.FullID, m_scenePresence.UUID);
  413. return anim;
  414. }
  415. /// <summary>
  416. ///
  417. /// </summary>
  418. /// <param name="animations"></param>
  419. /// <param name="seqs"></param>
  420. /// <param name="objectIDs"></param>
  421. public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
  422. {
  423. if (m_scenePresence.IsChildAgent)
  424. return;
  425. m_scenePresence.Scene.ForEachClient(
  426. delegate(IClientAPI client)
  427. {
  428. client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
  429. });
  430. }
  431. public void SendAnimPackToClient(IClientAPI client)
  432. {
  433. if (m_scenePresence.IsChildAgent)
  434. return;
  435. UUID[] animIDs;
  436. int[] sequenceNums;
  437. UUID[] objectIDs;
  438. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  439. client.SendAnimations(animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs);
  440. }
  441. /// <summary>
  442. /// Send animation information about this avatar to all clients.
  443. /// </summary>
  444. public void SendAnimPack()
  445. {
  446. //m_log.Debug("Sending animation pack to all");
  447. if (m_scenePresence.IsChildAgent)
  448. return;
  449. UUID[] animIDs;
  450. int[] sequenceNums;
  451. UUID[] objectIDs;
  452. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  453. SendAnimPack(animIDs, sequenceNums, objectIDs);
  454. }
  455. }
  456. }