Merge branch 'careminster' into tests

avinationmerge
KittoFlora 2009-11-19 20:20:03 +01:00
commit 251d1b8fbb
23 changed files with 911 additions and 546 deletions

View File

@ -32,11 +32,11 @@ using OpenSim.Framework;
namespace OpenSim.Data
{
public class PresenceData
public struct PresenceData
{
public UUID PrincipalID;
public UUID RegionID;
public Dictionary<string, object> Data;
public UUID UUID;
public UUID currentRegion;
public Dictionary<string, string> Data;
}
/// <summary>
@ -48,7 +48,8 @@ namespace OpenSim.Data
PresenceData Get(UUID principalID);
bool SetDataItem(UUID principalID, string item, string value);
bool SetUserDataItem(UUID principalID, string item, string value);
bool SetRegionDataItem(UUID principalID, string item, string value);
bool Delete(UUID regionID);
}

View File

@ -112,7 +112,7 @@ namespace OpenSim.Data.MySQL
for (int i = 0 ; i < fields.Length ; i++)
{
cmd.Parameters.AddWithValue(fields[i], keys[i]);
terms.Add(fields[i] + " = ?" + fields[i]);
terms.Add("`" + fields[i] + "` = ?" + fields[i]);
}
string where = String.Join(" and ", terms.ToArray());
@ -190,11 +190,26 @@ namespace OpenSim.Data.MySQL
return DoQuery(cmd);
}
public void Store(T row)
public bool Store(T row)
{
MySqlCommand cmd = new MySqlCommand();
string query = "";
return false;
}
public bool Delete(string field, string val)
{
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field);
cmd.Parameters.AddWithValue(field, val);
if (ExecuteNonQuery(cmd) > 0)
return true;
return false;
}
}
}

View File

@ -1153,7 +1153,7 @@ namespace OpenSim.Framework
prim.Light.Radius = this.LightRadius;
}
prim.Textures = new Primitive.TextureEntry(this.TextureEntry, 0, this.TextureEntry.Length);
prim.Textures = this.Textures;
prim.Properties = new Primitive.ObjectProperties();
prim.Properties.Name = "Primitive";

View File

@ -28,33 +28,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.IO;
using System.Text;
using HttpServer;
@ -77,9 +50,7 @@ namespace OpenSim.Framework.Servers.HttpServer
private readonly BaseHttpServer m_server;
private BlockingQueue<PollServiceHttpRequest> m_request;
private bool m_running = true;
private int m_timeout = 250;
private int m_timeout = 250;
public PollServiceWorkerThread(BaseHttpServer pSrv, int pTimeout)
{
@ -135,4 +106,4 @@ namespace OpenSim.Framework.Servers.HttpServer
m_request.Enqueue(pPollServiceHttpRequest);
}
}
}
}

View File

@ -124,7 +124,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
if (RenderPlugins.ContainsKey(contentType))
{
DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID;
updater.PrimID = primID;
@ -275,7 +274,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
/// </summary>
public void DataReceived(byte[] data, Scene scene)
{
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
if (part == null || data == null || data.Length <= 1)
@ -364,7 +362,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
{
// scene.CommsManager.AssetCache.ExpireAsset(oldID);
scene.AssetService.Delete(oldID.ToString());
}
}
@ -433,4 +430,4 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
#endregion
}
}
}

View File

