diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs index 2155b4c6f1..3188c6c662 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/AuraMetaEntity.cs @@ -1,114 +1,136 @@ +#region Header + // AuraMetaEntity.cs created with MonoDevelop // User: bongiojp at 3:03 PM 8/6/2008 // // To change standard headers go to Edit->Preferences->Coding->Standard Headers // +#endregion Header + using System; using System.Collections.Generic; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - - public class AuraMetaEntity : PointMetaEntity - { - //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. - public AuraMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) : base(scene, LocalId, groupPos, transparency) - { - SetAura(color, scale); - } - - public AuraMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) : base(scene, uuid, LocalId, groupPos, transparency) - { - SetAura(color, scale); - } - - private float Average(LLVector3 values) - { - return (values.X + values.Y + values.Z)/3f; - } - - public void SetAura(LLVector3 color, LLVector3 scale) - { - SetAura(color, Average(scale) * 2.0f); - } + public class AuraMetaEntity : PointMetaEntity + { + #region Constructors - public void SetAura(LLVector3 color, float radius) - { - SceneObjectPart From = m_Entity.RootPart; - - //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); - float burstRadius = 0.1f; - Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; - float age = 1.5f; - float burstRate = 0.4f; - if (radius >= 8.0f) - { - //float sizeOfObject = radius / 2.0f; - burstRadius = (radius - 8.0f)/3f; - burstRate = 1.5f; - radius = 7.99f; - patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; - age = 4.0f; - } - SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); - } - public void SetAura(SceneObjectPart From, LLVector3 color, float radius, float burstRadius, float age, float burstRate, libsecondlife.Primitive.ParticleSystem.SourcePattern patternFlags) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency - /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE - prules.PartStartScaleY = 0.5f; - prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE - prules.PartEndScaleY = 0.5f; - */ - prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE - prules.PartStartScaleY = radius; - prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE - prules.PartEndScaleY = radius; - prules.PartMaxAge = age; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - prules.Pattern = patternFlags; //PSYS_SRC_PATTERN - //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT - //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS - prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN + //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. + public AuraMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) + : base(scene, LocalId, groupPos, transparency) + { + SetAura(color, scale); + } + + public AuraMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, LLVector3 color, LLVector3 scale) + : base(scene, uuid, LocalId, groupPos, transparency) + { + SetAura(color, scale); + } + + #endregion Constructors + + #region Private Methods + + private float Average(LLVector3 values) + { + return (values.X + values.Y + values.Z)/3f; + } + + #endregion Private Methods + + #region Public Methods + + public void SetAura(LLVector3 color, LLVector3 scale) + { + SetAura(color, Average(scale) * 2.0f); + } + + public void SetAura(LLVector3 color, float radius) + { + SceneObjectPart From = m_Entity.RootPart; + + //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); + float burstRadius = 0.1f; + Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; + float age = 1.5f; + float burstRate = 0.4f; + if (radius >= 8.0f) + { + //float sizeOfObject = radius / 2.0f; + burstRadius = (radius - 8.0f)/3f; + burstRate = 1.5f; + radius = 7.99f; + patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; + age = 4.0f; + } + SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); + } + + public void SetAura(SceneObjectPart From, LLVector3 color, float radius, float burstRadius, float age, float burstRate, libsecondlife.Primitive.ParticleSystem.SourcePattern patternFlags) + { + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | + // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | + // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; + prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR + prules.PartStartColor.G = color.Y; + prules.PartStartColor.B = color.Z; + prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency + prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR + prules.PartEndColor.G = color.Y; + prules.PartEndColor.B = color.Z; + prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency + /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE + prules.PartStartScaleY = 0.5f; + prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE + prules.PartEndScaleY = 0.5f; + */ + prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE + prules.PartStartScaleY = radius; + prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE + prules.PartEndScaleY = radius; + prules.PartMaxAge = age; //PSYS_PART_MAX_AGE + prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL + prules.PartAcceleration.Y = 0.0f; + prules.PartAcceleration.Z = 0.0f; + prules.Pattern = patternFlags; //PSYS_SRC_PATTERN + //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank + prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE + prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT + //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS + prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS + prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - //prules.Target = To; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - } -} + prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE + //prules.Target = To; //PSYS_SRC_TARGET_KEY + prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA + prules.AngularVelocity.Y = 0.0f; + prules.AngularVelocity.Z = 0.0f; + prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN + prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END + + prules.CRC = 1; //activates the particle system?? + From.AddNewParticleSystem(prules); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs index 499d1bc020..cea9550eaa 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/BeamMetaEntity.cs @@ -1,98 +1,114 @@ +#region Header + // BeamMetaEntity.cs created with MonoDevelop // User: bongiojp at 3:03 PM 8/6/2008 // // To change standard headers go to Edit->Preferences->Coding->Standard Headers // +#endregion Header + using System; using System.Collections.Generic; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - - public class BeamMetaEntity : PointMetaEntity - { - - public BeamMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) : base(scene, LocalId, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public BeamMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) : base(scene, uuid, LocalId, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public void SetBeamToUUID(SceneObjectPart To, LLVector3 color) - { - SceneObjectPart From = m_Entity.RootPart; - //Scale size of particles to distance objects are apart (for better visibility) - LLVector3 FromPos = From.GetWorldPosition(); - LLVector3 ToPos = From.GetWorldPosition(); - LLUUID toUUID = To.UUID; - float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + - Math.Pow(FromPos.X-ToPos.Y, 2) + - Math.Pow(FromPos.X-ToPos.Z, 2) - ) - ); - //float rate = (float) (distance/4f); - float rate = 0.5f; - float scale = (float) (distance/128f); - float speed = (float) (2.0f - distance/128f); - - SetBeamToUUID(From, To, color, rate, scale, speed); - } - - public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, LLVector3 color, float rate, float scale, float speed) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency - prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE - prules.PartStartScaleY = scale; - prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE - prules.PartEndScaleY = scale; - prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN - //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = rate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT - prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN + public class BeamMetaEntity : PointMetaEntity + { + #region Constructors + + public BeamMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) + : base(scene, LocalId, groupPos, transparency) + { + SetBeamToUUID(To, color); + } + + public BeamMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency, SceneObjectPart To, LLVector3 color) + : base(scene, uuid, LocalId, groupPos, transparency) + { + SetBeamToUUID(To, color); + } + + #endregion Constructors + + #region Public Methods + + public void SetBeamToUUID(SceneObjectPart To, LLVector3 color) + { + SceneObjectPart From = m_Entity.RootPart; + //Scale size of particles to distance objects are apart (for better visibility) + LLVector3 FromPos = From.GetWorldPosition(); + LLVector3 ToPos = From.GetWorldPosition(); + LLUUID toUUID = To.UUID; + float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + + Math.Pow(FromPos.X-ToPos.Y, 2) + + Math.Pow(FromPos.X-ToPos.Z, 2) + ) + ); + //float rate = (float) (distance/4f); + float rate = 0.5f; + float scale = (float) (distance/128f); + float speed = (float) (2.0f - distance/128f); + + SetBeamToUUID(From, To, color, rate, scale, speed); + } + + public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, LLVector3 color, float rate, float scale, float speed) + { + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | + // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS + prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | + Primitive.ParticleSystem.ParticleDataFlags.TargetPos; + prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR + prules.PartStartColor.G = color.Y; + prules.PartStartColor.B = color.Z; + prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency + prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR + prules.PartEndColor.G = color.Y; + prules.PartEndColor.B = color.Z; + prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency + prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE + prules.PartStartScaleY = scale; + prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE + prules.PartEndScaleY = scale; + prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE + prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL + prules.PartAcceleration.Y = 0.0f; + prules.PartAcceleration.Z = 0.0f; + //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN + //prules.Texture = LLUUID.Zero;//= LLUUID //PSYS_SRC_TEXTURE, default used if blank + prules.BurstRate = rate; //PSYS_SRC_BURST_RATE + prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT + prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS + prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - } -} + prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE + prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY + prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA + prules.AngularVelocity.Y = 0.0f; + prules.AngularVelocity.Z = 0.0f; + prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN + prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END + + prules.CRC = 1; //activates the particle system?? + From.AddNewParticleSystem(prules); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs index d3ca3cfc6e..a179fb1659 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMController.cs @@ -1,684 +1,721 @@ +#region Header + // CMController.cs // User: bongiojp // +#endregion Header + using System; -using System.Collections.Generic; using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + using libsecondlife; + using OpenSim; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using System.Threading; -using System.Diagnostics; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - /// - /// 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, - /// 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. - /// - public class CMController - { - - /// - /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. - /// - private struct Work - { - public WorkType Type; - public Object Data1; //Just space for holding data. - public Object Data2; //Just more space for holding data. - public uint LocalId; //Convenient - public LLUUID UUID; //Convenient - } - - /// - /// Identifies what the data in struct Work should be used for. - /// - private enum WorkType - { - NONE, - OBJECTATTRIBUTECHANGE, - PRIMITIVEADDED, - OBJECTDUPLICATED, - OBJECTKILLED, - UNDODID, - NEWCLIENT, - SIMCHAT - } - - /// - /// 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. - /// - [Flags] - private enum State - { - NONE = 0, - DIRTY = 1, // The meta entities may not correctly represent the last revision. - SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. - } - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. - /// - private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); - - /// - /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. - /// - Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); - - /// - /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. - /// - IEstateModule m_estateModule = null; - - Thread m_thread = null; - State m_state = State.NONE; - bool init = false; - - //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) - CMModel m_model = null; - CMView m_view = null; - int m_channel = -1; - - /// - /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. - /// - /// - /// - /// - /// - /// - /// - /// - /// The first scene to keep track of. - /// - /// - /// The simchat channel number to listen to for instructions - /// - public CMController(CMModel model, CMView view, Scene scene, int channel) - { - m_model = model; m_view = view; m_channel = channel; - RegisterNewRegion(scene); - Initialize(model, view, scene, channel); - } - - private void Initialize(CMModel model, CMView view, Scene scene, int channel) - { - lock(this) - { - m_estateModule = scene.RequestModuleInterface(); - m_thread = new Thread( MainLoop ); - m_thread.Name = "Content Management"; - m_thread.IsBackground = true; - m_thread.Start(); - ThreadTracker.Add(m_thread); - m_state = State.NONE; - } - } - - /// - /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. - /// - /// - /// A - /// - public void RegisterNewRegion(Scene scene) - { - m_sceneList.Add(scene.RegionInfo.RegionID, scene); - - m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); - m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); - - scene.EventManager.OnNewClient += StartManaging; - scene.EventManager.OnRemovePresence += StopManaging; - // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; - } - - /// - /// 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. - /// - private void MainLoop() - { - CMModel model = m_model; CMView view = m_view; int channel = m_channel; - Work currentJob = new Work(); - while(true) - { - currentJob = m_WorkQueue.Dequeue(); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); - switch(currentJob.Type) - { - case WorkType.NONE: - break; - case WorkType.OBJECTATTRIBUTECHANGE: - ObjectAttributeChanged(model, view, currentJob.LocalId); - break; - case WorkType.PRIMITIVEADDED: - PrimitiveAdded(model, view, currentJob); - break; - case WorkType.OBJECTDUPLICATED: - ObjectDuplicated(model, view, currentJob.LocalId); - break; - case WorkType.OBJECTKILLED: - ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); - break; - case WorkType.UNDODID: - UndoDid(model, view, currentJob.UUID); - break; - case WorkType.NEWCLIENT: - NewClient(view, (IClientAPI) currentJob.Data1); - break; - case WorkType.SIMCHAT: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); - SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); - break; - default: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); - break; - } - } - } - - /// - /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. - /// - private void NewClient(CMView view, IClientAPI client) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.SendMetaEntitiesToNewClient(client); - } + /// + /// 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, + /// 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. + /// + public class CMController + { + #region Static Fields - /// - /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. - /// - private void ObjectDuplicated(CMModel model, CMView view, uint localId) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayAuras(model.CheckForNewEntitiesMissingAuras( GetGroupByPrim(localId).Scene )); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.RemoveOrUpdateDeletedEntity(group); - model.RemoveOrUpdateDeletedEntity(group); - } - } + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Only called by the MainLoop. - /// - private void UndoDid(CMModel model, CMView view, LLUUID uuid) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); - if (ent != null) - view.DisplayEntity(ent); - } - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) - { - SceneObjectGroup group = null; - if ((m_state & State.SHOWING_CHANGES) > 0) - { - group = GetGroupByPrim(LocalId); - if (group != null) - { - view.DisplayAuras( model.UpdateNormalEntityEffects(group) ); //Might be a normal entity (green aura) - m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) - } - } - } - - /// - /// Only called by the MainLoop. - /// - private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - foreach(Object scene in m_sceneList.Values) - m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); - } - } - - /// - /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. - /// - public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) + /// + /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. + /// + private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); + + #endregion Static Fields + + #region Fields + + bool init = false; + int m_channel = -1; + + /// + /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. + /// + IEstateModule m_estateModule = null; + + //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) + CMModel m_model = null; + + /// + /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. + /// + Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); + State m_state = State.NONE; + Thread m_thread = null; + CMView m_view = null; + + #endregion Fields + + #region Constructors + + /// + /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. + /// + /// + /// + /// + /// + /// + /// + /// + /// The first scene to keep track of. + /// + /// + /// The simchat channel number to listen to for instructions + /// + public CMController(CMModel model, CMView view, Scene scene, int channel) { - if (e.Channel != channel) - return; - if (e.Sender == null) - return; - - m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); - - IClientAPI client = e.Sender; - Scene scene = (Scene) e.Scene; - string message = e.Message; - string[] args = e.Message.Split(new char[] {' '}); - - ScenePresence avatar = scene.GetScenePresence(client.AgentId); - - if (!(m_estateModule.IsManager(avatar.UUID))) - { - m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); - view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); - return; - } - - switch(args[0]) - { - case "ci": - case "commit": - commit(message, scene, model, view); - break; - case "dm": - case "diff-mode": - diffmode(scene, model, view); - break; - case "rb": - case "rollback": - rollback(scene, model, view); - break; - case "help": - m_view.DisplayHelpMenu(scene); - break; - default: - view.SendSimChatMessage(scene, "Command not found: " + args[0]); - break; - } - } - - /// - /// Only called from within the SimChat method. Hides all auras and meta entities, - /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, - /// then lets the view update the clients of the new objects. - /// - protected void rollback(Scene scene, CMModel model, CMView view) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.HideAllAuras(); - view.HideAllMetaEntities(); - } - - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); - foreach(Scene currScene in proximitySceneList) - model.RollbackRegion(currScene); - - if ((m_state & State.DIRTY) != 0 ) - { - model.DeleteAllMetaObjects(); - foreach(Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayRecentChanges(); - - } - - /// - /// Only called from within the SimChat method. - /// - protected void diffmode(Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); - - if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF - { - view.SendSimChatMessage(scene, "Hiding all meta objects."); - view.HideAllMetaEntities(); - view.HideAllAuras(); - view.SendSimChatMessage(scene, "Diff-mode = OFF"); - - m_state &= ~State.SHOWING_CHANGES; - return; - } - else // TURN ON - { - if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) - { - view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - //Recreate them from backend files - foreach(Object currScene in m_sceneList.Values) - model.UpdateCMEntities((Scene) currScene); - } - else if ((m_state & State.DIRTY) != 0) { - view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); - foreach(Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } + m_model = model; m_view = view; m_channel = channel; + RegisterNewRegion(scene); + Initialize(model, view, scene, channel); + } - view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); - foreach(Scene currScene in proximitySceneList) - model.CheckForNewEntitiesMissingAuras(currScene); - view.DisplayRecentChanges(); - - view.SendSimChatMessage(scene, "Diff-mode = ON"); - m_state |= State.SHOWING_CHANGES; - m_state &= ~State.DIRTY; - } - } - - /// - /// Only called from within the SimChat method. - /// - protected void commit(string message, Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); - - string[] args = message.Split(new char[] {' '}); - - char[] logMessage = {' '}; - if (args.Length > 1) - { - logMessage = new char[message.Length - (args[0].Length)]; - message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); - } - - m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); - foreach(Scene currScene in proximitySceneList) - { - model.CommitRegion(currScene, new String(logMessage)); - view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); - } - - view.SendSimChatMessage(scene, "Successfully saved all regions."); - m_state |= State.DIRTY; - - if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES - { - view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - - //Recreate them from backend files - foreach(Scene currScene in proximitySceneList) - { - model.UpdateCMEntities(currScene); - view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); - } - - //Display new objects to users1 - view.DisplayRecentChanges(); - view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); - m_state &= ~(State.DIRTY); - m_state |= State.SHOWING_CHANGES; - } - } + #endregion Constructors - /// - /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. - /// - protected static System.Collections.Generic.List ScenesInOrderOfProximity( Hashtable sceneList, Scene scene) - { - int somethingAddedToList = 1; - System.Collections.Generic.List newList = new List(); - newList.Add(scene); - - if (! sceneList.ContainsValue(scene)) - { - foreach(Object sceneObj in sceneList) - newList.Add((Scene) sceneObj); - return newList; - } - - while(somethingAddedToList > 0) - { - somethingAddedToList = 0; - for(int i = 0; i < newList.Count; i++) - { - foreach(Object sceneObj in sceneList.Values) - { - if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (! newList.Contains((Scene)sceneObj)) ) - { - newList.Add((Scene)sceneObj); - somethingAddedToList++; - } - } - } - } - - foreach(Object sceneObj in sceneList.Values) - if (! newList.Contains((Scene)sceneObj)) - newList.Add((Scene)sceneObj); - - return newList; - } - - /// - /// 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. - /// - private SceneObjectGroup GetGroupByPrim(uint localID) + #region Private Methods + + //------------------------------------------------ EVENTS ----------------------------------------------------// + private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) { - foreach(Object currScene in m_sceneList.Values) - { - foreach (EntityBase ent in ((Scene)currScene).GetEntities()) - { - if (ent is SceneObjectGroup) - { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) - return (SceneObjectGroup)ent; - } - } - } + } + + /// + /// 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. + /// + private SceneObjectGroup GetGroupByPrim(uint localID) + { + foreach(Object currScene in m_sceneList.Values) + { + foreach (EntityBase ent in ((Scene)currScene).GetEntities()) + { + if (ent is SceneObjectGroup) + { + if (((SceneObjectGroup)ent).HasChildPrim(localID)) + return (SceneObjectGroup)ent; + } + } + } return null; } - //------------------------------------------------ EVENTS ----------------------------------------------------// - - private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) - { - } - - /// - /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. - /// - protected void StartManaging(IClientAPI client) - { - m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); - client.OnChatFromViewer += SimChatSent; - init = true; - - OnNewClient(client); - - m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); - client.OnUpdatePrimScale += UpdateSingleScale; + + private void Initialize(CMModel model, CMView view, Scene scene, int channel) + { + lock(this) + { + m_estateModule = scene.RequestModuleInterface(); + m_thread = new Thread( MainLoop ); + m_thread.Name = "Content Management"; + m_thread.IsBackground = true; + m_thread.Start(); + ThreadTracker.Add(m_thread); + m_state = State.NONE; + } + } + + /// + /// 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. + /// + private void MainLoop() + { + CMModel model = m_model; CMView view = m_view; int channel = m_channel; + Work currentJob = new Work(); + while(true) + { + currentJob = m_WorkQueue.Dequeue(); + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); + switch(currentJob.Type) + { + case WorkType.NONE: + break; + case WorkType.OBJECTATTRIBUTECHANGE: + ObjectAttributeChanged(model, view, currentJob.LocalId); + break; + case WorkType.PRIMITIVEADDED: + PrimitiveAdded(model, view, currentJob); + break; + case WorkType.OBJECTDUPLICATED: + ObjectDuplicated(model, view, currentJob.LocalId); + break; + case WorkType.OBJECTKILLED: + ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); + break; + case WorkType.UNDODID: + UndoDid(model, view, currentJob.UUID); + break; + case WorkType.NEWCLIENT: + NewClient(view, (IClientAPI) currentJob.Data1); + break; + case WorkType.SIMCHAT: + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); + SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); + break; + default: + m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); + break; + } + } + } + + /// + /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. + /// + private void NewClient(CMView view, IClientAPI client) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + view.SendMetaEntitiesToNewClient(client); + } + + /// + /// Only called by the MainLoop. + /// + private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) + { + SceneObjectGroup group = null; + if ((m_state & State.SHOWING_CHANGES) > 0) + { + group = GetGroupByPrim(LocalId); + if (group != null) + { + view.DisplayAuras( model.UpdateNormalEntityEffects(group) ); //Might be a normal entity (green aura) + m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) + } + } + } + + /// + /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. + /// + private void ObjectDuplicated(CMModel model, CMView view, uint localId) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + view.DisplayAuras(model.CheckForNewEntitiesMissingAuras( GetGroupByPrim(localId).Scene )); + } + + /// + /// Only called by the MainLoop. + /// + private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + view.RemoveOrUpdateDeletedEntity(group); + model.RemoveOrUpdateDeletedEntity(group); + } + } + + /// + /// Only called by the MainLoop. + /// + private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + foreach(Object scene in m_sceneList.Values) + m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); + } + } + + /// + /// Only called by the MainLoop. + /// + private void UndoDid(CMModel model, CMView view, LLUUID uuid) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); + if (ent != null) + view.DisplayEntity(ent); + } + } + + #endregion Private Methods + + #region Protected Methods + + protected void GroupBeingDeleted(SceneObjectGroup group) + { + m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTKILLED; + moreWork.Data1 = group.Copy(); + m_WorkQueue.Enqueue(moreWork); + } + + protected void ObjectDuplicated(uint localID, LLVector3 offset, uint dupeFlags, LLUUID AgentID, LLUUID GroupID) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTDUPLICATED; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] dup queue"); + } + + protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, LLUUID AgentID, LLUUID GroupID, + LLUUID RayTargetObj, LLVector3 RayEnd, LLVector3 RayStart, + bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTDUPLICATED; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] dup queue"); + } + + protected void OnNewClient(IClientAPI client) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.NEWCLIENT; + moreWork.Data1 = client; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] new client"); + } + + protected void OnUnDid(IClientAPI remoteClient, LLUUID primId) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.UNDODID; + moreWork.UUID = primId; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] undid"); + } + + /// + /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. + /// + protected static System.Collections.Generic.List ScenesInOrderOfProximity( Hashtable sceneList, Scene scene) + { + int somethingAddedToList = 1; + System.Collections.Generic.List newList = new List(); + newList.Add(scene); + + if (! sceneList.ContainsValue(scene)) + { + foreach(Object sceneObj in sceneList) + newList.Add((Scene) sceneObj); + return newList; + } + + while(somethingAddedToList > 0) + { + somethingAddedToList = 0; + for(int i = 0; i < newList.Count; i++) + { + foreach(Object sceneObj in sceneList.Values) + { + if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (! newList.Contains((Scene)sceneObj)) ) + { + newList.Add((Scene)sceneObj); + somethingAddedToList++; + } + } + } + } + + foreach(Object sceneObj in sceneList.Values) + if (! newList.Contains((Scene)sceneObj)) + newList.Add((Scene)sceneObj); + + return newList; + } + + //This is stupid, the same information is contained in the first and second argument + protected void SimChatSent(Object x, OSChatMessage e) + { + m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); + m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); + Work moreWork = new Work(); + moreWork.Type = WorkType.SIMCHAT; + moreWork.Data1 = e; + m_WorkQueue.Enqueue(moreWork); + } + + /// + /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. + /// + protected void StartManaging(IClientAPI client) + { + m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); + client.OnChatFromViewer += SimChatSent; + init = true; + + OnNewClient(client); + + m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); + client.OnUpdatePrimScale += UpdateSingleScale; client.OnUpdatePrimGroupScale += UpdateMultipleScale; - client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; + client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; client.OnUpdatePrimSinglePosition += UpdateSinglePosition; client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; client.OnUpdatePrimSingleRotation += UpdateSingleRotation; - client.OnAddPrim += UpdateNewParts; - client.OnObjectDuplicate += ObjectDuplicated; + client.OnAddPrim += UpdateNewParts; + client.OnObjectDuplicate += ObjectDuplicated; client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; - client.OnUndo += OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - } - - /// - /// - /// - protected void StopManaging(LLUUID clientUUID) - { - foreach(Object sceneobj in m_sceneList.Values) - { - ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); - if (presence != null) - { - IClientAPI client = presence.ControllingClient; - m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); - client.OnChatFromViewer -= SimChatSent; - - m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); - client.OnUpdatePrimScale -= UpdateSingleScale; - client.OnUpdatePrimGroupScale -= UpdateMultipleScale; - client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; - client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; - client.OnAddPrim -= UpdateNewParts; - client.OnObjectDuplicate -= ObjectDuplicated; - client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; - client.OnUndo -= OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - return; - } - } - } - - protected void GroupBeingDeleted(SceneObjectGroup group) - { - m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTKILLED; - moreWork.Data1 = group.Copy(); - m_WorkQueue.Enqueue(moreWork); - } - - //This is stupid, the same information is contained in the first and second argument - protected void SimChatSent(Object x, OSChatMessage e) - { - m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); - m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); - Work moreWork = new Work(); - moreWork.Type = WorkType.SIMCHAT; - moreWork.Data1 = e; - m_WorkQueue.Enqueue(moreWork); - } - - protected void ObjectDuplicated(uint localID, LLVector3 offset, uint dupeFlags, LLUUID AgentID, LLUUID GroupID) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, LLUUID AgentID, LLUUID GroupID, - LLUUID RayTargetObj, LLVector3 RayEnd, LLVector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void OnNewClient(IClientAPI client) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.NEWCLIENT; - moreWork.Data1 = client; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new client"); - } - - protected void OnUnDid(IClientAPI remoteClient, LLUUID primId) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.UNDODID; - moreWork.UUID = primId; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] undid"); - } - - protected void UpdateSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] move"); - } - - /// - /// - /// - protected void UpdateSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateSingleScale(uint localID, LLVector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] scale"); - } - - protected void UpdateMultiplePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] pos"); - } - - protected void UpdateMultipleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateMultipleScale(uint localID, LLVector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT]scale"); - } - - protected void UpdateNewParts(LLUUID ownerID, LLVector3 RayEnd, LLQuaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, LLVector3 RayStart, LLUUID RayTargetID, - byte RayEndIsIntersection) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.PRIMITIVEADDED; - moreWork.UUID = ownerID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new parts"); + client.OnUndo += OnUnDid; + //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; } - } -} + + /// + /// + /// + protected void StopManaging(LLUUID clientUUID) + { + foreach(Object sceneobj in m_sceneList.Values) + { + ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); + if (presence != null) + { + IClientAPI client = presence.ControllingClient; + m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); + client.OnChatFromViewer -= SimChatSent; + + m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); + client.OnUpdatePrimScale -= UpdateSingleScale; + client.OnUpdatePrimGroupScale -= UpdateMultipleScale; + client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; + client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; + client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; + client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; + client.OnAddPrim -= UpdateNewParts; + client.OnObjectDuplicate -= ObjectDuplicated; + client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; + client.OnUndo -= OnUnDid; + //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; + return; + } + } + } + + protected void UpdateMultiplePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] pos"); + } + + protected void UpdateMultipleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] rot"); + } + + protected void UpdateMultipleScale(uint localID, LLVector3 scale, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT]scale"); + } + + protected void UpdateNewParts(LLUUID ownerID, LLVector3 RayEnd, LLQuaternion rot, PrimitiveBaseShape shape, + byte bypassRaycast, LLVector3 RayStart, LLUUID RayTargetID, + byte RayEndIsIntersection) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.PRIMITIVEADDED; + moreWork.UUID = ownerID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] new parts"); + } + + protected void UpdateSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] move"); + } + + /// + /// + /// + protected void UpdateSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] rot"); + } + + protected void UpdateSingleScale(uint localID, LLVector3 scale, IClientAPI remoteClient) + { + Work moreWork = new Work(); + moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; + moreWork.LocalId = localID; + m_WorkQueue.Enqueue(moreWork); + m_log.Debug("[CONTENT MANAGEMENT] scale"); + } + + /// + /// Only called from within the SimChat method. + /// + protected void commit(string message, Scene scene, CMModel model, CMView view) + { + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); + + string[] args = message.Split(new char[] {' '}); + + char[] logMessage = {' '}; + if (args.Length > 1) + { + logMessage = new char[message.Length - (args[0].Length)]; + message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); + } + + m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); + foreach(Scene currScene in proximitySceneList) + { + model.CommitRegion(currScene, new String(logMessage)); + view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); + } + + view.SendSimChatMessage(scene, "Successfully saved all regions."); + m_state |= State.DIRTY; + + if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES + { + view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); + //Hide objects from users and Forget about them + view.HideAllMetaEntities(); + view.HideAllAuras(); + model.DeleteAllMetaObjects(); + + //Recreate them from backend files + foreach(Scene currScene in proximitySceneList) + { + model.UpdateCMEntities(currScene); + view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); + } + + //Display new objects to users1 + view.DisplayRecentChanges(); + view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); + m_state &= ~(State.DIRTY); + m_state |= State.SHOWING_CHANGES; + } + } + + /// + /// Only called from within the SimChat method. + /// + protected void diffmode(Scene scene, CMModel model, CMView view) + { + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); + + if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF + { + view.SendSimChatMessage(scene, "Hiding all meta objects."); + view.HideAllMetaEntities(); + view.HideAllAuras(); + view.SendSimChatMessage(scene, "Diff-mode = OFF"); + + m_state &= ~State.SHOWING_CHANGES; + return; + } + else // TURN ON + { + if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) + { + view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); + //Hide objects from users and Forget about them + view.HideAllMetaEntities(); + view.HideAllAuras(); + model.DeleteAllMetaObjects(); + //Recreate them from backend files + foreach(Object currScene in m_sceneList.Values) + model.UpdateCMEntities((Scene) currScene); + } + else if ((m_state & State.DIRTY) != 0) { + view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); + foreach(Scene currScene in proximitySceneList) + model.UpdateCMEntities(currScene); + } + + view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); + foreach(Scene currScene in proximitySceneList) + model.CheckForNewEntitiesMissingAuras(currScene); + view.DisplayRecentChanges(); + + view.SendSimChatMessage(scene, "Diff-mode = ON"); + m_state |= State.SHOWING_CHANGES; + m_state &= ~State.DIRTY; + } + } + + /// + /// Only called from within the SimChat method. Hides all auras and meta entities, + /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, + /// then lets the view update the clients of the new objects. + /// + protected void rollback(Scene scene, CMModel model, CMView view) + { + if ((m_state & State.SHOWING_CHANGES) > 0) + { + view.HideAllAuras(); + view.HideAllMetaEntities(); + } + + System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity( m_sceneList, scene); + foreach(Scene currScene in proximitySceneList) + model.RollbackRegion(currScene); + + if ((m_state & State.DIRTY) != 0 ) + { + model.DeleteAllMetaObjects(); + foreach(Scene currScene in proximitySceneList) + model.UpdateCMEntities(currScene); + } + + if ((m_state & State.SHOWING_CHANGES) > 0) + view.DisplayRecentChanges(); + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. + /// + /// + /// A + /// + public void RegisterNewRegion(Scene scene) + { + m_sceneList.Add(scene.RegionInfo.RegionID, scene); + + m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); + m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); + + scene.EventManager.OnNewClient += StartManaging; + scene.EventManager.OnRemovePresence += StopManaging; + // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; + scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; + } + + /// + /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. + /// + public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) + { + if (e.Channel != channel) + return; + if (e.Sender == null) + return; + + m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); + + IClientAPI client = e.Sender; + Scene scene = (Scene) e.Scene; + string message = e.Message; + string[] args = e.Message.Split(new char[] {' '}); + + ScenePresence avatar = scene.GetScenePresence(client.AgentId); + + if (!(m_estateModule.IsManager(avatar.UUID))) + { + m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); + view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); + return; + } + + switch(args[0]) + { + case "ci": + case "commit": + commit(message, scene, model, view); + break; + case "dm": + case "diff-mode": + diffmode(scene, model, view); + break; + case "rb": + case "rollback": + rollback(scene, model, view); + break; + case "help": + m_view.DisplayHelpMenu(scene); + break; + default: + view.SendSimChatMessage(scene, "Command not found: " + args[0]); + break; + } + } + + #endregion Public Methods + + #region Other + + /// + /// 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. + /// + [Flags] + private enum State + { + NONE = 0, + DIRTY = 1, // The meta entities may not correctly represent the last revision. + SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. + } + + /// + /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. + /// + private struct Work + { + #region Fields + + public Object Data1; //Just space for holding data. + public Object Data2; //Just more space for holding data. + public uint LocalId; //Convenient + public WorkType Type; + public LLUUID UUID; //Convenient + + #endregion Fields + } + + /// + /// Identifies what the data in struct Work should be used for. + /// + private enum WorkType + { + NONE, + OBJECTATTRIBUTECHANGE, + PRIMITIVEADDED, + OBJECTDUPLICATED, + OBJECTKILLED, + UNDODID, + NEWCLIENT, + SIMCHAT + } + + #endregion Other + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs index 9f50e239fb..2383a6d2cd 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMEntityCollection.cs @@ -1,148 +1,169 @@ +#region Header + // CMEntityCollection.cs created with MonoDevelop // User: bongiojp at 10:09 AM 7/7/2008 // // Creates, Deletes, Stores ContentManagementEntities // +#endregion Header using System; -using System.Collections.Generic; using System.Collections; +using System.Collections.Generic; +using System.Threading; + using libsecondlife; + using Nini.Config; + using OpenSim; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using System.Threading; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - public class CMEntityCollection - { - // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or - // old versions of deleted SceneObjectGroups will be stored in this hash table. - // The LLUUID keys are from the SceneObjectGroup RootPart UUIDs - protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //LLUUID to ContentManagementEntity - - // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable - // The LLUUID keys are from the SceneObjectPart that they are supposed to be on. - protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //LLUUID to AuraMetaEntity - - public Hashtable Entities - { - get { return m_CMEntityHash; } - } - - public Hashtable Auras - { - get {return m_NewlyCreatedEntityAura; } - } - - public CMEntityCollection() - {} - - public bool AddAura(ContentManagementEntity aura) - { - if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) - return false; - m_NewlyCreatedEntityAura.Add(aura.UUID, aura); - return true; - } - - public bool AddEntity(ContentManagementEntity ent) - { - if (m_CMEntityHash.ContainsKey(ent.UUID)) - return false; - m_CMEntityHash.Add(ent.UUID, ent); - return true; - } - - public bool RemoveNewlyCreatedEntityAura(LLUUID uuid) - { - if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) - return false; - m_NewlyCreatedEntityAura.Remove(uuid); - return true; - } - - public bool RemoveEntity(LLUUID uuid) - { - if (!m_CMEntityHash.ContainsKey(uuid)) - return false; - m_CMEntityHash.Remove(uuid); - return true; - } - - public void ClearAll() - { - m_CMEntityHash.Clear(); - m_NewlyCreatedEntityAura.Clear(); - } - + public class CMEntityCollection + { + #region Fields - - // Old uuid and new sceneobjectgroup - public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) - { - AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, - part.ParentGroup.Scene.PrimIDAllocate(), - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new LLVector3(0,254,0), - part.Scale - ); - m_NewlyCreatedEntityAura.Add(part.UUID, ent); - return ent; - } + // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or + // old versions of deleted SceneObjectGroups will be stored in this hash table. + // The LLUUID keys are from the SceneObjectGroup RootPart UUIDs + protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //LLUUID to ContentManagementEntity - // Old uuid and new sceneobjectgroup - public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) - { - ContentManagementEntity ent = new ContentManagementEntity(group, false); - m_CMEntityHash.Add(group.UUID, ent); - return ent; - } - - public ContentManagementEntity CreateNewEntity(String xml, Scene scene) - { - ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); - if (ent == null) - return null; - m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); - return ent; - } - - // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash - public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List currList) - { - System.Collections.ArrayList missingList = new System.Collections.ArrayList(); - SceneObjectGroup temp = null; - foreach( EntityBase currObj in currList ) - { - if (! (currObj is SceneObjectGroup)) - continue; - temp = (SceneObjectGroup) currObj; - - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach(SceneObjectPart part in temp.Children.Values) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach(SceneObjectPart part in temp.Children.Values) - missingList.Add(part); - } - } - return missingList; - } - } -} + // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable + // The LLUUID keys are from the SceneObjectPart that they are supposed to be on. + protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //LLUUID to AuraMetaEntity + + #endregion Fields + + #region Constructors + + public CMEntityCollection() + { + } + + #endregion Constructors + + #region Public Properties + + public Hashtable Auras + { + get {return m_NewlyCreatedEntityAura; } + } + + public Hashtable Entities + { + get { return m_CMEntityHash; } + } + + #endregion Public Properties + + #region Public Methods + + public bool AddAura(ContentManagementEntity aura) + { + if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) + return false; + m_NewlyCreatedEntityAura.Add(aura.UUID, aura); + return true; + } + + public bool AddEntity(ContentManagementEntity ent) + { + if (m_CMEntityHash.ContainsKey(ent.UUID)) + return false; + m_CMEntityHash.Add(ent.UUID, ent); + return true; + } + + // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash + public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List currList) + { + System.Collections.ArrayList missingList = new System.Collections.ArrayList(); + SceneObjectGroup temp = null; + foreach( EntityBase currObj in currList ) + { + if (! (currObj is SceneObjectGroup)) + continue; + temp = (SceneObjectGroup) currObj; + + if (m_CMEntityHash.ContainsKey(temp.UUID)) + { + foreach(SceneObjectPart part in temp.Children.Values) + if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) + missingList.Add(part); + } + else //Entire group is missing from revision. (and is a new part in region) + { + foreach(SceneObjectPart part in temp.Children.Values) + missingList.Add(part); + } + } + return missingList; + } + + public void ClearAll() + { + m_CMEntityHash.Clear(); + m_NewlyCreatedEntityAura.Clear(); + } + + // Old uuid and new sceneobjectgroup + public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) + { + AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, + part.ParentGroup.Scene.PrimIDAllocate(), + part.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new LLVector3(0,254,0), + part.Scale + ); + m_NewlyCreatedEntityAura.Add(part.UUID, ent); + return ent; + } + + // Old uuid and new sceneobjectgroup + public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) + { + ContentManagementEntity ent = new ContentManagementEntity(group, false); + m_CMEntityHash.Add(group.UUID, ent); + return ent; + } + + public ContentManagementEntity CreateNewEntity(String xml, Scene scene) + { + ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); + if (ent == null) + return null; + m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); + return ent; + } + + public bool RemoveEntity(LLUUID uuid) + { + if (!m_CMEntityHash.ContainsKey(uuid)) + return false; + m_CMEntityHash.Remove(uuid); + return true; + } + + public bool RemoveNewlyCreatedEntityAura(LLUUID uuid) + { + if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) + return false; + m_NewlyCreatedEntityAura.Remove(uuid); + return true; + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs index a47f83ab7b..3355fa3617 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMModel.cs @@ -1,47 +1,128 @@ +#region Header + // CMModel.cs // User: bongiojp // // +#endregion Header + using System; -using System.Collections.Generic; using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; + using libsecondlife; + using OpenSim; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using System.Diagnostics; namespace OpenSim.Region.Environment.Modules.ContentManagement { - public class CMModel - { + { + #region Static Fields + static float TimeToUpdate = 0; static float TimeToConvertXml = 0; - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - IContentDatabase m_database = null; - + + #endregion Static Fields + + #region Fields + /// /// The class that contains all auras and metaentities used in the CMS. /// CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); - + IContentDatabase m_database = null; + + #endregion Fields + + #region Constructors + + public CMModel() + { + } + + #endregion Constructors + + #region Public Properties + public CMEntityCollection MetaEntityCollection { get { return m_MetaEntityCollection; } } - - public CMModel() + + #endregion Public Properties + + #region Public Methods + + /// + /// 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 + /// it is a new part that must have a green aura (for diff mode). + /// Returns list of ContentManagementEntities + /// + public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) { + ArrayList missingList = null; + ArrayList newList = new ArrayList(); + + m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); + + //Check if the current scene has groups not included in the current list of MetaEntities + //If so, then the current scene's parts that are new should be marked green. + missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); + + foreach(Object missingPart in missingList) + { + if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) + continue; + newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); + } + m_log.Info("Number of missing objects found: " + newList.Count); + return newList; } - + + /// + /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. + /// + public void CommitRegion(Scene scene, String logMessage) + { + m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); + m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); + m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); + } + + public void DeleteAllMetaObjects() + { + m_MetaEntityCollection.ClearAll(); + } + + public ContentManagementEntity FindMetaEntityAffectedByUndo(LLUUID uuid) + { + ContentManagementEntity ent = GetMetaGroupByPrim(uuid); + return ent; + } + + //-------------------------------- HELPERS --------------------------------------------------------------------// + public ContentManagementEntity GetMetaGroupByPrim(LLUUID uuid) + { + foreach (Object ent in m_MetaEntityCollection.Entities.Values) + { + if (((ContentManagementEntity)ent).HasChildPrim(uuid)) + return (ContentManagementEntity)ent; + } + return null; + } + public void Initialise(string database) { if (database == "FileSystemDatabase") @@ -49,12 +130,12 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement else if (database == "GitDatabase") m_database = new GitDatabase(); } - + public void InitialiseDatabase(Scene scene, string dir) { m_database.Initialise(scene, dir); } - + /// /// Should be called just once to finish initializing the database. /// @@ -62,13 +143,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement { m_database.PostInitialise(); } - - public ContentManagementEntity FindMetaEntityAffectedByUndo(LLUUID uuid) - { - ContentManagementEntity ent = GetMetaGroupByPrim(uuid); - return ent; - } - + /// /// Removes the green aura when an a new scene object group is deleted. /// @@ -79,17 +154,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); } - - /// - /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. - /// - public void CommitRegion(Scene scene, String logMessage) - { - m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); - m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); - m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); - } - + /// /// Retrieves the latest revision of a region in xml form, /// converts it to scene object groups and scene presences, @@ -105,20 +170,20 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement Dictionary ReplacementList = new Dictionary(); int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); EntityBase[] searchArray; - + xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); if (xmllist == null) { m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); return; } - + m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); - + m_log.ErrorFormat("[CMMODEL]: 1"); - + foreach (string xml in xmllist) { try{ @@ -143,7 +208,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement { if (entity == null) continue; - + if (entity is ScenePresence) { ReplacementList.Add(entity.UUID, entity); @@ -162,7 +227,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement } break; } - + foreach(LLUUID uuid in deleteListUUIDs.Keys) { try @@ -179,7 +244,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); } } - + lock (scene) { scene.Entities = ReplacementList; @@ -191,7 +256,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement { if (!(ent is SceneObjectGroup)) continue; - + if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) LLObject.ObjectFlags.Phantom) == 0) ((SceneObjectGroup)ent).ApplyPhysics(true); ((SceneObjectGroup)ent).AttachToBackup(); @@ -206,32 +271,6 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); scene.Backup(); } - - /// - /// Detects if a scene object group from the scene list has moved or changed scale. The green aura - /// that surrounds the object is then moved or scaled with the group. - /// - public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) - { - System.Collections.ArrayList auraList = new System.Collections.ArrayList(); - if (group == null) - return null; - foreach(SceneObjectPart part in group.Children.Values) - { - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new LLVector3(0,254,0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } - } - return auraList; - } - - public void DeleteAllMetaObjects() - { - m_MetaEntityCollection.ClearAll(); - } /// /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences @@ -257,53 +296,37 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement TimeToConvertXml += y.ElapsedMilliseconds; m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); - + m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); CheckForNewEntitiesMissingAuras(scene); - + x.Stop(); TimeToUpdate += x.ElapsedMilliseconds; m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); - } - - /// - /// 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 - /// it is a new part that must have a green aura (for diff mode). - /// Returns list of ContentManagementEntities - /// - public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) - { - ArrayList missingList = null; - ArrayList newList = new ArrayList(); - - m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); - - //Check if the current scene has groups not included in the current list of MetaEntities - //If so, then the current scene's parts that are new should be marked green. - missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); - foreach(Object missingPart in missingList) - { - if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) - continue; - newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); - } - m_log.Info("Number of missing objects found: " + newList.Count); - return newList; - } - - //-------------------------------- HELPERS --------------------------------------------------------------------// - - public ContentManagementEntity GetMetaGroupByPrim(LLUUID uuid) + /// + /// Detects if a scene object group from the scene list has moved or changed scale. The green aura + /// that surrounds the object is then moved or scaled with the group. + /// + public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) { - foreach (Object ent in m_MetaEntityCollection.Entities.Values) + System.Collections.ArrayList auraList = new System.Collections.ArrayList(); + if (group == null) + return null; + foreach(SceneObjectPart part in group.Children.Values) { - if (((ContentManagementEntity)ent).HasChildPrim(uuid)) - return (ContentManagementEntity)ent; + if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) + { + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new LLVector3(0,254,0), part.Scale); + ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); + auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); + } } - return null; + return auraList; } - } + + #endregion Public Methods + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs index f8b0ec9483..f801f67fa3 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/CMView.cs @@ -1,156 +1,181 @@ +#region Header + // CMView.cs created with MonoDevelop // User: bongiojp at 11:57 AM 7/3/2008 // // To change standard headers go to Edit->Preferences->Coding->Standard Headers // +#endregion Header + using System; -using System.Collections.Generic; using System.Collections; +using System.Collections.Generic; + using libsecondlife; + using OpenSim; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - public class CMView - { - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - CMModel m_model = null; - - public CMView() - {} - - public void Initialise(CMModel model) - { - m_model = model; - } - - public void SendMetaEntitiesToNewClient(IClientAPI client) - { - } - - /// - /// update all clients of red/green/blue auras and meta entities that the model knows about. - /// - public void DisplayRecentChanges() - { - m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); - DisplayEntities(m_model.MetaEntityCollection); - DisplayAuras(m_model.MetaEntityCollection); - } - - /// - /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. - /// If it's a new scene object, any green aura attached to it is deleted. - /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will - /// figure out that there should be a red aura and not a blue aura/beam. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with revisioned parts that have been deleted. - if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) - ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); - - // Deal with new parts not revisioned that have been deleted. - foreach(SceneObjectPart part in group.Children.Values) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } + public class CMView + { + #region Static Fields - // Auras To - public void DisplayAuras(CMEntityCollection auraCollection) - { - foreach( Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - - // Entities to ALL - public void DisplayEntities(CMEntityCollection entityCollection) - { - foreach( Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Auras To Client - public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) - { - foreach( Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdate(client); - } - - // Entities to Client - public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) - { - foreach( Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdate(client); - } - - // Entity to ALL - public void DisplayEntity(ContentManagementEntity ent) - { - ent.SendFullDiffUpdateToAll(); - } - - public void DisplayMetaEntity(LLUUID uuid) - { - ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); - if (group != null) - group.SendFullDiffUpdateToAll(); - } - - // Auras from List To ALL - public void DisplayAuras(ArrayList list) - { - foreach( Object ent in list) - { - m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - } - - // Entities from List to ALL - public void DisplayEntities(ArrayList list) - { - foreach( Object ent in list) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - public void DisplayHelpMenu(Scene scene) - { - string menu = "Menu:\n"; - menu += "commit (ci) - saves current state of the region to a database on the server\n"; - 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"; - SendSimChatMessage(scene, menu); - } - - public void SendSimChatMessage(Scene scene, string message) - { - scene.SimChat(Helpers.StringToField(message), - ChatTypeEnum.Broadcast, 0, new LLVector3(0,0,0), "Content Manager", LLUUID.Zero, false); - } - - public void Hide(ContentManagementEntity ent) - { - ent.HideFromAll(); - } - - public void HideAllMetaEntities() - { - foreach(Object obj in m_model.MetaEntityCollection.Entities.Values) - ((ContentManagementEntity)obj).HideFromAll(); - } - - public void HideAllAuras() - { - foreach(Object obj in m_model.MetaEntityCollection.Auras.Values) - ((MetaEntity)obj).HideFromAll(); - } - } -} + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + CMModel m_model = null; + + #endregion Fields + + #region Constructors + + public CMView() + { + } + + #endregion Constructors + + #region Public Methods + + // Auras To + public void DisplayAuras(CMEntityCollection auraCollection) + { + foreach( Object ent in auraCollection.Auras.Values) + ((AuraMetaEntity)ent).SendFullUpdateToAll(); + } + + // Auras To Client + public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) + { + foreach( Object ent in auraCollection.Auras.Values) + ((AuraMetaEntity)ent).SendFullUpdate(client); + } + + // Auras from List To ALL + public void DisplayAuras(ArrayList list) + { + foreach( Object ent in list) + { + m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); + ((AuraMetaEntity)ent).SendFullUpdateToAll(); + } + } + + // Entities to ALL + public void DisplayEntities(CMEntityCollection entityCollection) + { + foreach( Object ent in entityCollection.Entities.Values) + ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); + } + + // Entities to Client + public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) + { + foreach( Object ent in entityCollection.Entities.Values) + ((ContentManagementEntity)ent).SendFullDiffUpdate(client); + } + + // Entities from List to ALL + public void DisplayEntities(ArrayList list) + { + foreach( Object ent in list) + ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); + } + + // Entity to ALL + public void DisplayEntity(ContentManagementEntity ent) + { + ent.SendFullDiffUpdateToAll(); + } + + public void DisplayHelpMenu(Scene scene) + { + string menu = "Menu:\n"; + menu += "commit (ci) - saves current state of the region to a database on the server\n"; + 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"; + SendSimChatMessage(scene, menu); + } + + public void DisplayMetaEntity(LLUUID uuid) + { + ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); + if (group != null) + group.SendFullDiffUpdateToAll(); + } + + /// + /// update all clients of red/green/blue auras and meta entities that the model knows about. + /// + public void DisplayRecentChanges() + { + m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); + DisplayEntities(m_model.MetaEntityCollection); + DisplayAuras(m_model.MetaEntityCollection); + } + + public void Hide(ContentManagementEntity ent) + { + ent.HideFromAll(); + } + + public void HideAllAuras() + { + foreach(Object obj in m_model.MetaEntityCollection.Auras.Values) + ((MetaEntity)obj).HideFromAll(); + } + + public void HideAllMetaEntities() + { + foreach(Object obj in m_model.MetaEntityCollection.Entities.Values) + ((ContentManagementEntity)obj).HideFromAll(); + } + + public void Initialise(CMModel model) + { + m_model = model; + } + + /// + /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. + /// If it's a new scene object, any green aura attached to it is deleted. + /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will + /// figure out that there should be a red aura and not a blue aura/beam. + /// + public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) + { + // Deal with revisioned parts that have been deleted. + if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) + ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); + + // Deal with new parts not revisioned that have been deleted. + foreach(SceneObjectPart part in group.Children.Values) + if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) + ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); + } + + public void SendMetaEntitiesToNewClient(IClientAPI client) + { + } + + public void SendSimChatMessage(Scene scene, string message) + { + scene.SimChat(Helpers.StringToField(message), + ChatTypeEnum.Broadcast, 0, new LLVector3(0,0,0), "Content Manager", LLUUID.Zero, false); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs index fb9df8f6ab..bdf8560d64 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementEntity.cs @@ -1,326 +1,362 @@ +#region Header + // ContentManagementEntity.cs // User: bongiojp // // +#endregion Header + using System; using System.Collections.Generic; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement { - public class ContentManagementEntity : MetaEntity - { - static float TimeToDiff = 0; - static float TimeToCreateEntities = 0; - - // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. - // This can come in handy. - protected SceneObjectGroup m_UnchangedEntity = null; - protected Dictionary m_BeamEntities = new Dictionary(); - protected Dictionary m_AuraEntities = new Dictionary(); - - /// - /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. - /// - bool DiffersFromSceneGroup = false; - - public SceneObjectGroup UnchangedEntity - { - get { return m_UnchangedEntity; } - } - - public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) : base(Unchanged, false) - { - m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); - } - - public ContentManagementEntity(string objectXML, Scene scene, bool physics) : base(objectXML, scene, false) - { - m_UnchangedEntity = new SceneObjectGroup(objectXML); - } - - public override void Hide(IClientAPI client) - { - base.Hide(client); - foreach(MetaEntity group in m_AuraEntities.Values) - group.Hide(client); - foreach(MetaEntity group in m_BeamEntities.Values) - group.Hide(client); - } - - public override void HideFromAll() - { - base.HideFromAll(); - foreach(MetaEntity group in m_AuraEntities.Values) - group.HideFromAll(); - foreach(MetaEntity group in m_BeamEntities.Values) - group.HideFromAll(); - } - - public void SendFullDiffUpdateToAll() - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdateToAll(); - SendFullAuraUpdateToAll(); - SendFullBeamUpdateToAll(); - } - } - - public void SendFullDiffUpdate(IClientAPI client) - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdate(client); - SendFullAuraUpdate(client); - SendFullBeamUpdate(client); - } - } - - public void SendFullBeamUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach(BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullAuraUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach(AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullBeamUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach(BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullAuraUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach(AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdateToAll(); - } - } - - /// - /// 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. - /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. - /// - public void FindDifferences() - { - System.Collections.Generic.List sceneEntityList = m_Entity.Scene.GetEntities(); - DiffersFromSceneGroup = false; - // if group is not contained in scene's list - if(!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) - { - foreach(SceneObjectPart part in m_UnchangedEntity.Children.Values) - { - // if scene list no longer contains this part, display translucent part and mark with red aura - if(! ContainsKey(sceneEntityList, part.UUID)) - { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new LLVector3(254,0,0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - m_Entity.Scene.PrimIDAllocate(), - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new LLVector3(254,0,0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); - } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id - } - - // a deleted part has no where to point a beam particle system, - // if a metapart had a particle system (maybe it represented a moved part) remove it - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - - DiffersFromSceneGroup = true; - } - // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately - else - { - MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); - } - } - - /// - /// Returns true if there was a change between meta entity and the entity group, false otherwise. - /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). - /// - public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) - { - SceneObjectPart sceneEntityPart; - SceneObjectPart metaEntityPart; - Diff differences; - bool changed = false; - - // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user - // had originally saved. - // m_Entity will NOT necessarily be the same entity as the user had saved. - foreach(SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) - { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) - { - sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences&Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_Entity.Scene.PrimIDAllocate(), - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new LLVector3(0,0,254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - m_Entity.Scene.PrimIDAllocate(), - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new LLVector3(0,0,254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part - { - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); - } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - m_Entity.Scene.PrimIDAllocate(), - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new LLVector3(254,0,0), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - } - return changed; - } - - private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, LLUUID uuid) + public class ContentManagementEntity : MetaEntity + { + #region Static Fields + + static float TimeToDiff = 0; + static float TimeToCreateEntities = 0; + + #endregion Static Fields + + #region Fields + + protected Dictionary m_AuraEntities = new Dictionary(); + protected Dictionary m_BeamEntities = new Dictionary(); + + // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. + // This can come in handy. + protected SceneObjectGroup m_UnchangedEntity = null; + + /// + /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. + /// + bool DiffersFromSceneGroup = false; + + #endregion Fields + + #region Constructors + + public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) + : base(Unchanged, false) { - foreach (EntityBase ent in list) - { - if (ent is SceneObjectGroup) - if (ent.UUID == uuid) - return (SceneObjectGroup)ent; - } - return null; - } + m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); + } - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. - /// - public bool HasChildPrim(LLUUID uuid) - { - if (m_UnchangedEntity.Children.ContainsKey(uuid)) - return true; - return false; - } + public ContentManagementEntity(string objectXML, Scene scene, bool physics) + : base(objectXML, scene, false) + { + m_UnchangedEntity = new SceneObjectGroup(objectXML); + } - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. - /// - public bool HasChildPrim(uint localID) - { - foreach( SceneObjectPart part in m_UnchangedEntity.Children.Values) - if ( part.LocalId == localID ) - return true; - return false; - } - - /// - /// Check if an entitybase list (like that returned by scene.GetEntities() ) contains a group with the rootpart uuid that matches the current uuid. - /// - private bool ContainsKey(List list, LLUUID uuid) - { - foreach( EntityBase part in list) - if (part.UUID == uuid) - return true; - return false; - } - } -} + #endregion Constructors + + #region Public Properties + + public SceneObjectGroup UnchangedEntity + { + get { return m_UnchangedEntity; } + } + + #endregion Public Properties + + #region Private Methods + + /// + /// Check if an entitybase list (like that returned by scene.GetEntities() ) contains a group with the rootpart uuid that matches the current uuid. + /// + private bool ContainsKey(List list, LLUUID uuid) + { + foreach( EntityBase part in list) + if (part.UUID == uuid) + return true; + return false; + } + + private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, LLUUID uuid) + { + foreach (EntityBase ent in list) + { + if (ent is SceneObjectGroup) + if (ent.UUID == uuid) + return (SceneObjectGroup)ent; + } + return null; + } + + #endregion Private Methods + + #region Public Methods + + /// + /// 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. + /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. + /// + public void FindDifferences() + { + System.Collections.Generic.List sceneEntityList = m_Entity.Scene.GetEntities(); + DiffersFromSceneGroup = false; + // if group is not contained in scene's list + if(!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) + { + foreach(SceneObjectPart part in m_UnchangedEntity.Children.Values) + { + // if scene list no longer contains this part, display translucent part and mark with red aura + if(! ContainsKey(sceneEntityList, part.UUID)) + { + // if already displaying a red aura over part, make sure its red + if (m_AuraEntities.ContainsKey(part.UUID)) + { + m_AuraEntities[part.UUID].SetAura(new LLVector3(254,0,0), part.Scale); + } + else + { + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + m_Entity.Scene.PrimIDAllocate(), + part.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new LLVector3(254,0,0), + part.Scale + ); + m_AuraEntities.Add(part.UUID, auraGroup); + } + SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); + SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); + } + // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id + } + + // a deleted part has no where to point a beam particle system, + // if a metapart had a particle system (maybe it represented a moved part) remove it + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + + DiffersFromSceneGroup = true; + } + // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately + else + { + MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); + } + } + + /// + /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. + /// + public bool HasChildPrim(LLUUID uuid) + { + if (m_UnchangedEntity.Children.ContainsKey(uuid)) + return true; + return false; + } + + /// + /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. + /// + public bool HasChildPrim(uint localID) + { + foreach( SceneObjectPart part in m_UnchangedEntity.Children.Values) + if ( part.LocalId == localID ) + return true; + return false; + } + + public override void Hide(IClientAPI client) + { + base.Hide(client); + foreach(MetaEntity group in m_AuraEntities.Values) + group.Hide(client); + foreach(MetaEntity group in m_BeamEntities.Values) + group.Hide(client); + } + + public override void HideFromAll() + { + base.HideFromAll(); + foreach(MetaEntity group in m_AuraEntities.Values) + group.HideFromAll(); + foreach(MetaEntity group in m_BeamEntities.Values) + group.HideFromAll(); + } + + /// + /// Returns true if there was a change between meta entity and the entity group, false otherwise. + /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). + /// + public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) + { + SceneObjectPart sceneEntityPart; + SceneObjectPart metaEntityPart; + Diff differences; + bool changed = false; + + // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user + // had originally saved. + // m_Entity will NOT necessarily be the same entity as the user had saved. + foreach(SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) + { + //This is the part that we use to show changes. + metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); + if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) + { + sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; + differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); + if (differences != Diff.NONE) + metaEntityPart.Text = "CHANGE: " + differences.ToString(); + if (differences != 0) + { + // Root Part that has been modified + if ((differences&Diff.POSITION) > 0) + { + // If the position of any part has changed, make sure the RootPart of the + // meta entity is pointing with a beam particle system + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, + m_Entity.Scene.PrimIDAllocate(), + m_UnchangedEntity.RootPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + sceneEntityPart, + new LLVector3(0,0,254) + ); + m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); + } + + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + m_Entity.Scene.PrimIDAllocate(), + UnchangedPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new LLVector3(0,0,254), + UnchangedPart.Scale + ); + m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); + SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); + + DiffersFromSceneGroup = true; + } + else // no differences between scene part and meta part + { + if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) + { + m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); + m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); + } + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + SetPartTransparency(metaEntityPart, MetaEntity.NONE); + } + } + else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. + { + if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) + { + m_AuraEntities[UnchangedPart.UUID].HideFromAll(); + m_AuraEntities.Remove(UnchangedPart.UUID); + } + AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, + m_Entity.Scene.PrimIDAllocate(), + UnchangedPart.GetWorldPosition(), + MetaEntity.TRANSLUCENT, + new LLVector3(254,0,0), + UnchangedPart.Scale + ); + m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); + SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); + + DiffersFromSceneGroup = true; + } + } + return changed; + } + + public void SendFullAuraUpdate(IClientAPI client) + { + if (DiffersFromSceneGroup) + { + foreach(AuraMetaEntity group in m_AuraEntities.Values) + group.SendFullUpdate(client); + } + } + + public void SendFullAuraUpdateToAll() + { + if (DiffersFromSceneGroup) + { + foreach(AuraMetaEntity group in m_AuraEntities.Values) + group.SendFullUpdateToAll(); + } + } + + public void SendFullBeamUpdate(IClientAPI client) + { + if (DiffersFromSceneGroup) + { + foreach(BeamMetaEntity group in m_BeamEntities.Values) + group.SendFullUpdate(client); + } + } + + public void SendFullBeamUpdateToAll() + { + if (DiffersFromSceneGroup) + { + foreach(BeamMetaEntity group in m_BeamEntities.Values) + group.SendFullUpdateToAll(); + } + } + + public void SendFullDiffUpdate(IClientAPI client) + { + FindDifferences(); + if (DiffersFromSceneGroup) + { + SendFullUpdate(client); + SendFullAuraUpdate(client); + SendFullBeamUpdate(client); + } + } + + public void SendFullDiffUpdateToAll() + { + FindDifferences(); + if (DiffersFromSceneGroup) + { + SendFullUpdateToAll(); + SendFullAuraUpdateToAll(); + SendFullBeamUpdateToAll(); + } + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs index 413d00d338..ef27f46aa7 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/ContentManagementModule.cs @@ -1,31 +1,69 @@ +#region Header + // ContentManagementModule.cs // User: bongiojp +#endregion Header + using System; using System.Collections.Generic; +using System.Threading; + using libsecondlife; + using Nini.Config; + using OpenSim; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using System.Threading; - + namespace OpenSim.Region.Environment.Modules.ContentManagement { public class ContentManagementModule : IRegionModule { + #region Static Fields + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - CMController m_control = null; - CMModel m_model = null; - CMView m_view = null; + + #endregion Static Fields + + #region Fields + bool initialised = false; - bool m_posted = false; + CMController m_control = null; bool m_enabled = false; - + CMModel m_model = null; + bool m_posted = false; + CMView m_view = null; + + #endregion Fields + + #region Public Properties + + public bool IsSharedModule + { + get { return true; } + } + + public string Name + { + get { return "ContentManagementModule"; } + } + + #endregion Public Properties + + #region Public Methods + + public void Close() + { + } + public void Initialise(Scene scene, IConfigSource source) { string databaseDir = "./"; @@ -52,13 +90,13 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); m_enabled = false; } - + if (!m_enabled) { m_log.Info("[Content Management]: Content Management System is not Enabled."); return; } - + lock(this) { if (!initialised) //only init once @@ -79,12 +117,12 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement } } } - + public void PostInitialise() { if (! m_enabled) return; - + lock(this) { if (!m_posted) //only post once @@ -94,18 +132,7 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement } } } - - public void Close() - {} - - public string Name - { - get { return "ContentManagementModule"; } - } - public bool IsSharedModule - { - get { return true; } - } + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs index e1f519b462..680cefbde4 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/FileSystemDatabase.cs @@ -1,159 +1,132 @@ +#region Header + // FileSystemDatabase.cs // User: bongiojp +#endregion Header + using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using Slash = System.IO.Path; using System.Reflection; using System.Xml; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Modules.World.Serialiser; using OpenSim.Region.Environment.Modules.World.Terrain; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using Slash=System.IO.Path; -using System.Diagnostics; namespace OpenSim.Region.Environment.Modules.ContentManagement { - public class FileSystemDatabase : IContentDatabase - { - public static float TimeToDownload = 0; - public static float TimeToSave = 0; - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_repodir = null; - private Dictionary m_serialiser = new Dictionary(); - private Dictionary m_scenes = new Dictionary(); - - public FileSystemDatabase() - { - } - - public void Initialise(Scene scene, string dir) - { - lock(this) - { - if (m_repodir == null) - m_repodir = dir; - } - lock(m_scenes) - m_scenes.Add(scene.RegionInfo.RegionID, scene); - } - - - // Run once and only once. - public void PostInitialise() - { - SetupSerialiser(); - - m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); - CreateDirectory(); - } - - // called by postinitialise - private void SetupSerialiser() + public class FileSystemDatabase : IContentDatabase + { + #region Static Fields + + public static float TimeToDownload = 0; + public static float TimeToSave = 0; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + private string m_repodir = null; + private Dictionary m_scenes = new Dictionary(); + private Dictionary m_serialiser = new Dictionary(); + + #endregion Fields + + #region Constructors + + public FileSystemDatabase() + { + } + + #endregion Constructors + + #region Private Methods + + // called by postinitialise + private void CreateDirectory() + { + string scenedir; + if (!Directory.Exists(m_repodir)) + Directory.CreateDirectory(m_repodir); + + foreach (LLUUID region in m_scenes.Keys) + { + scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; + if (!Directory.Exists(scenedir)) + Directory.CreateDirectory(scenedir); + } + } + + // called by postinitialise + private void SetupSerialiser() { if (m_serialiser.Count == 0) - foreach(LLUUID region in m_scenes.Keys) - m_serialiser.Add(region, - m_scenes[region].RequestModuleInterface() - ); + foreach(LLUUID region in m_scenes.Keys) + m_serialiser.Add(region, + m_scenes[region].RequestModuleInterface() + ); } - - // called by postinitialise - private void CreateDirectory() - { - string scenedir; - if (!Directory.Exists(m_repodir)) - Directory.CreateDirectory(m_repodir); - - foreach (LLUUID region in m_scenes.Keys) - { - scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - } - } - - public int NumOfRegionRev(LLUUID regionid) - { - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - m_log.Info("[FSDB]: Reading scene dir: " + scenedir); - string[] directories = Directory.GetDirectories(scenedir); - return directories.Length; - } - - public int GetMostRecentRevision(LLUUID regionid) - { - return NumOfRegionRev(regionid); - } - - public void SaveRegion(LLUUID regionid, string regionName, string logMessage) - { - m_log.Info("[FSDB]: ..............................."); - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - - int newRevisionNum = GetMostRecentRevision(regionid)+1; - string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); - if (!Directory.Exists(revisiondir)) - Directory.CreateDirectory(revisiondir); - - try { - Stopwatch x = new Stopwatch(); - x.Start(); - if (m_scenes.ContainsKey(regionid)) - { - m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); - } - x.Stop(); - TimeToSave += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); - return; - } - - try { - // Finish by writing log message. - FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); - StreamWriter sw = new StreamWriter(file); - sw.Write(logMessage); - sw.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); - return; - } - } - - public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision) - { - System.Collections.ArrayList objectList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); + + #endregion Private Methods + + #region Public Methods + + public int GetMostRecentRevision(LLUUID regionid) + { + return NumOfRegionRev(regionid); + } + + public string GetRegionObjectHeightMap(LLUUID regionid) + { + String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + + Slash.DirectorySeparatorChar + "heightmap.r32"; + FileStream fs = new FileStream( filename, FileMode.Open); + StreamReader sr = new StreamReader(fs); + String result = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + return result; + } + + public string GetRegionObjectHeightMap(LLUUID regionid, int revision) + { + String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + + Slash.DirectorySeparatorChar + "heightmap.r32"; + FileStream fs = new FileStream( filename, FileMode.Open); + StreamReader sr = new StreamReader(fs); + String result = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + return result; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision) + { + System.Collections.ArrayList objectList = new System.Collections.ArrayList(); + string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + + + revision + Slash.DirectorySeparatorChar + "objects.xml"; + XmlDocument doc = new XmlDocument(); XmlNode rootNode; //int primCount = 0; - //SceneObjectGroup obj = null; - - if(File.Exists(filename)) + //SceneObjectGroup obj = null; + + if(File.Exists(filename)) { XmlTextReader reader = new XmlTextReader(filename); reader.WhitespaceHandling = WhitespaceHandling.None; @@ -162,99 +135,153 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement rootNode = doc.FirstChild; foreach (XmlNode aPrimNode in rootNode.ChildNodes) { - objectList.Add(aPrimNode.OuterXml); - } - return objectList; - } - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid) - { - int revision = NumOfRegionRev(regionid); - m_log.Info("[FSDB]: found revisions:" + revision); - System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - + objectList.Add(aPrimNode.OuterXml); + } + return objectList; + } + return null; + } - m_log.Info("[FSDB]: Checking if " + filename + " exists."); - if(File.Exists(filename)) - { - Stopwatch x = new Stopwatch(); - x.Start(); - + public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid) + { + int revision = NumOfRegionRev(regionid); + m_log.Info("[FSDB]: found revisions:" + revision); + System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); + string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + + + revision + Slash.DirectorySeparatorChar + "objects.xml"; + XmlDocument doc = new XmlDocument(); + XmlNode rootNode; + + + m_log.Info("[FSDB]: Checking if " + filename + " exists."); + if(File.Exists(filename)) + { + Stopwatch x = new Stopwatch(); + x.Start(); + XmlTextReader reader = new XmlTextReader(filename); reader.WhitespaceHandling = WhitespaceHandling.None; doc.Load(reader); reader.Close(); rootNode = doc.FirstChild; - + foreach (XmlNode aPrimNode in rootNode.ChildNodes) - xmlList.Add(aPrimNode.OuterXml); - - x.Stop(); - TimeToDownload += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); - - return xmlList; - } - return null; - } - - public string GetRegionObjectHeightMap(LLUUID regionid) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream( filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public string GetRegionObjectHeightMap(LLUUID regionid, int revision) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream( filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID regionid) - { - SortedDictionary revisionDict = new SortedDictionary(); - - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - string[] directories = Directory.GetDirectories(scenedir); - - FileStream fs = null; - StreamReader sr = null; - String logMessage = ""; - String logLocation = ""; - foreach(string revisionDir in directories) - { - try { - logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; - fs = new FileStream( logLocation, FileMode.Open); - sr = new StreamReader(fs); - logMessage = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - revisionDict.Add(revisionDir, logMessage); - } - catch (Exception) - {} - } - - return revisionDict; - } - } -} + xmlList.Add(aPrimNode.OuterXml); + + x.Stop(); + TimeToDownload += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); + + return xmlList; + } + return null; + } + + public void Initialise(Scene scene, string dir) + { + lock(this) + { + if (m_repodir == null) + m_repodir = dir; + } + lock(m_scenes) + m_scenes.Add(scene.RegionInfo.RegionID, scene); + } + + public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID regionid) + { + SortedDictionary revisionDict = new SortedDictionary(); + + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + string[] directories = Directory.GetDirectories(scenedir); + + FileStream fs = null; + StreamReader sr = null; + String logMessage = ""; + String logLocation = ""; + foreach(string revisionDir in directories) + { + try { + logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; + fs = new FileStream( logLocation, FileMode.Open); + sr = new StreamReader(fs); + logMessage = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + revisionDict.Add(revisionDir, logMessage); + } + catch (Exception) + {} + } + + return revisionDict; + } + + public int NumOfRegionRev(LLUUID regionid) + { + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + m_log.Info("[FSDB]: Reading scene dir: " + scenedir); + string[] directories = Directory.GetDirectories(scenedir); + return directories.Length; + } + + // Run once and only once. + public void PostInitialise() + { + SetupSerialiser(); + + m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); + CreateDirectory(); + } + + public void SaveRegion(LLUUID regionid, string regionName, string logMessage) + { + m_log.Info("[FSDB]: ..............................."); + string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; + + m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); + if (!Directory.Exists(scenedir)) + Directory.CreateDirectory(scenedir); + + int newRevisionNum = GetMostRecentRevision(regionid)+1; + string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; + + m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); + if (!Directory.Exists(revisiondir)) + Directory.CreateDirectory(revisiondir); + + try { + Stopwatch x = new Stopwatch(); + x.Start(); + if (m_scenes.ContainsKey(regionid)) + { + m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); + } + x.Stop(); + TimeToSave += x.ElapsedMilliseconds; + m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); + m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); + } + catch (Exception e) + { + m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); + return; + } + + try { + // Finish by writing log message. + FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); + StreamWriter sw = new StreamWriter(file); + sw.Write(logMessage); + sw.Close(); + } + catch (Exception e) + { + m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); + return; + } + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs index e337482c59..5e85b2efff 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/GitDatabase.cs @@ -1,130 +1,142 @@ +#region Header + // GitDatabase.cs // // // +#endregion Header + using System; using System.Collections.Generic; using System.IO; +using Slash = System.IO.Path; using System.Reflection; using System.Xml; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Modules.World.Serialiser; using OpenSim.Region.Environment.Modules.World.Terrain; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using Slash=System.IO.Path; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - /// - /// Just a stub :-( - /// - public class GitDatabase : IContentDatabase - { - - public GitDatabase() - { - } + /// + /// Just a stub :-( + /// + public class GitDatabase : IContentDatabase + { + #region Constructors - public void Initialise(Scene scene, String dir) - { - - } - - public void PostInitialise() - { - - } + public GitDatabase() + { + } - public int NumOfObjectRev(LLUUID id) - { - return 0; - } + #endregion Constructors - public int NumOfRegionRev(LLUUID regionid) - { - return 0; - } + #region Public Methods - public bool InRepository(LLUUID id) - { - return false; - } + public SceneObjectGroup GetMostRecentObjectRevision(LLUUID id) + { + return null; + } - public void SaveRegion(LLUUID regionid, string regionName, string logMessage) - { - - } + public int GetMostRecentRevision(LLUUID regionid) + { + return 0; + } - public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid) - { - return null; - } + public SceneObjectGroup GetObjectRevision(LLUUID id, int revision) + { + return null; + } - public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectXML(LLUUID regionid) - { - return null; - } - - public string GetRegionObjectXML(LLUUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectHeightMap(LLUUID regionid) - { - return null; - } - - public string GetRegionObjectHeightMap(LLUUID regionid, int revision) - { - return null; - } - - public System.Collections.ArrayList GetObjectsFromRegion(LLUUID regionid, int revision) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID id) - { - return null; - } + public System.Collections.ArrayList GetObjectsFromRegion(LLUUID regionid, int revision) + { + return null; + } - public void SaveObject(SceneObjectGroup entity) - { - } - - public SceneObjectGroup GetMostRecentObjectRevision(LLUUID id) - { - return null; - } - - public SceneObjectGroup GetObjectRevision(LLUUID id, int revision) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(LLUUID id) - { - return null; - } - - public int GetMostRecentRevision(LLUUID regionid) - { - return 0; - } - } -} + public string GetRegionObjectHeightMap(LLUUID regionid) + { + return null; + } + + public string GetRegionObjectHeightMap(LLUUID regionid, int revision) + { + return null; + } + + public string GetRegionObjectXML(LLUUID regionid) + { + return null; + } + + public string GetRegionObjectXML(LLUUID regionid, int revision) + { + return null; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid) + { + return null; + } + + public System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision) + { + return null; + } + + public bool InRepository(LLUUID id) + { + return false; + } + + public void Initialise(Scene scene, String dir) + { + } + + public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(LLUUID id) + { + return null; + } + + public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID id) + { + return null; + } + + public int NumOfObjectRev(LLUUID id) + { + return 0; + } + + public int NumOfRegionRev(LLUUID regionid) + { + return 0; + } + + public void PostInitialise() + { + } + + public void SaveObject(SceneObjectGroup entity) + { + } + + public void SaveRegion(LLUUID regionid, string regionName, string logMessage) + { + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs index f37f95df12..1d8197827d 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/IContentDatabase.cs @@ -1,57 +1,70 @@ +#region Header + // IContentDatabase.cs // User: bongiojp // // // +#endregion Header + using System; + using libsecondlife; + using OpenSim.Region.Environment.Scenes; + using Nini.Config; namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public interface IContentDatabase - { - /// - /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. - /// Initialise should be called one for each region to be contained in the database. The directory should be the full path - /// to the repository and will only be defined once, regardless of how many times the method is called. - /// - void Initialise(Scene scene, String dir); - - /// - /// Should be called once after Initialise has been called. - /// - void PostInitialise(); - - /// - /// Returns the total number of revisions saved for a specific region. - /// - int NumOfRegionRev(LLUUID regionid); - - /// - /// Saves the Region terrain map and objects within the region as xml to the database. - /// - void SaveRegion(LLUUID regionid, string regionName, string logMessage); +{ + public interface IContentDatabase + { + #region Methods - /// - /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. - /// - System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid); - System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision); - - string GetRegionObjectHeightMap(LLUUID regionid); - string GetRegionObjectHeightMap(LLUUID regionid, int revision); - - /// - /// Returns a list of the revision numbers and corresponding log messages for a given region. - /// - System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID id); + /// + /// Returns the most recent revision number of a region. + /// + int GetMostRecentRevision(LLUUID regionid); - /// - /// Returns the most recent revision number of a region. - /// - int GetMostRecentRevision(LLUUID regionid); - } -} + string GetRegionObjectHeightMap(LLUUID regionid); + + string GetRegionObjectHeightMap(LLUUID regionid, int revision); + + /// + /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. + /// + System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid); + + System.Collections.ArrayList GetRegionObjectXMLList(LLUUID regionid, int revision); + + /// + /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. + /// Initialise should be called one for each region to be contained in the database. The directory should be the full path + /// to the repository and will only be defined once, regardless of how many times the method is called. + /// + void Initialise(Scene scene, String dir); + + /// + /// Returns a list of the revision numbers and corresponding log messages for a given region. + /// + System.Collections.Generic.SortedDictionary ListOfRegionRevisions(LLUUID id); + + /// + /// Returns the total number of revisions saved for a specific region. + /// + int NumOfRegionRev(LLUUID regionid); + + /// + /// Should be called once after Initialise has been called. + /// + void PostInitialise(); + + /// + /// Saves the Region terrain map and objects within the region as xml to the database. + /// + void SaveRegion(LLUUID regionid, string regionName, string logMessage); + + #endregion Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs index f0763d36b6..c2030542d5 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/MetaEntity.cs @@ -1,219 +1,256 @@ +#region Header + // MetaEntity.cs // User: bongiojp // // TODO: // 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. +#endregion Header using System; using System.Collections.Generic; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement -{ - public class MetaEntity - { - protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. - protected uint m_metaLocalid; - - // Settings for transparency of metaentity - public const float NONE = 0f; - public const float TRANSLUCENT = .5f; - public const float INVISIBLE = .95f; - - public Scene Scene - { - get { return m_Entity.Scene; } - } - - public SceneObjectPart RootPart - { - get { return m_Entity.RootPart; } - set { m_Entity.RootPart = value; } - } - - public LLUUID UUID - { - get { return m_Entity.UUID; } - set { m_Entity.UUID = value; } - } - - public uint LocalId - { - get { return m_Entity.LocalId; } - set { m_Entity.LocalId = value; } - } - - public SceneObjectGroup ObjectGroup - { - get { return m_Entity; } - } - - public Dictionary Children - { - get { return m_Entity.Children; } - set { m_Entity.Children = value; } - } - - public int PrimCount - { - get { return m_Entity.PrimCount; } - } - - public MetaEntity() - { - } - - /// - /// Makes a new meta entity by copying the given scene object group. - /// The physics boolean is just a stub right now. - /// - public MetaEntity(SceneObjectGroup orig, bool physics) - { - m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); - Initialize(physics); - } - - /// - /// Takes an XML description of a scene object group and converts it to a meta entity. - /// - public MetaEntity(string objectXML, Scene scene, bool physics) - { - m_Entity = new SceneObjectGroup(objectXML); - m_Entity.SetScene(scene); - Initialize(physics); - } +{ + public class MetaEntity + { + #region Constants - // The metaentity objectgroup must have unique localids as well as unique uuids. - // localids are used by the client to refer to parts. - // uuids are sent to the client and back to the server to identify parts on the server side. - /// - /// Changes localids and uuids of m_Entity. - /// - protected void Initialize(bool physics) - { - //make new uuids - Dictionary parts = new Dictionary(); - foreach(SceneObjectPart part in m_Entity.Children.Values) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - // make new localids - foreach (SceneObjectPart part in m_Entity.Children.Values) - part.LocalId = m_Entity.Scene.PrimIDAllocate(); - - //finalize - m_Entity.UpdateParentIDs(); - m_Entity.RootPart.PhysActor = null; - m_Entity.Children = parts; - - } - - public void SendFullUpdate(IClientAPI client) - { - // Not sure what clientFlags should be but 0 seems to work - SendFullUpdate(client, 0); - } - public void SendFullUpdateToAll() - { - uint clientFlags = 0; - m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) - { m_Entity.SendFullUpdateToClient(controller, clientFlags); } - ); - } - - public void SendFullUpdate(IClientAPI client, uint clientFlags) - { - m_Entity.SendFullUpdateToClient(client, clientFlags); - } - - /// - /// Hides the metaentity from a single client. - /// - public virtual void Hide(IClientAPI client) - { - //This deletes the group without removing from any databases. - //This is important because we are not IN any database. - //m_Entity.FakeDeleteGroup(); - foreach( SceneObjectPart part in m_Entity.Children.Values) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); - } - - /// - /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. - /// - public virtual void HideFromAll() - { - foreach( SceneObjectPart part in m_Entity.Children.Values) - m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } - ); - } - - /// - /// Makes a single SceneObjectPart see through. - /// - /// - /// A - /// The part to make see through - /// - /// - /// A - /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. - /// - public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) - { - LLObject.TextureEntry tex = null; - LLColor texcolor; - try - { - tex = part.Shape.Textures; - texcolor = new LLColor(); - } - catch(Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); - return; - } - - for (uint i = 0; i < tex.FaceTextures.Length; i++) - { - try { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = transparencyAmount; - tex.FaceTextures[i].RGBA = texcolor; - } - } - catch (Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); - continue; - } - } - try { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = transparencyAmount; - tex.DefaultTexture.RGBA = texcolor; - part.Shape.TextureEntry = tex.ToBytes(); - } - catch (Exception) - { - //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); - } - } - } + public const float INVISIBLE = .95f; + + // Settings for transparency of metaentity + public const float NONE = 0f; + public const float TRANSLUCENT = .5f; + + #endregion Constants + + #region Static Fields + + protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Fields + + protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. + protected uint m_metaLocalid; + + #endregion Fields + + #region Constructors + + public MetaEntity() + { + } + + /// + /// Makes a new meta entity by copying the given scene object group. + /// The physics boolean is just a stub right now. + /// + public MetaEntity(SceneObjectGroup orig, bool physics) + { + m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); + Initialize(physics); + } + + /// + /// Takes an XML description of a scene object group and converts it to a meta entity. + /// + public MetaEntity(string objectXML, Scene scene, bool physics) + { + m_Entity = new SceneObjectGroup(objectXML); + m_Entity.SetScene(scene); + Initialize(physics); + } + + #endregion Constructors + + #region Public Properties + + public Dictionary Children + { + get { return m_Entity.Children; } + set { m_Entity.Children = value; } + } + + public uint LocalId + { + get { return m_Entity.LocalId; } + set { m_Entity.LocalId = value; } + } + + public SceneObjectGroup ObjectGroup + { + get { return m_Entity; } + } + + public int PrimCount + { + get { return m_Entity.PrimCount; } + } + + public SceneObjectPart RootPart + { + get { return m_Entity.RootPart; } + set { m_Entity.RootPart = value; } + } + + public Scene Scene + { + get { return m_Entity.Scene; } + } + + public LLUUID UUID + { + get { return m_Entity.UUID; } + set { m_Entity.UUID = value; } + } + + #endregion Public Properties + + #region Protected Methods + + // The metaentity objectgroup must have unique localids as well as unique uuids. + // localids are used by the client to refer to parts. + // uuids are sent to the client and back to the server to identify parts on the server side. + /// + /// Changes localids and uuids of m_Entity. + /// + protected void Initialize(bool physics) + { + //make new uuids + Dictionary parts = new Dictionary(); + foreach(SceneObjectPart part in m_Entity.Children.Values) + { + part.ResetIDs(part.LinkNum); + parts.Add(part.UUID, part); + } + + // make new localids + foreach (SceneObjectPart part in m_Entity.Children.Values) + part.LocalId = m_Entity.Scene.PrimIDAllocate(); + + //finalize + m_Entity.UpdateParentIDs(); + m_Entity.RootPart.PhysActor = null; + m_Entity.Children = parts; + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Hides the metaentity from a single client. + /// + public virtual void Hide(IClientAPI client) + { + //This deletes the group without removing from any databases. + //This is important because we are not IN any database. + //m_Entity.FakeDeleteGroup(); + foreach( SceneObjectPart part in m_Entity.Children.Values) + client.SendKillObject(m_Entity.RegionHandle, part.LocalId); + } + + /// + /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. + /// + public virtual void HideFromAll() + { + foreach( SceneObjectPart part in m_Entity.Children.Values) + m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) + { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } + ); + } + + public void SendFullUpdate(IClientAPI client) + { + // Not sure what clientFlags should be but 0 seems to work + SendFullUpdate(client, 0); + } + + public void SendFullUpdate(IClientAPI client, uint clientFlags) + { + m_Entity.SendFullUpdateToClient(client, clientFlags); + } + + public void SendFullUpdateToAll() + { + uint clientFlags = 0; + m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) + { m_Entity.SendFullUpdateToClient(controller, clientFlags); } + ); + } + + /// + /// Makes a single SceneObjectPart see through. + /// + /// + /// A + /// The part to make see through + /// + /// + /// A + /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. + /// + public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) + { + LLObject.TextureEntry tex = null; + LLColor texcolor; + try + { + tex = part.Shape.Textures; + texcolor = new LLColor(); + } + catch(Exception) + { + //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); + return; + } + + for (uint i = 0; i < tex.FaceTextures.Length; i++) + { + try { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = transparencyAmount; + tex.FaceTextures[i].RGBA = texcolor; + } + } + catch (Exception) + { + //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); + continue; + } + } + try { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = transparencyAmount; + tex.DefaultTexture.RGBA = texcolor; + part.Shape.TextureEntry = tex.ToBytes(); + } + catch (Exception) + { + //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); + } + } + + #endregion Public Methods + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs index 55365ac4c4..bfa7e5d0de 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/PointMetaEntity.cs @@ -1,81 +1,97 @@ +#region Header + // PointMetaEntity.cs created with MonoDevelop // User: bongiojp at 3:03 PM 8/6/2008 // // To change standard headers go to Edit->Preferences->Coding->Standard Headers // +#endregion Header + using System; using System.Collections.Generic; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; namespace OpenSim.Region.Environment.Modules.ContentManagement { - - - public class PointMetaEntity : MetaEntity - { - - public PointMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency) : base() - { - CreatePointEntity(scene, LLUUID.Random(), LocalId, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - public PointMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency) : base() - { - CreatePointEntity(scene, uuid, LocalId, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - private void CreatePointEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos) - { - SceneObjectGroup x = new SceneObjectGroup(); - SceneObjectPart y = new SceneObjectPart(); - - //Initialize part - y.Name = "Very Small Point"; + public class PointMetaEntity : MetaEntity + { + #region Constructors + + public PointMetaEntity(Scene scene, uint LocalId, LLVector3 groupPos, float transparency) + : base() + { + CreatePointEntity(scene, LLUUID.Random(), LocalId, groupPos); + SetPartTransparency(m_Entity.RootPart, transparency); + } + + public PointMetaEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos, float transparency) + : base() + { + CreatePointEntity(scene, uuid, LocalId, groupPos); + SetPartTransparency(m_Entity.RootPart, transparency); + } + + #endregion Constructors + + #region Private Methods + + private void CreatePointEntity(Scene scene, LLUUID uuid, uint LocalId, LLVector3 groupPos) + { + SceneObjectGroup x = new SceneObjectGroup(); + SceneObjectPart y = new SceneObjectPart(); + + //Initialize part + y.Name = "Very Small Point"; y.RegionHandle = scene.RegionInfo.RegionHandle; y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; y.OwnerID = LLUUID.Zero; y.CreatorID = LLUUID.Zero; y.LastOwnerID = LLUUID.Zero; - y.UUID = uuid; - - y.LocalId = LocalId; - + y.UUID = uuid; + + y.LocalId = LocalId; + y.Shape = PrimitiveBaseShape.CreateBox(); - y.Scale = new LLVector3(0.01f,0.01f,0.01f); + y.Scale = new LLVector3(0.01f,0.01f,0.01f); y.LastOwnerID = LLUUID.Zero; y.GroupPosition = groupPos; - y.OffsetPosition = new LLVector3(0, 0, 0); - y.RotationOffset = new LLQuaternion(0,0,0,0); + y.OffsetPosition = new LLVector3(0, 0, 0); + y.RotationOffset = new LLQuaternion(0,0,0,0); y.Velocity = new LLVector3(0, 0, 0); y.RotationalVelocity = new LLVector3(0, 0, 0); y.AngularVelocity = new LLVector3(0, 0, 0); y.Acceleration = new LLVector3(0, 0, 0); - + y.Flags = 0; y.TrimPermissions(); - - //Initialize group and add part as root part - x.SetScene(scene); + + //Initialize group and add part as root part + x.SetScene(scene); y.SetParent(x); y.ParentID = 0; y.LinkNum = 0; x.Children.Add(y.UUID, y); x.RootPart = y; x.RegionHandle = scene.RegionInfo.RegionHandle; - x.SetScene(scene); - - m_Entity = x; - } - } -} + x.SetScene(scene); + + m_Entity = x; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs index c3817efa3e..6f34d3b39f 100644 --- a/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs +++ b/OpenSim/Region/Environment/Modules/ContentManagementSystem/SceneObjectGroupDiff.cs @@ -1,87 +1,113 @@ +#region Header + // SceneObjectGroupDiff.cs // User: bongiojp +#endregion Header + using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; + using libsecondlife; + using Nini.Config; + using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; -using log4net; using OpenSim.Region.Physics.Manager; + +using log4net; + using Axiom.Math; -using System.Diagnostics; namespace OpenSim.Region.Environment.Modules.ContentManagement { - [Flags] - public enum Diff - { - NONE = 0, - FACECOLOR = 1, - SHAPE = 1<<1, - MATERIAL = 1<<2, - TEXTURE = 1<<3, - SCALE = 1<<4, - POSITION = 1<<5, - OFFSETPOSITION = 1<<6, - ROTATIONOFFSET = 1<<7, - ROTATIONALVELOCITY = 1<<8, - ACCELERATION = 1<<9, - ANGULARVELOCITY = 1<<10, - VELOCITY = 1<<11, - OBJECTOWNER = 1<<12, - PERMISSIONS = 1<<13, - DESCRIPTION = 1<<14, - NAME = 1<<15, - SCRIPT = 1<<16, - CLICKACTION = 1<<17, - PARTICLESYSTEM = 1<<18, - GLOW = 1<<19, - SALEPRICE = 1<<20, - SITNAME = 1<<21, - SITTARGETORIENTATION = 1<<22, - SITTARGETPOSITION = 1<<23, - TEXT = 1<<24, - TOUCHNAME = 1<<25 - }; - - public static class Difference - { - static float TimeToDiff = 0; - - private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - private static int TruncateSignificant(float num, int digits) - { - return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); - // return (int) ((num * (10*digits))/10*digits); - } - - private static bool AreVectorsEquivalent(LLVector3 first, LLVector3 second) - { - if(TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) - && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) - && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) - ) - return true; - else - return false; - } - - private static bool AreQuaternionsEquivalent(LLQuaternion first, LLQuaternion second) - { - LLVector3 firstVector = llRot2Euler(first); - LLVector3 secondVector = llRot2Euler(second); - return AreVectorsEquivalent(firstVector, secondVector); - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - // Also changed the original function from LSL_Types to LL types + #region Enumerations + + [Flags] + public enum Diff + { + NONE = 0, + FACECOLOR = 1, + SHAPE = 1<<1, + MATERIAL = 1<<2, + TEXTURE = 1<<3, + SCALE = 1<<4, + POSITION = 1<<5, + OFFSETPOSITION = 1<<6, + ROTATIONOFFSET = 1<<7, + ROTATIONALVELOCITY = 1<<8, + ACCELERATION = 1<<9, + ANGULARVELOCITY = 1<<10, + VELOCITY = 1<<11, + OBJECTOWNER = 1<<12, + PERMISSIONS = 1<<13, + DESCRIPTION = 1<<14, + NAME = 1<<15, + SCRIPT = 1<<16, + CLICKACTION = 1<<17, + PARTICLESYSTEM = 1<<18, + GLOW = 1<<19, + SALEPRICE = 1<<20, + SITNAME = 1<<21, + SITTARGETORIENTATION = 1<<22, + SITTARGETPOSITION = 1<<23, + TEXT = 1<<24, + TOUCHNAME = 1<<25 + } + + #endregion Enumerations + + public static class Difference + { + #region Static Fields + + static float TimeToDiff = 0; + private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #endregion Static Fields + + #region Private Methods + + private static bool AreQuaternionsEquivalent(LLQuaternion first, LLQuaternion second) + { + LLVector3 firstVector = llRot2Euler(first); + LLVector3 secondVector = llRot2Euler(second); + return AreVectorsEquivalent(firstVector, secondVector); + } + + private static bool AreVectorsEquivalent(LLVector3 first, LLVector3 second) + { + if(TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) + && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) + && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) + ) + return true; + else + return false; + } + + // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs + private static double NormalizeAngle(double angle) + { + angle = angle % (Math.PI * 2); + if (angle < 0) angle = angle + Math.PI * 2; + return angle; + } + + private static int TruncateSignificant(float num, int digits) + { + return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); + // return (int) ((num * (10*digits))/10*digits); + } + + // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs + // Also changed the original function from LSL_Types to LL types private static LLVector3 llRot2Euler(LLQuaternion r) - { + { LLQuaternion t = new LLQuaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); double m = (t.X + t.Y + t.Z + t.W); if (m == 0) return new LLVector3(); @@ -96,74 +122,72 @@ namespace OpenSim.Region.Environment.Modules.ContentManagement else 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))); } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - private static double NormalizeAngle(double angle) - { - angle = angle % (Math.PI * 2); - if (angle < 0) angle = angle + Math.PI * 2; - return angle; + + #endregion Private Methods + + #region Public Methods + + /// + /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts + /// and returns a Diff bitmask which details what the differences are. + /// + public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) + { + Stopwatch x = new Stopwatch(); + x.Start(); + + Diff result = 0; + + // VECTOR COMPARISONS + if(! AreVectorsEquivalent(first.Acceleration, second.Acceleration)) + result |= Diff.ACCELERATION; + if(! AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) + result |= Diff.POSITION; + if(! AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) + result |= Diff.ANGULARVELOCITY; + if(! AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) + result |= Diff.OFFSETPOSITION; + if(! AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity)) + result |= Diff.ROTATIONALVELOCITY; + if(! AreVectorsEquivalent(first.Scale, second.Scale)) + result |= Diff.SCALE; + if(! AreVectorsEquivalent(first.Velocity, second.Velocity)) + result |= Diff.VELOCITY; + + + // QUATERNION COMPARISONS + if(! AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) + result |= Diff.ROTATIONOFFSET; + + + // MISC COMPARISONS (LLUUID, Byte) + if(first.ClickAction != second.ClickAction) + result |= Diff.CLICKACTION; + if(first.ObjectOwner != second.ObjectOwner) + result |= Diff.OBJECTOWNER; + + + // STRING COMPARISONS + if(first.Description != second.Description) + result |= Diff.DESCRIPTION; + if(first.Material != second.Material) + result |= Diff.MATERIAL; + if(first.Name != second.Name) + result |= Diff.NAME; + if(first.SitName != second.SitName) + result |= Diff.SITNAME; + if(first.Text != second.Text) + result |= Diff.TEXT; + if(first.TouchName != second.TouchName) + result |= Diff.TOUCHNAME; + + x.Stop(); + TimeToDiff += x.ElapsedMilliseconds; + //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); + + return result; } - - /// - /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts - /// and returns a Diff bitmask which details what the differences are. - /// - public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - Diff result = 0; - - // VECTOR COMPARISONS - if(! AreVectorsEquivalent(first.Acceleration, second.Acceleration)) - result |= Diff.ACCELERATION; - if(! AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) - result |= Diff.POSITION; - if(! AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) - result |= Diff.ANGULARVELOCITY; - if(! AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) - result |= Diff.OFFSETPOSITION; - if(! AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity)) - result |= Diff.ROTATIONALVELOCITY; - if(! AreVectorsEquivalent(first.Scale, second.Scale)) - result |= Diff.SCALE; - if(! AreVectorsEquivalent(first.Velocity, second.Velocity)) - result |= Diff.VELOCITY; - - // QUATERNION COMPARISONS - if(! AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) - result |= Diff.ROTATIONOFFSET; - - - // MISC COMPARISONS (LLUUID, Byte) - if(first.ClickAction != second.ClickAction) - result |= Diff.CLICKACTION; - if(first.ObjectOwner != second.ObjectOwner) - result |= Diff.OBJECTOWNER; - - - // STRING COMPARISONS - if(first.Description != second.Description) - result |= Diff.DESCRIPTION; - if(first.Material != second.Material) - result |= Diff.MATERIAL; - if(first.Name != second.Name) - result |= Diff.NAME; - if(first.SitName != second.SitName) - result |= Diff.SITNAME; - if(first.Text != second.Text) - result |= Diff.TEXT; - if(first.TouchName != second.TouchName) - result |= Diff.TOUCHNAME; - - x.Stop(); - TimeToDiff += x.ElapsedMilliseconds; - //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); - - return result; - } - } -} + #endregion Public Methods + } +} \ No newline at end of file