aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs152
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs138
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs546
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs9
11 files changed, 742 insertions, 216 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 2359bd6..b77ead3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -27,12 +27,15 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
32using System.Threading;
31using log4net; 33using log4net;
32using Nini.Config; 34using Nini.Config;
33using Mono.Addins; 35using Mono.Addins;
34using OpenMetaverse; 36using OpenMetaverse;
35using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Servers;
36using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
@@ -48,67 +51,49 @@ namespace OpenSim.Region.ClientStack.Linden
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class WebFetchInvDescModule : INonSharedRegionModule 52 public class WebFetchInvDescModule : INonSharedRegionModule
50 { 53 {
51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 55
53 private Scene m_scene; 56 private Scene m_scene;
54 57
55 private IInventoryService m_InventoryService; 58 private IInventoryService m_InventoryService;
56 private ILibraryService m_LibraryService; 59 private ILibraryService m_LibraryService;
57 60
58 private bool m_Enabled; 61 private WebFetchInvDescHandler m_webFetchHandler;
59 62
60 private string m_fetchInventoryDescendents2Url; 63 private ManualResetEvent m_ev = new ManualResetEvent(true);
61 private string m_webFetchInventoryDescendentsUrl; 64 private object m_lock = new object();
62 65
63 private WebFetchInvDescHandler m_webFetchHandler; 66 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
67 private Dictionary<UUID, Hashtable> m_requests = new Dictionary<UUID, Hashtable>();
64 68
65 #region ISharedRegionModule Members 69 #region ISharedRegionModule Members
66 70
67 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
68 { 72 {
69 IConfig config = source.Configs["ClientStack.LindenCaps"];
70 if (config == null)
71 return;
72
73 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
74 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
75
76 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
77 {
78 m_Enabled = true;
79 }
80 } 73 }
81 74
82 public void AddRegion(Scene s) 75 public void AddRegion(Scene s)
83 { 76 {
84 if (!m_Enabled)
85 return;
86
87 m_scene = s; 77 m_scene = s;
88 } 78 }
89 79
90 public void RemoveRegion(Scene s) 80 public void RemoveRegion(Scene s)
91 { 81 {
92 if (!m_Enabled)
93 return;
94
95 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 82 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
83 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
96 m_scene = null; 84 m_scene = null;
97 } 85 }
98 86
99 public void RegionLoaded(Scene s) 87 public void RegionLoaded(Scene s)
100 { 88 {
101 if (!m_Enabled)
102 return;
103
104 m_InventoryService = m_scene.InventoryService; 89 m_InventoryService = m_scene.InventoryService;
105 m_LibraryService = m_scene.LibraryService; 90 m_LibraryService = m_scene.LibraryService;
106 91
107 // We'll reuse the same handler for all requests. 92 // We'll reuse the same handler for all requests.
108 if (m_fetchInventoryDescendents2Url == "localhost" || m_webFetchInventoryDescendentsUrl == "localhost") 93 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
109 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
110 94
111 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 95 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
96 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
112 } 97 }
113 98
114 public void PostInitialise() 99 public void PostInitialise()
@@ -128,41 +113,110 @@ namespace OpenSim.Region.ClientStack.Linden
128 113
129 private void RegisterCaps(UUID agentID, Caps caps) 114 private void RegisterCaps(UUID agentID, Caps caps)
130 { 115 {
131 if (m_webFetchInventoryDescendentsUrl != "") 116 string capUrl = "/CAPS/" + UUID.Random() + "/";
132 RegisterFetchCap(agentID, caps, "WebFetchInventoryDescendents", m_webFetchInventoryDescendentsUrl); 117
118 // Register this as a poll service
119 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, agentID, 300000);
120 args.Type = PollServiceEventArgs.EventType.Inventory;
121 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
122
123 string hostName = m_scene.RegionInfo.ExternalHostName;
124 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
125 string protocol = "http";
126
127 if (MainServer.Instance.UseSSL)
128 {
129 hostName = MainServer.Instance.SSLCommonName;
130 port = MainServer.Instance.SSLPort;
131 protocol = "https";
132 }
133 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
133 134
134 if (m_fetchInventoryDescendents2Url != "") 135 m_capsDict[agentID] = capUrl;
135 RegisterFetchCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
136 } 136 }
137 137
138 private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) 138 private void DeregisterCaps(UUID agentID, Caps caps)
139 { 139 {
140 string capUrl; 140 string capUrl;
141 141
142 if (url == "localhost") 142 if (m_capsDict.TryGetValue(agentID, out capUrl))
143 { 143 {
144 capUrl = "/CAPS/" + UUID.Random(); 144 MainServer.Instance.RemoveHTTPHandler("", capUrl);
145 m_capsDict.Remove(agentID);
146 }
147 }
145 148
146 IRequestHandler reqHandler 149 public void HttpRequestHandler(UUID requestID, Hashtable request)
147 = new RestStreamHandler( 150 {
148 "POST", 151// m_log.DebugFormat("[FETCH2]: Received request {0}", requestID);
149 capUrl, 152 m_requests[requestID] = request;
150 m_webFetchHandler.FetchInventoryDescendentsRequest, 153 }
151 "FetchInventoryDescendents2",
152 agentID.ToString());
153 154
154 caps.RegisterHandler(capName, reqHandler); 155 private bool HasEvents(UUID requestID, UUID sessionID)
156 {
157 lock (m_lock)
158 {
159 if (m_ev.WaitOne(0))
160 {
161 m_ev.Reset();
162 return true;
163 }
164 return false;
155 } 165 }
156 else 166 }
167
168 private Hashtable NoEvents(UUID requestID, UUID sessionID)
169 {
170 m_requests.Remove(requestID);
171
172 Hashtable response = new Hashtable();
173
174 response["int_response_code"] = 500;
175 response["str_response_string"] = "Script timeout";
176 response["content_type"] = "text/plain";
177 response["keepalive"] = false;
178 response["reusecontext"] = false;
179
180 return response;
181 }
182
183 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
184 {
185 Hashtable response = new Hashtable();
186
187 response["int_response_code"] = 500;
188 response["str_response_string"] = "Internal error";
189 response["content_type"] = "text/plain";
190 response["keepalive"] = false;
191 response["reusecontext"] = false;
192
193 try
157 { 194 {
158 capUrl = url; 195 Hashtable requestHash;
196 if (!m_requests.TryGetValue(requestID, out requestHash))
197 {
198 lock (m_lock)
199 m_ev.Set();
200 response["str_response_string"] = "Invalid request";
201 return response;
202 }
203
204// m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID);
159 205
160 caps.RegisterHandler(capName, capUrl); 206 string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null);
207
208 m_requests.Remove(requestID);
209
210 response["int_response_code"] = 200;
211 response["str_response_string"] = reply;
212 }
213 finally
214 {
215 lock (m_lock)
216 m_ev.Set();
161 } 217 }
162 218
163// m_log.DebugFormat( 219 return response;
164// "[WEB FETCH INV DESC MODULE]: Registered capability {0} at {1} in region {2} for {3}",
165// capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
166 } 220 }
167 } 221 }
168} \ No newline at end of file 222}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index fb73e1d..60ab70e 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
110 /// <summary>Handlers for incoming packets</summary> 110 /// <summary>Handlers for incoming packets</summary>
111 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 111 //PacketEventDictionary packetEvents = new PacketEventDictionary();
112 /// <summary>Incoming packets that are awaiting handling</summary> 112 /// <summary>Incoming packets that are awaiting handling</summary>
113 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 113 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
114
115 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
116
114 /// <summary></summary> 117 /// <summary></summary>
115 //private UDPClientCollection m_clients = new UDPClientCollection(); 118 //private UDPClientCollection m_clients = new UDPClientCollection();
116 /// <summary>Bandwidth throttle for this UDP server</summary> 119 /// <summary>Bandwidth throttle for this UDP server</summary>
@@ -919,7 +922,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
919 #endregion Ping Check Handling 922 #endregion Ping Check Handling
920 923
921 // Inbox insertion 924 // Inbox insertion
922 packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); 925 if (packet.Type == PacketType.AgentUpdate ||
926 packet.Type == PacketType.ChatFromViewer)
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
928 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
923 } 931 }
924 932
925 #region BinaryStats 933 #region BinaryStats
@@ -1471,8 +1479,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1471 Packet packet = incomingPacket.Packet; 1479 Packet packet = incomingPacket.Packet;
1472 LLClientView client = incomingPacket.Client; 1480 LLClientView client = incomingPacket.Client;
1473 1481
1474 if (client.IsActive) 1482// if (client.IsActive)
1475 { 1483// {
1476 m_currentIncomingClient = client; 1484 m_currentIncomingClient = client;
1477 1485
1478 try 1486 try
@@ -1499,13 +1507,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1499 { 1507 {
1500 m_currentIncomingClient = null; 1508 m_currentIncomingClient = null;
1501 } 1509 }
1502 } 1510// }
1503 else 1511// else
1504 { 1512// {
1505 m_log.DebugFormat( 1513// m_log.DebugFormat(
1506 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1514// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1507 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1515// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1508 } 1516// }
1509 } 1517 }
1510 1518
1511 protected void LogoutHandler(IClientAPI client) 1519 protected void LogoutHandler(IClientAPI client)
@@ -1519,4 +1527,112 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1519 } 1527 }
1520 } 1528 }
1521 } 1529 }
1530
1531 internal class DoubleQueue<T> where T:class
1532 {
1533 private Queue<T> m_lowQueue = new Queue<T>();
1534 private Queue<T> m_highQueue = new Queue<T>();
1535
1536 private object m_syncRoot = new object();
1537 private Semaphore m_s = new Semaphore(0, 1);
1538
1539 public DoubleQueue()
1540 {
1541 }
1542
1543 public virtual int Count
1544 {
1545 get { return m_highQueue.Count + m_lowQueue.Count; }
1546 }
1547
1548 public virtual void Enqueue(T data)
1549 {
1550 Enqueue(m_lowQueue, data);
1551 }
1552
1553 public virtual void EnqueueLow(T data)
1554 {
1555 Enqueue(m_lowQueue, data);
1556 }
1557
1558 public virtual void EnqueueHigh(T data)
1559 {
1560 Enqueue(m_highQueue, data);
1561 }
1562
1563 private void Enqueue(Queue<T> q, T data)
1564 {
1565 lock (m_syncRoot)
1566 {
1567 m_lowQueue.Enqueue(data);
1568 m_s.WaitOne(0);
1569 m_s.Release();
1570 }
1571 }
1572
1573 public virtual T Dequeue()
1574 {
1575 return Dequeue(Timeout.Infinite);
1576 }
1577
1578 public virtual T Dequeue(int tmo)
1579 {
1580 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1581 }
1582
1583 public virtual T Dequeue(TimeSpan wait)
1584 {
1585 T res = null;
1586
1587 if (!Dequeue(wait, ref res))
1588 return null;
1589
1590 return res;
1591 }
1592
1593 public bool Dequeue(int timeout, ref T res)
1594 {
1595 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1596 }
1597
1598 public bool Dequeue(TimeSpan wait, ref T res)
1599 {
1600 if (!m_s.WaitOne(wait))
1601 return false;
1602
1603 lock (m_syncRoot)
1604 {
1605 if (m_highQueue.Count > 0)
1606 res = m_highQueue.Dequeue();
1607 else
1608 res = m_lowQueue.Dequeue();
1609
1610 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1611 return true;
1612
1613 try
1614 {
1615 m_s.Release();
1616 }
1617 catch
1618 {
1619 }
1620
1621 return true;
1622 }
1623 }
1624
1625 public virtual void Clear()
1626 {
1627
1628 lock (m_syncRoot)
1629 {
1630 // Make sure sem count is 0
1631 m_s.WaitOne(0);
1632
1633 m_lowQueue.Clear();
1634 m_highQueue.Clear();
1635 }
1636 }
1637 }
1522} 1638}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index c248f95..538dd5f 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
1855 if (grp.RootPart.PhysActor != null) 1855 if (grp.RootPart.PhysActor != null)
1856 grp.RootPart.PhysActor.CrossingFailure(); 1856 grp.RootPart.PhysActor.CrossingFailure();
1857 1857
1858 if (grp.RootPart.KeyframeMotion != null)
1859 grp.RootPart.KeyframeMotion.CrossingFailure();
1860
1858 grp.ScheduleGroupForFullUpdate(); 1861 grp.ScheduleGroupForFullUpdate();
1859 } 1862 }
1860 1863
@@ -1910,8 +1913,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1910 grp, e); 1913 grp, e);
1911 } 1914 }
1912 } 1915 }
1916/*
1917 * done on caller ( not in attachments crossing for now)
1913 else 1918 else
1914 { 1919 {
1920
1915 if (!grp.IsDeleted) 1921 if (!grp.IsDeleted)
1916 { 1922 {
1917 PhysicsActor pa = grp.RootPart.PhysActor; 1923 PhysicsActor pa = grp.RootPart.PhysActor;
@@ -1920,15 +1926,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1920 pa.CrossingFailure(); 1926 pa.CrossingFailure();
1921 if (grp.RootPart.KeyframeMotion != null) 1927 if (grp.RootPart.KeyframeMotion != null)
1922 { 1928 {
1923 grp.RootPart.Velocity = Vector3.Zero; 1929 // moved to KeyframeMotion.CrossingFailure
1930// grp.RootPart.Velocity = Vector3.Zero;
1924 grp.RootPart.KeyframeMotion.CrossingFailure(); 1931 grp.RootPart.KeyframeMotion.CrossingFailure();
1925 grp.SendGroupRootTerseUpdate(); 1932// grp.SendGroupRootTerseUpdate();
1926 } 1933 }
1927 } 1934 }
1928 } 1935 }
1929 1936
1930 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp); 1937 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
1931 } 1938 }
1939 */
1932 } 1940 }
1933 else 1941 else
1934 { 1942 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index 25ee4c6..d809ac2 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
140 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID) 140 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
141 { 141 {
142 // Not implemented at the regions 142 // Not implemented at the regions
143 realID = UUID.Zero;
143 return string.Empty; 144 return string.Empty;
144 } 145 }
145 146
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index b7b0d27..e4e6f2c 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -38,8 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
38 [Flags] 38 [Flags]
39 public enum DataFormat : int 39 public enum DataFormat : int
40 { 40 {
41 Translation = 1, 41 Translation = 2,
42 Rotation = 2 42 Rotation = 1
43 } 43 }
44 44
45 [Serializable] 45 [Serializable]
@@ -53,17 +53,42 @@ namespace OpenSim.Region.Framework.Scenes
53 public Vector3 AngularVelocity; 53 public Vector3 AngularVelocity;
54 }; 54 };
55 55
56 private Vector3 m_serializedPosition;
56 private Vector3 m_basePosition; 57 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation; 58 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59 59
60 private Keyframe m_currentFrame; 60 private Keyframe m_currentFrame;
61
61 private List<Keyframe> m_frames = new List<Keyframe>(); 62 private List<Keyframe> m_frames = new List<Keyframe>();
62 63
63 private Keyframe[] m_keyframes; 64 private Keyframe[] m_keyframes;
64 65
65 [NonSerialized()] 66 [NonSerialized()]
66 protected Timer m_timer = new Timer(); 67 protected Timer m_timer = null;
68
69 // timer lock
70 [NonSerialized()]
71 private object m_onTimerLock;
72
73 // timer overrun detect
74 // prevents overlap or timer events threads frozen on the lock
75 [NonSerialized()]
76 private bool m_inOnTimer;
77
78 // skip timer events.
79 //timer.stop doesn't assure there aren't event threads still being fired
80 [NonSerialized()]
81 private bool m_timerStopped;
82
83 [NonSerialized()]
84 private bool m_isCrossing;
85
86 [NonSerialized()]
87 private bool m_waitingCrossing;
88
89 // retry position for cross fail
90 [NonSerialized()]
91 private Vector3 m_nextPosition;
67 92
68 [NonSerialized()] 93 [NonSerialized()]
69 private SceneObjectGroup m_group; 94 private SceneObjectGroup m_group;
@@ -88,54 +113,120 @@ namespace OpenSim.Region.Framework.Scenes
88 { 113 {
89 set 114 set
90 { 115 {
91 if (value) 116 if (m_group != null)
92 { 117 {
93 // Once we're let go, recompute positions 118 if (!value)
94 if (m_selected) 119 {
95 UpdateSceneObject(m_group); 120 // Once we're let go, recompute positions
96 } 121 if (m_selected)
97 else 122 UpdateSceneObject(m_group);
98 { 123 }
99 // Save selection position in case we get moved 124 else
100 if (!m_selected) 125 {
101 m_serializedPosition = m_group.AbsolutePosition; 126 // Save selection position in case we get moved
127 if (!m_selected)
128 {
129 StopTimer();
130 m_serializedPosition = m_group.AbsolutePosition;
131 }
132 }
102 } 133 }
103 m_selected = value; } 134 m_isCrossing = false;
135 m_waitingCrossing = false;
136 m_selected = value;
137 }
104 } 138 }
105 139
140 private void StartTimer()
141 {
142 if (m_timer == null)
143 return;
144 m_timerStopped = false;
145 m_timer.Start();
146 }
147
148 private void StopTimer()
149 {
150 if (m_timer == null || m_timerStopped)
151 return;
152 m_timerStopped = true;
153 m_timer.Stop();
154 }
155
156 private void RemoveTimer()
157 {
158 if (m_timer == null)
159 return;
160 m_timerStopped = true;
161 m_timer.Stop();
162 m_timer.Elapsed -= OnTimer;
163 m_timer = null;
164 }
165
166
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 167 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 { 168 {
108 MemoryStream ms = new MemoryStream(data); 169 KeyframeMotion newMotion = null;
109 170
110 BinaryFormatter fmt = new BinaryFormatter(); 171 try
172 {
173 MemoryStream ms = new MemoryStream(data);
174 BinaryFormatter fmt = new BinaryFormatter();
175
176 newMotion = (KeyframeMotion)fmt.Deserialize(ms);
177
178 newMotion.m_group = grp;
111 179
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms); 180 if (grp != null && grp.IsSelected)
181 newMotion.m_selected = true;
113 182
114 // This will be started when position is updated 183 newMotion.m_onTimerLock = new object();
115 newMotion.m_timer = new Timer(); 184 newMotion.m_timerStopped = false;
116 newMotion.m_timer.Interval = (int)timerInterval; 185 newMotion.m_inOnTimer = false;
117 newMotion.m_timer.AutoReset = true; 186 newMotion.m_isCrossing = false;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer; 187 newMotion.m_waitingCrossing = false;
188 }
189 catch
190 {
191 newMotion = null;
192 }
119 193
120 return newMotion; 194 return newMotion;
121 } 195 }
122 196
123 public void UpdateSceneObject(SceneObjectGroup grp) 197 public void UpdateSceneObject(SceneObjectGroup grp)
124 { 198 {
125 m_group = grp; 199// lock (m_onTimerLock)
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 { 200 {
132 Keyframe k = m_frames[i]; 201 m_isCrossing = false;
133 k.Position += offset; 202 m_waitingCrossing = false;
134 m_frames[i] = k; 203 StopTimer();
135 } 204
205 if (grp == null)
206 return;
207
208 m_group = grp;
209 Vector3 grppos = grp.AbsolutePosition;
210 Vector3 offset = grppos - m_serializedPosition;
211 // avoid doing it more than once
212 // current this will happen draging a prim to other region
213 m_serializedPosition = grppos;
214
215 m_basePosition += offset;
216 m_currentFrame.Position += offset;
136 217
137 if (m_running) 218 m_nextPosition += offset;
138 Start(); 219
220 for (int i = 0; i < m_frames.Count; i++)
221 {
222 Keyframe k = m_frames[i];
223 k.Position += offset;
224 m_frames[i]=k;
225 }
226
227 if (m_running)
228 Start();
229 }
139 } 230 }
140 231
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) 232 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@@ -144,12 +235,17 @@ namespace OpenSim.Region.Framework.Scenes
144 m_data = data; 235 m_data = data;
145 236
146 m_group = grp; 237 m_group = grp;
147 m_basePosition = grp.AbsolutePosition; 238 if (grp != null)
148 m_baseRotation = grp.GroupRotation; 239 {
240 m_basePosition = grp.AbsolutePosition;
241 m_baseRotation = grp.GroupRotation;
242 }
149 243
150 m_timer.Interval = (int)timerInterval; 244 m_onTimerLock = new object();
151 m_timer.AutoReset = true; 245 m_timerStopped = true;
152 m_timer.Elapsed += OnTimer; 246 m_inOnTimer = false;
247 m_isCrossing = false;
248 m_waitingCrossing = false;
153 } 249 }
154 250
155 public void SetKeyframes(Keyframe[] frames) 251 public void SetKeyframes(Keyframe[] frames)
@@ -157,19 +253,93 @@ namespace OpenSim.Region.Framework.Scenes
157 m_keyframes = frames; 253 m_keyframes = frames;
158 } 254 }
159 255
256 public KeyframeMotion Copy(SceneObjectGroup newgrp)
257 {
258 StopTimer();
259
260 KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data);
261
262 newmotion.m_group = newgrp;
263
264 if (m_keyframes != null)
265 {
266 newmotion.m_keyframes = new Keyframe[m_keyframes.Length];
267 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
268 }
269
270 newmotion.m_frames = new List<Keyframe>(m_frames);
271
272 newmotion.m_basePosition = m_basePosition;
273 newmotion.m_baseRotation = m_baseRotation;
274
275 newmotion.m_currentFrame = m_currentFrame;
276
277 if (m_selected)
278 newmotion.m_serializedPosition = m_serializedPosition;
279 else
280 {
281 if (m_group != null)
282 newmotion.m_serializedPosition = m_group.AbsolutePosition;
283 else
284 newmotion.m_serializedPosition = m_serializedPosition;
285 }
286
287 newmotion.m_iterations = m_iterations;
288 newmotion.m_running = m_running;
289
290 if (m_running && !m_waitingCrossing)
291 StartTimer();
292
293 return newmotion;
294 }
295
296 public void Delete()
297 {
298 m_running = false;
299 RemoveTimer();
300 m_isCrossing = false;
301 m_waitingCrossing = false;
302 m_frames.Clear();
303 m_keyframes = null;
304 }
305
160 public void Start() 306 public void Start()
161 { 307 {
162 if (m_keyframes.Length > 0) 308 m_isCrossing = false;
163 m_timer.Start(); 309 m_waitingCrossing = false;
164 m_running = true; 310 if (m_keyframes != null && m_group != null && m_keyframes.Length > 0)
311 {
312 if (m_timer == null)
313 {
314 m_timer = new Timer();
315 m_timer.Interval = timerInterval;
316 m_timer.AutoReset = true;
317 m_timer.Elapsed += OnTimer;
318 }
319 else
320 {
321 StopTimer();
322 m_timer.Interval = timerInterval;
323 }
324
325 m_inOnTimer = false;
326 StartTimer();
327 m_running = true;
328 }
329 else
330 {
331 m_running = false;
332 RemoveTimer();
333 }
165 } 334 }
166 335
167 public void Stop() 336 public void Stop()
168 { 337 {
169 // Failed object creation 338 m_running = false;
170 if (m_timer == null) 339 m_isCrossing = false;
171 return; 340 m_waitingCrossing = false;
172 m_timer.Stop(); 341
342 RemoveTimer();
173 343
174 m_basePosition = m_group.AbsolutePosition; 344 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation; 345 m_baseRotation = m_group.GroupRotation;
@@ -179,17 +349,16 @@ namespace OpenSim.Region.Framework.Scenes
179 m_group.SendGroupRootTerseUpdate(); 349 m_group.SendGroupRootTerseUpdate();
180 350
181 m_frames.Clear(); 351 m_frames.Clear();
182 m_running = false;
183 } 352 }
184 353
185 public void Pause() 354 public void Pause()
186 { 355 {
356 m_running = false;
357 RemoveTimer();
358
187 m_group.RootPart.Velocity = Vector3.Zero; 359 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 360 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate(); 361 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 } 362 }
194 363
195 private void GetNextList() 364 private void GetNextList()
@@ -222,9 +391,16 @@ namespace OpenSim.Region.Framework.Scenes
222 Keyframe k = m_keyframes[i]; 391 Keyframe k = m_keyframes[i];
223 392
224 if (k.Position.HasValue) 393 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos; 394 {
395 k.Position = (k.Position * direction);
396// k.Velocity = (Vector3)k.Position / (k.TimeMS / 1000.0f);
397 k.Position += pos;
398 }
226 else 399 else
400 {
227 k.Position = pos; 401 k.Position = pos;
402// k.Velocity = Vector3.Zero;
403 }
228 404
229 k.StartRotation = rot; 405 k.StartRotation = rot;
230 if (k.Rotation.HasValue) 406 if (k.Rotation.HasValue)
@@ -238,6 +414,8 @@ namespace OpenSim.Region.Framework.Scenes
238 k.Rotation = rot; 414 k.Rotation = rot;
239 } 415 }
240 416
417/* ang vel not in use for now
418
241 float angle = 0; 419 float angle = 0;
242 420
243 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; 421 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 +445,7 @@ namespace OpenSim.Region.Framework.Scenes
267 } 445 }
268 446
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000)); 447 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
448 */
270 k.TimeTotal = k.TimeMS; 449 k.TimeTotal = k.TimeMS;
271 450
272 m_frames.Add(k); 451 m_frames.Add(k);
@@ -284,139 +463,232 @@ namespace OpenSim.Region.Framework.Scenes
284 463
285 protected void OnTimer(object sender, ElapsedEventArgs e) 464 protected void OnTimer(object sender, ElapsedEventArgs e)
286 { 465 {
287 if (m_frames.Count == 0) 466 if (m_timerStopped) // trap events still in air even after a timer.stop
288 { 467 return;
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299 468
300 if (m_selected) 469 if (m_inOnTimer) // don't let overruns to happen
301 { 470 {
302 if (m_group.RootPart.Velocity != Vector3.Zero) 471 m_log.Warn("[KeyFrame]: timer overrun");
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return; 472 return;
308 } 473 }
309 474
310 // Do the frame processing 475 if (m_group == null)
311 double steps = (double)m_currentFrame.TimeMS / timerInterval; 476 return;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313 477
314 if (steps <= 1.0) 478 lock (m_onTimerLock)
315 { 479 {
316 m_currentFrame.TimeMS = 0;
317 480
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; 481 m_inOnTimer = true;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326 482
327 bool update = false; 483 bool update = false;
328 484
329 if (Vector3.Mag(motionThisFrame) >= 0.05f) 485 try
330 { 486 {
331 m_group.AbsolutePosition += motionThisFrame; 487 if (m_selected)
332 m_group.RootPart.Velocity = v; 488 {
333 update = true; 489 if (m_group.RootPart.Velocity != Vector3.Zero)
334 } 490 {
491 m_group.RootPart.Velocity = Vector3.Zero;
492 m_group.SendGroupRootTerseUpdate();
493 }
494 m_inOnTimer = false;
495 return;
496 }
335 497
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) 498 if (m_isCrossing)
337 { 499 {
338 Quaternion current = m_group.GroupRotation; 500 // if crossing and timer running then cross failed
501 // wait some time then
502 // retry to set the position that evtually caused the outbound
503 // if still outside region this will call startCrossing below
504 m_isCrossing = false;
505 m_group.AbsolutePosition = m_nextPosition;
506 if (!m_isCrossing)
507 {
508 StopTimer();
509 m_timer.Interval = timerInterval;
510 StartTimer();
511 }
512 m_inOnTimer = false;
513 return;
514 }
339 515
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 516 if (m_frames.Count == 0)
517 {
518 GetNextList();
341 519
342 float angle = 0; 520 if (m_frames.Count == 0)
521 {
522 Stop();
523 m_inOnTimer = false;
524 return;
525 }
343 526
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 527 m_currentFrame = m_frames[0];
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 528 m_currentFrame.TimeMS += (int)timerInterval;
346 float aa_bb = aa * bb;
347 529
348 if (aa_bb == 0) 530 //force a update on a keyframe transition
531 update = true;
532 }
533
534 m_currentFrame.TimeMS -= (int)timerInterval;
535
536 // Do the frame processing
537 double steps = (double)m_currentFrame.TimeMS / timerInterval;
538
539 if (steps <= 0.0)
349 { 540 {
350 angle = 0; 541 m_group.RootPart.Velocity = Vector3.Zero;
542 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
543
544 m_nextPosition = (Vector3)m_currentFrame.Position;
545 m_group.AbsolutePosition = m_nextPosition;
546
547 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
548
549 m_frames.RemoveAt(0);
550 if (m_frames.Count > 0)
551 m_currentFrame = m_frames[0];
552
553 update = true;
351 } 554 }
352 else 555 else
353 { 556 {
354 float ab = current.X * step.X + 557 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359 558
360 if (q > 1.0f) 559 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
560 Vector3 motionThisFrame = v / (float)steps;
561 v = v * 1000 / m_currentFrame.TimeMS;
562
563 if (Vector3.Mag(motionThisFrame) >= 0.05f)
361 { 564 {
362 angle = 0; 565 // m_group.AbsolutePosition += motionThisFrame;
566 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
567 m_group.AbsolutePosition = m_nextPosition;
568
569 m_group.RootPart.Velocity = v;
570 update = true;
363 } 571 }
364 else 572
573 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
365 { 574 {
366 angle = (float)Math.Acos(2 * q - 1); 575 Quaternion current = m_group.GroupRotation;
576
577 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
578/* use simpler change detection
579 * float angle = 0;
580
581 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
582 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
583 float aa_bb = aa * bb;
584
585 if (aa_bb == 0)
586 {
587 angle = 0;
588 }
589 else
590 {
591 float ab = current.X * step.X +
592 current.Y * step.Y +
593 current.Z * step.Z +
594 current.W * step.W;
595 float q = (ab * ab) / aa_bb;
596
597 if (q > 1.0f)
598 {
599 angle = 0;
600 }
601 else
602 {
603 angle = (float)Math.Acos(2 * q - 1);
604 }
605 }
606
607 if (angle > 0.01f)
608 */
609 if(Math.Abs(step.X - current.X) > 0.001f
610 || Math.Abs(step.Y - current.Y) > 0.001f
611 || Math.Abs(step.Z - current.Z) > 0.001f)
612 // assuming w is a dependente var
613
614 {
615 m_group.UpdateGroupRotationR(step);
616 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
617 update = true;
618 }
367 } 619 }
368 } 620 }
369 621
370 if (angle > 0.01f) 622 if (update)
371 { 623 m_group.SendGroupRootTerseUpdate();
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383 624
384 if (m_currentFrame.TimeMS <= 0) 625 }
385 { 626 catch ( Exception ex)
386 m_group.RootPart.Velocity = Vector3.Zero; 627 {
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 628 // still happening sometimes
388 m_group.SendGroupRootTerseUpdate(); 629 // lets try to see where
630 m_log.Warn("[KeyFrame]: timer overrun" + ex.Message);
631 }
389 632
390 m_frames.RemoveAt(0); 633 finally
391 if (m_frames.Count > 0) 634 {
392 m_currentFrame = m_frames[0]; 635 // make sure we do not let this frozen
636 m_inOnTimer = false;
637 }
393 } 638 }
394 } 639 }
395 640
396 public Byte[] Serialize() 641 public Byte[] Serialize()
397 { 642 {
643 StopTimer();
398 MemoryStream ms = new MemoryStream(); 644 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400 645
401 BinaryFormatter fmt = new BinaryFormatter(); 646 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group; 647 SceneObjectGroup tmp = m_group;
403 m_group = null; 648 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition; 649 if (!m_selected && tmp != null)
650 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this); 651 fmt.Serialize(ms, this);
406 m_group = tmp; 652 m_group = tmp;
653 if (m_running && !m_waitingCrossing)
654 StartTimer();
655
407 return ms.ToArray(); 656 return ms.ToArray();
408 } 657 }
409 658
659 public void StartCrossingCheck()
660 {
661 // timer will be restart by crossingFailure
662 // or never since crossing worked and this
663 // should be deleted
664 StopTimer();
665
666 m_isCrossing = true;
667 m_waitingCrossing = true;
668
669// to remove / retune to smoth crossings
670 if (m_group.RootPart.Velocity != Vector3.Zero)
671 {
672 m_group.RootPart.Velocity = Vector3.Zero;
673 m_group.SendGroupRootTerseUpdate();
674 }
675 }
676
410 public void CrossingFailure() 677 public void CrossingFailure()
411 { 678 {
412 // The serialization has stopped the timer, so let's wait a moment 679 m_waitingCrossing = false;
413 // then retry the crossing. We'll get back here if it fails. 680
414 Util.FireAndForget(delegate (object x) 681 if (m_group != null)
415 { 682 {
416 Thread.Sleep(60000); 683 m_group.RootPart.Velocity = Vector3.Zero;
417 if (m_running) 684 m_group.SendGroupRootTerseUpdate();
418 m_timer.Start(); 685
419 }); 686 if (m_running && m_timer != null)
687 {
688 m_timer.Interval = 60000;
689 StartTimer();
690 }
691 }
420 } 692 }
421 } 693 }
422} 694}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 7e781c3..16c0d25 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
422 ); 422 );
423 } 423 }
424 424
425 private class DescendentsRequestData
426 {
427 public IClientAPI RemoteClient;
428 public UUID FolderID;
429 public UUID OwnerID;
430 public bool FetchFolders;
431 public bool FetchItems;
432 public int SortOrder;
433 }
434
435 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
436 private Object m_descendentsRequestLock = new Object();
437 private bool m_descendentsRequestProcessing = false;
438
425 /// <summary> 439 /// <summary>
426 /// Tell the client about the various child items and folders contained in the requested folder. 440 /// Tell the client about the various child items and folders contained in the requested folder.
427 /// </summary> 441 /// </summary>
@@ -458,17 +472,38 @@ namespace OpenSim.Region.Framework.Scenes
458 } 472 }
459 } 473 }
460 474
461 // We're going to send the reply async, because there may be 475 lock (m_descendentsRequestLock)
462 // an enormous quantity of packets -- basically the entire inventory! 476 {
463 // We don't want to block the client thread while all that is happening. 477 if (!m_descendentsRequestProcessing)
464 SendInventoryDelegate d = SendInventoryAsync; 478 {
465 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 479 m_descendentsRequestProcessing = true;
480
481 // We're going to send the reply async, because there may be
482 // an enormous quantity of packets -- basically the entire inventory!
483 // We don't want to block the client thread while all that is happening.
484 SendInventoryDelegate d = SendInventoryAsync;
485 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
486
487 return;
488 }
489
490 DescendentsRequestData req = new DescendentsRequestData();
491 req.RemoteClient = remoteClient;
492 req.FolderID = folderID;
493 req.OwnerID = ownerID;
494 req.FetchFolders = fetchFolders;
495 req.FetchItems = fetchItems;
496 req.SortOrder = sortOrder;
497
498 m_descendentsRequestQueue.Enqueue(req);
499 }
466 } 500 }
467 501
468 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 502 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
469 503
470 void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder) 504 void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder)
471 { 505 {
506 Thread.Sleep(20);
472 SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems); 507 SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems);
473 } 508 }
474 509
@@ -476,6 +511,21 @@ namespace OpenSim.Region.Framework.Scenes
476 { 511 {
477 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 512 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
478 d.EndInvoke(iar); 513 d.EndInvoke(iar);
514
515 lock (m_descendentsRequestLock)
516 {
517 if (m_descendentsRequestQueue.Count > 0)
518 {
519 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
520
521 d = SendInventoryAsync;
522 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
523
524 return;
525 }
526
527 m_descendentsRequestProcessing = false;
528 }
479 } 529 }
480 530
481 /// <summary> 531 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 5b529c3..8fb6c3b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2376,6 +2376,12 @@ namespace OpenSim.Region.Framework.Scenes
2376 2376
2377 foreach (SceneObjectPart part in partList) 2377 foreach (SceneObjectPart part in partList)
2378 { 2378 {
2379 if (part.KeyframeMotion != null)
2380 {
2381 part.KeyframeMotion.Delete();
2382 part.KeyframeMotion = null;
2383 }
2384
2379 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2385 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2380 { 2386 {
2381 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2387 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 fcb1571..0448c25 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -509,6 +509,9 @@ namespace OpenSim.Region.Framework.Scenes
509 Vector3 newpos = Vector3.Zero; 509 Vector3 newpos = Vector3.Zero;
510 OpenSim.Services.Interfaces.GridRegion destination = null; 510 OpenSim.Services.Interfaces.GridRegion destination = null;
511 511
512 if (m_rootPart.KeyframeMotion != null)
513 m_rootPart.KeyframeMotion.StartCrossingCheck();
514
512 bool canCross = true; 515 bool canCross = true;
513 foreach (ScenePresence av in m_linkedAvatars) 516 foreach (ScenePresence av in m_linkedAvatars)
514 { 517 {
@@ -551,7 +554,7 @@ namespace OpenSim.Region.Framework.Scenes
551 av.ParentID = 0; 554 av.ParentID = 0;
552 } 555 }
553 556
554// m_linkedAvatars.Clear(); 557 // m_linkedAvatars.Clear();
555 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 558 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
556 559
557 // Normalize 560 // Normalize
@@ -599,11 +602,16 @@ namespace OpenSim.Region.Framework.Scenes
599 avsToCross.Clear(); 602 avsToCross.Clear();
600 603
601 } 604 }
602 else if (RootPart.PhysActor != null) 605 else
603 { 606 {
604 RootPart.PhysActor.CrossingFailure(); 607 if (m_rootPart.KeyframeMotion != null)
605 } 608 m_rootPart.KeyframeMotion.CrossingFailure();
606 609
610 if (RootPart.PhysActor != null)
611 {
612 RootPart.PhysActor.CrossingFailure();
613 }
614 }
607 Vector3 oldp = AbsolutePosition; 615 Vector3 oldp = AbsolutePosition;
608 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); 616 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
609 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); 617 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
@@ -2054,15 +2062,16 @@ namespace OpenSim.Region.Framework.Scenes
2054 HasGroupChangedDueToDelink = false; 2062 HasGroupChangedDueToDelink = false;
2055 2063
2056 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2064 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2065/*
2057 backup_group.ForEachPart(delegate(SceneObjectPart part) 2066 backup_group.ForEachPart(delegate(SceneObjectPart part)
2058 { 2067 {
2059 if (part.KeyframeMotion != null) 2068 if (part.KeyframeMotion != null)
2060 { 2069 {
2061 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); 2070 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2062 part.KeyframeMotion.UpdateSceneObject(this); 2071// part.KeyframeMotion.UpdateSceneObject(this);
2063 } 2072 }
2064 }); 2073 });
2065 2074*/
2066 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2075 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
2067 2076
2068 backup_group.ForEachPart(delegate(SceneObjectPart part) 2077 backup_group.ForEachPart(delegate(SceneObjectPart part)
@@ -3025,7 +3034,8 @@ namespace OpenSim.Region.Framework.Scenes
3025 /// <param name="objectGroup"></param> 3034 /// <param name="objectGroup"></param>
3026 public virtual void DetachFromBackup() 3035 public virtual void DetachFromBackup()
3027 { 3036 {
3028 m_scene.SceneGraph.FireDetachFromBackup(this); 3037 if (m_scene != null)
3038 m_scene.SceneGraph.FireDetachFromBackup(this);
3029 if (m_isBackedUp && Scene != null) 3039 if (m_isBackedUp && Scene != null)
3030 m_scene.EventManager.OnBackup -= ProcessBackup; 3040 m_scene.EventManager.OnBackup -= ProcessBackup;
3031 3041
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4ed3413..8e419f9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -769,7 +769,7 @@ namespace OpenSim.Region.Framework.Scenes
769 { 769 {
770 m_groupPosition = value; 770 m_groupPosition = value;
771 PhysicsActor actor = PhysActor; 771 PhysicsActor actor = PhysActor;
772 if (actor != null) 772 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
773 { 773 {
774 try 774 try
775 { 775 {
@@ -2110,6 +2110,9 @@ namespace OpenSim.Region.Framework.Scenes
2110 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2110 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
2111 dupe.Shape.ExtraParams = extraP; 2111 dupe.Shape.ExtraParams = extraP;
2112 2112
2113 if (KeyframeMotion != null)
2114 dupe.KeyframeMotion = KeyframeMotion.Copy(null);
2115
2113 if (userExposed) 2116 if (userExposed)
2114 { 2117 {
2115 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) 2118 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
@@ -3407,6 +3410,9 @@ namespace OpenSim.Region.Framework.Scenes
3407 /// </summary> 3410 /// </summary>
3408 public void SendTerseUpdateToAllClients() 3411 public void SendTerseUpdateToAllClients()
3409 { 3412 {
3413 if (ParentGroup == null || ParentGroup.Scene == null)
3414 return;
3415
3410 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3416 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3411 { 3417 {
3412 SendTerseUpdateToClient(client); 3418 SendTerseUpdateToClient(client);
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 134bd9d..123c158 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
1241 1241
1242 if (sog.RootPart.KeyframeMotion != null) 1242 if (sog.RootPart.KeyframeMotion != null)
1243 { 1243 {
1244 Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); 1244 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1245 1245
1246 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); 1246 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1247 writer.WriteBase64(data, 0, data.Length); 1247 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 61e8a28..4335592 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -5442,7 +5442,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5442 // for completion and should LSL_Key ever be implemented 5442 // for completion and should LSL_Key ever be implemented
5443 // as it's own struct 5443 // as it's own struct
5444 else if (!(src.Data[index] is LSL_String || 5444 else if (!(src.Data[index] is LSL_String ||
5445 src.Data[index] is LSL_Key)) 5445 src.Data[index] is LSL_Key ||
5446 src.Data[index] is String))
5446 { 5447 {
5447 return ""; 5448 return "";
5448 } 5449 }
@@ -7750,6 +7751,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7750 foreach (ScenePresence p in avatars) 7751 foreach (ScenePresence p in avatars)
7751 parts.Add(p); 7752 parts.Add(p);
7752 7753
7754 remaining = null;
7753 foreach (object part in parts) 7755 foreach (object part in parts)
7754 { 7756 {
7755 if (part is SceneObjectPart) 7757 if (part is SceneObjectPart)
@@ -12379,7 +12381,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12379 public void llCollisionSprite(string impact_sprite) 12381 public void llCollisionSprite(string impact_sprite)
12380 { 12382 {
12381 m_host.AddScriptLPS(1); 12383 m_host.AddScriptLPS(1);
12382 NotImplemented("llCollisionSprite"); 12384 // Viewer 2.0 broke this and it's likely LL has no intention
12385 // of fixing it. Therefore, letting this be a NOP seems appropriate.
12383 } 12386 }
12384 12387
12385 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 12388 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
@@ -12524,7 +12527,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12524 if (frames.Data.Length > 0) // We are getting a new motion 12527 if (frames.Data.Length > 0) // We are getting a new motion
12525 { 12528 {
12526 if (group.RootPart.KeyframeMotion != null) 12529 if (group.RootPart.KeyframeMotion != null)
12527 group.RootPart.KeyframeMotion.Stop(); 12530 group.RootPart.KeyframeMotion.Delete();
12528 group.RootPart.KeyframeMotion = null; 12531 group.RootPart.KeyframeMotion = null;
12529 12532
12530 int idx = 0; 12533 int idx = 0;