@ -30,10 +30,8 @@ using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IDynamicTextureManager
{
void RegisterRender(string handleType, IDynamicTextureRender render);
void ReturnData(UUID id, byte[] data);

View File

@ -32,20 +32,21 @@ using OpenMetaverse;
using Animation = OpenSim.Framework.Animation;
namespace OpenSim.Region.Framework.Scenes
namespace OpenSim.Region.Framework.Scenes.Animation
{
[Serializable]
public class AnimationSet
{
public static AvatarAnimations Animations = new AvatarAnimations();
private Animation m_defaultAnimation = new Animation();
private List<Animation> m_animations = new List<Animation>();
private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
public Animation DefaultAnimation
public OpenSim.Framework.Animation DefaultAnimation
{
get { return m_defaultAnimation; }
}
public AnimationSet()
{
ResetDefaultAnimation();
@ -71,7 +72,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!HasAnimation(animID))
{
m_animations.Add(new Animation(animID, sequenceNum, objectID));
m_animations.Add(new OpenSim.Framework.Animation(animID, sequenceNum, objectID));
return true;
}
}
@ -115,7 +116,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (m_defaultAnimation.AnimID != animID)
{
m_defaultAnimation = new Animation(animID, sequenceNum, objectID);
m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
return true;
}
return false;
@ -159,13 +160,13 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public Animation[] ToArray()
public OpenSim.Framework.Animation[] ToArray()
{
Animation[] theArray = new Animation[m_animations.Count];
OpenSim.Framework.Animation[] theArray = new OpenSim.Framework.Animation[m_animations.Count];
uint i = 0;
try
{
foreach (Animation anim in m_animations)
foreach (OpenSim.Framework.Animation anim in m_animations)
theArray[i++] = anim;
}
catch
@ -175,9 +176,9 @@ namespace OpenSim.Region.Framework.Scenes
return theArray;
}
public void FromArray(Animation[] theArray)
public void FromArray(OpenSim.Framework.Animation[] theArray)
{
foreach (Animation anim in theArray)
foreach (OpenSim.Framework.Animation anim in theArray)
m_animations.Add(anim);
}
}

View File

@ -29,7 +29,7 @@ using System.Collections.Generic;
using System.Xml;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Scenes
namespace OpenSim.Region.Framework.Scenes.Animation
{
public class AvatarAnimations
{

View File

@ -29,7 +29,7 @@ using System;
using System.IO;
using OpenMetaverse;
namespace OpenSim.Region.Framework.Scenes
namespace OpenSim.Region.Framework.Scenes.Animation
{
/// <summary>
/// Written to decode and encode a binary animation asset.

View File

@ -0,0 +1,448 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Framework.Scenes.Animation
{
/// <summary>
/// Handle all animation duties for a scene presence
/// </summary>
public class ScenePresenceAnimator
{
public AnimationSet Animations
{
get { return m_animations; }
}
protected AnimationSet m_animations = new AnimationSet();
/// <value>
/// The current movement animation
/// </value>
public string CurrentMovementAnimation
{
get { return m_movementAnimation; }
}
protected string m_movementAnimation = "DEFAULT";
private int m_animTickFall;
private int m_animTickJump;
/// <value>
/// The scene presence that this animator applies to
/// </value>
protected ScenePresence m_scenePresence;
public ScenePresenceAnimator(ScenePresence sp)
{
m_scenePresence = sp;
}
public void AddAnimation(UUID animID, UUID objectID)
{
if (m_scenePresence.IsChildAgent)
return;
if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
SendAnimPack();
}
// Called from scripts
public void AddAnimation(string name, UUID objectID)
{
if (m_scenePresence.IsChildAgent)
return;
UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
if (animID == UUID.Zero)
return;
AddAnimation(animID, objectID);
}
public void RemoveAnimation(UUID animID)
{
if (m_scenePresence.IsChildAgent)
return;
if (m_animations.Remove(animID))
SendAnimPack();
}
// Called from scripts
public void RemoveAnimation(string name)
{
if (m_scenePresence.IsChildAgent)
return;
UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
if (animID == UUID.Zero)
return;
RemoveAnimation(animID);
}
public void ResetAnimations()
{
m_animations.Clear();
}
/// <summary>
/// The movement animation is reserved for "main" animations
/// that are mutually exclusive, e.g. flying and sitting.
/// </summary>
public void TrySetMovementAnimation(string anim)
{
//m_log.DebugFormat("Updating movement animation to {0}", anim);
if (!m_scenePresence.IsChildAgent)
{
if (m_animations.TrySetDefaultAnimation(
anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero))
{
// 16384 is CHANGED_ANIMATION
m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
SendAnimPack();
}
}
}
/// <summary>
/// This method determines the proper movement related animation
/// </summary>
public string GetMovementAnimation()
{
const float FALL_DELAY = 0.33f;
const float PREJUMP_DELAY = 0.25f;
#region Inputs
AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
PhysicsActor actor = m_scenePresence.PhysicsActor;
// Create forward and left vectors from the current avatar rotation
Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
// Check control flags
bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG;
bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS;
bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
//bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
//bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
//bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
//bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
// Direction in which the avatar is trying to move
Vector3 move = Vector3.Zero;
if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
if (heldLeft) { move.X += left.X; move.Y += left.Y; }
if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
if (heldUp) { move.Z += 1; }
if (heldDown) { move.Z -= 1; }
// Is the avatar trying to move?
// bool moving = (move != Vector3.Zero);
bool jumping = m_animTickJump != 0;
#endregion Inputs
#region Flying
if (actor != null && actor.Flying)
{
m_animTickFall = 0;
m_animTickJump = 0;
if (move.X != 0f || move.Y != 0f)
{
return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
}
else if (move.Z > 0f)
{
return "HOVER_UP";
}
else if (move.Z < 0f)
{
if (actor != null && actor.IsColliding)
return "LAND";
else
return "HOVER_DOWN";
}
else
{
return "HOVER";
}
}
#endregion Flying
#region Falling/Floating/Landing
if (actor == null || !actor.IsColliding)
{
float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
{
// Just started falling
m_animTickFall = Environment.TickCount;
}
else if (!jumping && fallElapsed > FALL_DELAY)
{
// Falling long enough to trigger the animation
return "FALLDOWN";
}
return m_movementAnimation;
}
#endregion Falling/Floating/Landing
#region Ground Movement
if (m_movementAnimation == "FALLDOWN")
{
m_animTickFall = Environment.TickCount;
// TODO: SOFT_LAND support
return "LAND";
}
else if (m_movementAnimation == "LAND")
{
float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
if (landElapsed <= FALL_DELAY)
return "LAND";
}
m_animTickFall = 0;
if (move.Z > 0f)
{
// Jumping
if (!jumping)
{
// Begin prejump
m_animTickJump = Environment.TickCount;
return "PREJUMP";
}
else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f)
{
// Start actual jump
if (m_animTickJump == -1)
{
// Already jumping! End the current jump
m_animTickJump = 0;
return "JUMP";
}
m_animTickJump = -1;
return "JUMP";
}
}
else
{
// Not jumping
m_animTickJump = 0;
if (move.X != 0f || move.Y != 0f)
{
// Walking / crouchwalking / running
if (move.Z < 0f)
return "CROUCHWALK";
else if (m_scenePresence.SetAlwaysRun)
return "RUN";
else
return "WALK";
}
else
{
// Not walking
if (move.Z < 0f)
return "CROUCH";
else
return "STAND";
}
}
#endregion Ground Movement
return m_movementAnimation;
}
/// <summary>
/// Update the movement animation of this avatar according to its current state
/// </summary>
public void UpdateMovementAnimations()
{
m_movementAnimation = GetMovementAnimation();
if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
{
// This was the previous behavior before PREJUMP
TrySetMovementAnimation("JUMP");
}
else
{
TrySetMovementAnimation(m_movementAnimation);
}
}
public UUID[] GetAnimationArray()
{
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
return animIDs;
}
public BinBVHAnimation GenerateRandomAnimation()
{
int rnditerations = 3;
BinBVHAnimation anim = new BinBVHAnimation();
List<string> parts = new List<string>();
parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso");
parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft");
parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck");
parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight");
parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight");
parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight");
parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft");
anim.HandPose = 1;
anim.InPoint = 0;
anim.OutPoint = (rnditerations * .10f);
anim.Priority = 7;
anim.Loop = false;
anim.Length = (rnditerations * .10f);
anim.ExpressionName = "afraid";
anim.EaseInTime = 0;
anim.EaseOutTime = 0;
string[] strjoints = parts.ToArray();
anim.Joints = new binBVHJoint[strjoints.Length];
for (int j = 0; j < strjoints.Length; j++)
{
anim.Joints[j] = new binBVHJoint();
anim.Joints[j].Name = strjoints[j];
anim.Joints[j].Priority = 7;
anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations];
anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations];
Random rnd = new Random();
for (int i = 0; i < rnditerations; i++)
{
anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
anim.Joints[j].rotationkeys[i].time = (i*.10f);
anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].positionkeys[i] = new binBVHJointKey();
anim.Joints[j].positionkeys[i].time = (i*.10f);
anim.Joints[j].positionkeys[i].key_element.X = 0;
anim.Joints[j].positionkeys[i].key_element.Y = 0;
anim.Joints[j].positionkeys[i].key_element.Z = 0;
}
}
AssetBase Animasset = new AssetBase(UUID.Random(), "Random Animation", (sbyte)AssetType.Animation);
Animasset.Data = anim.ToBytes();
Animasset.Temporary = true;
Animasset.Local = true;
Animasset.Description = "dance";
//BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data);
m_scenePresence.Scene.AssetService.Store(Animasset);
AddAnimation(Animasset.FullID, m_scenePresence.UUID);
return anim;
}
/// <summary>
///
/// </summary>
/// <param name="animations"></param>
/// <param name="seqs"></param>
/// <param name="objectIDs"></param>
public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
{
if (m_scenePresence.IsChildAgent)
return;
m_scenePresence.Scene.ForEachClient(
delegate(IClientAPI client)
{
client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
});
}
public void SendAnimPackToClient(IClientAPI client)
{
if (m_scenePresence.IsChildAgent)
return;
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
m_scenePresence.ControllingClient.SendAnimations(
animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs);
}
/// <summary>
/// Send animation information about this avatar to all clients.
/// </summary>
public void SendAnimPack()
{
//m_log.Debug("Sending animation pack to all");
if (m_scenePresence.IsChildAgent)
return;
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
SendAnimPack(animIDs, sequenceNums, objectIDs);
}
}
}

