From db3f0a37485bfecc831104d9dbcd397404364e79 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 16 Aug 2012 15:26:16 +0100 Subject: [PATCH 01/16] fix vs2010 build --- .../Authentication/LocalAuthenticationServiceConnector.cs | 1 + .../AuthenticationService/PasswordAuthenticationService.cs | 1 - .../AuthenticationService/WebkeyAuthenticationService.cs | 1 - .../WebkeyOrPasswordAuthenticationService.cs | 5 ++++- .../SimianGrid/SimianAuthenticationServiceConnector.cs | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs index 25ee4c6fed..d809ac23df 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs @@ -140,6 +140,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID) { // Not implemented at the regions + realID = UUID.Zero; return string.Empty; } diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs index 9d12d477ec..a069838ee7 100644 --- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs @@ -65,7 +65,6 @@ namespace OpenSim.Services.AuthenticationService public string Authenticate(UUID principalID, string password, int lifetime) { UUID realID; - return Authenticate(principalID, password, lifetime, out realID); } diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs index 47b4fa6ad0..1510168750 100644 --- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs @@ -63,7 +63,6 @@ namespace OpenSim.Services.AuthenticationService public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID) { realID = UUID.Zero; - return Authenticate(principalID, password, lifetime); } diff --git a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs index 7fbf36dc3d..bbc847006f 100644 --- a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs @@ -64,6 +64,7 @@ namespace OpenSim.Services.AuthenticationService { AuthenticationData data = m_Database.Get(principalID); string result = String.Empty; + realID = UUID.Zero; if (data != null && data.Data != null) { if (data.Data.ContainsKey("webLoginKey")) @@ -85,7 +86,7 @@ namespace OpenSim.Services.AuthenticationService } } - realID = UUID.Zero; + if (result == string.Empty) { @@ -96,6 +97,8 @@ namespace OpenSim.Services.AuthenticationService { m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); } + + return result; } } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 331d485fd5..ffae0da834 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -104,6 +104,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID) { + realID = UUID.Zero; return Authenticate(principalID, password, lifetime); } From f9a318380be0ddcce3c8bbc09c13bfb0206674f1 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 16 Aug 2012 22:14:56 +0100 Subject: [PATCH 02/16] let setLinkPrimParams terminate even if there are no more parts. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d6aafaf818..1433cc9747 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7778,10 +7778,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api remaining = SetPrimParams((ScenePresence)part, rules); } - while((object)remaining != null && remaining.Length > 2) + while ((object)remaining != null && remaining.Length > 2) { linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1,-1); + rules = remaining.GetSublist(1, -1); parts.Clear(); prims = GetLinkParts(linknumber); avatars = GetLinkAvatars(linknumber); @@ -7790,6 +7790,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (ScenePresence p in avatars) parts.Add(p); + remaining = null; foreach (object part in parts) { if (part is SceneObjectPart) From 7e17f4296e91129990c15cdaaa1689922a57f9aa Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 24 Aug 2012 23:48:01 +0200 Subject: [PATCH 03/16] Fix background inventory loading (Viewer 3) so it won't lag out the sim --- .../HttpServer/PollServiceEventArgs.cs | 3 +- .../HttpServer/PollServiceRequestManager.cs | 3 +- .../Linden/Caps/WebFetchInvDescModule.cs | 160 ++++++++++++------ 3 files changed, 111 insertions(+), 55 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs index bb43cd2d62..c24a0000bc 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs @@ -51,7 +51,8 @@ namespace OpenSim.Framework.Servers.HttpServer public enum EventType : int { Normal = 0, - LslHttp = 1 + LslHttp = 1, + Inventory = 2 } public PollServiceEventArgs( diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index a385110b53..a1dee4e591 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -231,7 +231,8 @@ namespace OpenSim.Framework.Servers.HttpServer { if (m_running) { - if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LslHttp) + if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LslHttp || + req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Inventory) { m_requests.Enqueue(req); } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 2359bd6683..61387ed696 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -27,12 +27,15 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Reflection; +using System.Threading; using log4net; using Nini.Config; using Mono.Addins; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -48,67 +51,49 @@ namespace OpenSim.Region.ClientStack.Linden [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class WebFetchInvDescModule : INonSharedRegionModule { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; private IInventoryService m_InventoryService; private ILibraryService m_LibraryService; - private bool m_Enabled; - - private string m_fetchInventoryDescendents2Url; - private string m_webFetchInventoryDescendentsUrl; - private WebFetchInvDescHandler m_webFetchHandler; + private ManualResetEvent m_ev = new ManualResetEvent(true); + private object m_lock = new object(); + + private Dictionary m_capsDict = new Dictionary(); + private Dictionary m_requests = new Dictionary(); + #region ISharedRegionModule Members public void Initialise(IConfigSource source) { - IConfig config = source.Configs["ClientStack.LindenCaps"]; - if (config == null) - return; - - m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); - m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); - - if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) - { - m_Enabled = true; - } } public void AddRegion(Scene s) { - if (!m_Enabled) - return; - m_scene = s; } public void RemoveRegion(Scene s) { - if (!m_Enabled) - return; - m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; m_scene = null; } public void RegionLoaded(Scene s) { - if (!m_Enabled) - return; - m_InventoryService = m_scene.InventoryService; m_LibraryService = m_scene.LibraryService; // We'll reuse the same handler for all requests. - if (m_fetchInventoryDescendents2Url == "localhost" || m_webFetchInventoryDescendentsUrl == "localhost") - m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); + m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); m_scene.EventManager.OnRegisterCaps += RegisterCaps; + m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; } public void PostInitialise() @@ -128,41 +113,110 @@ namespace OpenSim.Region.ClientStack.Linden private void RegisterCaps(UUID agentID, Caps caps) { - if (m_webFetchInventoryDescendentsUrl != "") - RegisterFetchCap(agentID, caps, "WebFetchInventoryDescendents", m_webFetchInventoryDescendentsUrl); + string capUrl = "/CAPS/" + UUID.Random() + "/"; - if (m_fetchInventoryDescendents2Url != "") - RegisterFetchCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url); + // Register this as a poll service + PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, agentID, 300000); + args.Type = PollServiceEventArgs.EventType.Inventory; + MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + + string hostName = m_scene.RegionInfo.ExternalHostName; + uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; + string protocol = "http"; + + if (MainServer.Instance.UseSSL) + { + hostName = MainServer.Instance.SSLCommonName; + port = MainServer.Instance.SSLPort; + protocol = "https"; + } + caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); + + m_capsDict[agentID] = capUrl; } - private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) + private void DeregisterCaps(UUID agentID, Caps caps) { string capUrl; - if (url == "localhost") + if (m_capsDict.TryGetValue(agentID, out capUrl)) { - capUrl = "/CAPS/" + UUID.Random(); - - IRequestHandler reqHandler - = new RestStreamHandler( - "POST", - capUrl, - m_webFetchHandler.FetchInventoryDescendentsRequest, - "FetchInventoryDescendents2", - agentID.ToString()); - - caps.RegisterHandler(capName, reqHandler); + MainServer.Instance.RemoveHTTPHandler("", capUrl); + m_capsDict.Remove(agentID); } - else - { - capUrl = url; + } - caps.RegisterHandler(capName, capUrl); + public void HttpRequestHandler(UUID requestID, Hashtable request) + { + m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); + m_requests[requestID] = request; + } + + private bool HasEvents(UUID requestID, UUID sessionID) + { + lock (m_lock) + { + if (m_ev.WaitOne(0)) + { + m_ev.Reset(); + return true; + } + return false; + } + } + + private Hashtable NoEvents(UUID requestID, UUID sessionID) + { + m_requests.Remove(requestID); + + Hashtable response = new Hashtable(); + + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + return response; + } + + private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) + { + Hashtable response = new Hashtable(); + + response["int_response_code"] = 500; + response["str_response_string"] = "Internal error"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + try + { + Hashtable requestHash; + if (!m_requests.TryGetValue(requestID, out requestHash)) + { + lock (m_lock) + m_ev.Set(); + response["str_response_string"] = "Invalid request"; + return response; + } + + m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID); + + string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null); + + m_requests.Remove(requestID); + + response["int_response_code"] = 200; + response["str_response_string"] = reply; + } + finally + { + lock (m_lock) + m_ev.Set(); } -// m_log.DebugFormat( -// "[WEB FETCH INV DESC MODULE]: Registered capability {0} at {1} in region {2} for {3}", -// capName, capUrl, m_scene.RegionInfo.RegionName, agentID); + return response; } } -} \ No newline at end of file +} From 6d48dbf8caaf862d096bf5a7d39fb1a28afe46b7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 24 Aug 2012 23:49:31 +0200 Subject: [PATCH 04/16] Remove debug spam --- .../Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 61387ed696..b77ead325e 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.ClientStack.Linden public void HttpRequestHandler(UUID requestID, Hashtable request) { - m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); +// m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); m_requests[requestID] = request; } @@ -201,7 +201,7 @@ namespace OpenSim.Region.ClientStack.Linden return response; } - m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID); +// m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID); string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null); From bfa22e2f52780d532db9b8a59f9751390d072c2c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Aug 2012 23:49:37 +0200 Subject: [PATCH 05/16] Make llCollisionSprite not throw anymore --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d8ef772246..5830eff22f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -12818,7 +12818,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llCollisionSprite(string impact_sprite) { m_host.AddScriptLPS(1); - NotImplemented("llCollisionSprite"); + // Viewer 2.0 broke this and it's likely LL has no intention + // of fixing it. Therefore, letting this be a NOP seems appropriate. } public void llGodLikeRezObject(string inventory, LSL_Vector pos) From b1d0fab954545e1ed9aa13c0c760b3371042c437 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 26 Aug 2012 20:33:45 +0100 Subject: [PATCH 06/16] fix incoerence btw KFM_TRANSLATION and ROTATION LSL constants and internal DataFormat enum, using values from the KFM constants --- OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index b7b0d27388..6ee09b712a 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] From ef6e007a4c7301dbd7a1a0392a07664e7034201b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 28 Aug 2012 03:21:03 +0100 Subject: [PATCH 07/16] [possible still very broken] mess around keyframes. timer events threads overlaps, some null objects exceptions, region crossing... --- OpenSim/Data/MySQL/MySQLSimulationData.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 12 +- .../Region/Framework/Scenes/KeyframeMotion.cs | 384 +++++++++++++----- OpenSim/Region/Framework/Scenes/Scene.cs | 6 + .../Framework/Scenes/SceneObjectGroup.cs | 29 +- .../Framework/Scenes/SceneObjectPart.cs | 5 +- .../Serialization/SceneObjectSerializer.cs | 2 +- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- 8 files changed, 319 insertions(+), 123 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 4d7c0c937c..3b90c854c9 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -1698,7 +1698,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); if (prim.KeyframeMotion != null) - cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize()); + cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize(true)); else cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]); 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 6ee09b712a..4e6425fea1 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -58,12 +58,31 @@ namespace OpenSim.Region.Framework.Scenes 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_skipOnTimer; + + // retry position for cross fail + [NonSerialized()] + private Vector3 m_nextPosition; [NonSerialized()] private SceneObjectGroup m_group; @@ -88,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes { set { - if (value) + if (!value) { // Once we're let go, recompute positions if (m_selected) @@ -100,7 +119,8 @@ namespace OpenSim.Region.Framework.Scenes if (!m_selected) m_serializedPosition = m_group.AbsolutePosition; } - m_selected = value; } + m_selected = value; + } } public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) @@ -111,31 +131,65 @@ namespace OpenSim.Region.Framework.Scenes KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms); +/* + * create timer in start() + * this was creating unneeded timers + // 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_skipOnTimer = false; + newMotion.m_inOnTimer = false; 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_skipOnTimer = true; + if (m_timer != null) + m_timer.Stop(); - 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; + } +*/ + 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 +197,16 @@ namespace OpenSim.Region.Framework.Scenes m_mode = mode; m_data = data; + m_onTimerLock = new object(); + m_group = grp; m_basePosition = grp.AbsolutePosition; m_baseRotation = grp.GroupRotation; - +/* m_timer.Interval = (int)timerInterval; m_timer.AutoReset = true; m_timer.Elapsed += OnTimer; + */ } public void SetKeyframes(Keyframe[] frames) @@ -157,19 +214,63 @@ namespace OpenSim.Region.Framework.Scenes m_keyframes = frames; } + public void Delete() + { + m_skipOnTimer = true; + m_frames.Clear(); + m_keyframes = null; + m_running = false; + + if (m_timer == null) + return; + + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; + } + public void Start() { if (m_keyframes.Length > 0) + { + if (m_timer == null) + { + m_timer = new Timer(); + m_timer.Interval = (int)timerInterval; + m_timer.AutoReset = true; + m_timer.Elapsed += OnTimer; + } + + m_skipOnTimer = false; + m_inOnTimer = false; + m_timer.Start(); - m_running = true; + m_running = true; + } + else + { + m_running = false; + m_skipOnTimer = true; + if (m_timer != null) + { + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; + } + } } public void Stop() { + m_skipOnTimer = true; + // Failed object creation if (m_timer == null) return; + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; m_basePosition = m_group.AbsolutePosition; m_baseRotation = m_group.GroupRotation; @@ -184,6 +285,8 @@ namespace OpenSim.Region.Framework.Scenes public void Pause() { + m_skipOnTimer = true; + m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); m_group.SendGroupRootTerseUpdate(); @@ -284,138 +387,197 @@ namespace OpenSim.Region.Framework.Scenes protected void OnTimer(object sender, ElapsedEventArgs e) { - if (m_frames.Count == 0) + if (m_inOnTimer) { - 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.Error("[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 (steps <= 1.0) +// lock (m_onTimerLock) { - m_currentFrame.TimeMS = 0; + if (m_skipOnTimer) + return; - 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; - - bool update = false; - - if (Vector3.Mag(motionThisFrame) >= 0.05f) + m_inOnTimer = true; + 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_frames.Count == 0) { - angle = 0; + GetNextList(); + + if (m_frames.Count == 0) + { + Stop(); + m_inOnTimer = false; + 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_inOnTimer = false; + 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 (steps <= 1.0) + { + m_currentFrame.TimeMS = 0; + + // m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; + m_nextPosition = (Vector3)m_currentFrame.Position; + m_group.AbsolutePosition = m_nextPosition; + + m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); } 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; + Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; + Vector3 motionThisFrame = v / (float)steps; + v = v * 1000 / m_currentFrame.TimeMS; - if (q > 1.0f) + bool update = false; + + 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); + + 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) + { + m_group.UpdateGroupRotationR(step); + //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); + update = true; + } } + + if (update) + m_group.SendGroupRootTerseUpdate(); } - if (angle > 0.01f) + m_currentFrame.TimeMS -= (int)timerInterval; + + if (m_currentFrame.TimeMS <= 0) { - m_group.UpdateGroupRotationR(step); - //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); - update = true; + 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]; } } - - 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 + { + m_inOnTimer = false; + } } } - public Byte[] Serialize() + public Byte[] Serialize(bool StopMoveTimer) { MemoryStream ms = new MemoryStream(); - m_timer.Stop(); + if (StopMoveTimer && m_timer != null) + { + m_skipOnTimer = true; + 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(); +// lock (m_onTimerLock) + { + BinaryFormatter fmt = new BinaryFormatter(); + SceneObjectGroup tmp = m_group; + m_group = null; + if(!m_selected) + m_serializedPosition = tmp.AbsolutePosition; + fmt.Serialize(ms, this); + m_group = tmp; + return ms.ToArray(); + } + } + + public void StartCrossingCheck() + { + m_skipOnTimer = true; + if (m_timer != null) + m_timer.Stop(); + + 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. + // if it is a open border there is no serialization + // so make sure timer is actually stopped + + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + Util.FireAndForget(delegate (object x) { Thread.Sleep(60000); if (m_running) + { + m_skipOnTimer = false; m_timer.Start(); + m_group.AbsolutePosition = m_nextPosition; + } }); } } 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..65a1da2f94 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); @@ -2058,8 +2066,8 @@ namespace OpenSim.Region.Framework.Scenes { if (part.KeyframeMotion != null) { - part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); - part.KeyframeMotion.UpdateSceneObject(this); + part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize(false)); +// part.KeyframeMotion.UpdateSceneObject(this); } }); @@ -4407,6 +4415,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(true)); + // 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..1c756078e7 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(true); 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 d8ef772246..207d0621a6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -12963,7 +12963,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; From 5284e514d5e71e6f1637bff133db6de73e6ff7ef Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 28 Aug 2012 22:16:01 +0200 Subject: [PATCH 08/16] Fix a nullref while object is being created --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index eee53d75ec..da312f345f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3025,7 +3025,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; From 378a79e7cc6be3191dea41b617c05febd7ee5cbe Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 28 Aug 2012 22:17:17 +0200 Subject: [PATCH 09/16] Add a queue with two priority levels. This is a drop in replacement for the BlockingQueue from OMV, but allows two priorities. --- .../ClientStack/Linden/UDP/LLUDPServer.cs | 113 +++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 7042c9a228..f9ba14ca10 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 @@ -1519,4 +1526,106 @@ 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; + + m_s.Release(); + + 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(); + } + } + } } From 72ac0665b207f7f840b861086b3a620a9942775f Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 29 Aug 2012 00:35:06 +0100 Subject: [PATCH 10/16] [Potentially broken] keyframes changes.. since it's there, use timer for crossing retries and not still another thread, etc... --- .../Region/Framework/Scenes/KeyframeMotion.cs | 280 +++++++++++------- 1 file changed, 165 insertions(+), 115 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 4e6425fea1..5333177d79 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -53,9 +53,9 @@ 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; @@ -78,7 +78,13 @@ namespace OpenSim.Region.Framework.Scenes // skip timer events. //timer.stop doesn't assure there aren't event threads still being fired [NonSerialized()] - private bool m_skipOnTimer; + private bool m_timerStopped; + + [NonSerialized()] + private bool m_crossing; + + [NonSerialized()] + private int m_crossFailcntr; // retry position for cross fail [NonSerialized()] @@ -107,6 +113,8 @@ namespace OpenSim.Region.Framework.Scenes { set { + m_crossing = false; + m_crossFailcntr = 0; if (!value) { // Once we're let go, recompute positions @@ -117,39 +125,58 @@ 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; } } + 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(); + } + 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); -/* - * create timer in start() - * this was creating unneeded timers + newMotion.m_group = grp; - // This will be started when position is updated + if (grp != null && grp.IsSelected) + newMotion.m_selected = true; - 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; + newMotion.m_onTimerLock = new object(); + newMotion.m_timerStopped = false; + newMotion.m_inOnTimer = false; + newMotion.m_crossing = false; + newMotion.m_crossFailcntr = 0; + } + catch + { + newMotion = null; + } - if (grp != null && grp.IsSelected) - newMotion.m_selected = true; - - newMotion.m_onTimerLock = new object(); - newMotion.m_skipOnTimer = false; - newMotion.m_inOnTimer = false; return newMotion; } @@ -157,9 +184,9 @@ namespace OpenSim.Region.Framework.Scenes { // lock (m_onTimerLock) { - m_skipOnTimer = true; - if (m_timer != null) - m_timer.Stop(); + m_crossing = false; + m_crossFailcntr = 0; + StopTimer(); m_group = grp; Vector3 grppos = grp.AbsolutePosition; @@ -172,14 +199,7 @@ namespace OpenSim.Region.Framework.Scenes 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; - } -*/ + for (int i = 0; i < m_frames.Count; i++) { Keyframe k = m_frames[i]; @@ -202,11 +222,8 @@ namespace OpenSim.Region.Framework.Scenes m_group = grp; m_basePosition = grp.AbsolutePosition; m_baseRotation = grp.GroupRotation; -/* - m_timer.Interval = (int)timerInterval; - m_timer.AutoReset = true; - m_timer.Elapsed += OnTimer; - */ + m_crossing = false; + m_crossFailcntr = 0; } public void SetKeyframes(Keyframe[] frames) @@ -216,21 +233,23 @@ namespace OpenSim.Region.Framework.Scenes public void Delete() { - m_skipOnTimer = true; + m_running = false; + m_crossing = false; + m_crossFailcntr = 0; + StopTimer(); m_frames.Clear(); m_keyframes = null; - m_running = false; if (m_timer == null) return; - - m_timer.Stop(); m_timer.Elapsed -= OnTimer; m_timer = null; } public void Start() { + m_crossing = false; + m_crossFailcntr = 0; if (m_keyframes.Length > 0) { if (m_timer == null) @@ -241,19 +260,16 @@ namespace OpenSim.Region.Framework.Scenes m_timer.Elapsed += OnTimer; } - m_skipOnTimer = false; m_inOnTimer = false; - - m_timer.Start(); + StartTimer(); m_running = true; } else { m_running = false; - m_skipOnTimer = true; if (m_timer != null) { - m_timer.Stop(); + StopTimer(); m_timer.Elapsed -= OnTimer; m_timer = null; } @@ -262,13 +278,11 @@ namespace OpenSim.Region.Framework.Scenes public void Stop() { - m_skipOnTimer = true; + m_running = false; + m_crossing = false; + m_crossFailcntr = 0; - // Failed object creation - if (m_timer == null) - return; - - m_timer.Stop(); + StopTimer(); m_timer.Elapsed -= OnTimer; m_timer = null; @@ -280,19 +294,17 @@ namespace OpenSim.Region.Framework.Scenes m_group.SendGroupRootTerseUpdate(); m_frames.Clear(); - m_running = false; } public void Pause() { - m_skipOnTimer = true; + m_running = false; + m_crossFailcntr = 0; + StopTimer(); m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); m_group.SendGroupRootTerseUpdate(); - - m_timer.Stop(); - m_running = false; } private void GetNextList() @@ -325,9 +337,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) @@ -341,6 +360,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; @@ -370,6 +391,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); @@ -387,20 +409,56 @@ namespace OpenSim.Region.Framework.Scenes protected void OnTimer(object sender, ElapsedEventArgs e) { - if (m_inOnTimer) + if (m_timerStopped) // trap events still in air even after a timer.stop + return; + + if (m_inOnTimer) // don't let overruns to happen { - m_log.Error("[KeyFrame]: timer overrun"); + m_log.Warn("[KeyFrame]: timer overrun"); return; } + if (m_group == null) + return; + // lock (m_onTimerLock) { - if (m_skipOnTimer) - return; m_inOnTimer = true; + + bool update = false; + try { + if (m_selected) + { + if (m_group.RootPart.Velocity != Vector3.Zero) + { + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + } + m_inOnTimer = false; + return; + } + + if (m_crossing) + { + // 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_crossing = false; + m_group.AbsolutePosition = m_nextPosition; + if (!m_crossing) + { + StopTimer(); + m_timer.Interval = timerInterval; + StartTimer(); + } + m_inOnTimer = false; + return; + } + if (m_frames.Count == 0) { GetNextList(); @@ -413,41 +471,41 @@ namespace OpenSim.Region.Framework.Scenes } m_currentFrame = m_frames[0]; + m_currentFrame.TimeMS += (int)timerInterval; + + //force a update on a keyframe transition + update = true; } - if (m_selected) - { - if (m_group.RootPart.Velocity != Vector3.Zero) - { - m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); - } - m_inOnTimer = false; - return; - } + m_currentFrame.TimeMS -= (int)timerInterval; // 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 (steps <= 1.0) + if (steps <= 0.0) { - m_currentFrame.TimeMS = 0; + m_group.RootPart.Velocity = Vector3.Zero; + m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); - // m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; 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 complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; + Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; Vector3 motionThisFrame = v / (float)steps; v = v * 1000 / m_currentFrame.TimeMS; - bool update = false; - if (Vector3.Mag(motionThisFrame) >= 0.05f) { // m_group.AbsolutePosition += motionThisFrame; @@ -463,8 +521,8 @@ namespace OpenSim.Region.Framework.Scenes Quaternion current = m_group.GroupRotation; Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); - - float angle = 0; +/* 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; @@ -493,6 +551,12 @@ namespace OpenSim.Region.Framework.Scenes } 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); @@ -500,25 +564,22 @@ namespace OpenSim.Region.Framework.Scenes } } - 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); + if (update) m_group.SendGroupRootTerseUpdate(); - m_frames.RemoveAt(0); - if (m_frames.Count > 0) - m_currentFrame = m_frames[0]; - } } + catch ( Exception ex) + { + // still happening sometimes + // lets try to see what + m_log.Warn("[KeyFrame]: timer overrun" + ex.Message); + } + finally { + // make sure we do not let this frozen m_inOnTimer = false; } } @@ -528,10 +589,7 @@ namespace OpenSim.Region.Framework.Scenes { MemoryStream ms = new MemoryStream(); if (StopMoveTimer && m_timer != null) - { - m_skipOnTimer = true; - m_timer.Stop(); - } + StopTimer(); // lock (m_onTimerLock) { @@ -548,10 +606,9 @@ namespace OpenSim.Region.Framework.Scenes public void StartCrossingCheck() { - m_skipOnTimer = true; - if (m_timer != null) - m_timer.Stop(); - + StopTimer(); + m_crossing = true; +// to remove / retune to smoth crossings if (m_group.RootPart.Velocity != Vector3.Zero) { m_group.RootPart.Velocity = Vector3.Zero; @@ -561,24 +618,17 @@ namespace OpenSim.Region.Framework.Scenes 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. - // if it is a open border there is no serialization - // so make sure timer is actually stopped - - m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); - - Util.FireAndForget(delegate (object x) + if (m_group != null) { - Thread.Sleep(60000); - if (m_running) + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + + if (m_running && m_timer != null) { - m_skipOnTimer = false; - m_timer.Start(); - m_group.AbsolutePosition = m_nextPosition; + m_timer.Interval = 60000; + StartTimer(); } - }); + } } } } From 2e54c3cc8f4caf6b6d056ae04419b171942a17d7 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 29 Aug 2012 03:19:47 +0100 Subject: [PATCH 11/16] A few more changes to keyframes --- OpenSim/Data/MySQL/MySQLSimulationData.cs | 2 +- .../Region/Framework/Scenes/KeyframeMotion.cs | 174 ++++++++++++------ .../Framework/Scenes/SceneObjectGroup.cs | 4 +- .../Serialization/SceneObjectSerializer.cs | 2 +- 4 files changed, 117 insertions(+), 65 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 3b90c854c9..4d7c0c937c 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -1698,7 +1698,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); if (prim.KeyframeMotion != null) - cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize(true)); + cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize()); else cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]); diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 5333177d79..42e3860fde 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -81,10 +81,10 @@ namespace OpenSim.Region.Framework.Scenes private bool m_timerStopped; [NonSerialized()] - private bool m_crossing; + private bool m_isCrossing; [NonSerialized()] - private int m_crossFailcntr; + private bool m_waitingCrossing; // retry position for cross fail [NonSerialized()] @@ -112,9 +112,7 @@ namespace OpenSim.Region.Framework.Scenes public bool Selected { set - { - m_crossing = false; - m_crossFailcntr = 0; + { if (!value) { // Once we're let go, recompute positions @@ -130,6 +128,8 @@ namespace OpenSim.Region.Framework.Scenes m_serializedPosition = m_group.AbsolutePosition; } } + m_isCrossing = false; + m_waitingCrossing = false; m_selected = value; } } @@ -150,6 +150,17 @@ namespace OpenSim.Region.Framework.Scenes 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) { KeyframeMotion newMotion = null; @@ -169,8 +180,8 @@ namespace OpenSim.Region.Framework.Scenes newMotion.m_onTimerLock = new object(); newMotion.m_timerStopped = false; newMotion.m_inOnTimer = false; - newMotion.m_crossing = false; - newMotion.m_crossFailcntr = 0; + newMotion.m_isCrossing = false; + newMotion.m_waitingCrossing = false; } catch { @@ -184,8 +195,8 @@ namespace OpenSim.Region.Framework.Scenes { // lock (m_onTimerLock) { - m_crossing = false; - m_crossFailcntr = 0; + m_isCrossing = false; + m_waitingCrossing = false; StopTimer(); m_group = grp; @@ -220,10 +231,13 @@ namespace OpenSim.Region.Framework.Scenes m_onTimerLock = new object(); m_group = grp; - m_basePosition = grp.AbsolutePosition; - m_baseRotation = grp.GroupRotation; - m_crossing = false; - m_crossFailcntr = 0; + if (grp != null) + { + m_basePosition = grp.AbsolutePosition; + m_baseRotation = grp.GroupRotation; + } + m_isCrossing = false; + m_waitingCrossing = false; } public void SetKeyframes(Keyframe[] frames) @@ -231,34 +245,74 @@ 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; - m_crossing = false; - m_crossFailcntr = 0; - StopTimer(); + RemoveTimer(); + m_isCrossing = false; + m_waitingCrossing = false; m_frames.Clear(); m_keyframes = null; - - if (m_timer == null) - return; - m_timer.Elapsed -= OnTimer; - m_timer = null; } public void Start() { - m_crossing = false; - m_crossFailcntr = 0; + m_isCrossing = false; + m_waitingCrossing = false; if (m_keyframes.Length > 0) { if (m_timer == null) { m_timer = new Timer(); - m_timer.Interval = (int)timerInterval; + m_timer.Interval = timerInterval; m_timer.AutoReset = true; m_timer.Elapsed += OnTimer; } + else + { + StopTimer(); + m_timer.Interval = timerInterval; + } m_inOnTimer = false; StartTimer(); @@ -267,24 +321,17 @@ namespace OpenSim.Region.Framework.Scenes else { m_running = false; - if (m_timer != null) - { - StopTimer(); - m_timer.Elapsed -= OnTimer; - m_timer = null; - } + RemoveTimer(); } } public void Stop() { m_running = false; - m_crossing = false; - m_crossFailcntr = 0; + m_isCrossing = false; + m_waitingCrossing = false; - StopTimer(); - m_timer.Elapsed -= OnTimer; - m_timer = null; + RemoveTimer(); m_basePosition = m_group.AbsolutePosition; m_baseRotation = m_group.GroupRotation; @@ -299,8 +346,7 @@ namespace OpenSim.Region.Framework.Scenes public void Pause() { m_running = false; - m_crossFailcntr = 0; - StopTimer(); + RemoveTimer(); m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); @@ -421,7 +467,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_group == null) return; -// lock (m_onTimerLock) + lock (m_onTimerLock) { m_inOnTimer = true; @@ -441,15 +487,15 @@ namespace OpenSim.Region.Framework.Scenes return; } - if (m_crossing) + 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_crossing = false; + m_isCrossing = false; m_group.AbsolutePosition = m_nextPosition; - if (!m_crossing) + if (!m_isCrossing) { StopTimer(); m_timer.Interval = timerInterval; @@ -552,9 +598,9 @@ namespace OpenSim.Region.Framework.Scenes 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) + 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 { @@ -563,7 +609,6 @@ namespace OpenSim.Region.Framework.Scenes update = true; } } - } if (update) @@ -573,7 +618,7 @@ namespace OpenSim.Region.Framework.Scenes catch ( Exception ex) { // still happening sometimes - // lets try to see what + // lets try to see where m_log.Warn("[KeyFrame]: timer overrun" + ex.Message); } @@ -585,29 +630,34 @@ namespace OpenSim.Region.Framework.Scenes } } - public Byte[] Serialize(bool StopMoveTimer) + public Byte[] Serialize() { + StopTimer(); MemoryStream ms = new MemoryStream(); - if (StopMoveTimer && m_timer != null) - StopTimer(); -// lock (m_onTimerLock) - { - BinaryFormatter fmt = new BinaryFormatter(); - SceneObjectGroup tmp = m_group; - m_group = null; - if(!m_selected) - m_serializedPosition = tmp.AbsolutePosition; - fmt.Serialize(ms, this); - m_group = tmp; - return ms.ToArray(); - } + BinaryFormatter fmt = new BinaryFormatter(); + SceneObjectGroup tmp = m_group; + m_group = null; + 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_crossing = true; + + m_isCrossing = true; + m_waitingCrossing = true; + // to remove / retune to smoth crossings if (m_group.RootPart.Velocity != Vector3.Zero) { @@ -618,6 +668,8 @@ namespace OpenSim.Region.Framework.Scenes public void CrossingFailure() { + m_waitingCrossing = false; + if (m_group != null) { m_group.RootPart.Velocity = Vector3.Zero; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 65a1da2f94..834d27b7ac 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2066,7 +2066,7 @@ namespace OpenSim.Region.Framework.Scenes { if (part.KeyframeMotion != null) { - part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize(false)); + part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); // part.KeyframeMotion.UpdateSceneObject(this); } }); @@ -4419,7 +4419,7 @@ namespace OpenSim.Region.Framework.Scenes { if (part.KeyframeMotion != null) { - part.KeyframeMotion = KeyframeMotion.FromData(sog, part.KeyframeMotion.Serialize(true)); + part.KeyframeMotion = KeyframeMotion.FromData(sog, part.KeyframeMotion.Serialize()); // this is called later // part.KeyframeMotion.UpdateSceneObject(this); } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 1c756078e7..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(true); + Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); writer.WriteBase64(data, 0, data.Length); From 34f069493894654d23c18550182561a93ec023b0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 29 Aug 2012 11:35:21 +0200 Subject: [PATCH 12/16] Remove Justin's addition to avoid sending incoming packets to inactive clients This also causes the initial AgentUpdate to be rejected because our processing is asynchronous. --- .../ClientStack/Linden/UDP/LLUDPServer.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index f9ba14ca10..c817e44b29 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1478,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 @@ -1506,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) From 74465df43f7ee92f44ba65c19c01e02fa1f13e98 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 29 Aug 2012 11:45:28 +0200 Subject: [PATCH 13/16] Fix issue with the quit packet being stuck int he queue and a one packet delay. Also fix semaphore excetion caused by enqueueing while dequque is taking place. --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index c817e44b29..75a47d5379 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1606,10 +1606,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP else res = m_lowQueue.Dequeue(); - if (m_highQueue.Count == 0 || m_lowQueue.Count == 0) + if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) return true; - m_s.Release(); + try + { + m_s.Release(); + } + catch + { + } return true; } From 67f18655d50914857a1fffe75995155e7a6d5b8e Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 29 Aug 2012 22:06:43 +0200 Subject: [PATCH 14/16] Allow llList2Key to also act on System.String --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7dae53a280..d5e611c5e4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5475,7 +5475,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // for completion and should LSL_Key ever be implemented // as it's own struct else if (!(src.Data[index] is LSL_String || - src.Data[index] is LSL_Key)) + src.Data[index] is LSL_Key || + src.Data[index] is String)) { return ""; } From 211f4fb4114b2b26abe9c056bca9f6159ccbd125 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 30 Aug 2012 00:34:12 +0200 Subject: [PATCH 15/16] Sequence inventory descendents requests to reduce inventory server load and movement lag. --- .../ClientStack/Linden/UDP/LLUDPServer.cs | 1 + .../Framework/Scenes/Scene.PacketHandlers.cs | 60 +++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 75a47d5379..d6513c5403 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -927,6 +927,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); else packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); +// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); } #region BinaryStats diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 431b90302a..e9705435bc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -422,6 +422,20 @@ namespace OpenSim.Region.Framework.Scenes ); } + private class DescendentsRequestData + { + public IClientAPI RemoteClient; + public UUID FolderID; + public UUID OwnerID; + public bool FetchFolders; + public bool FetchItems; + public int SortOrder; + } + + private Queue m_descendentsRequestQueue = new Queue(); + private Object m_descendentsRequestLock = new Object(); + private bool m_descendentsRequestProcessing = false; + /// /// Tell the client about the various child items and folders contained in the requested folder. /// @@ -458,17 +472,38 @@ namespace OpenSim.Region.Framework.Scenes } } - // We're going to send the reply async, because there may be - // an enormous quantity of packets -- basically the entire inventory! - // We don't want to block the client thread while all that is happening. - SendInventoryDelegate d = SendInventoryAsync; - d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); + lock (m_descendentsRequestLock) + { + if (!m_descendentsRequestProcessing) + { + m_descendentsRequestProcessing = true; + + // We're going to send the reply async, because there may be + // an enormous quantity of packets -- basically the entire inventory! + // We don't want to block the client thread while all that is happening. + SendInventoryDelegate d = SendInventoryAsync; + d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); + + return; + } + + DescendentsRequestData req = new DescendentsRequestData(); + req.RemoteClient = remoteClient; + req.FolderID = folderID; + req.OwnerID = ownerID; + req.FetchFolders = fetchFolders; + req.FetchItems = fetchItems; + req.SortOrder = sortOrder; + + m_descendentsRequestQueue.Enqueue(req); + } } delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder) { + Thread.Sleep(20); SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems); } @@ -476,6 +511,21 @@ namespace OpenSim.Region.Framework.Scenes { SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; d.EndInvoke(iar); + + lock (m_descendentsRequestLock) + { + if (m_descendentsRequestQueue.Count > 0) + { + DescendentsRequestData req = m_descendentsRequestQueue.Dequeue(); + + d = SendInventoryAsync; + d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d); + + return; + } + + m_descendentsRequestProcessing = false; + } } /// From c821153a4fcc0a0d806d2c9be63cf48494e4dd06 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 30 Aug 2012 00:15:46 +0100 Subject: [PATCH 16/16] [possible still bad] make use of keyframemotion.copy on sop.copy, replacing fromdata(seralize). for now its called with null group since sop.copy() hasn't usable new group information, so for copied keyframes be fully operational UpdateSceneObject(newgroup) needs to be called on them. --- .../Region/Framework/Scenes/KeyframeMotion.cs | 58 +++++++++++-------- .../Framework/Scenes/SceneObjectGroup.cs | 12 +--- .../Framework/Scenes/SceneObjectPart.cs | 3 + 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 42e3860fde..e4e6f2c882 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -112,20 +112,23 @@ namespace OpenSim.Region.Framework.Scenes public bool Selected { set - { - if (!value) + { + if (m_group != null) { - // Once we're let go, recompute positions - if (m_selected) - UpdateSceneObject(m_group); - } - else - { - // Save selection position in case we get moved - if (!m_selected) + if (!value) { - StopTimer(); - m_serializedPosition = m_group.AbsolutePosition; + // Once we're let go, recompute positions + if (m_selected) + UpdateSceneObject(m_group); + } + else + { + // Save selection position in case we get moved + if (!m_selected) + { + StopTimer(); + m_serializedPosition = m_group.AbsolutePosition; + } } } m_isCrossing = false; @@ -199,6 +202,9 @@ namespace OpenSim.Region.Framework.Scenes m_waitingCrossing = false; StopTimer(); + if (grp == null) + return; + m_group = grp; Vector3 grppos = grp.AbsolutePosition; Vector3 offset = grppos - m_serializedPosition; @@ -228,14 +234,16 @@ namespace OpenSim.Region.Framework.Scenes m_mode = mode; m_data = data; - m_onTimerLock = new object(); - m_group = grp; if (grp != null) { m_basePosition = grp.AbsolutePosition; m_baseRotation = grp.GroupRotation; } + + m_onTimerLock = new object(); + m_timerStopped = true; + m_inOnTimer = false; m_isCrossing = false; m_waitingCrossing = false; } @@ -249,18 +257,23 @@ namespace OpenSim.Region.Framework.Scenes { StopTimer(); - KeyframeMotion newmotion = new KeyframeMotion(newgrp, m_mode, m_data); + KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data); - if (newgrp != null && newgrp.IsSelected) - newmotion.m_selected = true; + newmotion.m_group = newgrp; if (m_keyframes != null) + { + newmotion.m_keyframes = new Keyframe[m_keyframes.Length]; m_keyframes.CopyTo(newmotion.m_keyframes, 0); + } newmotion.m_frames = new List(m_frames); + + newmotion.m_basePosition = m_basePosition; + newmotion.m_baseRotation = m_baseRotation; + newmotion.m_currentFrame = m_currentFrame; - newmotion.m_nextPosition = m_nextPosition; if (m_selected) newmotion.m_serializedPosition = m_serializedPosition; else @@ -272,12 +285,7 @@ namespace OpenSim.Region.Framework.Scenes } 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; + newmotion.m_running = m_running; if (m_running && !m_waitingCrossing) StartTimer(); @@ -299,7 +307,7 @@ namespace OpenSim.Region.Framework.Scenes { m_isCrossing = false; m_waitingCrossing = false; - if (m_keyframes.Length > 0) + if (m_keyframes != null && m_group != null && m_keyframes.Length > 0) { if (m_timer == null) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 834d27b7ac..fe34ad4325 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2062,6 +2062,7 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChangedDueToDelink = false; m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); +/* backup_group.ForEachPart(delegate(SceneObjectPart part) { if (part.KeyframeMotion != null) @@ -2070,7 +2071,7 @@ namespace OpenSim.Region.Framework.Scenes // part.KeyframeMotion.UpdateSceneObject(this); } }); - +*/ datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); backup_group.ForEachPart(delegate(SceneObjectPart part) @@ -4415,15 +4416,6 @@ 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 bf5fc992a8..4788a24553 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2110,6 +2110,9 @@ namespace OpenSim.Region.Framework.Scenes Array.Copy(Shape.ExtraParams, extraP, extraP.Length); dupe.Shape.ExtraParams = extraP; + if (KeyframeMotion != null) + dupe.KeyframeMotion = KeyframeMotion.Copy(null); + if (userExposed) { if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)