aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDan Lake2011-11-11 17:16:52 -0800
committerDan Lake2011-11-11 17:16:52 -0800
commit5fd17491509fb4b939666cdc37951e213f054242 (patch)
tree966baad538ac254ca1e1ba6cd83cc6487bf2726d
parentdoh - correct build break (diff)
downloadopensim-SC_OLD-5fd17491509fb4b939666cdc37951e213f054242.zip
opensim-SC_OLD-5fd17491509fb4b939666cdc37951e213f054242.tar.gz
opensim-SC_OLD-5fd17491509fb4b939666cdc37951e213f054242.tar.bz2
opensim-SC_OLD-5fd17491509fb4b939666cdc37951e213f054242.tar.xz
Remove SceneViewer from ScenePresence to reduce quadruple queueing of
prim update to only triple queuing. Existing method was: 1. Schedule prim for update, adding to scene update list 2. Update on SOGs during heartbeat queues update onto each SceneViewer 3. Update on SPs during heartbeat queues update onto each IClientAPI 4. ProcessEntityUpdates queues updates into UDP send stack Now the SceneViewer has been eliminated so updates are scheduled at any time and then put onto the IClientAPI priority queues immediately during SceneGraph.UpdateObjectGroups.
-rw-r--r--OpenSim/Region/Application/OpenSim.cs18
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISceneViewer.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs251
7 files changed, 22 insertions, 427 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 0cad8a9..ee26e4f 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -1049,24 +1049,6 @@ namespace OpenSim
1049 MainConsole.Instance.Output(handlers.ToString()); 1049 MainConsole.Instance.Output(handlers.ToString());
1050 break; 1050 break;
1051 1051
1052 case "pending-objects":
1053 System.Text.StringBuilder pending = new System.Text.StringBuilder("Pending objects:\n");
1054 m_sceneManager.ForEachScene(
1055 delegate(Scene scene)
1056 {
1057 scene.ForEachScenePresence(
1058 delegate(ScenePresence sp)
1059 {
1060 pending.AppendFormat("{0}: {1} {2} pending\n",
1061 scene.RegionInfo.RegionName, sp.Name, sp.SceneViewer.GetPendingObjectsCount());
1062 }
1063 );
1064 }
1065 );
1066
1067 MainConsole.Instance.Output(pending.ToString());
1068 break;
1069
1070 case "modules": 1052 case "modules":
1071 MainConsole.Instance.Output("The currently loaded shared modules are:"); 1053 MainConsole.Instance.Output("The currently loaded shared modules are:");
1072 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) 1054 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
diff --git a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
deleted file mode 100644
index e715e70..0000000
--- a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 /// <summary>
34 /// Sends scheduled updates to it's associated ScenePresence.
35 /// </summary>
36 public interface ISceneViewer
37 {
38// void Reset();
39 void Close();
40
41 /// <summary>
42 /// Add the part to the queue of parts for which we need to send an update to the client
43 /// </summary>
44 /// <param name="part"></param>
45 void QueuePartForUpdate(SceneObjectPart part);
46
47 void SendPrimUpdates();
48 int GetPendingObjectsCount();
49 }
50} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 3b90c16..ce5b493 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2540,6 +2540,16 @@ namespace OpenSim.Region.Framework.Scenes
2540 if (vialogin) 2540 if (vialogin)
2541 EventManager.TriggerOnClientLogin(client); 2541 EventManager.TriggerOnClientLogin(client);
2542 } 2542 }
2543
2544 // Send all scene object to the new client
2545 Util.FireAndForget(delegate
2546 {
2547 Entities.ForEach(delegate(EntityBase e)
2548 {
2549 if (e != null && e is SceneObjectGroup)
2550 ((SceneObjectGroup)e).SendFullUpdateToClient(client);
2551 });
2552 });
2543 } 2553 }
2544 2554
2545 /// <summary> 2555 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 4355394..9587d5f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1760,30 +1760,6 @@ namespace OpenSim.Region.Framework.Scenes
1760 } 1760 }
1761 } 1761 }
1762 1762
1763 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1764 {
1765// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
1766
1767 RootPart.AddFullUpdateToAvatar(presence);
1768
1769 SceneObjectPart[] parts = m_parts.GetArray();
1770 for (int i = 0; i < parts.Length; i++)
1771 {
1772 SceneObjectPart part = parts[i];
1773 if (part != RootPart)
1774 part.AddFullUpdateToAvatar(presence);
1775 }
1776 }
1777
1778 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1779 {
1780// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
1781
1782 SceneObjectPart[] parts = m_parts.GetArray();
1783 for (int i = 0; i < parts.Length; i++)
1784 parts[i].AddTerseUpdateToAvatar(presence);
1785 }
1786
1787 /// <summary> 1763 /// <summary>
1788 /// Schedule a full update for this scene object 1764 /// Schedule a full update for this scene object
1789 /// </summary> 1765 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4e1383c..f693b36 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1373,25 +1373,6 @@ namespace OpenSim.Region.Framework.Scenes
1373 // m_log.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString()); 1373 // m_log.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
1374 } 1374 }
1375 1375
1376 /// <summary>
1377 /// Tell all scene presences that they should send updates for this part to their clients
1378 /// </summary>
1379 public void AddFullUpdateToAllAvatars()
1380 {
1381 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1382 {
1383 AddFullUpdateToAvatar(avatar);
1384 });
1385 }
1386
1387 /// <summary>
1388 /// Tell the scene presence that it should send updates for this part to its client
1389 /// </summary>
1390 public void AddFullUpdateToAvatar(ScenePresence presence)
1391 {
1392 presence.SceneViewer.QueuePartForUpdate(this);
1393 }
1394
1395 public void AddNewParticleSystem(Primitive.ParticleSystem pSystem) 1376 public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
1396 { 1377 {
1397 m_particleSystem = pSystem.GetBytes(); 1378 m_particleSystem = pSystem.GetBytes();
@@ -1402,20 +1383,6 @@ namespace OpenSim.Region.Framework.Scenes
1402 m_particleSystem = new byte[0]; 1383 m_particleSystem = new byte[0];
1403 } 1384 }
1404 1385
1405 /// Terse updates
1406 public void AddTerseUpdateToAllAvatars()
1407 {
1408 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1409 {
1410 AddTerseUpdateToAvatar(avatar);
1411 });
1412 }
1413
1414 public void AddTerseUpdateToAvatar(ScenePresence presence)
1415 {
1416 presence.SceneViewer.QueuePartForUpdate(this);
1417 }
1418
1419 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) 1386 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
1420 { 1387 {
1421 byte[] data = new byte[16]; 1388 byte[] data = new byte[16];
@@ -2650,8 +2617,6 @@ namespace OpenSim.Region.Framework.Scenes
2650 //ParentGroup.RootPart.m_groupPosition = newpos; 2617 //ParentGroup.RootPart.m_groupPosition = newpos;
2651 } 2618 }
2652 ScheduleTerseUpdate(); 2619 ScheduleTerseUpdate();
2653
2654 //SendTerseUpdateToAllClients();
2655 } 2620 }
2656 2621
2657 public void PreloadSound(string sound) 2622 public void PreloadSound(string sound)
@@ -2834,6 +2799,13 @@ namespace OpenSim.Region.Framework.Scenes
2834 if (ParentGroup == null) 2799 if (ParentGroup == null)
2835 return; 2800 return;
2836 2801
2802 // This was pulled from SceneViewer. Attachments always receive full updates.
2803 // I could not verify if this is a requirement but this maintains existing behavior
2804 if (ParentGroup.IsAttachment)
2805 {
2806 ScheduleFullUpdate();
2807 }
2808
2837 if (UpdateFlag == UpdateRequired.NONE) 2809 if (UpdateFlag == UpdateRequired.NONE)
2838 { 2810 {
2839 ParentGroup.HasGroupChanged = true; 2811 ParentGroup.HasGroupChanged = true;
@@ -2928,23 +2900,6 @@ namespace OpenSim.Region.Framework.Scenes
2928 } 2900 }
2929 2901
2930 /// <summary> 2902 /// <summary>
2931 /// Send a full update to all clients except the one nominated.
2932 /// </summary>
2933 /// <param name="agentID"></param>
2934 public void SendFullUpdateToAllClientsExcept(UUID agentID)
2935 {
2936 if (ParentGroup == null)
2937 return;
2938
2939 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2940 {
2941 // Ugly reference :(
2942 if (avatar.UUID != agentID)
2943 SendFullUpdate(avatar.ControllingClient, avatar.GenerateClientFlags(UUID));
2944 });
2945 }
2946
2947 /// <summary>
2948 /// Sends a full update to the client 2903 /// Sends a full update to the client
2949 /// </summary> 2904 /// </summary>
2950 /// <param name="remoteClient"></param> 2905 /// <param name="remoteClient"></param>
@@ -3020,7 +2975,8 @@ namespace OpenSim.Region.Framework.Scenes
3020 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 2975 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
3021 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2976 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3022 { 2977 {
3023 AddTerseUpdateToAllAvatars(); 2978
2979 SendTerseUpdateToAllClients();
3024 ClearUpdateSchedule(); 2980 ClearUpdateSchedule();
3025 2981
3026 // Update the "last" values 2982 // Update the "last" values
@@ -3035,7 +2991,7 @@ namespace OpenSim.Region.Framework.Scenes
3035 } 2991 }
3036 case UpdateRequired.FULL: 2992 case UpdateRequired.FULL:
3037 { 2993 {
3038 AddFullUpdateToAllAvatars(); 2994 SendFullUpdateToAllClients();
3039 break; 2995 break;
3040 } 2996 }
3041 } 2997 }
@@ -3140,9 +3096,9 @@ namespace OpenSim.Region.Framework.Scenes
3140 /// </summary> 3096 /// </summary>
3141 public void SendTerseUpdateToAllClients() 3097 public void SendTerseUpdateToAllClients()
3142 { 3098 {
3143 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3099 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3144 { 3100 {
3145 SendTerseUpdateToClient(avatar.ControllingClient); 3101 SendTerseUpdateToClient(client);
3146 }); 3102 });
3147 } 3103 }
3148 3104
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3fee642..a4cb7cf 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -135,7 +135,6 @@ namespace OpenSim.Region.Framework.Scenes
135 private Vector3 m_lastPosition; 135 private Vector3 m_lastPosition;
136 private Quaternion m_lastRotation; 136 private Quaternion m_lastRotation;
137 private Vector3 m_lastVelocity; 137 private Vector3 m_lastVelocity;
138 //private int m_lastTerseSent;
139 138
140 private Vector3? m_forceToApply; 139 private Vector3? m_forceToApply;
141 private int m_userFlags; 140 private int m_userFlags;
@@ -644,14 +643,6 @@ namespace OpenSim.Region.Framework.Scenes
644 set { m_health = value; } 643 set { m_health = value; }
645 } 644 }
646 645
647 private ISceneViewer m_sceneViewer;
648
649 public ISceneViewer SceneViewer
650 {
651 get { return m_sceneViewer; }
652 private set { m_sceneViewer = value; }
653 }
654
655 public void AdjustKnownSeeds() 646 public void AdjustKnownSeeds()
656 { 647 {
657 Dictionary<ulong, string> seeds; 648 Dictionary<ulong, string> seeds;
@@ -755,7 +746,6 @@ namespace OpenSim.Region.Framework.Scenes
755 AttachmentsSyncLock = new Object(); 746 AttachmentsSyncLock = new Object();
756 747
757 m_sendCourseLocationsMethod = SendCoarseLocationsDefault; 748 m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
758 SceneViewer = new SceneViewer(this);
759 Animator = new ScenePresenceAnimator(this); 749 Animator = new ScenePresenceAnimator(this);
760 PresenceType = type; 750 PresenceType = type;
761 DrawDistance = world.DefaultDrawDistance; 751 DrawDistance = world.DefaultDrawDistance;
@@ -866,16 +856,6 @@ namespace OpenSim.Region.Framework.Scenes
866 return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); 856 return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
867 } 857 }
868 858
869 /// <summary>
870 /// Send updates to the client about prims which have been placed on the update queue. We don't
871 /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
872 /// timestamp has already been sent.
873 /// </summary>
874 public void SendPrimUpdates()
875 {
876 SceneViewer.SendPrimUpdates();
877 }
878
879 #region Status Methods 859 #region Status Methods
880 860
881 /// <summary> 861 /// <summary>
@@ -2412,10 +2392,6 @@ namespace OpenSim.Region.Framework.Scenes
2412 const float ROTATION_TOLERANCE = 0.01f; 2392 const float ROTATION_TOLERANCE = 0.01f;
2413 const float VELOCITY_TOLERANCE = 0.001f; 2393 const float VELOCITY_TOLERANCE = 0.001f;
2414 const float POSITION_TOLERANCE = 0.05f; 2394 const float POSITION_TOLERANCE = 0.05f;
2415 //const int TIME_MS_TOLERANCE = 3000;
2416
2417 if (!sendingPrims)
2418 Util.FireAndForget(delegate { sendingPrims = true; SendPrimUpdates(); sendingPrims = false; });
2419 2395
2420 if (IsChildAgent == false) 2396 if (IsChildAgent == false)
2421 { 2397 {
@@ -2427,7 +2403,6 @@ namespace OpenSim.Region.Framework.Scenes
2427 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || 2403 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
2428 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || 2404 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
2429 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) 2405 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
2430 //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2431 { 2406 {
2432 SendTerseUpdateToAllClients(); 2407 SendTerseUpdateToAllClients();
2433 2408
@@ -2435,7 +2410,6 @@ namespace OpenSim.Region.Framework.Scenes
2435 m_lastPosition = m_pos; 2410 m_lastPosition = m_pos;
2436 m_lastRotation = Rotation; 2411 m_lastRotation = Rotation;
2437 m_lastVelocity = Velocity; 2412 m_lastVelocity = Velocity;
2438 //m_lastTerseSent = Environment.TickCount;
2439 } 2413 }
2440 2414
2441 // followed suggestion from mic bowman. reversed the two lines below. 2415 // followed suggestion from mic bowman. reversed the two lines below.
@@ -3418,8 +3392,6 @@ namespace OpenSim.Region.Framework.Scenes
3418 // unsetting the elapsed callback should be enough to allow for cleanup however. 3392 // unsetting the elapsed callback should be enough to allow for cleanup however.
3419 // m_reprioritizationTimer.Dispose(); 3393 // m_reprioritizationTimer.Dispose();
3420 3394
3421 SceneViewer.Close();
3422
3423 RemoveFromPhysicalScene(); 3395 RemoveFromPhysicalScene();
3424 Animator.Close(); 3396 Animator.Close();
3425 Animator = null; 3397 Animator = null;
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
deleted file mode 100644
index d6bb81c..0000000
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ /dev/null
@@ -1,251 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using log4net;
32using OpenSim.Framework;
33using OpenSim.Framework.Client;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes.Types;
36
37namespace OpenSim.Region.Framework.Scenes
38{
39 public class SceneViewer : ISceneViewer
40 {
41 /// <summary>
42 /// Is this scene viewer enabled?
43 /// </summary>
44 private bool IsEnabled { get; set; }
45
46 /// <summary>
47 /// The scene presence serviced by this viewer.
48 /// </summary>
49 protected ScenePresence m_presence;
50
51 /// <summary>
52 /// The queue of parts for which we need to send out updates.
53 /// </summary>
54 protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
55
56 /// <summary>
57 /// The queue of objects for which we need to send out updates.
58 /// </summary>
59 protected Queue<SceneObjectGroup> m_pendingObjects;
60
61 /// <summary>
62 /// The last update assocated with a given part update.
63 /// </summary>
64 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
65
66 public SceneViewer(ScenePresence presence)
67 {
68 m_presence = presence;
69 IsEnabled = true;
70 }
71
72 public void QueuePartForUpdate(SceneObjectPart part)
73 {
74 if (!IsEnabled)
75 return;
76
77 lock (m_partsUpdateQueue)
78 {
79 m_partsUpdateQueue.Enqueue(part);
80 }
81 }
82
83 public void SendPrimUpdates()
84 {
85 if (m_pendingObjects == null)
86 {
87 m_pendingObjects = new Queue<SceneObjectGroup>();
88
89 lock (m_pendingObjects)
90 {
91 EntityBase[] entities = m_presence.Scene.Entities.GetEntities();
92 foreach (EntityBase e in entities)
93 {
94 if (e != null && e is SceneObjectGroup)
95 m_pendingObjects.Enqueue((SceneObjectGroup)e);
96 }
97 }
98 }
99
100 lock (m_pendingObjects)
101 {
102 // We must do this under lock so that we don't suffer a race condition if another thread closes the
103 // viewer
104 if (!IsEnabled)
105 return;
106
107 while (m_pendingObjects != null && m_pendingObjects.Count > 0)
108 {
109 SceneObjectGroup g = m_pendingObjects.Dequeue();
110 // Yes, this can really happen
111 if (g == null)
112 continue;
113
114 // This is where we should check for draw distance
115 // do culling and stuff. Problem with that is that until
116 // we recheck in movement, that won't work right.
117 // So it's not implemented now.
118 //
119
120 // Don't even queue if we have sent this one
121 //
122 if (!m_updateTimes.ContainsKey(g.UUID))
123 g.ScheduleFullUpdateToAvatar(m_presence);
124 }
125
126 while (m_partsUpdateQueue.Count > 0)
127 {
128 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
129
130 if (part.ParentGroup.IsDeleted)
131 continue;
132
133 if (m_updateTimes.ContainsKey(part.UUID))
134 {
135 ScenePartUpdate update = m_updateTimes[part.UUID];
136
137 // We deal with the possibility that two updates occur at
138 // the same unix time at the update point itself.
139 if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
140 {
141 // m_log.DebugFormat(
142 // "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
143 // part.Name, part.UUID, part.TimeStampFull);
144
145 part.SendFullUpdate(m_presence.ControllingClient,
146 m_presence.GenerateClientFlags(part.UUID));
147
148 // We'll update to the part's timestamp rather than
149 // the current time to avoid the race condition
150 // whereby the next tick occurs while we are doing
151 // this update. If this happened, then subsequent
152 // updates which occurred on the same tick or the
153 // next tick of the last update would be ignored.
154 update.LastFullUpdateTime = part.TimeStampFull;
155 }
156 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
157 {
158 // m_log.DebugFormat(
159 // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
160 // part.Name, part.UUID, part.TimeStampTerse);
161
162 part.SendTerseUpdateToClient(m_presence.ControllingClient);
163
164 update.LastTerseUpdateTime = part.TimeStampTerse;
165 }
166 }
167 else
168 {
169 //never been sent to client before so do full update
170 ScenePartUpdate update = new ScenePartUpdate();
171 update.FullID = part.UUID;
172 update.LastFullUpdateTime = part.TimeStampFull;
173 m_updateTimes.Add(part.UUID, update);
174
175 // Attachment handling
176 //
177 if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
178 {
179 if (part != part.ParentGroup.RootPart)
180 continue;
181
182 part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient);
183 continue;
184 }
185
186 part.SendFullUpdate(m_presence.ControllingClient,
187 m_presence.GenerateClientFlags(part.UUID));
188 }
189 }
190 }
191 }
192
193// public void Reset()
194// {
195// if (m_pendingObjects == null)
196// return;
197//
198// lock (m_pendingObjects)
199// {
200// if (m_pendingObjects != null)
201// {
202// m_pendingObjects.Clear();
203// m_pendingObjects = null;
204// }
205// }
206// }
207
208 public void Close()
209 {
210 lock (m_pendingObjects)
211 {
212 // We perform this under the m_pendingObjects lock in order to avoid a race condition with another
213 // thread on SendPrimUpdates()
214 IsEnabled = false;
215
216 lock (m_updateTimes)
217 {
218 m_updateTimes.Clear();
219 }
220
221 lock (m_partsUpdateQueue)
222 {
223 m_partsUpdateQueue.Clear();
224 }
225 }
226 }
227
228 public int GetPendingObjectsCount()
229 {
230 if (m_pendingObjects != null)
231 lock (m_pendingObjects)
232 return m_pendingObjects.Count;
233
234 return 0;
235 }
236
237 public class ScenePartUpdate
238 {
239 public UUID FullID;
240 public uint LastFullUpdateTime;
241 public uint LastTerseUpdateTime;
242
243 public ScenePartUpdate()
244 {
245 FullID = UUID.Zero;
246 LastFullUpdateTime = 0;
247 LastTerseUpdateTime = 0;
248 }
249 }
250 }
251}