View File

@ -82,7 +82,7 @@ namespace OpenSim.Region.Framework.Scenes.Hypergrid
IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
// Reset animations; the viewer does that in teleports.
avatar.ResetAnimations();
avatar.Animator.ResetAnimations();
if (regionHandle == m_regionInfo.RegionHandle)
{

View File

@ -1266,7 +1266,7 @@ namespace OpenSim.Region.Framework.Scenes
// allocations, and there is no more work to be done until someone logs in
GC.Collect();
m_log.Debug("[REGION]: Enabling Logins");
m_log.DebugFormat("[REGION]: Enabling Logins for {0}", RegionInfo.RegionName);
loginsdisabled = false;
}
}
@ -1276,24 +1276,25 @@ namespace OpenSim.Region.Framework.Scenes
}
catch (AccessViolationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
//catch (NullReferenceException e)
//{
// m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
// m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
//}
catch (InvalidOperationException e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
catch (Exception e)
{
m_log.Error("[Scene]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
}
finally
{
m_lastupdate = DateTime.UtcNow;
}
maintc = Environment.TickCount - maintc;
maintc = (int)(m_timespan * 1000) - maintc;

View File

@ -801,7 +801,7 @@ namespace OpenSim.Region.Framework.Scenes
IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
// Reset animations; the viewer does that in teleports.
avatar.ResetAnimations();
avatar.Animator.ResetAnimations();
if (regionHandle == m_regionInfo.RegionHandle)
{

View File

@ -35,6 +35,7 @@ using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Animation;
using OpenSim.Region.Framework.Scenes.Types;
using OpenSim.Region.Physics.Manager;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
@ -79,6 +80,7 @@ namespace OpenSim.Region.Framework.Scenes
// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
/// <summary>
/// Experimentally determined "fudge factor" to make sit-target positions
/// the same as in SecondLife. Fudge factor was tested for 36 different
@ -93,7 +95,15 @@ namespace OpenSim.Region.Framework.Scenes
private ISceneViewer m_sceneViewer;
private AnimationSet m_animations = new AnimationSet();
/// <value>
/// The animator for this avatar
/// </value>
public ScenePresenceAnimator Animator
{
get { return m_animator; }
}
protected ScenePresenceAnimator m_animator;
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@ -134,12 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
private int m_perfMonMS;
private bool m_setAlwaysRun;
private string m_movementAnimation = "DEFAULT";
private int m_animTickFall;
private int m_animTickJump;
private bool m_useFlySlow;
private bool m_usePreJump;
private bool m_forceFly;
private bool m_flyDisabled;
@ -227,7 +232,6 @@ namespace OpenSim.Region.Framework.Scenes
DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
}
/// <summary>
/// Position at which a significant movement was made
@ -238,7 +242,10 @@ namespace OpenSim.Region.Framework.Scenes
string m_callbackURI;
ulong m_rootRegionHandle;
private IScriptModule[] m_scriptEngines;
/// <value>
/// Script engines present in the scene
/// </value>
private IScriptModule[] m_scriptEngines;
#region Properties
@ -586,11 +593,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public AnimationSet Animations
{
get { return m_animations; }
}
private bool m_inTransit;
private bool m_mouseLook;
private bool m_leftButtonDown;
@ -625,6 +627,7 @@ namespace OpenSim.Region.Framework.Scenes
private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo)
{
m_animator = new ScenePresenceAnimator(this);
m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
CreateSceneViewer();
m_rootRegionHandle = reginfo.RegionHandle;
@ -637,15 +640,12 @@ namespace OpenSim.Region.Framework.Scenes
m_regionInfo = reginfo;
m_localId = m_scene.AllocateLocalId();
m_useFlySlow = m_scene.m_useFlySlow;
m_usePreJump = m_scene.m_usePreJump;
IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
if (gm != null)
m_grouptitle = gm.GetGroupTitle(m_uuid);
m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
AbsolutePosition = posLastSignificantMove = m_CameraCenter =
m_lastCameraCenter = m_controllingClient.StartPos;
@ -656,7 +656,8 @@ namespace OpenSim.Region.Framework.Scenes
AdjustKnownSeeds();
TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
// TODO: I think, this won't send anything, as we are still a child here...
Animator.TrySetMovementAnimation("STAND");
// we created a new ScenePresence (a new child agent) in a fresh region.
// Request info about all the (root) agents in this region
@ -665,21 +666,18 @@ namespace OpenSim.Region.Framework.Scenes
RegisterToEvents();
SetDirectionVectors();
}
public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
AvatarWearable[] wearables)
: this(client, world, reginfo)
{
CreateSceneViewer();
m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
}
public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
: this(client, world, reginfo)
{
CreateSceneViewer();
m_appearance = appearance;
}
@ -857,7 +855,7 @@ namespace OpenSim.Region.Framework.Scenes
// Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
// avatar to return to the standing position in mid-air. On login it looks like this is being sent
// elsewhere anyway
//SendAnimPack();
// Animator.SendAnimPack();
m_scene.SwapRootAgentCount(false);
@ -879,7 +877,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence presence = animAgents[i];
if (presence != this)
presence.SendAnimPackToClient(ControllingClient);
presence.Animator.SendAnimPackToClient(ControllingClient);
}
m_scene.EventManager.TriggerOnMakeRootAgent(this);
@ -894,7 +892,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void MakeChildAgent()
{
m_animations.Clear();
Animator.ResetAnimations();
// m_log.DebugFormat(
// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
@ -995,7 +993,7 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
}
TrySetMovementAnimation("LAND");
Animator.TrySetMovementAnimation("LAND");
SendFullUpdateToAllClients();
}
@ -1247,7 +1245,7 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: This doesn't prevent the user from walking yet.
// Setting parent ID would fix this, if we knew what value
// to use. Or we could add a m_isSitting variable.
TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
}
// In the future, these values might need to go global.
@ -1453,7 +1451,7 @@ namespace OpenSim.Region.Framework.Scenes
AddNewMovement(agent_control_v3, q);
if (update_movementflag)
UpdateMovementAnimations();
Animator.UpdateMovementAnimations();
}
}
@ -1561,7 +1559,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/// <summary>
/// Perform the logic necessary to stand the client up. This method also executes
/// Perform the logic necessary to stand the avatar up. This method also executes
/// the stand animation.
/// </summary>
public void StandUp()
@ -1611,7 +1609,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
TrySetMovementAnimation("STAND");
Animator.TrySetMovementAnimation("STAND");
}
private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@ -1850,7 +1848,7 @@ namespace OpenSim.Region.Framework.Scenes
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
TrySetMovementAnimation(sitAnimation);
Animator.TrySetMovementAnimation(sitAnimation);
SendFullUpdateToAllClients();
// This may seem stupid, but Our Full updates don't send avatar rotation :P
// So we're also sending a terse update (which has avatar rotation)
@ -1870,352 +1868,15 @@ namespace OpenSim.Region.Framework.Scenes
PhysicsActor.SetAlwaysRun = pSetAlwaysRun;
}
}
public BinBVHAnimation GenerateRandomAnimation()
{
int rnditerations = 3;
BinBVHAnimation anim = new BinBVHAnimation();
List<string> parts = new List<string>();
parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso");
parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft");
parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck");
parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight");
parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight");
parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight");
parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft");
anim.HandPose = 1;
anim.InPoint = 0;
anim.OutPoint = (rnditerations * .10f);
anim.Priority = 7;
anim.Loop = false;
anim.Length = (rnditerations * .10f);
anim.ExpressionName = "afraid";
anim.EaseInTime = 0;
anim.EaseOutTime = 0;
string[] strjoints = parts.ToArray();
anim.Joints = new binBVHJoint[strjoints.Length];
for (int j = 0; j < strjoints.Length; j++)
{
anim.Joints[j] = new binBVHJoint();
anim.Joints[j].Name = strjoints[j];
anim.Joints[j].Priority = 7;
anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations];
anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations];
Random rnd = new Random();
for (int i = 0; i < rnditerations; i++)
{
anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
anim.Joints[j].rotationkeys[i].time = (i*.10f);
anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1);
anim.Joints[j].positionkeys[i] = new binBVHJointKey();
anim.Joints[j].positionkeys[i].time = (i*.10f);
anim.Joints[j].positionkeys[i].key_element.X = 0;
anim.Joints[j].positionkeys[i].key_element.Y = 0;
anim.Joints[j].positionkeys[i].key_element.Z = 0;
}
}
AssetBase Animasset = new AssetBase(UUID.Random(), "Random Animation", (sbyte)AssetType.Animation);
Animasset.Data = anim.ToBytes();
Animasset.Temporary = true;
Animasset.Local = true;
Animasset.Description = "dance";
//BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data);
m_scene.AssetService.Store(Animasset);
AddAnimation(Animasset.FullID, UUID);
return anim;
}
public void AddAnimation(UUID animID, UUID objectID)
{
if (m_isChildAgent)
return;
if (m_animations.Add(animID, m_controllingClient.NextAnimationSequenceNumber, objectID))
SendAnimPack();
}
// Called from scripts
public void AddAnimation(string name, UUID objectID)
{
if (m_isChildAgent)
return;
UUID animID = m_controllingClient.GetDefaultAnimation(name);
if (animID == UUID.Zero)
return;
AddAnimation(animID, objectID);
}
public void RemoveAnimation(UUID animID)
{
if (m_isChildAgent)
return;
if (m_animations.Remove(animID))
SendAnimPack();
}
// Called from scripts
public void RemoveAnimation(string name)
{
if (m_isChildAgent)
return;
UUID animID = m_controllingClient.GetDefaultAnimation(name);
if (animID == UUID.Zero)
return;
RemoveAnimation(animID);
}
public UUID[] GetAnimationArray()
{
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
return animIDs;
}
public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
{
AddAnimation(animID, UUID.Zero);
Animator.AddAnimation(animID, UUID.Zero);
}
public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
{
RemoveAnimation(animID);
}
/// <summary>
/// The movement animation is reserved for "main" animations
/// that are mutually exclusive, e.g. flying and sitting.
/// </summary>
protected void TrySetMovementAnimation(string anim)
{
//m_log.DebugFormat("Updating movement animation to {0}", anim);
if (!m_isChildAgent)
{
if (m_animations.TrySetDefaultAnimation(anim, m_controllingClient.NextAnimationSequenceNumber, UUID.Zero))
{
if (m_scriptEngines != null)
{
lock (m_attachments)
{
foreach (SceneObjectGroup grp in m_attachments)
{
// 16384 is CHANGED_ANIMATION
//
// Send this to all attachment root prims
//
foreach (IScriptModule m in m_scriptEngines)
{
if (m == null) // No script engine loaded
continue;
m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { 16384 });
}
}
}
}
SendAnimPack();
}
}
}
/// <summary>
/// This method determines the proper movement related animation
/// </summary>
public string GetMovementAnimation()
{
const float FALL_DELAY = 0.33f;
const float PREJUMP_DELAY = 0.25f;
#region Inputs
AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_AgentControlFlags;
PhysicsActor actor = m_physicsActor;
// Create forward and left vectors from the current avatar rotation
Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_bodyRot);
Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
// Check control flags
bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG;
bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS;
bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
//bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
//bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
//bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
//bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
// Direction in which the avatar is trying to move
Vector3 move = Vector3.Zero;
if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
if (heldLeft) { move.X += left.X; move.Y += left.Y; }
if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
if (heldUp) { move.Z += 1; }
if (heldDown) { move.Z -= 1; }
// Is the avatar trying to move?
// bool moving = (move != Vector3.Zero);
bool jumping = m_animTickJump != 0;
#endregion Inputs
#region Flying
if (actor != null && actor.Flying)
{
m_animTickFall = 0;
m_animTickJump = 0;
if (move.X != 0f || move.Y != 0f)
{
return (m_useFlySlow ? "FLYSLOW" : "FLY");
}
else if (move.Z > 0f)
{
return "HOVER_UP";
}
else if (move.Z < 0f)
{
if (actor != null && actor.IsColliding)
return "LAND";
else
return "HOVER_DOWN";
}
else
{
return "HOVER";
}
}
#endregion Flying
#region Falling/Floating/Landing
if (actor == null || !actor.IsColliding)
{
float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
{
// Just started falling
m_animTickFall = Environment.TickCount;
}
else if (!jumping && fallElapsed > FALL_DELAY)
{
// Falling long enough to trigger the animation
return "FALLDOWN";
}
return m_movementAnimation;
}
#endregion Falling/Floating/Landing
#region Ground Movement
if (m_movementAnimation == "FALLDOWN")
{
m_animTickFall = Environment.TickCount;
// TODO: SOFT_LAND support
return "LAND";
}
else if (m_movementAnimation == "LAND")
{
float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
if (landElapsed <= FALL_DELAY)
return "LAND";
}
m_animTickFall = 0;
if (move.Z > 0f)
{
// Jumping
if (!jumping)
{
// Begin prejump
m_animTickJump = Environment.TickCount;
return "PREJUMP";
}
else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f)
{
// Start actual jump
if (m_animTickJump == -1)
{
// Already jumping! End the current jump
m_animTickJump = 0;
return "JUMP";
}
m_animTickJump = -1;
return "JUMP";
}
}
else
{
// Not jumping
m_animTickJump = 0;
if (move.X != 0f || move.Y != 0f)
{
// Walking / crouchwalking / running
if (move.Z < 0f)
return "CROUCHWALK";
else if (m_setAlwaysRun)
return "RUN";
else
return "WALK";
}
else
{
// Not walking
if (move.Z < 0f)
return "CROUCH";
else
return "STAND";
}
}
#endregion Ground Movement
return m_movementAnimation;
}
/// <summary>
/// Update the movement animation of this avatar according to its current state
/// </summary>
protected void UpdateMovementAnimations()
{
m_movementAnimation = GetMovementAnimation();
if (m_movementAnimation == "PREJUMP" && !m_usePreJump)
{
// This was the previous behavior before PREJUMP
TrySetMovementAnimation("JUMP");
}
else
{
TrySetMovementAnimation(m_movementAnimation);
}
Animator.RemoveAnimation(animID);
}
/// <summary>
@ -2289,8 +1950,8 @@ namespace OpenSim.Region.Framework.Scenes
direc.Z *= 3.0f;
// TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
TrySetMovementAnimation("PREJUMP");
TrySetMovementAnimation("JUMP");
Animator.TrySetMovementAnimation("PREJUMP");
Animator.TrySetMovementAnimation("JUMP");
}
}
}
@ -2504,7 +2165,7 @@ namespace OpenSim.Region.Framework.Scenes
{
avatar.SendFullUpdateToOtherClient(this);
avatar.SendAppearanceToOtherAgent(this);
avatar.SendAnimPackToClient(ControllingClient);
avatar.Animator.SendAnimPackToClient(ControllingClient);
}
}
}
@ -2512,7 +2173,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.StatsReporter.AddAgentUpdates(avatars.Length);
m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
//SendAnimPack();
//Animator.SendAnimPack();
}
public void SendFullUpdateToAllClients()
@ -2529,7 +2190,7 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.StatsReporter.AddAgentUpdates(avatars.Count);
m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
SendAnimPack();
Animator.SendAnimPack();
}
/// <summary>
@ -2646,7 +2307,7 @@ namespace OpenSim.Region.Framework.Scenes
SendAppearanceToAllOtherAgents();
if (!m_startAnimationSet)
{
UpdateMovementAnimations();
Animator.UpdateMovementAnimations();
m_startAnimationSet = true;
}
@ -2674,54 +2335,6 @@ namespace OpenSim.Region.Framework.Scenes
set { m_appearance = value; }
}
/// <summary>
///
/// </summary>
/// <param name="animations"></param>
/// <param name="seqs"></param>
/// <param name="objectIDs"></param>
public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
{
if (m_isChildAgent)
return;
m_scene.ForEachClient(
delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); });
}
public void SendAnimPackToClient(IClientAPI client)
{
if (m_isChildAgent)
return;
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
client.SendAnimations(animIDs, sequenceNums, m_controllingClient.AgentId, objectIDs);
}
/// <summary>
/// Send animation information about this avatar to all clients.
/// </summary>
public void SendAnimPack()
{
//m_log.Debug("Sending animation pack to all");
if (m_isChildAgent)
return;
UUID[] animIDs;
int[] sequenceNums;
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
SendAnimPack(animIDs, sequenceNums, objectIDs);
}
#endregion
#region Significant Movement Method
@ -2919,13 +2532,9 @@ namespace OpenSim.Region.Framework.Scenes
public void Reset()
{
// Put the child agent back at the center
AbsolutePosition = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
ResetAnimations();
}
public void ResetAnimations()
{
m_animations.Clear();
AbsolutePosition
= new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
Animator.ResetAnimations();
}
/// <summary>
@ -3149,7 +2758,7 @@ namespace OpenSim.Region.Framework.Scenes
// Animations
try
{
cAgent.Anims = m_animations.ToArray();
cAgent.Anims = Animator.Animations.ToArray();
}
catch { }
@ -3228,15 +2837,13 @@ namespace OpenSim.Region.Framework.Scenes
// Animations
try
{
m_animations.Clear();
m_animations.FromArray(cAgent.Anims);
Animator.ResetAnimations();
Animator.Animations.FromArray(cAgent.Anims);
}
catch { }
//cAgent.GroupID = ??
//Groups???
}
public bool CopyAgent(out IAgentData agent)
@ -3318,7 +2925,7 @@ namespace OpenSim.Region.Framework.Scenes
//if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
// The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
// as of this comment the interval is set in AddToPhysicalScene
UpdateMovementAnimations();
Animator.UpdateMovementAnimations();
CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
@ -3327,7 +2934,7 @@ namespace OpenSim.Region.Framework.Scenes
if (coldata.Count != 0)
{
switch (m_movementAnimation)
switch (Animator.CurrentMovementAnimation)
{
case "STAND":
case "WALK":
@ -3415,6 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes
}
m_attachments.Clear();
}
lock (m_knownChildRegions)
{
m_knownChildRegions.Clear();
@ -3425,6 +3033,7 @@ namespace OpenSim.Region.Framework.Scenes
m_reprioritization_timer.Enabled = false;
m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
}
// I don't get it but mono crashes when you try to dispose of this timer,
// unsetting the elapsed callback should be enough to allow for cleanup however.
//m_reprioritizationTimer.Dispose();
@ -3436,8 +3045,9 @@ namespace OpenSim.Region.Framework.Scenes
public ScenePresence()
{
m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
CreateSceneViewer();
m_animator = new ScenePresenceAnimator(this);
}
public void AddAttachment(SceneObjectGroup gobj)
@ -3497,6 +3107,35 @@ namespace OpenSim.Region.Framework.Scenes
return true;
}
/// <summary>
/// Send a script event to this scene presence's attachments
/// </summary>
/// <param name="eventName">The name of the event</param>
/// <param name="args">The arguments for the event</param>
public void SendScriptEventToAttachments(string eventName, Object[] args)
{
if (m_scriptEngines != null)
{
lock (m_attachments)
{
foreach (SceneObjectGroup grp in m_attachments)
{
// 16384 is CHANGED_ANIMATION
//
// Send this to all attachment root prims
//
foreach (IScriptModule m in m_scriptEngines)
{
if (m == null) // No script engine loaded
continue;
m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { 16384 });
}
}
}
}
}
public bool CrossAttachmentsIntoNewRegion(ulong regionHandle, bool silent)
{
lock (m_attachments)
@ -3939,4 +3578,4 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
}
}

