ScenePresenceAnimator.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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.Collections.Generic;
  29. using System.Linq;
  30. using System.Reflection;
  31. using System.Threading;
  32. using log4net;
  33. using OpenMetaverse;
  34. using OpenSim.Framework;
  35. using OpenSim.Region.Framework.Interfaces;
  36. using OpenSim.Region.Framework.Scenes;
  37. using OpenSim.Region.Physics.Manager;
  38. namespace OpenSim.Region.Framework.Scenes.Animation
  39. {
  40. /// <summary>
  41. /// Handle all animation duties for a scene presence
  42. /// </summary>
  43. public class ScenePresenceAnimator
  44. {
  45. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  46. public AnimationSet Animations
  47. {
  48. get { return m_animations; }
  49. }
  50. protected AnimationSet m_animations = new AnimationSet();
  51. /// <value>
  52. /// The current movement animation
  53. /// </value>
  54. public string CurrentMovementAnimation { get; private set; }
  55. private int m_animTickFall;
  56. public int m_animTickJump; // ScenePresence has to see this to control +Z force
  57. public bool m_jumping = false;
  58. public float m_jumpVelocity = 0f;
  59. // private int m_landing = 0;
  60. /// <summary>
  61. /// Is the avatar falling?
  62. /// </summary>
  63. public bool Falling { get; private set; }
  64. private float m_fallHeight;
  65. /// <value>
  66. /// The scene presence that this animator applies to
  67. /// </value>
  68. protected ScenePresence m_scenePresence;
  69. public ScenePresenceAnimator(ScenePresence sp)
  70. {
  71. m_scenePresence = sp;
  72. CurrentMovementAnimation = "CROUCH";
  73. }
  74. public void AddAnimation(UUID animID, UUID objectID)
  75. {
  76. if (m_scenePresence.IsChildAgent)
  77. return;
  78. if (m_scenePresence.Scene.DebugAnimations)
  79. m_log.DebugFormat(
  80. "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
  81. GetAnimName(animID), animID, m_scenePresence.Name);
  82. if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
  83. {
  84. SendAnimPack();
  85. m_scenePresence.TriggerScenePresenceUpdated();
  86. }
  87. }
  88. // Called from scripts
  89. public void AddAnimation(string name, UUID objectID)
  90. {
  91. if (m_scenePresence.IsChildAgent)
  92. return;
  93. // XXX: For some reason, we store all animations and use them with upper case names, but in LSL animations
  94. // are referenced with lower case names!
  95. UUID animID = DefaultAvatarAnimations.GetDefaultAnimation(name.ToUpper());
  96. if (animID == UUID.Zero)
  97. return;
  98. // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name);
  99. AddAnimation(animID, objectID);
  100. }
  101. /// <summary>
  102. /// Remove the specified animation
  103. /// </summary>
  104. /// <param name='animID'></param>
  105. /// <param name='allowNoDefault'>
  106. /// If true, then the default animation can be entirely removed.
  107. /// If false, then removing the default animation will reset it to the simulator default (currently STAND).
  108. /// </param>
  109. public void RemoveAnimation(UUID animID, bool allowNoDefault)
  110. {
  111. if (m_scenePresence.IsChildAgent)
  112. return;
  113. if (m_scenePresence.Scene.DebugAnimations)
  114. m_log.DebugFormat(
  115. "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
  116. GetAnimName(animID), animID, m_scenePresence.Name);
  117. if (m_animations.Remove(animID, allowNoDefault))
  118. {
  119. SendAnimPack();
  120. m_scenePresence.TriggerScenePresenceUpdated();
  121. }
  122. }
  123. // Called from scripts
  124. public void RemoveAnimation(string name)
  125. {
  126. if (m_scenePresence.IsChildAgent)
  127. return;
  128. // XXX: For some reason, we store all animations and use them with upper case names, but in LSL animations
  129. // are referenced with lower case names!
  130. UUID animID = DefaultAvatarAnimations.GetDefaultAnimation(name.ToUpper());
  131. if (animID == UUID.Zero)
  132. return;
  133. RemoveAnimation(animID, true);
  134. }
  135. public void ResetAnimations()
  136. {
  137. if (m_scenePresence.Scene.DebugAnimations)
  138. m_log.DebugFormat(
  139. "[SCENE PRESENCE ANIMATOR]: Resetting animations for {0} in {1}",
  140. m_scenePresence.Name, m_scenePresence.Scene.RegionInfo.RegionName);
  141. m_animations.Clear();
  142. }
  143. /// <summary>
  144. /// The movement animation is reserved for "main" animations
  145. /// that are mutually exclusive, e.g. flying and sitting.
  146. /// </summary>
  147. /// <returns>'true' if the animation was updated</returns>
  148. public bool TrySetMovementAnimation(string anim)
  149. {
  150. bool ret = false;
  151. if (!m_scenePresence.IsChildAgent)
  152. {
  153. // m_log.DebugFormat(
  154. // "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
  155. // anim, m_scenePresence.Name);
  156. if (m_animations.TrySetDefaultAnimation(
  157. anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
  158. {
  159. // m_log.DebugFormat(
  160. // "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
  161. // anim, m_scenePresence.Name);
  162. // 16384 is CHANGED_ANIMATION
  163. m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
  164. SendAnimPack();
  165. ret = true;
  166. }
  167. }
  168. else
  169. {
  170. m_log.WarnFormat(
  171. "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
  172. anim, m_scenePresence.Name);
  173. }
  174. return ret;
  175. }
  176. /// <summary>
  177. /// This method determines the proper movement related animation
  178. /// </summary>
  179. private string DetermineMovementAnimation()
  180. {
  181. const float FALL_DELAY = 800f;
  182. const float PREJUMP_DELAY = 200f;
  183. const float JUMP_PERIOD = 800f;
  184. #region Inputs
  185. AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
  186. PhysicsActor actor = m_scenePresence.PhysicsActor;
  187. // Create forward and left vectors from the current avatar rotation
  188. Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
  189. Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
  190. Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
  191. // Check control flags
  192. 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);
  193. 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);
  194. 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);
  195. 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);
  196. bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
  197. bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
  198. bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
  199. bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
  200. //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
  201. //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
  202. if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown)
  203. {
  204. heldTurnLeft = false;
  205. heldTurnRight = false;
  206. }
  207. // Direction in which the avatar is trying to move
  208. Vector3 move = Vector3.Zero;
  209. if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
  210. if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
  211. if (heldLeft) { move.X += left.X; move.Y += left.Y; }
  212. if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
  213. if (heldUp) { move.Z += 1; }
  214. if (heldDown) { move.Z -= 1; }
  215. // Is the avatar trying to move?
  216. // bool moving = (move != Vector3.Zero);
  217. #endregion Inputs
  218. #region Flying
  219. if (actor != null && actor.Flying)
  220. {
  221. m_animTickFall = 0;
  222. m_animTickJump = 0;
  223. m_jumping = false;
  224. Falling = false;
  225. m_jumpVelocity = 0f;
  226. actor.Selected = false;
  227. m_fallHeight = actor.Position.Z; // save latest flying height
  228. if (move.X != 0f || move.Y != 0f)
  229. {
  230. return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
  231. }
  232. else if (move.Z > 0f)
  233. {
  234. return "HOVER_UP";
  235. }
  236. else if (move.Z < 0f)
  237. {
  238. if (actor != null && actor.IsColliding)
  239. return "LAND";
  240. else
  241. return "HOVER_DOWN";
  242. }
  243. else
  244. {
  245. return "HOVER";
  246. }
  247. }
  248. #endregion Flying
  249. #region Falling/Floating/Landing
  250. if ((actor == null || !actor.IsColliding) && !m_jumping)
  251. {
  252. float fallElapsed = (float)(Environment.TickCount - m_animTickFall);
  253. float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
  254. if (!m_jumping && (fallVelocity < -3.0f))
  255. Falling = true;
  256. if (m_animTickFall == 0 || (fallVelocity >= 0.0f))
  257. {
  258. // not falling yet, or going up
  259. // reset start of fall time
  260. m_animTickFall = Environment.TickCount;
  261. }
  262. else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying))
  263. {
  264. // Falling long enough to trigger the animation
  265. return "FALLDOWN";
  266. }
  267. // Check if the user has stopped walking just now
  268. if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero))
  269. return "STAND";
  270. return CurrentMovementAnimation;
  271. }
  272. #endregion Falling/Floating/Landing
  273. #region Jumping // section added for jumping...
  274. int jumptime;
  275. jumptime = Environment.TickCount - m_animTickJump;
  276. if ((move.Z > 0f) && (!m_jumping))
  277. {
  278. // Start jumping, prejump
  279. m_animTickFall = 0;
  280. m_jumping = true;
  281. Falling = false;
  282. actor.Selected = true; // borrowed for jumping flag
  283. m_animTickJump = Environment.TickCount;
  284. m_jumpVelocity = 0.35f;
  285. return "PREJUMP";
  286. }
  287. if (m_jumping)
  288. {
  289. if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
  290. {
  291. // end jumping
  292. m_jumping = false;
  293. Falling = false;
  294. actor.Selected = false; // borrowed for jumping flag
  295. m_jumpVelocity = 0f;
  296. m_animTickFall = Environment.TickCount;
  297. return "LAND";
  298. }
  299. else if (jumptime > JUMP_PERIOD)
  300. {
  301. // jump down
  302. m_jumpVelocity = 0f;
  303. return "JUMP";
  304. }
  305. else if (jumptime > PREJUMP_DELAY)
  306. {
  307. // jump up
  308. m_jumping = true;
  309. m_jumpVelocity = 10f;
  310. return "JUMP";
  311. }
  312. }
  313. #endregion Jumping
  314. #region Ground Movement
  315. if (CurrentMovementAnimation == "FALLDOWN")
  316. {
  317. Falling = false;
  318. m_animTickFall = Environment.TickCount;
  319. // TODO: SOFT_LAND support
  320. float fallHeight = m_fallHeight - actor.Position.Z;
  321. if (fallHeight > 15.0f)
  322. return "STANDUP";
  323. else if (fallHeight > 8.0f)
  324. return "SOFT_LAND";
  325. else
  326. return "LAND";
  327. }
  328. else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP"))
  329. {
  330. int landElapsed = Environment.TickCount - m_animTickFall;
  331. int limit = 1000;
  332. if (CurrentMovementAnimation == "LAND")
  333. limit = 350;
  334. // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
  335. if ((m_animTickFall != 0) && (landElapsed <= limit))
  336. {
  337. return CurrentMovementAnimation;
  338. }
  339. else
  340. {
  341. m_fallHeight = actor.Position.Z; // save latest flying height
  342. return "STAND";
  343. }
  344. }
  345. // next section moved outside paren. and realigned for jumping
  346. if (move.X != 0f || move.Y != 0f)
  347. {
  348. m_fallHeight = actor.Position.Z; // save latest flying height
  349. Falling = false;
  350. // Walking / crouchwalking / running
  351. if (move.Z < 0f)
  352. return "CROUCHWALK";
  353. else if (m_scenePresence.SetAlwaysRun)
  354. return "RUN";
  355. else
  356. return "WALK";
  357. }
  358. else if (!m_jumping)
  359. {
  360. Falling = false;
  361. // Not walking
  362. if (move.Z < 0)
  363. return "CROUCH";
  364. else if (heldTurnLeft)
  365. return "TURNLEFT";
  366. else if (heldTurnRight)
  367. return "TURNRIGHT";
  368. else
  369. return "STAND";
  370. }
  371. #endregion Ground Movement
  372. Falling = false;
  373. return CurrentMovementAnimation;
  374. }
  375. /// <summary>
  376. /// Update the movement animation of this avatar according to its current state
  377. /// </summary>
  378. /// <returns>'true' if the animation was changed</returns>
  379. public bool UpdateMovementAnimations()
  380. {
  381. bool ret = false;
  382. lock (m_animations)
  383. {
  384. string newMovementAnimation = DetermineMovementAnimation();
  385. if (CurrentMovementAnimation != newMovementAnimation)
  386. {
  387. CurrentMovementAnimation = DetermineMovementAnimation();
  388. // m_log.DebugFormat(
  389. // "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
  390. // CurrentMovementAnimation, m_scenePresence.Name);
  391. // Only set it if it's actually changed, give a script
  392. // a chance to stop a default animation
  393. ret = TrySetMovementAnimation(CurrentMovementAnimation);
  394. }
  395. }
  396. return ret;
  397. }
  398. public UUID[] GetAnimationArray()
  399. {
  400. UUID[] animIDs;
  401. int[] sequenceNums;
  402. UUID[] objectIDs;
  403. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  404. return animIDs;
  405. }
  406. public BinBVHAnimation GenerateRandomAnimation()
  407. {
  408. int rnditerations = 3;
  409. BinBVHAnimation anim = new BinBVHAnimation();
  410. List<string> parts = new List<string>();
  411. parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso");
  412. parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft");
  413. parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck");
  414. parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight");
  415. parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight");
  416. parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight");
  417. parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft");
  418. anim.HandPose = 1;
  419. anim.InPoint = 0;
  420. anim.OutPoint = (rnditerations * .10f);
  421. anim.Priority = 7;
  422. anim.Loop = false;
  423. anim.Length = (rnditerations * .10f);
  424. anim.ExpressionName = "afraid";
  425. anim.EaseInTime = 0;
  426. anim.EaseOutTime = 0;
  427. string[] strjoints = parts.ToArray();
  428. anim.Joints = new binBVHJoint[strjoints.Length];
  429. for (int j = 0; j < strjoints.Length; j++)
  430. {
  431. anim.Joints[j] = new binBVHJoint();
  432. anim.Joints[j].Name = strjoints[j];
  433. anim.Joints[j].Priority = 7;
  434. anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations];
  435. anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations];
  436. Random rnd = new Random();
  437. for (int i = 0; i < rnditerations; i++)
  438. {
  439. anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
  440. anim.Joints[j].rotationkeys[i].time = (i*.10f);
  441. anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1);
  442. anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1);
  443. anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1);
  444. anim.Joints[j].positionkeys[i] = new binBVHJointKey();
  445. anim.Joints[j].positionkeys[i].time = (i*.10f);
  446. anim.Joints[j].positionkeys[i].key_element.X = 0;
  447. anim.Joints[j].positionkeys[i].key_element.Y = 0;
  448. anim.Joints[j].positionkeys[i].key_element.Z = 0;
  449. }
  450. }
  451. AssetBase Animasset = new AssetBase(UUID.Random(), "Random Animation", (sbyte)AssetType.Animation, m_scenePresence.UUID.ToString());
  452. Animasset.Data = anim.ToBytes();
  453. Animasset.Temporary = true;
  454. Animasset.Local = true;
  455. Animasset.Description = "dance";
  456. //BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data);
  457. m_scenePresence.Scene.AssetService.Store(Animasset);
  458. AddAnimation(Animasset.FullID, m_scenePresence.UUID);
  459. return anim;
  460. }
  461. /// <summary>
  462. ///
  463. /// </summary>
  464. /// <param name="animations"></param>
  465. /// <param name="seqs"></param>
  466. /// <param name="objectIDs"></param>
  467. public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
  468. {
  469. if (m_scenePresence.IsChildAgent)
  470. return;
  471. // m_log.DebugFormat(
  472. // "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'",
  473. // string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())),
  474. // string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())),
  475. // string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString())));
  476. m_scenePresence.Scene.ForEachClient(
  477. delegate(IClientAPI client)
  478. {
  479. client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
  480. });
  481. }
  482. public void SendAnimPackToClient(IClientAPI client)
  483. {
  484. if (m_scenePresence.IsChildAgent)
  485. return;
  486. UUID[] animIDs;
  487. int[] sequenceNums;
  488. UUID[] objectIDs;
  489. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  490. client.SendAnimations(animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs);
  491. }
  492. /// <summary>
  493. /// Send animation information about this avatar to all clients.
  494. /// </summary>
  495. public void SendAnimPack()
  496. {
  497. //m_log.Debug("Sending animation pack to all");
  498. if (m_scenePresence.IsChildAgent)
  499. return;
  500. UUID[] animIDs;
  501. int[] sequenceNums;
  502. UUID[] objectIDs;
  503. m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
  504. SendAnimPack(animIDs, sequenceNums, objectIDs);
  505. }
  506. public string GetAnimName(UUID animId)
  507. {
  508. string animName;
  509. if (!DefaultAvatarAnimations.AnimsNames.TryGetValue(animId, out animName))
  510. {
  511. AssetMetadata amd = m_scenePresence.Scene.AssetService.GetMetadata(animId.ToString());
  512. if (amd != null)
  513. animName = amd.Name;
  514. else
  515. animName = "Unknown";
  516. }
  517. return animName;
  518. }
  519. }
  520. }