diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 7042c9a228..75a47d5379 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -110,7 +110,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Handlers for incoming packets
//PacketEventDictionary packetEvents = new PacketEventDictionary();
/// Incoming packets that are awaiting handling
- private OpenMetaverse.BlockingQueue packetInbox = new OpenMetaverse.BlockingQueue();
+ //private OpenMetaverse.BlockingQueue packetInbox = new OpenMetaverse.BlockingQueue();
+
+ private DoubleQueue packetInbox = new DoubleQueue();
+
///
//private UDPClientCollection m_clients = new UDPClientCollection();
/// Bandwidth throttle for this UDP server
@@ -919,7 +922,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Ping Check Handling
// Inbox insertion
- packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
+ if (packet.Type == PacketType.AgentUpdate ||
+ packet.Type == PacketType.ChatFromViewer)
+ packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
+ else
+ packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
}
#region BinaryStats
@@ -1471,8 +1478,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Packet packet = incomingPacket.Packet;
LLClientView client = incomingPacket.Client;
- if (client.IsActive)
- {
+// if (client.IsActive)
+// {
m_currentIncomingClient = client;
try
@@ -1499,13 +1506,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
m_currentIncomingClient = null;
}
- }
- else
- {
- m_log.DebugFormat(
- "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
- packet.Type, client.Name, m_scene.RegionInfo.RegionName);
- }
+// }
+// else
+// {
+// m_log.DebugFormat(
+// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
+// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
+// }
}
protected void LogoutHandler(IClientAPI client)
@@ -1519,4 +1526,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
}
+
+ internal class DoubleQueue where T:class
+ {
+ private Queue m_lowQueue = new Queue();
+ private Queue m_highQueue = new Queue();
+
+ private object m_syncRoot = new object();
+ private Semaphore m_s = new Semaphore(0, 1);
+
+ public DoubleQueue()
+ {
+ }
+
+ public virtual int Count
+ {
+ get { return m_highQueue.Count + m_lowQueue.Count; }
+ }
+
+ public virtual void Enqueue(T data)
+ {
+ Enqueue(m_lowQueue, data);
+ }
+
+ public virtual void EnqueueLow(T data)
+ {
+ Enqueue(m_lowQueue, data);
+ }
+
+ public virtual void EnqueueHigh(T data)
+ {
+ Enqueue(m_highQueue, data);
+ }
+
+ private void Enqueue(Queue q, T data)
+ {
+ lock (m_syncRoot)
+ {
+ m_lowQueue.Enqueue(data);
+ m_s.WaitOne(0);
+ m_s.Release();
+ }
+ }
+
+ public virtual T Dequeue()
+ {
+ return Dequeue(Timeout.Infinite);
+ }
+
+ public virtual T Dequeue(int tmo)
+ {
+ return Dequeue(TimeSpan.FromMilliseconds(tmo));
+ }
+
+ public virtual T Dequeue(TimeSpan wait)
+ {
+ T res = null;
+
+ if (!Dequeue(wait, ref res))
+ return null;
+
+ return res;
+ }
+
+ public bool Dequeue(int timeout, ref T res)
+ {
+ return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
+ }
+
+ public bool Dequeue(TimeSpan wait, ref T res)
+ {
+ if (!m_s.WaitOne(wait))
+ return false;
+
+ lock (m_syncRoot)
+ {
+ if (m_highQueue.Count > 0)
+ res = m_highQueue.Dequeue();
+ else
+ res = m_lowQueue.Dequeue();
+
+ if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
+ return true;
+
+ try
+ {
+ m_s.Release();
+ }
+ catch
+ {
+ }
+
+ return true;
+ }
+ }
+
+ public virtual void Clear()
+ {
+
+ lock (m_syncRoot)
+ {
+ // Make sure sem count is 0
+ m_s.WaitOne(0);
+
+ m_lowQueue.Clear();
+ m_highQueue.Clear();
+ }
+ }
+ }
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 560f807167..9ffb851bbc 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -1855,6 +1855,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (grp.RootPart.PhysActor != null)
grp.RootPart.PhysActor.CrossingFailure();
+ if (grp.RootPart.KeyframeMotion != null)
+ grp.RootPart.KeyframeMotion.CrossingFailure();
+
grp.ScheduleGroupForFullUpdate();
}
@@ -1910,8 +1913,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
grp, e);
}
}
+/*
+ * done on caller ( not in attachments crossing for now)
else
{
+
if (!grp.IsDeleted)
{
PhysicsActor pa = grp.RootPart.PhysActor;
@@ -1920,15 +1926,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
pa.CrossingFailure();
if (grp.RootPart.KeyframeMotion != null)
{
- grp.RootPart.Velocity = Vector3.Zero;
+ // moved to KeyframeMotion.CrossingFailure
+// grp.RootPart.Velocity = Vector3.Zero;
grp.RootPart.KeyframeMotion.CrossingFailure();
- grp.SendGroupRootTerseUpdate();
+// grp.SendGroupRootTerseUpdate();
}
}
}
m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
}
+ */
}
else
{
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index b7b0d27388..42e3860fde 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -38,8 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
[Flags]
public enum DataFormat : int
{
- Translation = 1,
- Rotation = 2
+ Translation = 2,
+ Rotation = 1
}
[Serializable]
@@ -53,17 +53,42 @@ namespace OpenSim.Region.Framework.Scenes
public Vector3 AngularVelocity;
};
+ private Vector3 m_serializedPosition;
private Vector3 m_basePosition;
private Quaternion m_baseRotation;
- private Vector3 m_serializedPosition;
private Keyframe m_currentFrame;
+
private List m_frames = new List();
private Keyframe[] m_keyframes;
[NonSerialized()]
- protected Timer m_timer = new Timer();
+ protected Timer m_timer = null;
+
+ // timer lock
+ [NonSerialized()]
+ private object m_onTimerLock;
+
+ // timer overrun detect
+ // prevents overlap or timer events threads frozen on the lock
+ [NonSerialized()]
+ private bool m_inOnTimer;
+
+ // skip timer events.
+ //timer.stop doesn't assure there aren't event threads still being fired
+ [NonSerialized()]
+ private bool m_timerStopped;
+
+ [NonSerialized()]
+ private bool m_isCrossing;
+
+ [NonSerialized()]
+ private bool m_waitingCrossing;
+
+ // retry position for cross fail
+ [NonSerialized()]
+ private Vector3 m_nextPosition;
[NonSerialized()]
private SceneObjectGroup m_group;
@@ -87,8 +112,8 @@ namespace OpenSim.Region.Framework.Scenes
public bool Selected
{
set
- {
- if (value)
+ {
+ if (!value)
{
// Once we're let go, recompute positions
if (m_selected)
@@ -98,44 +123,104 @@ namespace OpenSim.Region.Framework.Scenes
{
// Save selection position in case we get moved
if (!m_selected)
+ {
+ StopTimer();
m_serializedPosition = m_group.AbsolutePosition;
+ }
}
- m_selected = value; }
+ m_isCrossing = false;
+ m_waitingCrossing = false;
+ m_selected = value;
+ }
}
+ private void StartTimer()
+ {
+ if (m_timer == null)
+ return;
+ m_timerStopped = false;
+ m_timer.Start();
+ }
+
+ private void StopTimer()
+ {
+ if (m_timer == null || m_timerStopped)
+ return;
+ m_timerStopped = true;
+ m_timer.Stop();
+ }
+
+ private void RemoveTimer()
+ {
+ if (m_timer == null)
+ return;
+ m_timerStopped = true;
+ m_timer.Stop();
+ m_timer.Elapsed -= OnTimer;
+ m_timer = null;
+ }
+
+
public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
{
- MemoryStream ms = new MemoryStream(data);
+ KeyframeMotion newMotion = null;
- BinaryFormatter fmt = new BinaryFormatter();
+ try
+ {
+ MemoryStream ms = new MemoryStream(data);
+ BinaryFormatter fmt = new BinaryFormatter();
- KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
+ newMotion = (KeyframeMotion)fmt.Deserialize(ms);
- // This will be started when position is updated
- newMotion.m_timer = new Timer();
- newMotion.m_timer.Interval = (int)timerInterval;
- newMotion.m_timer.AutoReset = true;
- newMotion.m_timer.Elapsed += newMotion.OnTimer;
+ newMotion.m_group = grp;
+
+ if (grp != null && grp.IsSelected)
+ newMotion.m_selected = true;
+
+ newMotion.m_onTimerLock = new object();
+ newMotion.m_timerStopped = false;
+ newMotion.m_inOnTimer = false;
+ newMotion.m_isCrossing = false;
+ newMotion.m_waitingCrossing = false;
+ }
+ catch
+ {
+ newMotion = null;
+ }
return newMotion;
}
public void UpdateSceneObject(SceneObjectGroup grp)
{
- m_group = grp;
- Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
-
- m_basePosition += offset;
- m_currentFrame.Position += offset;
- for (int i = 0 ; i < m_frames.Count ; i++)
+// lock (m_onTimerLock)
{
- Keyframe k = m_frames[i];
- k.Position += offset;
- m_frames[i] = k;
- }
+ m_isCrossing = false;
+ m_waitingCrossing = false;
+ StopTimer();
- if (m_running)
- Start();
+ m_group = grp;
+ Vector3 grppos = grp.AbsolutePosition;
+ Vector3 offset = grppos - m_serializedPosition;
+ // avoid doing it more than once
+ // current this will happen draging a prim to other region
+ m_serializedPosition = grppos;
+
+ m_basePosition += offset;
+ m_currentFrame.Position += offset;
+
+ m_nextPosition += offset;
+
+ for (int i = 0; i < m_frames.Count; i++)
+ {
+ Keyframe k = m_frames[i];
+ k.Position += offset;
+ m_frames[i]=k;
+ }
+
+ if (m_running)
+ Start();
+ }
}
public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@@ -143,13 +228,16 @@ namespace OpenSim.Region.Framework.Scenes
m_mode = mode;
m_data = data;
- m_group = grp;
- m_basePosition = grp.AbsolutePosition;
- m_baseRotation = grp.GroupRotation;
+ m_onTimerLock = new object();
- m_timer.Interval = (int)timerInterval;
- m_timer.AutoReset = true;
- m_timer.Elapsed += OnTimer;
+ m_group = grp;
+ if (grp != null)
+ {
+ m_basePosition = grp.AbsolutePosition;
+ m_baseRotation = grp.GroupRotation;
+ }
+ m_isCrossing = false;
+ m_waitingCrossing = false;
}
public void SetKeyframes(Keyframe[] frames)
@@ -157,19 +245,93 @@ namespace OpenSim.Region.Framework.Scenes
m_keyframes = frames;
}
+ public KeyframeMotion Copy(SceneObjectGroup newgrp)
+ {
+ StopTimer();
+
+ KeyframeMotion newmotion = new KeyframeMotion(newgrp, m_mode, m_data);
+
+ if (newgrp != null && newgrp.IsSelected)
+ newmotion.m_selected = true;
+
+ if (m_keyframes != null)
+ m_keyframes.CopyTo(newmotion.m_keyframes, 0);
+
+ newmotion.m_frames = new List(m_frames);
+ newmotion.m_currentFrame = m_currentFrame;
+
+ newmotion.m_nextPosition = m_nextPosition;
+ if (m_selected)
+ newmotion.m_serializedPosition = m_serializedPosition;
+ else
+ {
+ if (m_group != null)
+ newmotion.m_serializedPosition = m_group.AbsolutePosition;
+ else
+ newmotion.m_serializedPosition = m_serializedPosition;
+ }
+
+ newmotion.m_iterations = m_iterations;
+
+ newmotion.m_onTimerLock = new object();
+ newmotion.m_timerStopped = false;
+ newmotion.m_inOnTimer = false;
+ newmotion.m_isCrossing = false;
+ newmotion.m_waitingCrossing = false;
+
+ if (m_running && !m_waitingCrossing)
+ StartTimer();
+
+ return newmotion;
+ }
+
+ public void Delete()
+ {
+ m_running = false;
+ RemoveTimer();
+ m_isCrossing = false;
+ m_waitingCrossing = false;
+ m_frames.Clear();
+ m_keyframes = null;
+ }
+
public void Start()
{
+ m_isCrossing = false;
+ m_waitingCrossing = false;
if (m_keyframes.Length > 0)
- m_timer.Start();
- m_running = true;
+ {
+ if (m_timer == null)
+ {
+ m_timer = new Timer();
+ m_timer.Interval = timerInterval;
+ m_timer.AutoReset = true;
+ m_timer.Elapsed += OnTimer;
+ }
+ else
+ {
+ StopTimer();
+ m_timer.Interval = timerInterval;
+ }
+
+ m_inOnTimer = false;
+ StartTimer();
+ m_running = true;
+ }
+ else
+ {
+ m_running = false;
+ RemoveTimer();
+ }
}
public void Stop()
{
- // Failed object creation
- if (m_timer == null)
- return;
- m_timer.Stop();
+ m_running = false;
+ m_isCrossing = false;
+ m_waitingCrossing = false;
+
+ RemoveTimer();
m_basePosition = m_group.AbsolutePosition;
m_baseRotation = m_group.GroupRotation;
@@ -179,17 +341,16 @@ namespace OpenSim.Region.Framework.Scenes
m_group.SendGroupRootTerseUpdate();
m_frames.Clear();
- m_running = false;
}
public void Pause()
{
+ m_running = false;
+ RemoveTimer();
+
m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
m_group.SendGroupRootTerseUpdate();
-
- m_timer.Stop();
- m_running = false;
}
private void GetNextList()
@@ -222,9 +383,16 @@ namespace OpenSim.Region.Framework.Scenes
Keyframe k = m_keyframes[i];
if (k.Position.HasValue)
- k.Position = (k.Position * direction) + pos;
+ {
+ k.Position = (k.Position * direction);
+// k.Velocity = (Vector3)k.Position / (k.TimeMS / 1000.0f);
+ k.Position += pos;
+ }
else
+ {
k.Position = pos;
+// k.Velocity = Vector3.Zero;
+ }
k.StartRotation = rot;
if (k.Rotation.HasValue)
@@ -238,6 +406,8 @@ namespace OpenSim.Region.Framework.Scenes
k.Rotation = rot;
}
+/* ang vel not in use for now
+
float angle = 0;
float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
@@ -267,6 +437,7 @@ namespace OpenSim.Region.Framework.Scenes
}
k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
+ */
k.TimeTotal = k.TimeMS;
m_frames.Add(k);
@@ -284,139 +455,232 @@ namespace OpenSim.Region.Framework.Scenes
protected void OnTimer(object sender, ElapsedEventArgs e)
{
- if (m_frames.Count == 0)
+ if (m_timerStopped) // trap events still in air even after a timer.stop
+ return;
+
+ if (m_inOnTimer) // don't let overruns to happen
{
- GetNextList();
-
- if (m_frames.Count == 0)
- {
- Stop();
- return;
- }
-
- m_currentFrame = m_frames[0];
- }
-
- if (m_selected)
- {
- if (m_group.RootPart.Velocity != Vector3.Zero)
- {
- m_group.RootPart.Velocity = Vector3.Zero;
- m_group.SendGroupRootTerseUpdate();
- }
+ m_log.Warn("[KeyFrame]: timer overrun");
return;
}
- // Do the frame processing
- double steps = (double)m_currentFrame.TimeMS / timerInterval;
- float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
+ if (m_group == null)
+ return;
- if (steps <= 1.0)
+ lock (m_onTimerLock)
{
- m_currentFrame.TimeMS = 0;
- m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
- m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
- }
- else
- {
- Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
- Vector3 motionThisFrame = v / (float)steps;
- v = v * 1000 / m_currentFrame.TimeMS;
+ m_inOnTimer = true;
bool update = false;
- if (Vector3.Mag(motionThisFrame) >= 0.05f)
+ try
{
- m_group.AbsolutePosition += motionThisFrame;
- m_group.RootPart.Velocity = v;
- update = true;
- }
-
- if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
- {
- Quaternion current = m_group.GroupRotation;
-
- Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
-
- float angle = 0;
-
- float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
- float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
- float aa_bb = aa * bb;
-
- if (aa_bb == 0)
+ if (m_selected)
{
- angle = 0;
+ if (m_group.RootPart.Velocity != Vector3.Zero)
+ {
+ m_group.RootPart.Velocity = Vector3.Zero;
+ m_group.SendGroupRootTerseUpdate();
+ }
+ m_inOnTimer = false;
+ return;
+ }
+
+ if (m_isCrossing)
+ {
+ // if crossing and timer running then cross failed
+ // wait some time then
+ // retry to set the position that evtually caused the outbound
+ // if still outside region this will call startCrossing below
+ m_isCrossing = false;
+ m_group.AbsolutePosition = m_nextPosition;
+ if (!m_isCrossing)
+ {
+ StopTimer();
+ m_timer.Interval = timerInterval;
+ StartTimer();
+ }
+ m_inOnTimer = false;
+ return;
+ }
+
+ if (m_frames.Count == 0)
+ {
+ GetNextList();
+
+ if (m_frames.Count == 0)
+ {
+ Stop();
+ m_inOnTimer = false;
+ return;
+ }
+
+ m_currentFrame = m_frames[0];
+ m_currentFrame.TimeMS += (int)timerInterval;
+
+ //force a update on a keyframe transition
+ update = true;
+ }
+
+ m_currentFrame.TimeMS -= (int)timerInterval;
+
+ // Do the frame processing
+ double steps = (double)m_currentFrame.TimeMS / timerInterval;
+
+ if (steps <= 0.0)
+ {
+ m_group.RootPart.Velocity = Vector3.Zero;
+ m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
+
+ m_nextPosition = (Vector3)m_currentFrame.Position;
+ m_group.AbsolutePosition = m_nextPosition;
+
+ m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
+
+ m_frames.RemoveAt(0);
+ if (m_frames.Count > 0)
+ m_currentFrame = m_frames[0];
+
+ update = true;
}
else
{
- float ab = current.X * step.X +
- current.Y * step.Y +
- current.Z * step.Z +
- current.W * step.W;
- float q = (ab * ab) / aa_bb;
+ float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
- if (q > 1.0f)
+ Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
+ Vector3 motionThisFrame = v / (float)steps;
+ v = v * 1000 / m_currentFrame.TimeMS;
+
+ if (Vector3.Mag(motionThisFrame) >= 0.05f)
{
- angle = 0;
+ // m_group.AbsolutePosition += motionThisFrame;
+ m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
+ m_group.AbsolutePosition = m_nextPosition;
+
+ m_group.RootPart.Velocity = v;
+ update = true;
}
- else
+
+ if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
{
- angle = (float)Math.Acos(2 * q - 1);
+ Quaternion current = m_group.GroupRotation;
+
+ Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
+/* use simpler change detection
+ * float angle = 0;
+
+ float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
+ float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
+ float aa_bb = aa * bb;
+
+ if (aa_bb == 0)
+ {
+ angle = 0;
+ }
+ else
+ {
+ float ab = current.X * step.X +
+ current.Y * step.Y +
+ current.Z * step.Z +
+ current.W * step.W;
+ float q = (ab * ab) / aa_bb;
+
+ if (q > 1.0f)
+ {
+ angle = 0;
+ }
+ else
+ {
+ angle = (float)Math.Acos(2 * q - 1);
+ }
+ }
+
+ if (angle > 0.01f)
+ */
+ if(Math.Abs(step.X - current.X) > 0.001f
+ || Math.Abs(step.Y - current.Y) > 0.001f
+ || Math.Abs(step.Z - current.Z) > 0.001f)
+ // assuming w is a dependente var
+
+ {
+ m_group.UpdateGroupRotationR(step);
+ //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
+ update = true;
+ }
}
}
- if (angle > 0.01f)
- {
- m_group.UpdateGroupRotationR(step);
- //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
- update = true;
- }
+ if (update)
+ m_group.SendGroupRootTerseUpdate();
+
+ }
+ catch ( Exception ex)
+ {
+ // still happening sometimes
+ // lets try to see where
+ m_log.Warn("[KeyFrame]: timer overrun" + ex.Message);
}
- if (update)
- m_group.SendGroupRootTerseUpdate();
- }
-
- m_currentFrame.TimeMS -= (int)timerInterval;
-
- if (m_currentFrame.TimeMS <= 0)
- {
- m_group.RootPart.Velocity = Vector3.Zero;
- m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
- m_group.SendGroupRootTerseUpdate();
-
- m_frames.RemoveAt(0);
- if (m_frames.Count > 0)
- m_currentFrame = m_frames[0];
+ finally
+ {
+ // make sure we do not let this frozen
+ m_inOnTimer = false;
+ }
}
}
public Byte[] Serialize()
{
+ StopTimer();
MemoryStream ms = new MemoryStream();
- m_timer.Stop();
BinaryFormatter fmt = new BinaryFormatter();
SceneObjectGroup tmp = m_group;
m_group = null;
- m_serializedPosition = tmp.AbsolutePosition;
+ if (!m_selected && tmp != null)
+ m_serializedPosition = tmp.AbsolutePosition;
fmt.Serialize(ms, this);
m_group = tmp;
+ if (m_running && !m_waitingCrossing)
+ StartTimer();
+
return ms.ToArray();
}
+ public void StartCrossingCheck()
+ {
+ // timer will be restart by crossingFailure
+ // or never since crossing worked and this
+ // should be deleted
+ StopTimer();
+
+ m_isCrossing = true;
+ m_waitingCrossing = true;
+
+// to remove / retune to smoth crossings
+ if (m_group.RootPart.Velocity != Vector3.Zero)
+ {
+ m_group.RootPart.Velocity = Vector3.Zero;
+ m_group.SendGroupRootTerseUpdate();
+ }
+ }
+
public void CrossingFailure()
{
- // The serialization has stopped the timer, so let's wait a moment
- // then retry the crossing. We'll get back here if it fails.
- Util.FireAndForget(delegate (object x)
+ m_waitingCrossing = false;
+
+ if (m_group != null)
{
- Thread.Sleep(60000);
- if (m_running)
- m_timer.Start();
- });
+ m_group.RootPart.Velocity = Vector3.Zero;
+ m_group.SendGroupRootTerseUpdate();
+
+ if (m_running && m_timer != null)
+ {
+ m_timer.Interval = 60000;
+ StartTimer();
+ }
+ }
}
}
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 57fcf51f9e..0237021251 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2346,6 +2346,12 @@ namespace OpenSim.Region.Framework.Scenes
foreach (SceneObjectPart part in partList)
{
+ if (part.KeyframeMotion != null)
+ {
+ part.KeyframeMotion.Delete();
+ part.KeyframeMotion = null;
+ }
+
if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
{
PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index eee53d75ec..5052683870 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -509,6 +509,9 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 newpos = Vector3.Zero;
OpenSim.Services.Interfaces.GridRegion destination = null;
+ if (m_rootPart.KeyframeMotion != null)
+ m_rootPart.KeyframeMotion.StartCrossingCheck();
+
bool canCross = true;
foreach (ScenePresence av in m_linkedAvatars)
{
@@ -551,7 +554,7 @@ namespace OpenSim.Region.Framework.Scenes
av.ParentID = 0;
}
-// m_linkedAvatars.Clear();
+ // m_linkedAvatars.Clear();
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
// Normalize
@@ -599,11 +602,16 @@ namespace OpenSim.Region.Framework.Scenes
avsToCross.Clear();
}
- else if (RootPart.PhysActor != null)
+ else
{
- RootPart.PhysActor.CrossingFailure();
- }
+ if (m_rootPart.KeyframeMotion != null)
+ m_rootPart.KeyframeMotion.CrossingFailure();
+ if (RootPart.PhysActor != null)
+ {
+ RootPart.PhysActor.CrossingFailure();
+ }
+ }
Vector3 oldp = AbsolutePosition;
val.X = Util.Clamp(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
val.Y = Util.Clamp(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
@@ -2059,7 +2067,7 @@ namespace OpenSim.Region.Framework.Scenes
if (part.KeyframeMotion != null)
{
part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
- part.KeyframeMotion.UpdateSceneObject(this);
+// part.KeyframeMotion.UpdateSceneObject(this);
}
});
@@ -3025,7 +3033,8 @@ namespace OpenSim.Region.Framework.Scenes
///
public virtual void DetachFromBackup()
{
- m_scene.SceneGraph.FireDetachFromBackup(this);
+ if (m_scene != null)
+ m_scene.SceneGraph.FireDetachFromBackup(this);
if (m_isBackedUp && Scene != null)
m_scene.EventManager.OnBackup -= ProcessBackup;
@@ -4407,6 +4416,15 @@ namespace OpenSim.Region.Framework.Scenes
public virtual ISceneObject CloneForNewScene()
{
SceneObjectGroup sog = Copy(false);
+ sog.ForEachPart(delegate(SceneObjectPart part)
+ {
+ if (part.KeyframeMotion != null)
+ {
+ part.KeyframeMotion = KeyframeMotion.FromData(sog, part.KeyframeMotion.Serialize());
+ // this is called later
+// part.KeyframeMotion.UpdateSceneObject(this);
+ }
+ });
sog.IsDeleted = false;
return sog;
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index ed626d0e87..bf5fc992a8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -769,7 +769,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_groupPosition = value;
PhysicsActor actor = PhysActor;
- if (actor != null)
+ if (actor != null && ParentGroup.Scene.PhysicsScene != null)
{
try
{
@@ -3408,6 +3408,9 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendTerseUpdateToAllClients()
{
+ if (ParentGroup == null || ParentGroup.Scene == null)
+ return;
+
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
{
SendTerseUpdateToClient(client);
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 134bd9dca9..123c158e2c 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -1241,7 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
if (sog.RootPart.KeyframeMotion != null)
{
- Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
+ Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
writer.WriteBase64(data, 0, data.Length);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 5830eff22f..7dae53a280 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -12964,7 +12964,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (frames.Data.Length > 0) // We are getting a new motion
{
if (group.RootPart.KeyframeMotion != null)
- group.RootPart.KeyframeMotion.Stop();
+ group.RootPart.KeyframeMotion.Delete();
group.RootPart.KeyframeMotion = null;
int idx = 0;