View File

@ -1179,8 +1179,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
return m_clientRequestIDInfo[client.AgentId].RequestID;
}
return new GroupRequestID();
// Unreachable code!
// return new GroupRequestID();
}
/// <summary>

View File

@ -40,10 +40,11 @@ using OpenSim;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Region.CoreModules;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.CoreModules.World.Land;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Animation;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
@ -3097,11 +3098,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (presence != null)
{
// Do NOT try to parse UUID, animations cannot be triggered by ID
UUID animID=InventoryKey(anim, (int)AssetType.Animation);
UUID animID = InventoryKey(anim, (int)AssetType.Animation);
if (animID == UUID.Zero)
presence.AddAnimation(anim, m_host.UUID);
presence.Animator.AddAnimation(anim, m_host.UUID);
else
presence.AddAnimation(animID, m_host.UUID);
presence.Animator.AddAnimation(animID, m_host.UUID);
}
}
}
@ -3141,9 +3142,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (presence != null)
{
if (animID == UUID.Zero)
presence.RemoveAnimation(anim);
presence.Animator.RemoveAnimation(anim);
else
presence.RemoveAnimation(animID);
presence.Animator.RemoveAnimation(animID);
}
}
}
@ -3987,12 +3988,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (presence != null)
{
AnimationSet currentAnims = presence.Animations;
AnimationSet currentAnims = presence.Animator.Animations;
string currentAnimationState = String.Empty;
if (animationstateNames.TryGetValue(currentAnims.DefaultAnimation.AnimID, out currentAnimationState))
return currentAnimationState;
}
}
return String.Empty;
}
@ -5326,7 +5328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
flags |= ScriptBaseClass.AGENT_TYPING;
}
string agentMovementAnimation = agent.GetMovementAnimation();
string agentMovementAnimation = agent.Animator.GetMovementAnimation();
if (agentMovementAnimation == "CROUCH")
{
@ -5358,7 +5360,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
flags |= ScriptBaseClass.AGENT_SITTING;
}
if (agent.Animations.DefaultAnimation.AnimID == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
if (agent.Animator.Animations.DefaultAnimation.AnimID
== AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
{
flags |= ScriptBaseClass.AGENT_SITTING;
}
@ -7148,7 +7151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (av == null || av.IsChildAgent) // only if in the region
return l;
UUID[] anims;
anims = av.GetAnimationArray();
anims = av.Animator.GetAnimationArray();
foreach (UUID foo in anims)
l.Add(foo.ToString());
return l;
@ -7276,7 +7279,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
LSL_Vector lower;
LSL_Vector upper;
if (presence.Animations.DefaultAnimation.AnimID == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
if (presence.Animator.Animations.DefaultAnimation.AnimID
== AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
{
// This is for ground sitting avatars
float height = presence.Appearance.AvatarHeight / 2.66666667f;

View File

@ -741,9 +741,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
if (animID == UUID.Zero)
target.AddAnimation(animation, m_host.UUID);
target.Animator.AddAnimation(animation, m_host.UUID);
else
target.AddAnimation(animID, m_host.UUID);
target.Animator.AddAnimation(animID, m_host.UUID);
}
}
}
@ -773,10 +773,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
}
if (animID == UUID.Zero)
target.RemoveAnimation(animation);
target.Animator.RemoveAnimation(animation);
else
target.RemoveAnimation(animID);
target.Animator.RemoveAnimation(animID);
}
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
namespace OpenSim.Server.Handlers.Presence
{
public class PresenceServiceConnector : ServiceConnector
{
private IPresenceService m_PresenceService;
private string m_ConfigName = "PresenceService";
public PresenceServiceConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
string gridService = serverConfig.GetString("LocalServiceModule",
String.Empty);
if (gridService == String.Empty)
throw new Exception("No LocalServiceModule in config file");
Object[] args = new Object[] { config };
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(gridService, args);
server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService));
}
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using Nini.Config;
using log4net;
using System;
using System.Reflection;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenMetaverse;
namespace OpenSim.Server.Handlers.Presence
{
public class PresenceServerPostHandler : BaseStreamHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IPresenceService m_PresenceService;
public PresenceServerPostHandler(IPresenceService service) :
base("POST", "/presence")
{
m_PresenceService = service;
}
public override byte[] Handle(string path, Stream requestData,
OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
StreamReader sr = new StreamReader(requestData);
string body = sr.ReadToEnd();
sr.Close();
body = body.Trim();
//m_log.DebugFormat("[XXX]: query String: {0}", body);
try
{
Dictionary<string, string> request =
ServerUtils.ParseQueryString(body);
if (!request.ContainsKey("METHOD"))
return FailureResult();
string method = request["METHOD"];
switch (method)
{
case "report":
return Report(request);
}
m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method);
}
catch (Exception e)
{
m_log.Debug("[PRESENCE HANDLER]: Exception {0}" + e);
}
return FailureResult();
}
byte[] Report(Dictionary<string, string> request)
{
PresenceInfo info = new PresenceInfo();
info.Data = new Dictionary<string, string>();
if (request["PrincipalID"] == null || request["RegionID"] == null)
return FailureResult();
if (!UUID.TryParse(request["PrincipalID"].ToString(),
out info.PrincipalID))
return FailureResult();
if (!UUID.TryParse(request["RegionID"].ToString(),
out info.RegionID))
return FailureResult();
foreach (KeyValuePair<string, string> kvp in request)
{
if (kvp.Key == "METHOD" ||
kvp.Key == "PrincipalID" ||
kvp.Key == "RegionID")
continue;
info.Data[kvp.Key] = kvp.Value;
}
if (m_PresenceService.Report(info))
return SuccessResult();
return FailureResult();
}
private byte[] SuccessResult()
{
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
doc.AppendChild(xmlnode);
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
"");
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "Result", "");
result.AppendChild(doc.CreateTextNode("Success"));
rootElement.AppendChild(result);
return DocToBytes(doc);
}
private byte[] FailureResult()
{
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
"", "");
doc.AppendChild(xmlnode);
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
"");
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "Result", "");
result.AppendChild(doc.CreateTextNode("Failure"));
rootElement.AppendChild(result);
return DocToBytes(doc);
}
private byte[] DocToBytes(XmlDocument doc)
{
MemoryStream ms = new MemoryStream();
XmlTextWriter xw = new XmlTextWriter(ms, null);
xw.Formatting = Formatting.Indented;
doc.WriteTo(xw);
xw.Flush();
return ms.ToArray();
}
}
}

