aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/ContentManagementSystem
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/ContentManagementSystem')
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs114
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs98
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs684
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs148
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs309
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs156
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs326
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs111
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs260
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs130
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs57
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs219
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs81
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/README52
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/Requirements_documentation.odtbin0 -> 38196 bytes
-rw-r--r--OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs169
16 files changed, 2914 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs
new file mode 100644
index 0000000..2155b4c
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs
@@ -0,0 +1,114 @@
1// AuraMetaEntity.cs created with MonoDevelop
2// User: bongiojp at 3:03 PM 8/6/2008
3//
4// To change standard headers go to Edit->Preferences->Coding->Standard Headers
5//
6
7using System;
8using System.Collections.Generic;
9using System.Drawing;
10using libsecondlife;
11using Nini.Config;
12using OpenSim.Framework;
13using OpenSim.Region.Environment.Interfaces;
14using OpenSim.Region.Environment.Scenes;
15using log4net;
16using OpenSim.Region.Physics.Manager;
17using Axiom.Math;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22
23 public class AuraMetaEntity : PointMetaEntity
24 {
25 //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency.
26 public AuraMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) : base(scene, LocalId, groupPos, transparency)
27 {
28 SetAura(color, scale);
29 }
30
31 public AuraMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) : base(scene, uuid, LocalId, groupPos, transparency)
32 {
33 SetAura(color, scale);
34 }
35
36 private float Average(LLVector3 values)
37 {
38 return (values.X + values.Y + values.Z)/3f;
39 }
40
41 public void SetAura(LLVector3 color, LLVector3 scale)
42 {
43 SetAura(color, Average(scale) * 2.0f);
44 }
45
46 public void SetAura(LLVector3 color, float radius)
47 {
48 SceneObjectPart From = m_Entity.RootPart;
49
50 //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius);
51 float burstRadius = 0.1f;
52 Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None;
53 float age = 1.5f;
54 float burstRate = 0.4f;
55 if (radius >= 8.0f)
56 {
57 //float sizeOfObject = radius / 2.0f;
58 burstRadius = (radius - 8.0f)/3f;
59 burstRate = 1.5f;
60 radius = 7.99f;
61 patternFlags = Primitive.ParticleSystem.SourcePattern.Explode;
62 age = 4.0f;
63 }
64 SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags);
65 }
66 public void SetAura(SceneObjectPart From, LLVector3 color, float radius, float burstRadius, float age, float burstRate, libsecondlife.Primitive.ParticleSystem.SourcePattern patternFlags)
67 {
68 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
69 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive |
70 // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS
71 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam |
72 // Primitive.ParticleSystem.ParticleDataFlags.TargetPos;
73 prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR
74 prules.PartStartColor.G = color.Y;
75 prules.PartStartColor.B = color.Z;
76 prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency
77 prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR
78 prules.PartEndColor.G = color.Y;
79 prules.PartEndColor.B = color.Z;
80 prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency
81 /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE
82 prules.PartStartScaleY = 0.5f;
83 prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE
84 prules.PartEndScaleY = 0.5f;
85 */
86 prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE
87 prules.PartStartScaleY = radius;
88 prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE
89 prules.PartEndScaleY = radius;
90 prules.PartMaxAge = age; //PSYS_PART_MAX_AGE
91 prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL
92 prules.PartAcceleration.Y = 0.0f;
93 prules.PartAcceleration.Z = 0.0f;
94 prules.Pattern = patternFlags; //PSYS_SRC_PATTERN
95 //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank
96 prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE
97 prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT
98 //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS
99 prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS
100 prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN
101 prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX
102 prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE
103 //prules.Target = To; //PSYS_SRC_TARGET_KEY
104 prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA
105 prules.AngularVelocity.Y = 0.0f;
106 prules.AngularVelocity.Z = 0.0f;
107 prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN
108 prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END
109
110 prules.CRC = 1; //activates the particle system??
111 From.AddNewParticleSystem(prules);
112 }
113 }
114}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs
new file mode 100644
index 0000000..499d1bc
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs
@@ -0,0 +1,98 @@
1// BeamMetaEntity.cs created with MonoDevelop
2// User: bongiojp at 3:03 PM 8/6/2008
3//
4// To change standard headers go to Edit->Preferences->Coding->Standard Headers
5//
6
7using System;
8using System.Collections.Generic;
9using System.Drawing;
10using libsecondlife;
11using Nini.Config;
12using OpenSim.Framework;
13using OpenSim.Region.Environment.Interfaces;
14using OpenSim.Region.Environment.Scenes;
15using log4net;
16using OpenSim.Region.Physics.Manager;
17using Axiom.Math;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22
23 public class BeamMetaEntity : PointMetaEntity
24 {
25
26 public BeamMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) : base(scene, LocalId, groupPos, transparency)
27 {
28 SetBeamToUUID(To, color);
29 }
30
31 public BeamMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) : base(scene, uuid, LocalId, groupPos, transparency)
32 {
33 SetBeamToUUID(To, color);
34 }
35
36 public void SetBeamToUUID(SceneObjectPart To, LLVector3 color)
37 {
38 SceneObjectPart From = m_Entity.RootPart;
39 //Scale size of particles to distance objects are apart (for better visibility)
40 LLVector3 FromPos = From.GetWorldPosition();
41 LLVector3 ToPos = From.GetWorldPosition();
42 LLUUID toUUID = To.UUID;
43 float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) +
44 Math.Pow(FromPos.X-ToPos.Y, 2) +
45 Math.Pow(FromPos.X-ToPos.Z, 2)
46 )
47 );
48 //float rate = (float) (distance/4f);
49 float rate = 0.5f;
50 float scale = (float) (distance/128f);
51 float speed = (float) (2.0f - distance/128f);
52
53 SetBeamToUUID(From, To, color, rate, scale, speed);
54 }
55
56 public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, LLVector3 color, float rate, float scale, float speed)
57 {
58 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
59 //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive |
60 // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS
61 prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam |
62 Primitive.ParticleSystem.ParticleDataFlags.TargetPos;
63 prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR
64 prules.PartStartColor.G = color.Y;
65 prules.PartStartColor.B = color.Z;
66 prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency
67 prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR
68 prules.PartEndColor.G = color.Y;
69 prules.PartEndColor.B = color.Z;
70 prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency
71 prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE
72 prules.PartStartScaleY = scale;
73 prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE
74 prules.PartEndScaleY = scale;
75 prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE
76 prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL
77 prules.PartAcceleration.Y = 0.0f;
78 prules.PartAcceleration.Z = 0.0f;
79 //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN
80 //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank
81 prules.BurstRate = rate; //PSYS_SRC_BURST_RATE
82 prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT
83 prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS
84 prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN
85 prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX
86 prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE
87 prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY
88 prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA
89 prules.AngularVelocity.Y = 0.0f;
90 prules.AngularVelocity.Z = 0.0f;
91 prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN
92 prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END
93
94 prules.CRC = 1; //activates the particle system??
95 From.AddNewParticleSystem(prules);
96 }
97 }
98}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs
new file mode 100644
index 0000000..465741f
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs
@@ -0,0 +1,684 @@
1// CMController.cs
2// User: bongiojp
3//
4
5using System;
6using System.Collections.Generic;
7using System.Collections;
8using libsecondlife;
9using OpenSim;
10using OpenSim.Framework;
11using OpenSim.Region.Environment.Interfaces;
12using OpenSim.Region.Environment.Scenes;
13using log4net;
14using OpenSim.Region.Physics.Manager;
15using Axiom.Math;
16using System.Threading;
17using System.Diagnostics;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22 /// <summary>
23 /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread,
24 /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system.
25 /// </summary>
26 public class CMController
27 {
28
29 /// <value>
30 /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem.
31 /// </value>
32 private struct Work
33 {
34 public WorkType Type;
35 public Object Data1; //Just space for holding data.
36 public Object Data2; //Just more space for holding data.
37 public uint LocalId; //Convenient
38 public LLUUID UUID; //Convenient
39 }
40
41 /// <value>
42 /// Identifies what the data in struct Work should be used for.
43 /// </value>
44 private enum WorkType
45 {
46 NONE,
47 OBJECTATTRIBUTECHANGE,
48 PRIMITIVEADDED,
49 OBJECTDUPLICATED,
50 OBJECTKILLED,
51 UNDODID,
52 NEWCLIENT,
53 SIMCHAT
54 }
55
56 /// <value>
57 /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk.
58 /// </value>
59 [Flags]
60 private enum State
61 {
62 NONE = 0,
63 DIRTY = 1, // The meta entities may not correctly represent the last revision.
64 SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user.
65 }
66
67 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
68
69 /// <value>
70 /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue.
71 /// </value>
72 private static OpenSim.Framework.BlockingQueue<Work> m_WorkQueue = new OpenSim.Framework.BlockingQueue<Work>();
73
74 /// <value>
75 /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region.
76 /// </value>
77 Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable());
78
79 /// <value>
80 /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers.
81 /// </value>
82 IEstateModule m_estateModule = null;
83
84 Thread m_thread = null;
85 State m_state = State.NONE;
86 bool init = false;
87
88 //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop)
89 CMModel m_model = null;
90 CMView m_view = null;
91 int m_channel = -1;
92
93 /// <summary>
94 /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method.
95 /// </summary>
96 /// <param name="model">
97 /// <see cref="CMModel"/>
98 /// </param>
99 /// <param name="view">
100 /// <see cref="CMView"/>
101 /// </param>
102 /// <param name="scene">
103 /// The first scene to keep track of. <see cref="Scene"/>
104 /// </param>
105 /// <param name="channel">
106 /// The simchat channel number to listen to for instructions <see cref="System.Int32"/>
107 /// </param>
108 public CMController(CMModel model, CMView view, Scene scene, int channel)
109 {
110 m_model = model; m_view = view; m_channel = channel;
111 RegisterNewRegion(scene);
112 Initialize(model, view, scene, channel);
113 }
114
115 private void Initialize(CMModel model, CMView view, Scene scene, int channel)
116 {
117 lock(this)
118 {
119 m_estateModule = scene.RequestModuleInterface<IEstateModule>();
120 m_thread = new Thread( MainLoop );
121 m_thread.Name = "Content Management";
122 m_thread.IsBackground = true;
123 m_thread.Start();
124 ThreadTracker.Add(m_thread);
125 m_state = State.NONE;
126 }
127 }
128
129 /// <summary>
130 /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene.
131 /// </summary>
132 /// <param name="scene">
133 /// A <see cref="Scene"/>
134 /// </param>
135 public void RegisterNewRegion(Scene scene)
136 {
137 m_sceneList.Add(scene.RegionInfo.RegionID, scene);
138
139 m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID);
140 m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System.");
141
142 scene.EventManager.OnNewClient += StartManaging;
143 scene.EventManager.OnRemovePresence += StopManaging;
144 // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
145 scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted;
146 }
147
148 /// <summary>
149 /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions.
150 /// </summary>
151 private void MainLoop()
152 {
153 CMModel model = m_model; CMView view = m_view; int channel = m_channel;
154 Work currentJob = new Work();
155 while(true)
156 {
157 currentJob = m_WorkQueue.Dequeue();
158 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request");
159 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type);
160 switch(currentJob.Type)
161 {
162 case WorkType.NONE:
163 break;
164 case WorkType.OBJECTATTRIBUTECHANGE:
165 ObjectAttributeChanged(model, view, currentJob.LocalId);
166 break;
167 case WorkType.PRIMITIVEADDED:
168 PrimitiveAdded(model, view, currentJob);
169 break;
170 case WorkType.OBJECTDUPLICATED:
171 ObjectDuplicated(model, view, currentJob.LocalId);
172 break;
173 case WorkType.OBJECTKILLED:
174 ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1);
175 break;
176 case WorkType.UNDODID:
177 UndoDid(model, view, currentJob.UUID);
178 break;
179 case WorkType.NEWCLIENT:
180 NewClient(view, (IClientAPI) currentJob.Data1);
181 break;
182 case WorkType.SIMCHAT:
183 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((ChatFromViewerArgs) currentJob.Data1).Message);
184 SimChat(model, view, (ChatFromViewerArgs) currentJob.Data1, channel);
185 break;
186 default:
187 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?");
188 break;
189 }
190 }
191 }
192
193 /// <summary>
194 /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled.
195 /// </summary>
196 private void NewClient(CMView view, IClientAPI client)
197 {
198 if ((m_state & State.SHOWING_CHANGES) > 0)
199 view.SendMetaEntitiesToNewClient(client);
200 }
201
202 /// <summary>
203 /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied.
204 /// </summary>
205 private void ObjectDuplicated(CMModel model, CMView view, uint localId)
206 {
207 if ((m_state & State.SHOWING_CHANGES) > 0)
208 view.DisplayAuras(model.CheckForNewEntitiesMissingAuras( GetGroupByPrim(localId).Scene ));
209 }
210
211 /// <summary>
212 /// Only called by the MainLoop.
213 /// </summary>
214 private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group)
215 {
216 if ((m_state & State.SHOWING_CHANGES) > 0)
217 {
218 view.RemoveOrUpdateDeletedEntity(group);
219 model.RemoveOrUpdateDeletedEntity(group);
220 }
221 }
222
223 /// <summary>
224 /// Only called by the MainLoop.
225 /// </summary>
226 private void UndoDid(CMModel model, CMView view, LLUUID uuid)
227 {
228 if ((m_state & State.SHOWING_CHANGES) > 0)
229 {
230 ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid);
231 if (ent != null)
232 view.DisplayEntity(ent);
233 }
234 }
235
236 /// <summary>
237 /// Only called by the MainLoop.
238 /// </summary>
239 private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId)
240 {
241 SceneObjectGroup group = null;
242 if ((m_state & State.SHOWING_CHANGES) > 0)
243 {
244 group = GetGroupByPrim(LocalId);
245 if (group != null)
246 {
247 view.DisplayAuras( model.UpdateNormalEntityEffects(group) ); //Might be a normal entity (green aura)
248 m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura)
249 }
250 }
251 }
252
253 /// <summary>
254 /// Only called by the MainLoop.
255 /// </summary>
256 private void PrimitiveAdded(CMModel model, CMView view, Work currentJob)
257 {
258 if ((m_state & State.SHOWING_CHANGES) > 0)
259 {
260 foreach(Object scene in m_sceneList.Values)
261 m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene));
262 }
263 }
264
265 /// <summary>
266 /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command.
267 /// </summary>
268 public void SimChat(CMModel model, CMView view, ChatFromViewerArgs e, int channel)
269 {
270 if (e.Channel != channel)
271 return;
272 if (e.Sender == null)
273 return;
274
275 m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message);
276
277 IClientAPI client = e.Sender;
278 Scene scene = (Scene) e.Scene;
279 string message = e.Message;
280 string[] args = e.Message.Split(new char[] {' '});
281
282 ScenePresence avatar = scene.GetScenePresence(client.AgentId);
283
284 if (!(m_estateModule.IsManager(avatar.UUID)))
285 {
286 m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring.");
287 view.SendSimChatMessage(scene, "You must be an estate manager to perform that action.");
288 return;
289 }
290
291 switch(args[0])
292 {
293 case "ci":
294 case "commit":
295 commit(message, scene, model, view);
296 break;
297 case "dm":
298 case "diff-mode":
299 diffmode(scene, model, view);
300 break;
301 case "rb":
302 case "rollback":
303 rollback(scene, model, view);
304 break;
305 case "help":
306 m_view.DisplayHelpMenu(scene);
307 break;
308 default:
309 view.SendSimChatMessage(scene, "Command not found: " + args[0]);
310 break;
311 }
312 }
313
314 /// <summary>
315 /// Only called from within the SimChat method. Hides all auras and meta entities,
316 /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene,
317 /// then lets the view update the clients of the new objects.
318 /// </summary>
319 protected void rollback(Scene scene, CMModel model, CMView view)
320 {
321 if ((m_state & State.SHOWING_CHANGES) > 0)
322 {
323 view.HideAllAuras();
324 view.HideAllMetaEntities();
325 }
326
327 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene);
328 foreach(Scene currScene in proximitySceneList)
329 model.RollbackRegion(currScene);
330
331 if ((m_state & State.DIRTY) != 0 )
332 {
333 model.DeleteAllMetaObjects();
334 foreach(Scene currScene in proximitySceneList)
335 model.UpdateCMEntities(currScene);
336 }
337
338 if ((m_state & State.SHOWING_CHANGES) > 0)
339 view.DisplayRecentChanges();
340
341 }
342
343 /// <summary>
344 /// Only called from within the SimChat method.
345 /// </summary>
346 protected void diffmode(Scene scene, CMModel model, CMView view)
347 {
348 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene);
349
350 if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF
351 {
352 view.SendSimChatMessage(scene, "Hiding all meta objects.");
353 view.HideAllMetaEntities();
354 view.HideAllAuras();
355 view.SendSimChatMessage(scene, "Diff-mode = OFF");
356
357 m_state &= ~State.SHOWING_CHANGES;
358 return;
359 }
360 else // TURN ON
361 {
362 if ((m_state & State.DIRTY) != 0 || m_state == State.NONE)
363 {
364 view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision");
365 //Hide objects from users and Forget about them
366 view.HideAllMetaEntities();
367 view.HideAllAuras();
368 model.DeleteAllMetaObjects();
369 //Recreate them from backend files
370 foreach(Object currScene in m_sceneList.Values)
371 model.UpdateCMEntities((Scene) currScene);
372 }
373 else if ((m_state & State.DIRTY) != 0) {
374 view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision");
375 foreach(Scene currScene in proximitySceneList)
376 model.UpdateCMEntities(currScene);
377 }
378
379 view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment");
380 foreach(Scene currScene in proximitySceneList)
381 model.CheckForNewEntitiesMissingAuras(currScene);
382 view.DisplayRecentChanges();
383
384 view.SendSimChatMessage(scene, "Diff-mode = ON");
385 m_state |= State.SHOWING_CHANGES;
386 m_state &= ~State.DIRTY;
387 }
388 }
389
390 /// <summary>
391 /// Only called from within the SimChat method.
392 /// </summary>
393 protected void commit(string message, Scene scene, CMModel model, CMView view)
394 {
395 System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene);
396
397 string[] args = message.Split(new char[] {' '});
398
399 char[] logMessage = {' '};
400 if (args.Length > 1)
401 {
402 logMessage = new char[message.Length - (args[0].Length)];
403 message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length));
404 }
405
406 m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region.");
407 foreach(Scene currScene in proximitySceneList)
408 {
409 model.CommitRegion(currScene, new String(logMessage));
410 view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName);
411 }
412
413 view.SendSimChatMessage(scene, "Successfully saved all regions.");
414 m_state |= State.DIRTY;
415
416 if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES
417 {
418 view.SendSimChatMessage(scene, "Updating differences between new revision and current environment.");
419 //Hide objects from users and Forget about them
420 view.HideAllMetaEntities();
421 view.HideAllAuras();
422 model.DeleteAllMetaObjects();
423
424 //Recreate them from backend files
425 foreach(Scene currScene in proximitySceneList)
426 {
427 model.UpdateCMEntities(currScene);
428 view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName);
429 }
430
431 //Display new objects to users1
432 view.DisplayRecentChanges();
433 view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE.");
434 m_state &= ~(State.DIRTY);
435 m_state |= State.SHOWING_CHANGES;
436 }
437 }
438
439 /// <summary>
440 /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument.
441 /// </summary>
442 protected static System.Collections.Generic.List<Scene> ScenesInOrderOfProximity( Hashtable sceneList, Scene scene)
443 {
444 int somethingAddedToList = 1;
445 System.Collections.Generic.List<Scene> newList = new List<Scene>();
446 newList.Add(scene);
447
448 if (! sceneList.ContainsValue(scene))
449 {
450 foreach(Object sceneObj in sceneList)
451 newList.Add((Scene) sceneObj);
452 return newList;
453 }
454
455 while(somethingAddedToList > 0)
456 {
457 somethingAddedToList = 0;
458 for(int i = 0; i < newList.Count; i++)
459 {
460 foreach(Object sceneObj in sceneList.Values)
461 {
462 if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (! newList.Contains((Scene)sceneObj)) )
463 {
464 newList.Add((Scene)sceneObj);
465 somethingAddedToList++;
466 }
467 }
468 }
469 }
470
471 foreach(Object sceneObj in sceneList.Values)
472 if (! newList.Contains((Scene)sceneObj))
473 newList.Add((Scene)sceneObj);
474
475 return newList;
476 }
477
478 /// <summary>
479 /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned.
480 /// </summary>
481 private SceneObjectGroup GetGroupByPrim(uint localID)
482 {
483 foreach(Object currScene in m_sceneList.Values)
484 {
485 foreach (EntityBase ent in ((Scene)currScene).GetEntities())
486 {
487 if (ent is SceneObjectGroup)
488 {
489 if (((SceneObjectGroup)ent).HasChildPrim(localID))
490 return (SceneObjectGroup)ent;
491 }
492 }
493 }
494 return null;
495 }
496 //------------------------------------------------ EVENTS ----------------------------------------------------//
497
498 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID)
499 {
500 }
501
502 /// <summary>
503 /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions.
504 /// </summary>
505 protected void StartManaging(IClientAPI client)
506 {
507 m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services.");
508 client.OnChatFromViewer += SimChatSent;
509 init = true;
510
511 OnNewClient(client);
512
513 m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client.");
514 client.OnUpdatePrimScale += UpdateSingleScale;
515 client.OnUpdatePrimGroupScale += UpdateMultipleScale;
516 client.OnUpdatePrimGroupPosition += UpdateMultiplePosition;
517 client.OnUpdatePrimSinglePosition += UpdateSinglePosition;
518 client.OnUpdatePrimGroupRotation += UpdateMultipleRotation;
519 client.OnUpdatePrimSingleRotation += UpdateSingleRotation;
520 client.OnAddPrim += UpdateNewParts;
521 client.OnObjectDuplicate += ObjectDuplicated;
522 client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay;
523 client.OnUndo += OnUnDid;
524 //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation;
525 }
526
527 /// <summary>
528 ///
529 /// </summary>
530 protected void StopManaging(LLUUID clientUUID)
531 {
532 foreach(Object sceneobj in m_sceneList.Values)
533 {
534 ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID);
535 if (presence != null)
536 {
537 IClientAPI client = presence.ControllingClient;
538 m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services.");
539 client.OnChatFromViewer -= SimChatSent;
540
541 m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client");
542 client.OnUpdatePrimScale -= UpdateSingleScale;
543 client.OnUpdatePrimGroupScale -= UpdateMultipleScale;
544 client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition;
545 client.OnUpdatePrimSinglePosition -= UpdateSinglePosition;
546 client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation;
547 client.OnUpdatePrimSingleRotation -= UpdateSingleRotation;
548 client.OnAddPrim -= UpdateNewParts;
549 client.OnObjectDuplicate -= ObjectDuplicated;
550 client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay;
551 client.OnUndo -= OnUnDid;
552 //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation;
553 return;
554 }
555 }
556 }
557
558 protected void GroupBeingDeleted(SceneObjectGroup group)
559 {
560 m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!");
561 Work moreWork = new Work();
562 moreWork.Type = WorkType.OBJECTKILLED;
563 moreWork.Data1 = group.Copy();
564 m_WorkQueue.Enqueue(moreWork);
565 }
566
567 //This is stupid, the same information is contained in the first and second argument
568 protected void SimChatSent(Object x, ChatFromViewerArgs e)
569 {
570 m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!");
571 m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message);
572 Work moreWork = new Work();
573 moreWork.Type = WorkType.SIMCHAT;
574 moreWork.Data1 = e;
575 m_WorkQueue.Enqueue(moreWork);
576 }
577
578 protected void ObjectDuplicated(uint localID, LLVector3 offset, uint dupeFlags, LLUUID AgentID, LLUUID GroupID)
579 {
580 Work moreWork = new Work();
581 moreWork.Type = WorkType.OBJECTDUPLICATED;
582 moreWork.LocalId = localID;
583 m_WorkQueue.Enqueue(moreWork);
584 m_log.Debug("[CONTENT MANAGEMENT] dup queue");
585 }
586
587 protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, LLUUID AgentID, LLUUID GroupID,
588 LLUUID RayTargetObj, LLVector3 RayEnd, LLVector3 RayStart,
589 bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates)
590 {
591 Work moreWork = new Work();
592 moreWork.Type = WorkType.OBJECTDUPLICATED;
593 moreWork.LocalId = localID;
594 m_WorkQueue.Enqueue(moreWork);
595 m_log.Debug("[CONTENT MANAGEMENT] dup queue");
596 }
597
598 protected void OnNewClient(IClientAPI client)
599 {
600 Work moreWork = new Work();
601 moreWork.Type = WorkType.NEWCLIENT;
602 moreWork.Data1 = client;
603 m_WorkQueue.Enqueue(moreWork);
604 m_log.Debug("[CONTENT MANAGEMENT] new client");
605 }
606
607 protected void OnUnDid(IClientAPI remoteClient, LLUUID primId)
608 {
609 Work moreWork = new Work();
610 moreWork.Type = WorkType.UNDODID;
611 moreWork.UUID = primId;
612 m_WorkQueue.Enqueue(moreWork);
613 m_log.Debug("[CONTENT MANAGEMENT] undid");
614 }
615
616 protected void UpdateSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient)
617 {
618 Work moreWork = new Work();
619 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
620 moreWork.LocalId = localID;
621 m_WorkQueue.Enqueue(moreWork);
622 m_log.Debug("[CONTENT MANAGEMENT] move");
623 }
624
625 /// <summary>
626 ///
627 /// </summary>
628 protected void UpdateSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient)
629 {
630 Work moreWork = new Work();
631 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
632 moreWork.LocalId = localID;
633 m_WorkQueue.Enqueue(moreWork);
634 m_log.Debug("[CONTENT MANAGEMENT] rot");
635 }
636
637 protected void UpdateSingleScale(uint localID, LLVector3 scale, IClientAPI remoteClient)
638 {
639 Work moreWork = new Work();
640 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
641 moreWork.LocalId = localID;
642 m_WorkQueue.Enqueue(moreWork);
643 m_log.Debug("[CONTENT MANAGEMENT] scale");
644 }
645
646 protected void UpdateMultiplePosition(uint localID, LLVector3 pos, IClientAPI remoteClient)
647 {
648 Work moreWork = new Work();
649 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
650 moreWork.LocalId = localID;
651 m_WorkQueue.Enqueue(moreWork);
652 m_log.Debug("[CONTENT MANAGEMENT] pos");
653 }
654
655 protected void UpdateMultipleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient)
656 {
657 Work moreWork = new Work();
658 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
659 moreWork.LocalId = localID;
660 m_WorkQueue.Enqueue(moreWork);
661 m_log.Debug("[CONTENT MANAGEMENT] rot");
662 }
663
664 protected void UpdateMultipleScale(uint localID, LLVector3 scale, IClientAPI remoteClient)
665 {
666 Work moreWork = new Work();
667 moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE;
668 moreWork.LocalId = localID;
669 m_WorkQueue.Enqueue(moreWork);
670 m_log.Debug("[CONTENT MANAGEMENT]scale");
671 }
672
673 protected void UpdateNewParts(LLUUID ownerID, LLVector3 RayEnd, LLQuaternion rot, PrimitiveBaseShape shape,
674 byte bypassRaycast, LLVector3 RayStart, LLUUID RayTargetID,
675 byte RayEndIsIntersection)
676 {
677 Work moreWork = new Work();
678 moreWork.Type = WorkType.PRIMITIVEADDED;
679 moreWork.UUID = ownerID;
680 m_WorkQueue.Enqueue(moreWork);
681 m_log.Debug("[CONTENT MANAGEMENT] new parts");
682 }
683 }
684}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs
new file mode 100644
index 0000000..9f50e23
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs
@@ -0,0 +1,148 @@
1// CMEntityCollection.cs created with MonoDevelop
2// User: bongiojp at 10:09 AM 7/7/2008
3//
4// Creates, Deletes, Stores ContentManagementEntities
5//
6
7
8using System;
9using System.Collections.Generic;
10using System.Collections;
11using libsecondlife;
12using Nini.Config;
13using OpenSim;
14using OpenSim.Framework;
15using OpenSim.Region.Environment.Interfaces;
16using OpenSim.Region.Environment.Scenes;
17using log4net;
18using OpenSim.Region.Physics.Manager;
19using Axiom.Math;
20using System.Threading;
21
22namespace OpenSim.Region.Environment.Modules.ContentManagement
23{
24
25 public class CMEntityCollection
26 {
27 // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
28
29 // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or
30 // old versions of deleted SceneObjectGroups will be stored in this hash table.
31 // The LLUUID keys are from the SceneObjectGroup RootPart UUIDs
32 protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //LLUUID to ContentManagementEntity
33
34 // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable
35 // The LLUUID keys are from the SceneObjectPart that they are supposed to be on.
36 protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //LLUUID to AuraMetaEntity
37
38 public Hashtable Entities
39 {
40 get { return m_CMEntityHash; }
41 }
42
43 public Hashtable Auras
44 {
45 get {return m_NewlyCreatedEntityAura; }
46 }
47
48 public CMEntityCollection()
49 {}
50
51 public bool AddAura(ContentManagementEntity aura)
52 {
53 if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID))
54 return false;
55 m_NewlyCreatedEntityAura.Add(aura.UUID, aura);
56 return true;
57 }
58
59 public bool AddEntity(ContentManagementEntity ent)
60 {
61 if (m_CMEntityHash.ContainsKey(ent.UUID))
62 return false;
63 m_CMEntityHash.Add(ent.UUID, ent);
64 return true;
65 }
66
67 public bool RemoveNewlyCreatedEntityAura(LLUUID uuid)
68 {
69 if (!m_NewlyCreatedEntityAura.ContainsKey(uuid))
70 return false;
71 m_NewlyCreatedEntityAura.Remove(uuid);
72 return true;
73 }
74
75 public bool RemoveEntity(LLUUID uuid)
76 {
77 if (!m_CMEntityHash.ContainsKey(uuid))
78 return false;
79 m_CMEntityHash.Remove(uuid);
80 return true;
81 }
82
83 public void ClearAll()
84 {
85 m_CMEntityHash.Clear();
86 m_NewlyCreatedEntityAura.Clear();
87 }
88
89
90
91 // Old uuid and new sceneobjectgroup
92 public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part)
93 {
94 AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene,
95 part.ParentGroup.Scene.PrimIDAllocate(),
96 part.GetWorldPosition(),
97 MetaEntity.TRANSLUCENT,
98 new LLVector3(0,254,0),
99 part.Scale
100 );
101 m_NewlyCreatedEntityAura.Add(part.UUID, ent);
102 return ent;
103 }
104
105 // Old uuid and new sceneobjectgroup
106 public ContentManagementEntity CreateNewEntity(SceneObjectGroup group)
107 {
108 ContentManagementEntity ent = new ContentManagementEntity(group, false);
109 m_CMEntityHash.Add(group.UUID, ent);
110 return ent;
111 }
112
113 public ContentManagementEntity CreateNewEntity(String xml, Scene scene)
114 {
115 ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false);
116 if (ent == null)
117 return null;
118 m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent);
119 return ent;
120 }
121
122 // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash
123 public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List<EntityBase> currList)
124 {
125 System.Collections.ArrayList missingList = new System.Collections.ArrayList();
126 SceneObjectGroup temp = null;
127 foreach( EntityBase currObj in currList )
128 {
129 if (! (currObj is SceneObjectGroup))
130 continue;
131 temp = (SceneObjectGroup) currObj;
132
133 if (m_CMEntityHash.ContainsKey(temp.UUID))
134 {
135 foreach(SceneObjectPart part in temp.Children.Values)
136 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
137 missingList.Add(part);
138 }
139 else //Entire group is missing from revision. (and is a new part in region)
140 {
141 foreach(SceneObjectPart part in temp.Children.Values)
142 missingList.Add(part);
143 }
144 }
145 return missingList;
146 }
147 }
148}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs
new file mode 100644
index 0000000..d3b3b77
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs
@@ -0,0 +1,309 @@
1// CMModel.cs
2// User: bongiojp
3//
4//
5
6using System;
7using System.Collections.Generic;
8using System.Collections;
9using libsecondlife;
10using OpenSim;
11using OpenSim.Framework;
12using OpenSim.Region.Environment.Interfaces;
13using OpenSim.Region.Environment.Scenes;
14using log4net;
15using OpenSim.Region.Physics.Manager;
16using Axiom.Math;
17using System.Diagnostics;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22 public class CMModel
23 {
24 static float TimeToUpdate = 0;
25 static float TimeToConvertXml = 0;
26
27 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
28
29 IContentDatabase m_database = null;
30
31 /// <value>
32 /// The class that contains all auras and metaentities used in the CMS.
33 /// </value>
34 CMEntityCollection m_MetaEntityCollection = new CMEntityCollection();
35
36 public CMEntityCollection MetaEntityCollection
37 {
38 get { return m_MetaEntityCollection; }
39 }
40
41 public CMModel()
42 {
43 }
44
45 public void Initialise(string database)
46 {
47 if (database == "FileSystemDatabase")
48 m_database = new FileSystemDatabase();
49 else if (database == "GitDatabase")
50 m_database = new GitDatabase();
51 }
52
53 public void InitialiseDatabase(Scene scene, string dir)
54 {
55 m_database.Initialise(scene, dir);
56 }
57
58 /// <summary>
59 /// Should be called just once to finish initializing the database.
60 /// </summary>
61 public void PostInitialise()
62 {
63 m_database.PostInitialise();
64 }
65
66 public ContentManagementEntity FindMetaEntityAffectedByUndo(LLUUID uuid)
67 {
68 ContentManagementEntity ent = GetMetaGroupByPrim(uuid);
69 return ent;
70 }
71
72 /// <summary>
73 /// Removes the green aura when an a new scene object group is deleted.
74 /// </summary>
75 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
76 {
77 // Deal with new parts not revisioned that have been deleted.
78 foreach(SceneObjectPart part in group.Children.Values)
79 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
80 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
81 }
82
83 /// <summary>
84 /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message.
85 /// </summary>
86 public void CommitRegion(Scene scene, String logMessage)
87 {
88 m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length);
89 m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage);
90 m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName );
91 }
92
93 /// <summary>
94 /// Retrieves the latest revision of a region in xml form,
95 /// converts it to scene object groups and scene presences,
96 /// swaps the current scene's entity list with the revision's list.
97 /// Note: Since deleted objects while
98 /// </summary>
99 public void RollbackRegion(Scene scene)
100 {
101 System.Collections.ArrayList xmllist = null;
102 SceneObjectGroup temp = null;
103 System.Collections.Hashtable deleteListUUIDs = new Hashtable();
104 Dictionary<LLUUID, EntityBase> SearchList = new Dictionary<LLUUID,EntityBase>();
105 Dictionary<LLUUID, EntityBase> ReplacementList = new Dictionary<LLUUID,EntityBase>();
106 int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID);
107 EntityBase[] searchArray;
108
109 xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision);
110 if (xmllist == null)
111 {
112 m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ").");
113 return;
114 }
115
116 m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ").");
117 m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count);
118 m_log.Info("[CMMODEL]: Converting scene entities list to specified revision.");
119
120 m_log.ErrorFormat("[CMMODEL]: 1");
121
122 foreach (string xml in xmllist)
123 {
124 try{
125 temp = new SceneObjectGroup(xml);
126 temp.SetScene(scene);
127 foreach(SceneObjectPart part in temp.Children.Values)
128 part.RegionHandle = scene.RegionInfo.RegionHandle;
129 ReplacementList.Add(temp.UUID, (EntityBase)temp);
130 }
131 catch(Exception e)
132 {
133 m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e);
134 }
135 }
136
137 //If in scene but not in revision and not a client, remove them
138 while (true)
139 {
140 try
141 {
142 foreach(EntityBase entity in scene.GetEntities())
143 {
144 if (entity == null)
145 continue;
146
147 if (entity is ScenePresence)
148 {
149 ReplacementList.Add(entity.UUID, entity);
150 continue;
151 }
152 else //if (!ReplacementList.ContainsKey(entity.UUID))
153 deleteListUUIDs.Add(entity.UUID, 0);
154 }
155 }
156 catch(Exception e)
157 {
158 m_log.ErrorFormat("[CMMODEL]: " + e);
159 deleteListUUIDs.Clear();
160 ReplacementList.Clear();
161 continue;
162 }
163 break;
164 }
165
166 foreach(LLUUID uuid in deleteListUUIDs.Keys)
167 {
168 try
169 {
170 // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles.
171 ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup((SceneObjectGroup)scene.Entities[uuid]);
172 scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor);
173 scene.SendKillObject(scene.Entities[uuid].LocalId);
174 scene.m_innerScene.DeleteSceneObject(uuid, false);
175 ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup();
176 }
177 catch(Exception e)
178 {
179 m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e);
180 }
181 }
182
183 lock (scene)
184 {
185 scene.Entities = ReplacementList;
186 }
187
188 foreach(EntityBase ent in ReplacementList.Values)
189 {
190 try
191 {
192 if (!(ent is SceneObjectGroup))
193 continue;
194
195 if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) LLObject.ObjectFlags.Phantom) == 0)
196 ((SceneObjectGroup)ent).ApplyPhysics(true);
197 ((SceneObjectGroup)ent).AttachToBackup();
198 ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected.
199 ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate();
200 }
201 catch(Exception e)
202 {
203 m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e);
204 }
205 }
206 m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup.");
207 scene.Backup();
208 }
209
210 /// <summary>
211 /// Detects if a scene object group from the scene list has moved or changed scale. The green aura
212 /// that surrounds the object is then moved or scaled with the group.
213 /// </summary>
214 public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group)
215 {
216 System.Collections.ArrayList auraList = new System.Collections.ArrayList();
217 if (group == null)
218 return null;
219 foreach(SceneObjectPart part in group.Children.Values)
220 {
221 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
222 {
223 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new LLVector3(0,254,0), part.Scale);
224 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
225 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
226 }
227 }
228 return auraList;
229 }
230
231 public void DeleteAllMetaObjects()
232 {
233 m_MetaEntityCollection.ClearAll();
234 }
235
236 /// <summary>
237 /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences
238 /// and display the differences to clients.
239 /// </summary>
240 public void UpdateCMEntities(Scene scene)
241 {
242 Stopwatch x = new Stopwatch();
243 x.Start();
244
245 System.Collections.ArrayList xmllist = null;
246 m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID);
247 xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID);
248 m_log.Info("[FSDB]: got list");
249 if (xmllist == null)
250 return;
251
252 Stopwatch y = new Stopwatch();
253 y.Start();
254 foreach (string xml in xmllist)
255 m_MetaEntityCollection.CreateNewEntity(xml, scene);
256 y.Stop();
257 TimeToConvertXml += y.ElapsedMilliseconds;
258 m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds);
259 m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml);
260
261 m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras");
262 CheckForNewEntitiesMissingAuras(scene);
263
264 x.Stop();
265 TimeToUpdate += x.ElapsedMilliseconds;
266 m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds);
267 m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate);
268
269 }
270
271 /// <summary>
272 /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity
273 /// it is a new part that must have a green aura (for diff mode).
274 /// Returns list of ContentManagementEntities
275 /// </summary>
276 public ArrayList CheckForNewEntitiesMissingAuras(Scene scene)
277 {
278 ArrayList missingList = null;
279 ArrayList newList = new ArrayList();
280
281 m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName);
282
283 //Check if the current scene has groups not included in the current list of MetaEntities
284 //If so, then the current scene's parts that are new should be marked green.
285 missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities());
286
287 foreach(Object missingPart in missingList)
288 {
289 if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID))
290 continue;
291 newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart));
292 }
293 m_log.Info("Number of missing objects found: " + newList.Count);
294 return newList;
295 }
296
297//-------------------------------- HELPERS --------------------------------------------------------------------//
298
299 public ContentManagementEntity GetMetaGroupByPrim(LLUUID uuid)
300 {
301 foreach (Object ent in m_MetaEntityCollection.Entities.Values)
302 {
303 if (((ContentManagementEntity)ent).HasChildPrim(uuid))
304 return (ContentManagementEntity)ent;
305 }
306 return null;
307 }
308 }
309} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs
new file mode 100644
index 0000000..f8b0ec9
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs
@@ -0,0 +1,156 @@
1// CMView.cs created with MonoDevelop
2// User: bongiojp at 11:57 AM 7/3/2008
3//
4// To change standard headers go to Edit->Preferences->Coding->Standard Headers
5//
6
7using System;
8using System.Collections.Generic;
9using System.Collections;
10using libsecondlife;
11using OpenSim;
12using OpenSim.Framework;
13using OpenSim.Region.Environment.Interfaces;
14using OpenSim.Region.Environment.Scenes;
15using log4net;
16using OpenSim.Region.Physics.Manager;
17using Axiom.Math;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22 public class CMView
23 {
24 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
25 CMModel m_model = null;
26
27 public CMView()
28 {}
29
30 public void Initialise(CMModel model)
31 {
32 m_model = model;
33 }
34
35 public void SendMetaEntitiesToNewClient(IClientAPI client)
36 {
37 }
38
39 /// <summary>
40 /// update all clients of red/green/blue auras and meta entities that the model knows about.
41 /// </summary>
42 public void DisplayRecentChanges()
43 {
44 m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects.");
45 DisplayEntities(m_model.MetaEntityCollection);
46 DisplayAuras(m_model.MetaEntityCollection);
47 }
48
49 /// <summary>
50 /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted.
51 /// If it's a new scene object, any green aura attached to it is deleted.
52 /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will
53 /// figure out that there should be a red aura and not a blue aura/beam.
54 /// </summary>
55 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
56 {
57 // Deal with revisioned parts that have been deleted.
58 if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID))
59 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
60
61 // Deal with new parts not revisioned that have been deleted.
62 foreach(SceneObjectPart part in group.Children.Values)
63 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
64 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
65 }
66
67 // Auras To
68 public void DisplayAuras(CMEntityCollection auraCollection)
69 {
70 foreach( Object ent in auraCollection.Auras.Values)
71 ((AuraMetaEntity)ent).SendFullUpdateToAll();
72 }
73
74 // Entities to ALL
75 public void DisplayEntities(CMEntityCollection entityCollection)
76 {
77 foreach( Object ent in entityCollection.Entities.Values)
78 ((ContentManagementEntity)ent).SendFullDiffUpdateToAll();
79 }
80
81 // Auras To Client
82 public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client)
83 {
84 foreach( Object ent in auraCollection.Auras.Values)
85 ((AuraMetaEntity)ent).SendFullUpdate(client);
86 }
87
88 // Entities to Client
89 public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client)
90 {
91 foreach( Object ent in entityCollection.Entities.Values)
92 ((ContentManagementEntity)ent).SendFullDiffUpdate(client);
93 }
94
95 // Entity to ALL
96 public void DisplayEntity(ContentManagementEntity ent)
97 {
98 ent.SendFullDiffUpdateToAll();
99 }
100
101 public void DisplayMetaEntity(LLUUID uuid)
102 {
103 ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid);
104 if (group != null)
105 group.SendFullDiffUpdateToAll();
106 }
107
108 // Auras from List To ALL
109 public void DisplayAuras(ArrayList list)
110 {
111 foreach( Object ent in list)
112 {
113 m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW");
114 ((AuraMetaEntity)ent).SendFullUpdateToAll();
115 }
116 }
117
118 // Entities from List to ALL
119 public void DisplayEntities(ArrayList list)
120 {
121 foreach( Object ent in list)
122 ((ContentManagementEntity)ent).SendFullDiffUpdateToAll();
123 }
124
125 public void DisplayHelpMenu(Scene scene)
126 {
127 string menu = "Menu:\n";
128 menu += "commit (ci) - saves current state of the region to a database on the server\n";
129 menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n";
130 SendSimChatMessage(scene, menu);
131 }
132
133 public void SendSimChatMessage(Scene scene, string message)
134 {
135 scene.SimChat(Helpers.StringToField(message),
136 ChatTypeEnum.Broadcast, 0, new LLVector3(0,0,0), "Content Manager", LLUUID.Zero, false);
137 }
138
139 public void Hide(ContentManagementEntity ent)
140 {
141 ent.HideFromAll();
142 }
143
144 public void HideAllMetaEntities()
145 {
146 foreach(Object obj in m_model.MetaEntityCollection.Entities.Values)
147 ((ContentManagementEntity)obj).HideFromAll();
148 }
149
150 public void HideAllAuras()
151 {
152 foreach(Object obj in m_model.MetaEntityCollection.Auras.Values)
153 ((MetaEntity)obj).HideFromAll();
154 }
155 }
156}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs
new file mode 100644
index 0000000..fb9df8f
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs
@@ -0,0 +1,326 @@
1// ContentManagementEntity.cs
2// User: bongiojp
3//
4//
5
6using System;
7using System.Collections.Generic;
8using System.Drawing;
9using libsecondlife;
10using Nini.Config;
11using OpenSim.Framework;
12using OpenSim.Region.Environment.Interfaces;
13using OpenSim.Region.Environment.Scenes;
14using log4net;
15using OpenSim.Region.Physics.Manager;
16using Axiom.Math;
17
18namespace OpenSim.Region.Environment.Modules.ContentManagement
19{
20 public class ContentManagementEntity : MetaEntity
21 {
22 static float TimeToDiff = 0;
23 static float TimeToCreateEntities = 0;
24
25 // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different.
26 // This can come in handy.
27 protected SceneObjectGroup m_UnchangedEntity = null;
28 protected Dictionary<LLUUID, BeamMetaEntity> m_BeamEntities = new Dictionary<LLUUID, BeamMetaEntity>();
29 protected Dictionary<LLUUID, AuraMetaEntity> m_AuraEntities = new Dictionary<LLUUID, AuraMetaEntity>();
30
31 /// <value>
32 /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list.
33 /// </value>
34 bool DiffersFromSceneGroup = false;
35
36 public SceneObjectGroup UnchangedEntity
37 {
38 get { return m_UnchangedEntity; }
39 }
40
41 public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) : base(Unchanged, false)
42 {
43 m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false);
44 }
45
46 public ContentManagementEntity(string objectXML, Scene scene, bool physics) : base(objectXML, scene, false)
47 {
48 m_UnchangedEntity = new SceneObjectGroup(objectXML);
49 }
50
51 public override void Hide(IClientAPI client)
52 {
53 base.Hide(client);
54 foreach(MetaEntity group in m_AuraEntities.Values)
55 group.Hide(client);
56 foreach(MetaEntity group in m_BeamEntities.Values)
57 group.Hide(client);
58 }
59
60 public override void HideFromAll()
61 {
62 base.HideFromAll();
63 foreach(MetaEntity group in m_AuraEntities.Values)
64 group.HideFromAll();
65 foreach(MetaEntity group in m_BeamEntities.Values)
66 group.HideFromAll();
67 }
68
69 public void SendFullDiffUpdateToAll()
70 {
71 FindDifferences();
72 if (DiffersFromSceneGroup)
73 {
74 SendFullUpdateToAll();
75 SendFullAuraUpdateToAll();
76 SendFullBeamUpdateToAll();
77 }
78 }
79
80 public void SendFullDiffUpdate(IClientAPI client)
81 {
82 FindDifferences();
83 if (DiffersFromSceneGroup)
84 {
85 SendFullUpdate(client);
86 SendFullAuraUpdate(client);
87 SendFullBeamUpdate(client);
88 }
89 }
90
91 public void SendFullBeamUpdate(IClientAPI client)
92 {
93 if (DiffersFromSceneGroup)
94 {
95 foreach(BeamMetaEntity group in m_BeamEntities.Values)
96 group.SendFullUpdate(client);
97 }
98 }
99
100 public void SendFullAuraUpdate(IClientAPI client)
101 {
102 if (DiffersFromSceneGroup)
103 {
104 foreach(AuraMetaEntity group in m_AuraEntities.Values)
105 group.SendFullUpdate(client);
106 }
107 }
108
109 public void SendFullBeamUpdateToAll()
110 {
111 if (DiffersFromSceneGroup)
112 {
113 foreach(BeamMetaEntity group in m_BeamEntities.Values)
114 group.SendFullUpdateToAll();
115 }
116 }
117
118 public void SendFullAuraUpdateToAll()
119 {
120 if (DiffersFromSceneGroup)
121 {
122 foreach(AuraMetaEntity group in m_AuraEntities.Values)
123 group.SendFullUpdateToAll();
124 }
125 }
126
127 /// <summary>
128 /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately.
129 /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately.
130 /// </summary>
131 public void FindDifferences()
132 {
133 System.Collections.Generic.List<EntityBase> sceneEntityList = m_Entity.Scene.GetEntities();
134 DiffersFromSceneGroup = false;
135 // if group is not contained in scene's list
136 if(!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
137 {
138 foreach(SceneObjectPart part in m_UnchangedEntity.Children.Values)
139 {
140 // if scene list no longer contains this part, display translucent part and mark with red aura
141 if(! ContainsKey(sceneEntityList, part.UUID))
142 {
143 // if already displaying a red aura over part, make sure its red
144 if (m_AuraEntities.ContainsKey(part.UUID))
145 {
146 m_AuraEntities[part.UUID].SetAura(new LLVector3(254,0,0), part.Scale);
147 }
148 else
149 {
150 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
151 m_Entity.Scene.PrimIDAllocate(),
152 part.GetWorldPosition(),
153 MetaEntity.TRANSLUCENT,
154 new LLVector3(254,0,0),
155 part.Scale
156 );
157 m_AuraEntities.Add(part.UUID, auraGroup);
158 }
159 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
160 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
161 }
162 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
163 }
164
165 // a deleted part has no where to point a beam particle system,
166 // if a metapart had a particle system (maybe it represented a moved part) remove it
167 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
168 {
169 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
170 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
171 }
172
173 DiffersFromSceneGroup = true;
174 }
175 // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately
176 else
177 {
178 MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID));
179 }
180 }
181
182 /// <summary>
183 /// Returns true if there was a change between meta entity and the entity group, false otherwise.
184 /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated).
185 /// </summary>
186 public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup)
187 {
188 SceneObjectPart sceneEntityPart;
189 SceneObjectPart metaEntityPart;
190 Diff differences;
191 bool changed = false;
192
193 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
194 // had originally saved.
195 // m_Entity will NOT necessarily be the same entity as the user had saved.
196 foreach(SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
197 {
198 //This is the part that we use to show changes.
199 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
200 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
201 {
202 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
203 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
204 if (differences != Diff.NONE)
205 metaEntityPart.Text = "CHANGE: " + differences.ToString();
206 if (differences != 0)
207 {
208 // Root Part that has been modified
209 if ((differences&Diff.POSITION) > 0)
210 {
211 // If the position of any part has changed, make sure the RootPart of the
212 // meta entity is pointing with a beam particle system
213 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
214 {
215 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
216 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
217 }
218 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
219 m_Entity.Scene.PrimIDAllocate(),
220 m_UnchangedEntity.RootPart.GetWorldPosition(),
221 MetaEntity.TRANSLUCENT,
222 sceneEntityPart,
223 new LLVector3(0,0,254)
224 );
225 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
226 }
227
228 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
229 {
230 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
231 m_AuraEntities.Remove(UnchangedPart.UUID);
232 }
233 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
234 m_Entity.Scene.PrimIDAllocate(),
235 UnchangedPart.GetWorldPosition(),
236 MetaEntity.TRANSLUCENT,
237 new LLVector3(0,0,254),
238 UnchangedPart.Scale
239 );
240 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
241 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
242
243 DiffersFromSceneGroup = true;
244 }
245 else // no differences between scene part and meta part
246 {
247 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
248 {
249 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
250 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
251 }
252 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
253 {
254 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
255 m_AuraEntities.Remove(UnchangedPart.UUID);
256 }
257 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
258 }
259 }
260 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
261 {
262 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
263 {
264 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
265 m_AuraEntities.Remove(UnchangedPart.UUID);
266 }
267 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
268 m_Entity.Scene.PrimIDAllocate(),
269 UnchangedPart.GetWorldPosition(),
270 MetaEntity.TRANSLUCENT,
271 new LLVector3(254,0,0),
272 UnchangedPart.Scale
273 );
274 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
275 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
276
277 DiffersFromSceneGroup = true;
278 }
279 }
280 return changed;
281 }
282
283 private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List<EntityBase> list, LLUUID uuid)
284 {
285 foreach (EntityBase ent in list)
286 {
287 if (ent is SceneObjectGroup)
288 if (ent.UUID == uuid)
289 return (SceneObjectGroup)ent;
290 }
291 return null;
292 }
293
294 /// <summary>
295 /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID.
296 /// </summary>
297 public bool HasChildPrim(LLUUID uuid)
298 {
299 if (m_UnchangedEntity.Children.ContainsKey(uuid))
300 return true;
301 return false;
302 }
303
304 /// <summary>
305 /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId.
306 /// </summary>
307 public bool HasChildPrim(uint localID)
308 {
309 foreach( SceneObjectPart part in m_UnchangedEntity.Children.Values)
310 if ( part.LocalId == localID )
311 return true;
312 return false;
313 }
314
315 /// <summary>
316 /// Check if an entitybase list (like that returned by scene.GetEntities() ) contains a group with the rootpart uuid that matches the current uuid.
317 /// </summary>
318 private bool ContainsKey(List<EntityBase> list, LLUUID uuid)
319 {
320 foreach( EntityBase part in list)
321 if (part.UUID == uuid)
322 return true;
323 return false;
324 }
325 }
326}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs
new file mode 100644
index 0000000..22177ae
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs
@@ -0,0 +1,111 @@
1// ContentManagementModule.cs
2// User: bongiojp
3
4
5
6using System;
7using System.Collections.Generic;
8using libsecondlife;
9using Nini.Config;
10using OpenSim;
11using OpenSim.Framework;
12using OpenSim.Region.Environment.Interfaces;
13using OpenSim.Region.Environment.Scenes;
14using log4net;
15using OpenSim.Region.Physics.Manager;
16using Axiom.Math;
17using System.Threading;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21 public class ContentManagementModule : IRegionModule
22 {
23 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
24 CMController m_control = null;
25 CMModel m_model = null;
26 CMView m_view = null;
27 bool initialised = false;
28 bool m_posted = false;
29 bool m_enabled = true;
30
31 public void Initialise(Scene scene, IConfigSource source)
32 {
33 string databaseDir = "./";
34 string database = "FilesyStemDatabase";
35 int channel = 345;
36 try
37 {
38 if (!source.Configs["CMS"].GetBoolean("Enabled", false))
39 m_enabled = false;
40
41 databaseDir = source.Configs["CMS"].GetString("Directory", databaseDir);
42 database = source.Configs["CMS"].GetString("Database", database);
43 channel = source.Configs["CMS"].GetInt("Channel", channel);
44 if (database != "FileSystemDatabase" && database != "GitDatabase")
45 {
46 m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase");
47 m_enabled = false;
48 }
49 }
50 catch (Exception e)
51 {
52 m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e);
53 m_enabled = false;
54 }
55
56 if (!m_enabled)
57 {
58 m_log.Info("[Content Management]: Content Management System is not Enabled.");
59 return;
60 }
61
62 lock(this)
63 {
64 if (!initialised) //only init once
65 {
66 m_view = new CMView();
67 m_model = new CMModel();
68 m_control = new CMController(m_model, m_view, scene, channel);
69 m_model.Initialise(database);
70 m_view.Initialise(m_model);
71
72 initialised = true;
73 m_model.InitialiseDatabase(scene, databaseDir);
74 }
75 else
76 {
77 m_model.InitialiseDatabase(scene, databaseDir);
78 m_control.RegisterNewRegion(scene);
79 }
80 }
81 }
82
83 public void PostInitialise()
84 {
85 if (! m_enabled)
86 return;
87
88 lock(this)
89 {
90 if (!m_posted) //only post once
91 {
92 m_model.PostInitialise();
93 m_posted = true;
94 }
95 }
96 }
97
98 public void Close()
99 {}
100
101 public string Name
102 {
103 get { return "ContentManagementModule"; }
104 }
105
106 public bool IsSharedModule
107 {
108 get { return true; }
109 }
110 }
111}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs
new file mode 100644
index 0000000..e1f519b
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs
@@ -0,0 +1,260 @@
1// FileSystemDatabase.cs
2// User: bongiojp
3
4using System;
5using System.Collections.Generic;
6using System.IO;
7using System.Reflection;
8using System.Xml;
9using libsecondlife;
10using Nini.Config;
11using OpenSim.Framework;
12using OpenSim.Region.Environment.Interfaces;
13using OpenSim.Region.Environment.Modules.World.Serialiser;
14using OpenSim.Region.Environment.Modules.World.Terrain;
15using OpenSim.Region.Environment.Scenes;
16using log4net;
17using OpenSim.Region.Physics.Manager;
18using Axiom.Math;
19using Slash=System.IO.Path;
20using System.Diagnostics;
21
22namespace OpenSim.Region.Environment.Modules.ContentManagement
23{
24 public class FileSystemDatabase : IContentDatabase
25 {
26 public static float TimeToDownload = 0;
27 public static float TimeToSave = 0;
28
29 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
30
31 private string m_repodir = null;
32 private Dictionary<LLUUID, IRegionSerialiser> m_serialiser = new Dictionary<LLUUID, IRegionSerialiser>();
33 private Dictionary<LLUUID, Scene> m_scenes = new Dictionary<LLUUID, Scene>();
34
35 public FileSystemDatabase()
36 {
37 }
38
39 public void Initialise(Scene scene, string dir)
40 {
41 lock(this)
42 {
43 if (m_repodir == null)
44 m_repodir = dir;
45 }
46 lock(m_scenes)
47 m_scenes.Add(scene.RegionInfo.RegionID, scene);
48 }
49
50
51 // Run once and only once.
52 public void PostInitialise()
53 {
54 SetupSerialiser();
55
56 m_log.Info("[FSDB]: Creating repository in " + m_repodir + ".");
57 CreateDirectory();
58 }
59
60 // called by postinitialise
61 private void SetupSerialiser()
62 {
63 if (m_serialiser.Count == 0)
64 foreach(LLUUID region in m_scenes.Keys)
65 m_serialiser.Add(region,
66 m_scenes[region].RequestModuleInterface<IRegionSerialiser>()
67 );
68 }
69
70 // called by postinitialise
71 private void CreateDirectory()
72 {
73 string scenedir;
74 if (!Directory.Exists(m_repodir))
75 Directory.CreateDirectory(m_repodir);
76
77 foreach (LLUUID region in m_scenes.Keys)
78 {
79 scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar;
80 if (!Directory.Exists(scenedir))
81 Directory.CreateDirectory(scenedir);
82 }
83 }
84
85 public int NumOfRegionRev(LLUUID regionid)
86 {
87 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
88 m_log.Info("[FSDB]: Reading scene dir: " + scenedir);
89 string[] directories = Directory.GetDirectories(scenedir);
90 return directories.Length;
91 }
92
93 public int GetMostRecentRevision(LLUUID regionid)
94 {
95 return NumOfRegionRev(regionid);
96 }
97
98 public void SaveRegion(LLUUID regionid, string regionName, string logMessage)
99 {
100 m_log.Info("[FSDB]: ...............................");
101 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
102
103 m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir);
104 if (!Directory.Exists(scenedir))
105 Directory.CreateDirectory(scenedir);
106
107 int newRevisionNum = GetMostRecentRevision(regionid)+1;
108 string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar;
109
110 m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir);
111 if (!Directory.Exists(revisiondir))
112 Directory.CreateDirectory(revisiondir);
113
114 try {
115 Stopwatch x = new Stopwatch();
116 x.Start();
117 if (m_scenes.ContainsKey(regionid))
118 {
119 m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir);
120 }
121 x.Stop();
122 TimeToSave += x.ElapsedMilliseconds;
123 m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds);
124 m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave);
125 }
126 catch (Exception e)
127 {
128 m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e);
129 return;
130 }
131
132 try {
133 // Finish by writing log message.
134 FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite);
135 StreamWriter sw = new StreamWriter(file);
136 sw.Write(logMessage);
137 sw.Close();
138 }
139 catch (Exception e)
140 {
141 m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e);
142 return;
143 }
144 }
145
146 public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision)
147 {
148 System.Collections.ArrayList objectList = new System.Collections.ArrayList();
149 string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar +
150 + revision + Slash.DirectorySeparatorChar + "objects.xml";
151 XmlDocument doc = new XmlDocument();
152 XmlNode rootNode;
153 //int primCount = 0;
154 //SceneObjectGroup obj = null;
155
156 if(File.Exists(filename))
157 {
158 XmlTextReader reader = new XmlTextReader(filename);
159 reader.WhitespaceHandling = WhitespaceHandling.None;
160 doc.Load(reader);
161 reader.Close();
162 rootNode = doc.FirstChild;
163 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
164 {
165 objectList.Add(aPrimNode.OuterXml);
166 }
167 return objectList;
168 }
169 return null;
170 }
171
172 public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid)
173 {
174 int revision = NumOfRegionRev(regionid);
175 m_log.Info("[FSDB]: found revisions:" + revision);
176 System.Collections.ArrayList xmlList = new System.Collections.ArrayList();
177 string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar +
178 + revision + Slash.DirectorySeparatorChar + "objects.xml";
179 XmlDocument doc = new XmlDocument();
180 XmlNode rootNode;
181
182
183 m_log.Info("[FSDB]: Checking if " + filename + " exists.");
184 if(File.Exists(filename))
185 {
186 Stopwatch x = new Stopwatch();
187 x.Start();
188
189 XmlTextReader reader = new XmlTextReader(filename);
190 reader.WhitespaceHandling = WhitespaceHandling.None;
191 doc.Load(reader);
192 reader.Close();
193 rootNode = doc.FirstChild;
194
195 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
196 xmlList.Add(aPrimNode.OuterXml);
197
198 x.Stop();
199 TimeToDownload += x.ElapsedMilliseconds;
200 m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload);
201
202 return xmlList;
203 }
204 return null;
205 }
206
207 public string GetRegionObjectHeightMap(LLUUID regionid)
208 {
209 String filename = m_repodir + Slash.DirectorySeparatorChar + regionid +
210 Slash.DirectorySeparatorChar + "heightmap.r32";
211 FileStream fs = new FileStream( filename, FileMode.Open);
212 StreamReader sr = new StreamReader(fs);
213 String result = sr.ReadToEnd();
214 sr.Close();
215 fs.Close();
216 return result;
217 }
218
219 public string GetRegionObjectHeightMap(LLUUID regionid, int revision)
220 {
221 String filename = m_repodir + Slash.DirectorySeparatorChar + regionid +
222 Slash.DirectorySeparatorChar + "heightmap.r32";
223 FileStream fs = new FileStream( filename, FileMode.Open);
224 StreamReader sr = new StreamReader(fs);
225 String result = sr.ReadToEnd();
226 sr.Close();
227 fs.Close();
228 return result;
229 }
230
231 public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(LLUUID regionid)
232 {
233 SortedDictionary<string, string> revisionDict = new SortedDictionary<string,string>();
234
235 string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar;
236 string[] directories = Directory.GetDirectories(scenedir);
237
238 FileStream fs = null;
239 StreamReader sr = null;
240 String logMessage = "";
241 String logLocation = "";
242 foreach(string revisionDir in directories)
243 {
244 try {
245 logLocation = revisionDir + Slash.DirectorySeparatorChar + "log";
246 fs = new FileStream( logLocation, FileMode.Open);
247 sr = new StreamReader(fs);
248 logMessage = sr.ReadToEnd();
249 sr.Close();
250 fs.Close();
251 revisionDict.Add(revisionDir, logMessage);
252 }
253 catch (Exception)
254 {}
255 }
256
257 return revisionDict;
258 }
259 }
260}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs
new file mode 100644
index 0000000..e337482
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs
@@ -0,0 +1,130 @@
1// GitDatabase.cs
2//
3//
4//
5
6using System;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Xml;
11using libsecondlife;
12using Nini.Config;
13using OpenSim.Framework;
14using OpenSim.Region.Environment.Interfaces;
15using OpenSim.Region.Environment.Modules.World.Serialiser;
16using OpenSim.Region.Environment.Modules.World.Terrain;
17using OpenSim.Region.Environment.Scenes;
18using log4net;
19using OpenSim.Region.Physics.Manager;
20using Axiom.Math;
21using Slash=System.IO.Path;
22
23namespace OpenSim.Region.Environment.Modules.ContentManagement
24{
25
26 /// <summary>
27 /// Just a stub :-(
28 /// </summary>
29 public class GitDatabase : IContentDatabase
30 {
31
32 public GitDatabase()
33 {
34 }
35
36 public void Initialise(Scene scene, String dir)
37 {
38
39 }
40
41 public void PostInitialise()
42 {
43
44 }
45
46 public int NumOfObjectRev(LLUUID id)
47 {
48 return 0;
49 }
50
51 public int NumOfRegionRev(LLUUID regionid)
52 {
53 return 0;
54 }
55
56 public bool InRepository(LLUUID id)
57 {
58 return false;
59 }
60
61 public void SaveRegion(LLUUID regionid, string regionName, string logMessage)
62 {
63
64 }
65
66 public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid)
67 {
68 return null;
69 }
70
71 public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision)
72 {
73 return null;
74 }
75
76 public string GetRegionObjectXML(LLUUID regionid)
77 {
78 return null;
79 }
80
81 public string GetRegionObjectXML(LLUUID regionid, int revision)
82 {
83 return null;
84 }
85
86 public string GetRegionObjectHeightMap(LLUUID regionid)
87 {
88 return null;
89 }
90
91 public string GetRegionObjectHeightMap(LLUUID regionid, int revision)
92 {
93 return null;
94 }
95
96 public System.Collections.ArrayList GetObjectsFromRegion(LLUUID regionid, int revision)
97 {
98 return null;
99 }
100
101 public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(LLUUID id)
102 {
103 return null;
104 }
105
106 public void SaveObject(SceneObjectGroup entity)
107 {
108 }
109
110 public SceneObjectGroup GetMostRecentObjectRevision(LLUUID id)
111 {
112 return null;
113 }
114
115 public SceneObjectGroup GetObjectRevision(LLUUID id, int revision)
116 {
117 return null;
118 }
119
120 public System.Collections.Generic.SortedDictionary<string, string> ListOfObjectRevisions(LLUUID id)
121 {
122 return null;
123 }
124
125 public int GetMostRecentRevision(LLUUID regionid)
126 {
127 return 0;
128 }
129 }
130}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs
new file mode 100644
index 0000000..f37f95d
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs
@@ -0,0 +1,57 @@
1// IContentDatabase.cs
2// User: bongiojp
3//
4//
5//
6
7using System;
8using libsecondlife;
9using OpenSim.Region.Environment.Scenes;
10using Nini.Config;
11
12namespace OpenSim.Region.Environment.Modules.ContentManagement
13{
14 public interface IContentDatabase
15 {
16 /// <summary>
17 /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database.
18 /// Initialise should be called one for each region to be contained in the database. The directory should be the full path
19 /// to the repository and will only be defined once, regardless of how many times the method is called.
20 /// </summary>
21 void Initialise(Scene scene, String dir);
22
23 /// <summary>
24 /// Should be called once after Initialise has been called.
25 /// </summary>
26 void PostInitialise();
27
28 /// <summary>
29 /// Returns the total number of revisions saved for a specific region.
30 /// </summary>
31 int NumOfRegionRev(LLUUID regionid);
32
33 /// <summary>
34 /// Saves the Region terrain map and objects within the region as xml to the database.
35 /// </summary>
36 void SaveRegion(LLUUID regionid, string regionName, string logMessage);
37
38 /// <summary>
39 /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region.
40 /// </summary>
41 System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid);
42 System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision);
43
44 string GetRegionObjectHeightMap(LLUUID regionid);
45 string GetRegionObjectHeightMap(LLUUID regionid, int revision);
46
47 /// <summary>
48 /// Returns a list of the revision numbers and corresponding log messages for a given region.
49 /// </summary>
50 System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(LLUUID id);
51
52 /// <summary>
53 /// Returns the most recent revision number of a region.
54 /// </summary>
55 int GetMostRecentRevision(LLUUID regionid);
56 }
57}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs
new file mode 100644
index 0000000..f0763d3
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs
@@ -0,0 +1,219 @@
1// MetaEntity.cs
2// User: bongiojp
3//
4// TODO:
5// Create a physics manager to the meta object if there isn't one or the object knows of no scene but the user wants physics enabled.
6
7
8using System;
9using System.Collections.Generic;
10using System.Drawing;
11using libsecondlife;
12using Nini.Config;
13using OpenSim.Framework;
14using OpenSim.Region.Environment.Interfaces;
15using OpenSim.Region.Environment.Scenes;
16using log4net;
17using OpenSim.Region.Physics.Manager;
18using Axiom.Math;
19
20namespace OpenSim.Region.Environment.Modules.ContentManagement
21{
22 public class MetaEntity
23 {
24 protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
25
26 protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity.
27 protected uint m_metaLocalid;
28
29 // Settings for transparency of metaentity
30 public const float NONE = 0f;
31 public const float TRANSLUCENT = .5f;
32 public const float INVISIBLE = .95f;
33
34 public Scene Scene
35 {
36 get { return m_Entity.Scene; }
37 }
38
39 public SceneObjectPart RootPart
40 {
41 get { return m_Entity.RootPart; }
42 set { m_Entity.RootPart = value; }
43 }
44
45 public LLUUID UUID
46 {
47 get { return m_Entity.UUID; }
48 set { m_Entity.UUID = value; }
49 }
50
51 public uint LocalId
52 {
53 get { return m_Entity.LocalId; }
54 set { m_Entity.LocalId = value; }
55 }
56
57 public SceneObjectGroup ObjectGroup
58 {
59 get { return m_Entity; }
60 }
61
62 public Dictionary<LLUUID, SceneObjectPart> Children
63 {
64 get { return m_Entity.Children; }
65 set { m_Entity.Children = value; }
66 }
67
68 public int PrimCount
69 {
70 get { return m_Entity.PrimCount; }
71 }
72
73 public MetaEntity()
74 {
75 }
76
77 /// <summary>
78 /// Makes a new meta entity by copying the given scene object group.
79 /// The physics boolean is just a stub right now.
80 /// </summary>
81 public MetaEntity(SceneObjectGroup orig, bool physics)
82 {
83 m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false);
84 Initialize(physics);
85 }
86
87 /// <summary>
88 /// Takes an XML description of a scene object group and converts it to a meta entity.
89 /// </summary>
90 public MetaEntity(string objectXML, Scene scene, bool physics)
91 {
92 m_Entity = new SceneObjectGroup(objectXML);
93 m_Entity.SetScene(scene);
94 Initialize(physics);
95 }
96
97 // The metaentity objectgroup must have unique localids as well as unique uuids.
98 // localids are used by the client to refer to parts.
99 // uuids are sent to the client and back to the server to identify parts on the server side.
100 /// <summary>
101 /// Changes localids and uuids of m_Entity.
102 /// </summary>
103 protected void Initialize(bool physics)
104 {
105 //make new uuids
106 Dictionary<LLUUID, SceneObjectPart> parts = new Dictionary<LLUUID, SceneObjectPart>();
107 foreach(SceneObjectPart part in m_Entity.Children.Values)
108 {
109 part.ResetIDs(part.LinkNum);
110 parts.Add(part.UUID, part);
111 }
112
113 // make new localids
114 foreach (SceneObjectPart part in m_Entity.Children.Values)
115 part.LocalId = m_Entity.Scene.PrimIDAllocate();
116
117 //finalize
118 m_Entity.UpdateParentIDs();
119 m_Entity.RootPart.PhysActor = null;
120 m_Entity.Children = parts;
121
122 }
123
124 public void SendFullUpdate(IClientAPI client)
125 {
126 // Not sure what clientFlags should be but 0 seems to work
127 SendFullUpdate(client, 0);
128 }
129 public void SendFullUpdateToAll()
130 {
131 uint clientFlags = 0;
132 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller)
133 { m_Entity.SendFullUpdateToClient(controller, clientFlags); }
134 );
135 }
136
137 public void SendFullUpdate(IClientAPI client, uint clientFlags)
138 {
139 m_Entity.SendFullUpdateToClient(client, clientFlags);
140 }
141
142 /// <summary>
143 /// Hides the metaentity from a single client.
144 /// </summary>
145 public virtual void Hide(IClientAPI client)
146 {
147 //This deletes the group without removing from any databases.
148 //This is important because we are not IN any database.
149 //m_Entity.FakeDeleteGroup();
150 foreach( SceneObjectPart part in m_Entity.Children.Values)
151 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
152 }
153
154 /// <summary>
155 /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server.
156 /// </summary>
157 public virtual void HideFromAll()
158 {
159 foreach( SceneObjectPart part in m_Entity.Children.Values)
160 m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller)
161 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
162 );
163 }
164
165 /// <summary>
166 /// Makes a single SceneObjectPart see through.
167 /// </summary>
168 /// <param name="part">
169 /// A <see cref="SceneObjectPart"/>
170 /// The part to make see through
171 /// </param>
172 /// <param name="transparencyAmount">
173 /// A <see cref="System.Single"/>
174 /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible.
175 /// </param>
176 public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount)
177 {
178 LLObject.TextureEntry tex = null;
179 LLColor texcolor;
180 try
181 {
182 tex = part.Shape.Textures;
183 texcolor = new LLColor();
184 }
185 catch(Exception)
186 {
187 //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e);
188 return;
189 }
190
191 for (uint i = 0; i < tex.FaceTextures.Length; i++)
192 {
193 try {
194 if (tex.FaceTextures[i] != null)
195 {
196 texcolor = tex.FaceTextures[i].RGBA;
197 texcolor.A = transparencyAmount;
198 tex.FaceTextures[i].RGBA = texcolor;
199 }
200 }
201 catch (Exception)
202 {
203 //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e);
204 continue;
205 }
206 }
207 try {
208 texcolor = tex.DefaultTexture.RGBA;
209 texcolor.A = transparencyAmount;
210 tex.DefaultTexture.RGBA = texcolor;
211 part.Shape.TextureEntry = tex.ToBytes();
212 }
213 catch (Exception)
214 {
215 //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e);
216 }
217 }
218 }
219} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs
new file mode 100644
index 0000000..55365ac
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs
@@ -0,0 +1,81 @@
1// PointMetaEntity.cs created with MonoDevelop
2// User: bongiojp at 3:03 PM 8/6/2008
3//
4// To change standard headers go to Edit->Preferences->Coding->Standard Headers
5//
6
7using System;
8using System.Collections.Generic;
9using System.Drawing;
10using libsecondlife;
11using Nini.Config;
12using OpenSim.Framework;
13using OpenSim.Region.Environment.Interfaces;
14using OpenSim.Region.Environment.Scenes;
15using log4net;
16using OpenSim.Region.Physics.Manager;
17using Axiom.Math;
18
19namespace OpenSim.Region.Environment.Modules.ContentManagement
20{
21
22
23 public class PointMetaEntity : MetaEntity
24 {
25
26 public PointMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency) : base()
27 {
28 CreatePointEntity(scene, LLUUID.Random(), LocalId, groupPos);
29 SetPartTransparency(m_Entity.RootPart, transparency);
30 }
31
32 public PointMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency) : base()
33 {
34 CreatePointEntity(scene, uuid, LocalId, groupPos);
35 SetPartTransparency(m_Entity.RootPart, transparency);
36 }
37
38 private void CreatePointEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos)
39 {
40 SceneObjectGroup x = new SceneObjectGroup();
41 SceneObjectPart y = new SceneObjectPart();
42
43 //Initialize part
44 y.Name = "Very Small Point";
45 y.RegionHandle = scene.RegionInfo.RegionHandle;
46 y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
47 y.OwnerID = LLUUID.Zero;
48 y.CreatorID = LLUUID.Zero;
49 y.LastOwnerID = LLUUID.Zero;
50 y.UUID = uuid;
51
52 y.LocalId = LocalId;
53
54 y.Shape = PrimitiveBaseShape.CreateBox();
55 y.Scale = new LLVector3(0.01f,0.01f,0.01f);
56 y.LastOwnerID = LLUUID.Zero;
57 y.GroupPosition = groupPos;
58 y.OffsetPosition = new LLVector3(0, 0, 0);
59 y.RotationOffset = new LLQuaternion(0,0,0,0);
60 y.Velocity = new LLVector3(0, 0, 0);
61 y.RotationalVelocity = new LLVector3(0, 0, 0);
62 y.AngularVelocity = new LLVector3(0, 0, 0);
63 y.Acceleration = new LLVector3(0, 0, 0);
64
65 y.Flags = 0;
66 y.TrimPermissions();
67
68 //Initialize group and add part as root part
69 x.SetScene(scene);
70 y.SetParent(x);
71 y.ParentID = 0;
72 y.LinkNum = 0;
73 x.Children.Add(y.UUID, y);
74 x.RootPart = y;
75 x.RegionHandle = scene.RegionInfo.RegionHandle;
76 x.SetScene(scene);
77
78 m_Entity = x;
79 }
80 }
81}
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/README b/OpenSim/Region/Environment/Modules/ContentManagementSystem/README
new file mode 100644
index 0000000..1a69fef
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/README
@@ -0,0 +1,52 @@
1This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a
2reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/
3directory.
4
5To compile: nant
6To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory.
7
8
9--------------------------------------------------------------------------------------------------------------------
10To build the libgit.so file:
11
12#Download GIT git repository
13$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git
14$ cd git
15
16#Compile GIT
17#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC)
18$ autoconf
19$ ./configure
20$ CFLAGS="-g -O2 -Wall -c -fPIC" make
21
22#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation
23$ mkdir ../libgit-objects
24$ cp builtin*.o ../libgit-objects
25$ cp xdiff/*.o ../libgit-objects
26$ cp libgit.a ../libgit-objects
27
28#Remove the main symbol from any object files (like git.o)
29$ cd ../libgit-objects
30$ strip -N main *.o
31
32#Uncompress the plumbing objects from archive created by git
33$ ar x libgit.a
34
35#Create shared object file from all objects (including the zlib library)
36$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o
37
38
39#You can also just copy the following commands into a file and run as a script inside the git directory
40
41make clean
42autoconf
43./configure
44CFLAGS="-g -O2 -Wall -c -fPIC" make
45mkdir libgit-objects
46cp builtin*.o libgit-objects
47cp xdiff/*.o libgit-objects
48cp libgit.a libgit-objects
49cd libgit-objects
50strip -N main *.o
51ar x libgit.a
52ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/Requirements_documentation.odt b/OpenSim/Region/Environment/Modules/ContentManagementSystem/Requirements_documentation.odt
new file mode 100644
index 0000000..3fe7382
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/Requirements_documentation.odt
Binary files differ
diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs
new file mode 100644
index 0000000..c3817ef
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs
@@ -0,0 +1,169 @@
1// SceneObjectGroupDiff.cs
2// User: bongiojp
3
4using System;
5using System.Collections.Generic;
6using System.Drawing;
7using libsecondlife;
8using Nini.Config;
9using OpenSim.Framework;
10using OpenSim.Region.Environment.Interfaces;
11using OpenSim.Region.Environment.Scenes;
12using log4net;
13using OpenSim.Region.Physics.Manager;
14using Axiom.Math;
15using System.Diagnostics;
16
17namespace OpenSim.Region.Environment.Modules.ContentManagement
18{
19 [Flags]
20 public enum Diff
21 {
22 NONE = 0,
23 FACECOLOR = 1,
24 SHAPE = 1<<1,
25 MATERIAL = 1<<2,
26 TEXTURE = 1<<3,
27 SCALE = 1<<4,
28 POSITION = 1<<5,
29 OFFSETPOSITION = 1<<6,
30 ROTATIONOFFSET = 1<<7,
31 ROTATIONALVELOCITY = 1<<8,
32 ACCELERATION = 1<<9,
33 ANGULARVELOCITY = 1<<10,
34 VELOCITY = 1<<11,
35 OBJECTOWNER = 1<<12,
36 PERMISSIONS = 1<<13,
37 DESCRIPTION = 1<<14,
38 NAME = 1<<15,
39 SCRIPT = 1<<16,
40 CLICKACTION = 1<<17,
41 PARTICLESYSTEM = 1<<18,
42 GLOW = 1<<19,
43 SALEPRICE = 1<<20,
44 SITNAME = 1<<21,
45 SITTARGETORIENTATION = 1<<22,
46 SITTARGETPOSITION = 1<<23,
47 TEXT = 1<<24,
48 TOUCHNAME = 1<<25
49 };
50
51 public static class Difference
52 {
53 static float TimeToDiff = 0;
54
55 private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
56
57 private static int TruncateSignificant(float num, int digits)
58 {
59 return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits));
60 // return (int) ((num * (10*digits))/10*digits);
61 }
62
63 private static bool AreVectorsEquivalent(LLVector3 first, LLVector3 second)
64 {
65 if(TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2)
66 && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2)
67 && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2)
68 )
69 return true;
70 else
71 return false;
72 }
73
74 private static bool AreQuaternionsEquivalent(LLQuaternion first, LLQuaternion second)
75 {
76 LLVector3 firstVector = llRot2Euler(first);
77 LLVector3 secondVector = llRot2Euler(second);
78 return AreVectorsEquivalent(firstVector, secondVector);
79 }
80
81 // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
82 // Also changed the original function from LSL_Types to LL types
83 private static LLVector3 llRot2Euler(LLQuaternion r)
84 {
85 LLQuaternion t = new LLQuaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W);
86 double m = (t.X + t.Y + t.Z + t.W);
87 if (m == 0) return new LLVector3();
88 double n = 2 * (r.Y * r.W + r.X * r.Z);
89 double p = m * m - n * n;
90 if (p > 0)
91 return new LLVector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))),
92 (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
93 (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W))));
94 else if (n > 0)
95 return new LLVector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z)));
96 else
97 return new LLVector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z)));
98 }
99
100 // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
101 private static double NormalizeAngle(double angle)
102 {
103 angle = angle % (Math.PI * 2);
104 if (angle < 0) angle = angle + Math.PI * 2;
105 return angle;
106 }
107
108 /// <summary>
109 /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts
110 /// and returns a Diff bitmask which details what the differences are.
111 /// </summary>
112 public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second)
113 {
114 Stopwatch x = new Stopwatch();
115 x.Start();
116
117 Diff result = 0;
118
119 // VECTOR COMPARISONS
120 if(! AreVectorsEquivalent(first.Acceleration, second.Acceleration))
121 result |= Diff.ACCELERATION;
122 if(! AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition))
123 result |= Diff.POSITION;
124 if(! AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity))
125 result |= Diff.ANGULARVELOCITY;
126 if(! AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition))
127 result |= Diff.OFFSETPOSITION;
128 if(! AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity))
129 result |= Diff.ROTATIONALVELOCITY;
130 if(! AreVectorsEquivalent(first.Scale, second.Scale))
131 result |= Diff.SCALE;
132 if(! AreVectorsEquivalent(first.Velocity, second.Velocity))
133 result |= Diff.VELOCITY;
134
135
136 // QUATERNION COMPARISONS
137 if(! AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset))
138 result |= Diff.ROTATIONOFFSET;
139
140
141 // MISC COMPARISONS (LLUUID, Byte)
142 if(first.ClickAction != second.ClickAction)
143 result |= Diff.CLICKACTION;
144 if(first.ObjectOwner != second.ObjectOwner)
145 result |= Diff.OBJECTOWNER;
146
147
148 // STRING COMPARISONS
149 if(first.Description != second.Description)
150 result |= Diff.DESCRIPTION;
151 if(first.Material != second.Material)
152 result |= Diff.MATERIAL;
153 if(first.Name != second.Name)
154 result |= Diff.NAME;
155 if(first.SitName != second.SitName)
156 result |= Diff.SITNAME;
157 if(first.Text != second.Text)
158 result |= Diff.TEXT;
159 if(first.TouchName != second.TouchName)
160 result |= Diff.TOUCHNAME;
161
162 x.Stop();
163 TimeToDiff += x.ElapsedMilliseconds;
164 //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff);
165
166 return result;
167 }
168 }
169}