From aa552d0526349f0db6911dbd867c847cf4e810f6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 26 Feb 2012 12:29:35 +0100 Subject: [PATCH] Serialize Keyframe motion for region crossings --- .../Region/Framework/Scenes/KeyframeMotion.cs | 71 ++++++++++++++++++- OpenSim/Region/Framework/Scenes/Scene.cs | 2 + .../Framework/Scenes/SceneObjectGroup.cs | 5 ++ .../Serialization/SceneObjectSerializer.cs | 22 +++++- 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 239f7ca0d3..73db25b121 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -4,6 +4,7 @@ using System; using System.Timers; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Diagnostics; @@ -14,11 +15,14 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Physics.Manager; using OpenSim.Region.Framework.Scenes.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; using Timer = System.Timers.Timer; using log4net; namespace OpenSim.Region.Framework.Scenes { + [Serializable] public class KeyframeMotion { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -38,6 +42,7 @@ namespace OpenSim.Region.Framework.Scenes Rotation = 2 } + [Serializable] public struct Keyframe { public Vector3? Position; @@ -50,19 +55,24 @@ namespace OpenSim.Region.Framework.Scenes 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; - private Timer m_timer = new Timer(); + [NonSerialized()] + protected Timer m_timer = new Timer(); - private readonly SceneObjectGroup m_group; + [NonSerialized()] + private SceneObjectGroup m_group; private PlayMode m_mode = PlayMode.Forward; private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation; + private bool m_running = false; + private int m_iterations = 0; private const double timerInterval = 50.0; @@ -72,6 +82,41 @@ namespace OpenSim.Region.Framework.Scenes get { return m_data; } } + public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) + { + MemoryStream ms = new MemoryStream(data); + + BinaryFormatter fmt = new BinaryFormatter(); + + KeyframeMotion 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; + + 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++) + { + Keyframe k = m_frames[i]; + k.Position += offset; + m_frames[i] = k; + } + + if (m_running) + Start(); + } + public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) { m_mode = mode; @@ -95,10 +140,14 @@ namespace OpenSim.Region.Framework.Scenes { if (m_keyframes.Length > 0) m_timer.Start(); + m_running = true; } public void Stop() { + // Failed object creation + if (m_timer == null) + return; m_timer.Stop(); m_basePosition = m_group.AbsolutePosition; @@ -109,6 +158,7 @@ namespace OpenSim.Region.Framework.Scenes m_group.SendGroupRootTerseUpdate(); m_frames.Clear(); + m_running = false; } public void Pause() @@ -118,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes m_group.SendGroupRootTerseUpdate(); m_timer.Stop(); + m_running = false; } private void GetNextList() @@ -211,7 +262,7 @@ namespace OpenSim.Region.Framework.Scenes } } - private void OnTimer(object sender, ElapsedEventArgs e) + protected void OnTimer(object sender, ElapsedEventArgs e) { if (m_frames.Count == 0) { @@ -311,5 +362,19 @@ namespace OpenSim.Region.Framework.Scenes m_currentFrame = m_frames[0]; } } + + public Byte[] Serialize() + { + MemoryStream ms = new MemoryStream(); + m_timer.Stop(); + + BinaryFormatter fmt = new BinaryFormatter(); + SceneObjectGroup tmp = m_group; + m_group = null; + m_serializedPosition = tmp.AbsolutePosition; + fmt.Serialize(ms, this); + m_group = tmp; + return ms.ToArray(); + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fcbed9f963..c20da4beaf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2421,6 +2421,8 @@ namespace OpenSim.Region.Framework.Scenes if (newPosition != Vector3.Zero) newObject.RootPart.GroupPosition = newPosition; + if (newObject.KeyframeMotion != null) + newObject.KeyframeMotion.UpdateSceneObject(newObject); if (!AddSceneObject(newObject)) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9898681ec2..d4881890e9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1823,6 +1823,11 @@ namespace OpenSim.Region.Framework.Scenes // Name, UUID, m_scene.RegionInfo.RegionName); SceneObjectGroup backup_group = Copy(false); + if (KeyframeMotion != null) + { + backup_group.KeyframeMotion = KeyframeMotion.FromData(backup_group, KeyframeMotion.Serialize()); + KeyframeMotion.UpdateSceneObject(this); + } backup_group.RootPart.Velocity = RootPart.Velocity; backup_group.RootPart.Acceleration = RootPart.Acceleration; backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index ed761da0be..a9f3e843d7 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -244,6 +244,17 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sr.Close(); } + XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion"); + if (keymotion.Count > 0) + { + m_log.DebugFormat("[SERIALIZER]: Deserialized KeyframeMotion"); + sceneObject.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText)); + } + else + { + sceneObject.KeyframeMotion = null; + } + // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(doc); @@ -597,7 +608,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization obj.sopVehicle = _vehicle; } - private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) { List errorNodeNames; @@ -1168,6 +1178,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization }); writer.WriteEndElement(); + + if (sog.KeyframeMotion != null) + { + Byte[] data = sog.KeyframeMotion.Serialize(); + + writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); + writer.WriteBase64(data, 0, data.Length); + writer.WriteEndElement(); + } + writer.WriteEndElement(); }