View File

@ -231,13 +231,14 @@ namespace OpenSim.Services.Connectors
}
catch (TimeoutException e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetFolderContent operation to {0} timed out {0} {1}.", m_ServerURI,
e.Source, e.Message);
m_log.ErrorFormat(
"[INVENTORY CONNECTOR]: GetFolderContent operation to {0} for {1} timed out {2} {3}.",
m_ServerURI, folderID, e.Source, e.Message);
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetFolderContent operation failed, {0} {1} (old server?).",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetFolderContent operation failed for {0}, {1} {2} (old server?).",
folderID, e.Source, e.Message);
}
InventoryCollection nullCollection = new InventoryCollection();
@ -256,8 +257,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory folder operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory folder operation failed for {0} {1}, {2} {3}",
folder.Name, folder.ID, e.Source, e.Message);
}
return false;
@ -272,8 +273,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update inventory folder operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update inventory folder operation failed for {0} {1}, {2} {3}",
folder.Name, folder.ID, e.Source, e.Message);
}
return false;
@ -307,8 +308,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Move inventory folder operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Move inventory folder operation failed for {0} {1}, {2} {3}",
folder.Name, folder.ID, e.Source, e.Message);
}
return false;
@ -323,8 +324,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Move inventory folder operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Purge inventory folder operation failed for {0} {1}, {2} {3}",
folder.Name, folder.ID, e.Source, e.Message);
}
return false;
@ -340,8 +341,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Get folder items operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Get folder items operation failed for folder {0}, {1} {2}",
folderID, e.Source, e.Message);
}
return null;
@ -356,8 +357,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory item operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory item operation failed for {0} {1}, {2} {3}",
item.Name, item.ID, e.Source, e.Message);
}
return false;
@ -372,8 +373,8 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update new inventory item operation failed, {0} {1}",
e.Source, e.Message);
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update new inventory item operation failed for {0} {1}, {2} {3}",
item.Name, item.ID, e.Source, e.Message);
}
return false;
@ -443,7 +444,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Delete inventory item operation failed, {0} {1}",
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Delete inventory items operation failed, {0} {1}",
e.Source, e.Message);
}
@ -475,7 +476,7 @@ namespace OpenSim.Services.Connectors
}
catch (Exception e)
{
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Query inventory item operation failed, {0} {1}",
m_log.ErrorFormat("[INVENTORY CONNECTOR]: Query inventory folder operation failed, {0} {1}",
e.Source, e.Message);
}
@ -576,9 +577,6 @@ namespace OpenSim.Services.Connectors
}
callback(folders, items);
}
}
}

View File

@ -31,7 +31,15 @@ using OpenMetaverse;
namespace OpenSim.Services.Interfaces
{
public class PresenceInfo
{
public UUID PrincipalID;
public UUID RegionID;
public Dictionary<string, string> Data;
}
public interface IPresenceService
{
bool Report(PresenceInfo presence);
}
}

View File

@ -49,5 +49,19 @@ namespace OpenSim.Services.PresenceService
: base(config)
{
}
public bool Report(PresenceInfo presence)
{
PresenceData p = new PresenceData();
p.Data = new Dictionary<string, string>();
p.UUID = presence.PrincipalID;
p.currentRegion = presence.RegionID;
foreach (KeyValuePair<string, string> kvp in presence.Data)
p.Data[kvp.Key] = kvp.Value;
return false;
}
}
}

View File

@ -1,3 +1,29 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;