aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneViewer.cs
diff options
context:
space:
mode:
authorMW2009-06-26 12:09:43 +0000
committerMW2009-06-26 12:09:43 +0000
commit7a2c41dea0f1faf1c6de88d1a3da934d178bae84 (patch)
tree1a4f523917da00efd99366ce815c180888c9be1b /OpenSim/Region/Framework/Scenes/SceneViewer.cs
parentEnable the RemoteAdmin module to save regions as ini files rather than XML (diff)
downloadopensim-SC_OLD-7a2c41dea0f1faf1c6de88d1a3da934d178bae84.zip
opensim-SC_OLD-7a2c41dea0f1faf1c6de88d1a3da934d178bae84.tar.gz
opensim-SC_OLD-7a2c41dea0f1faf1c6de88d1a3da934d178bae84.tar.bz2
opensim-SC_OLD-7a2c41dea0f1faf1c6de88d1a3da934d178bae84.tar.xz
Extracted the code that handles the sending of prim updates to the client, from ScenePresence into ISceneViewer/SceneViewer. Currently ScenePresence "has" a ISceneViewer, although if we had a proper Node based scenegraph then it would most likely be attached directly to the nodes.
By extracting this code, it should make it easier to experiment with different ways of managing the update process. [Next step to make this module based, could be to create a SceneViewerFactoryModule]
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs226
1 files changed, 226 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
new file mode 100644
index 0000000..4e542b8
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -0,0 +1,226 @@
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.Framework.Communications.Cache;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes.Types;
37
38namespace OpenSim.Region.Framework.Scenes
39{
40 public class SceneViewer : ISceneViewer
41 {
42 protected ScenePresence m_presence;
43 protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
44 protected Queue<SceneObjectGroup> m_pendingObjects;
45
46 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
47
48 protected int m_maxPrimsPerFrame = 200;
49
50 public int MaxPrimsPerFrame
51 {
52 get { return m_maxPrimsPerFrame; }
53 set { m_maxPrimsPerFrame = value; }
54 }
55
56 public SceneViewer()
57 {
58 }
59
60 public SceneViewer(ScenePresence presence)
61 {
62 m_presence = presence;
63 }
64
65 /// <summary>
66 /// Add the part to the queue of parts for which we need to send an update to the client
67 /// </summary>
68 /// <param name="part"></param>
69 public void QueuePartForUpdate(SceneObjectPart part)
70 {
71 lock (m_partsUpdateQueue)
72 {
73 m_partsUpdateQueue.Enqueue(part);
74 }
75 }
76
77 public void SendPrimUpdates()
78 {
79 if (m_pendingObjects == null)
80 {
81 if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor))
82 {
83 m_pendingObjects = new Queue<SceneObjectGroup>();
84
85 List<EntityBase> ents = new List<EntityBase>(m_presence.Scene.Entities);
86 if (!m_presence.IsChildAgent) // Proximity sort makes no sense for
87 { // Child agents
88 ents.Sort(delegate(EntityBase a, EntityBase b)
89 {
90 return Vector3.Distance(m_presence.AbsolutePosition, a.AbsolutePosition).CompareTo(Vector3.Distance(m_presence.AbsolutePosition, b.AbsolutePosition));
91 });
92 }
93
94 foreach (EntityBase e in ents)
95 {
96 if (e is SceneObjectGroup)
97 m_pendingObjects.Enqueue((SceneObjectGroup)e);
98 }
99 }
100 }
101
102 while (m_pendingObjects != null && m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < m_maxPrimsPerFrame)
103 {
104 SceneObjectGroup g = m_pendingObjects.Dequeue();
105
106 // This is where we should check for draw distance
107 // do culling and stuff. Problem with that is that until
108 // we recheck in movement, that won't work right.
109 // So it's not implemented now.
110 //
111
112 // Don't even queue if we have sent this one
113 //
114 if (!m_updateTimes.ContainsKey(g.UUID))
115 g.ScheduleFullUpdateToAvatar(m_presence);
116 }
117
118 while (m_partsUpdateQueue.Count > 0)
119 {
120 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
121
122 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
123 continue;
124
125 if (m_updateTimes.ContainsKey(part.UUID))
126 {
127 ScenePartUpdate update = m_updateTimes[part.UUID];
128
129 // We deal with the possibility that two updates occur at
130 // the same unix time at the update point itself.
131
132 if ((update.LastFullUpdateTime < part.TimeStampFull) ||
133 part.IsAttachment)
134 {
135// m_log.DebugFormat(
136// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
137// part.Name, part.UUID, part.TimeStampFull);
138
139 part.SendFullUpdate(m_presence.ControllingClient,
140 m_presence.GenerateClientFlags(part.UUID));
141
142 // We'll update to the part's timestamp rather than
143 // the current time to avoid the race condition
144 // whereby the next tick occurs while we are doing
145 // this update. If this happened, then subsequent
146 // updates which occurred on the same tick or the
147 // next tick of the last update would be ignored.
148
149 update.LastFullUpdateTime = part.TimeStampFull;
150
151 }
152 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
153 {
154// m_log.DebugFormat(
155// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
156// part.Name, part.UUID, part.TimeStampTerse);
157
158 part.SendTerseUpdateToClient(m_presence.ControllingClient);
159
160 update.LastTerseUpdateTime = part.TimeStampTerse;
161 }
162 }
163 else
164 {
165 //never been sent to client before so do full update
166 ScenePartUpdate update = new ScenePartUpdate();
167 update.FullID = part.UUID;
168 update.LastFullUpdateTime = part.TimeStampFull;
169 m_updateTimes.Add(part.UUID, update);
170
171 // Attachment handling
172 //
173 if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
174 {
175 if (part != part.ParentGroup.RootPart)
176 continue;
177
178 part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient);
179 continue;
180 }
181
182 part.SendFullUpdate(m_presence.ControllingClient,
183 m_presence.GenerateClientFlags(part.UUID));
184 }
185 }
186
187 m_presence.ControllingClient.FlushPrimUpdates();
188 }
189
190 public void Reset()
191 {
192 lock (m_pendingObjects)
193 {
194 m_pendingObjects.Clear();
195 m_pendingObjects = null;
196 }
197 }
198
199 public void Close()
200 {
201 lock (m_updateTimes)
202 {
203 m_updateTimes.Clear();
204 }
205 lock (m_partsUpdateQueue)
206 {
207 m_partsUpdateQueue.Clear();
208 }
209 Reset();
210 }
211
212 public class ScenePartUpdate
213 {
214 public UUID FullID;
215 public uint LastFullUpdateTime;
216 public uint LastTerseUpdateTime;
217
218 public ScenePartUpdate()
219 {
220 FullID = UUID.Zero;
221 LastFullUpdateTime = 0;
222 LastTerseUpdateTime = 0;
223 }
224 }
225 }
226}