aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Animation
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Animation')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs388
1 files changed, 388 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
new file mode 100644
index 0000000..d22e24a
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -0,0 +1,388 @@
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
28using System;
29using OpenMetaverse;
30using OpenSim.Framework;
31using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Framework.Scenes.Animation
36{
37 /// <summary>
38 /// Handle all animation duties for a scene presence
39 /// </summary>
40 public class ScenePresenceAnimator
41 {
42 public AnimationSet Animations
43 {
44 get { return m_animations; }
45 }
46 protected AnimationSet m_animations = new AnimationSet();
47
48 /// <value>
49 /// The current movement animation
50 /// </value>
51 public string CurrentMovementAnimation
52 {
53 get { return m_movementAnimation; }
54 }
55 protected string m_movementAnimation = "DEFAULT";
56
57 private int m_animTickFall;
58 private int m_animTickJump;
59
60 /// <value>
61 /// The scene presence that this animator applies to
62 /// </value>
63 protected ScenePresence m_scenePresence;
64
65 public ScenePresenceAnimator(ScenePresence sp)
66 {
67 m_scenePresence = sp;
68 }
69
70 public void AddAnimation(UUID animID, UUID objectID)
71 {
72 if (m_scenePresence.IsChildAgent)
73 return;
74
75 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
76 SendAnimPack();
77 }
78
79 // Called from scripts
80 public void AddAnimation(string name, UUID objectID)
81 {
82 if (m_scenePresence.IsChildAgent)
83 return;
84
85 UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
86 if (animID == UUID.Zero)
87 return;
88
89 AddAnimation(animID, objectID);
90 }
91
92 public void RemoveAnimation(UUID animID)
93 {
94 if (m_scenePresence.IsChildAgent)
95 return;
96
97 if (m_animations.Remove(animID))
98 SendAnimPack();
99 }
100
101 // Called from scripts
102 public void RemoveAnimation(string name)
103 {
104 if (m_scenePresence.IsChildAgent)
105 return;
106
107 UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
108 if (animID == UUID.Zero)
109 return;
110
111 RemoveAnimation(animID);
112 }
113
114 public void ResetAnimations()
115 {
116 m_animations.Clear();
117 }
118
119 /// <summary>
120 /// The movement animation is reserved for "main" animations
121 /// that are mutually exclusive, e.g. flying and sitting.
122 /// </summary>
123 public void TrySetMovementAnimation(string anim)
124 {
125 //m_log.DebugFormat("Updating movement animation to {0}", anim);
126
127 if (!m_scenePresence.IsChildAgent)
128 {
129 if (m_animations.TrySetDefaultAnimation(
130 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero))
131 {
132 // 16384 is CHANGED_ANIMATION
133 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
134 SendAnimPack();
135 }
136 }
137 }
138
139 /// <summary>
140 /// This method determines the proper movement related animation
141 /// </summary>
142 public string GetMovementAnimation()
143 {
144 const float FALL_DELAY = 0.33f;
145 const float PREJUMP_DELAY = 0.25f;
146
147 #region Inputs
148
149 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
150 PhysicsActor actor = m_scenePresence.PhysicsActor;
151
152 // Create forward and left vectors from the current avatar rotation
153 Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
154 Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
155 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
156
157 // Check control flags
158 bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
159 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG;
160 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS;
161 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
162 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
163 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
164 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
165 bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
166 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
167 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
168
169 // Direction in which the avatar is trying to move
170 Vector3 move = Vector3.Zero;
171 if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
172 if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
173 if (heldLeft) { move.X += left.X; move.Y += left.Y; }
174 if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
175 if (heldUp) { move.Z += 1; }
176 if (heldDown) { move.Z -= 1; }
177
178 // Is the avatar trying to move?
179// bool moving = (move != Vector3.Zero);
180 bool jumping = m_animTickJump != 0;
181
182 #endregion Inputs
183
184 #region Flying
185
186 if (actor != null && actor.Flying)
187 {
188 m_animTickFall = 0;
189 m_animTickJump = 0;
190
191 if (move.X != 0f || move.Y != 0f)
192 {
193 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
194 }
195 else if (move.Z > 0f)
196 {
197 return "HOVER_UP";
198 }
199 else if (move.Z < 0f)
200 {
201 if (actor != null && actor.IsColliding)
202 return "LAND";
203 else
204 return "HOVER_DOWN";
205 }
206 else
207 {
208 return "HOVER";
209 }
210 }
211
212 #endregion Flying
213
214 #region Falling/Floating/Landing
215
216 if (actor == null || !actor.IsColliding)
217 {
218 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
219 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
220
221 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
222 {
223 // Just started falling
224 m_animTickFall = Environment.TickCount;
225 }
226 else if (!jumping && fallElapsed > FALL_DELAY)
227 {
228 // Falling long enough to trigger the animation
229 return "FALLDOWN";
230 }
231
232 return m_movementAnimation;
233 }
234
235 #endregion Falling/Floating/Landing
236
237 #region Ground Movement
238
239 if (m_movementAnimation == "FALLDOWN")
240 {
241 m_animTickFall = Environment.TickCount;
242
243 // TODO: SOFT_LAND support
244 return "LAND";
245 }
246 else if (m_movementAnimation == "LAND")
247 {
248 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
249
250 if (landElapsed <= FALL_DELAY)
251 return "LAND";
252 }
253
254 m_animTickFall = 0;
255
256 if (move.Z > 0f)
257 {
258 // Jumping
259 if (!jumping)
260 {
261 // Begin prejump
262 m_animTickJump = Environment.TickCount;
263 return "PREJUMP";
264 }
265 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f)
266 {
267 // Start actual jump
268 if (m_animTickJump == -1)
269 {
270 // Already jumping! End the current jump
271 m_animTickJump = 0;
272 return "JUMP";
273 }
274
275 m_animTickJump = -1;
276 return "JUMP";
277 }
278 }
279 else
280 {
281 // Not jumping
282 m_animTickJump = 0;
283
284 if (move.X != 0f || move.Y != 0f)
285 {
286 // Walking / crouchwalking / running
287 if (move.Z < 0f)
288 return "CROUCHWALK";
289 else if (m_scenePresence.SetAlwaysRun)
290 return "RUN";
291 else
292 return "WALK";
293 }
294 else
295 {
296 // Not walking
297 if (move.Z < 0f)
298 return "CROUCH";
299 else
300 return "STAND";
301 }
302 }
303
304 #endregion Ground Movement
305
306 return m_movementAnimation;
307 }
308
309 /// <summary>
310 /// Update the movement animation of this avatar according to its current state
311 /// </summary>
312 public void UpdateMovementAnimations()
313 {
314 m_movementAnimation = GetMovementAnimation();
315
316 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
317 {
318 // This was the previous behavior before PREJUMP
319 TrySetMovementAnimation("JUMP");
320 }
321 else
322 {
323 TrySetMovementAnimation(m_movementAnimation);
324 }
325 }
326
327 public UUID[] GetAnimationArray()
328 {
329 UUID[] animIDs;
330 int[] sequenceNums;
331 UUID[] objectIDs;
332 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
333 return animIDs;
334 }
335
336 /// <summary>
337 ///
338 /// </summary>
339 /// <param name="animations"></param>
340 /// <param name="seqs"></param>
341 /// <param name="objectIDs"></param>
342 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
343 {
344 if (m_scenePresence.IsChildAgent)
345 return;
346
347 m_scenePresence.Scene.ForEachClient(
348 delegate(IClientAPI client)
349 {
350 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
351 });
352 }
353
354 public void SendAnimPackToClient(IClientAPI client)
355 {
356 if (m_scenePresence.IsChildAgent)
357 return;
358
359 UUID[] animIDs;
360 int[] sequenceNums;
361 UUID[] objectIDs;
362
363 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
364
365 m_scenePresence.ControllingClient.SendAnimations(
366 animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs);
367 }
368
369 /// <summary>
370 /// Send animation information about this avatar to all clients.
371 /// </summary>
372 public void SendAnimPack()
373 {
374 //m_log.Debug("Sending animation pack to all");
375
376 if (m_scenePresence.IsChildAgent)
377 return;
378
379 UUID[] animIDs;
380 int[] sequenceNums;
381 UUID[] objectIDs;
382
383 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
384
385 SendAnimPack(animIDs, sequenceNums, objectIDs);
386 }
387 }
388} \ No newline at end of file