diff --git a/OpenMetaverse/Primitives/Primitive.cs b/OpenMetaverse/Primitives/Primitive.cs index 1eee4378..c1683d9d 100644 --- a/OpenMetaverse/Primitives/Primitive.cs +++ b/OpenMetaverse/Primitives/Primitive.cs @@ -1045,11 +1045,11 @@ namespace OpenMetaverse /// public float SoundRadius; /// - public string Text = String.Empty; + public string Text; /// public Color4 TextColor; /// - public string MediaURL = String.Empty; + public string MediaURL; /// public JointType Joint; /// @@ -1073,12 +1073,68 @@ namespace OpenMetaverse public Primitive() { // Default a few null property values to String.Empty + Text = String.Empty; + MediaURL = String.Empty; Properties.Name = String.Empty; Properties.Description = String.Empty; Properties.TouchName = String.Empty; Properties.SitName = String.Empty; } + public Primitive(Primitive prim) + { + ID = prim.ID; + GroupID = prim.GroupID; + LocalID = prim.LocalID; + ParentID = prim.ParentID; + RegionHandle = prim.RegionHandle; + Flags = prim.Flags; + if (prim.GenericData != null) + Buffer.BlockCopy(prim.GenericData, 0, GenericData, 0, prim.GenericData.Length); + else + GenericData = null; + Position = prim.Position; + Scale = prim.Scale; + Rotation = prim.Rotation; + Velocity = prim.Velocity; + AngularVelocity = prim.AngularVelocity; + Acceleration = prim.Acceleration; + CollisionPlane = prim.CollisionPlane; + Flexible = prim.Flexible; + Light = prim.Light; + Sculpt = prim.Sculpt; + ClickAction = prim.ClickAction; + Sound = prim.Sound; + OwnerID = prim.OwnerID; + SoundFlags = prim.SoundFlags; + SoundGain = prim.SoundGain; + SoundRadius = prim.SoundRadius; + Text = prim.Text; + TextColor = prim.TextColor; + MediaURL = prim.MediaURL; + Joint = prim.Joint; + JointPivot = prim.JointPivot; + JointAxisOrAnchor = prim.JointAxisOrAnchor; + if (prim.NameValues != null) + Array.Copy(prim.NameValues, NameValues, prim.NameValues.Length); + else + NameValues = null; + PrimData = prim.PrimData; + Properties = prim.Properties; + // FIXME: Get a real copy constructor for TextureEntry instead of serializing to bytes and back + if (prim.Textures != null) + { + byte[] textureBytes = prim.Textures.ToBytes(); + Textures = new TextureEntry(textureBytes, 0, textureBytes.Length); + } + else + { + Textures = null; + } + TextureAnim = prim.TextureAnim; + ParticleSys = prim.ParticleSys; + } + #endregion Constructors #region Public Methods diff --git a/Programs/Simian/Extensions/ObjectManager.cs b/Programs/Simian/Extensions/ObjectManager.cs index 16e55140..e3aa4402 100644 --- a/Programs/Simian/Extensions/ObjectManager.cs +++ b/Programs/Simian/Extensions/ObjectManager.cs @@ -166,7 +166,7 @@ namespace Simian.Extensions // Add this prim to the object database SimulationObject simObj = new SimulationObject(prim, Server); - Server.Scene.AddObject(this, agent, simObj); + Server.Scene.ObjectAdd(this, agent, simObj); } void ObjectSelectHandler(Packet packet, Agent agent) @@ -366,26 +366,28 @@ namespace Simian.Extensions SimulationObject obj; if (Server.Scene.TryGetObject(block.ObjectLocalID, out obj)) { - obj.Prim.PrimData.PathBegin = Primitive.UnpackBeginCut(block.PathBegin); - obj.Prim.PrimData.PathCurve = (PathCurve)block.PathCurve; - obj.Prim.PrimData.PathEnd = Primitive.UnpackEndCut(block.PathEnd); - obj.Prim.PrimData.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset); - obj.Prim.PrimData.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions); - obj.Prim.PrimData.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX); - obj.Prim.PrimData.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY); - obj.Prim.PrimData.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX); - obj.Prim.PrimData.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY); - obj.Prim.PrimData.PathSkew = Primitive.UnpackPathTwist(block.PathSkew); - obj.Prim.PrimData.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX); - obj.Prim.PrimData.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY); - obj.Prim.PrimData.PathTwist = Primitive.UnpackPathTwist(block.PathTwist); - obj.Prim.PrimData.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin); - obj.Prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin); - obj.Prim.PrimData.profileCurve = block.ProfileCurve; - obj.Prim.PrimData.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd); - obj.Prim.PrimData.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); + Primitive.ConstructionData data = obj.Prim.PrimData; - Server.Scene.ObjectUpdate(this, obj, 0, obj.Prim.Flags); + data.PathBegin = Primitive.UnpackBeginCut(block.PathBegin); + data.PathCurve = (PathCurve)block.PathCurve; + data.PathEnd = Primitive.UnpackEndCut(block.PathEnd); + data.PathRadiusOffset = Primitive.UnpackPathTwist(block.PathRadiusOffset); + data.PathRevolutions = Primitive.UnpackPathRevolutions(block.PathRevolutions); + data.PathScaleX = Primitive.UnpackPathScale(block.PathScaleX); + data.PathScaleY = Primitive.UnpackPathScale(block.PathScaleY); + data.PathShearX = Primitive.UnpackPathShear((sbyte)block.PathShearX); + data.PathShearY = Primitive.UnpackPathShear((sbyte)block.PathShearY); + data.PathSkew = Primitive.UnpackPathTwist(block.PathSkew); + data.PathTaperX = Primitive.UnpackPathTaper(block.PathTaperX); + data.PathTaperY = Primitive.UnpackPathTaper(block.PathTaperY); + data.PathTwist = Primitive.UnpackPathTwist(block.PathTwist); + data.PathTwistBegin = Primitive.UnpackPathTwist(block.PathTwistBegin); + data.ProfileBegin = Primitive.UnpackBeginCut(block.ProfileBegin); + data.profileCurve = block.ProfileCurve; + data.ProfileEnd = Primitive.UnpackEndCut(block.ProfileEnd); + data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); + + Server.Scene.ObjectModify(this, obj, data); } else { @@ -402,27 +404,29 @@ namespace Simian.Extensions SimulationObject obj; if (Server.Scene.TryGetObject(update.AgentData.ObjectLocalID, out obj)) { + PrimFlags flags = obj.Prim.Flags; + if (update.AgentData.CastsShadows) - obj.Prim.Flags |= PrimFlags.CastShadows; + flags |= PrimFlags.CastShadows; else - obj.Prim.Flags &= ~PrimFlags.CastShadows; + flags &= ~PrimFlags.CastShadows; if (update.AgentData.IsPhantom) - obj.Prim.Flags |= PrimFlags.Phantom; + flags |= PrimFlags.Phantom; else - obj.Prim.Flags &= ~PrimFlags.Phantom; + flags &= ~PrimFlags.Phantom; if (update.AgentData.IsTemporary) - obj.Prim.Flags |= PrimFlags.Temporary; + flags |= PrimFlags.Temporary; else - obj.Prim.Flags &= ~PrimFlags.Temporary; + flags &= ~PrimFlags.Temporary; if (update.AgentData.UsePhysics) - obj.Prim.Flags |= PrimFlags.Physics; + flags |= PrimFlags.Physics; else - obj.Prim.Flags &= ~PrimFlags.Physics; + flags &= ~PrimFlags.Physics; - Server.Scene.ObjectUpdate(this, obj, 0, obj.Prim.Flags); + Server.Scene.ObjectFlags(this, obj, flags); } else { @@ -480,7 +484,7 @@ namespace Simian.Extensions Server.Inventory.CreateItem(agent, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object, AssetType.Object, obj.Prim.ID, trash.ID, PermissionMask.All, PermissionMask.All, agent.AgentID, obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0); - Server.Scene.RemoveObject(this, obj); + Server.Scene.ObjectRemove(this, obj); Logger.DebugLog(String.Format("Derezzed prim {0} to agent inventory trash", obj.Prim.LocalID)); } @@ -525,36 +529,35 @@ namespace Simian.Extensions UpdateType type = (UpdateType)block.Type; bool linked = ((type & UpdateType.Linked) != 0); int pos = 0; + Vector3 position = obj.Prim.Position; + Quaternion rotation = obj.Prim.Rotation; + Vector3 scale = obj.Prim.Scale; if ((type & UpdateType.Position) != 0) { - Vector3 newpos = new Vector3(block.Data, pos); + position = new Vector3(block.Data, pos); pos += 12; - - obj.Prim.Position = newpos; } if ((type & UpdateType.Rotation) != 0) { - Quaternion newrot = new Quaternion(block.Data, pos, true); + rotation = new Quaternion(block.Data, pos, true); pos += 12; - - obj.Prim.Rotation = newrot; } if ((type & UpdateType.Scale) != 0) { - Vector3 newscale = new Vector3(block.Data, pos); + scale = new Vector3(block.Data, pos); pos += 12; // FIXME: Use this in linksets bool uniform = ((type & UpdateType.Uniform) != 0); - - obj.Prim.Scale = newscale; } // Although the object has already been modified, we need // to inform the scene manager of the changes so they are // sent to clients and propagated to other extensions - Server.Scene.ObjectUpdate(this, obj, 0, obj.Prim.Flags); + Server.Scene.ObjectTransform(this, obj, position, rotation, + obj.Prim.Velocity, obj.Prim.Acceleration, obj.Prim.AngularVelocity, + scale); } else { diff --git a/Programs/Simian/Extensions/SceneManager.cs b/Programs/Simian/Extensions/SceneManager.cs index a2578420..2d1a4016 100644 --- a/Programs/Simian/Extensions/SceneManager.cs +++ b/Programs/Simian/Extensions/SceneManager.cs @@ -18,9 +18,11 @@ namespace Simian.Extensions int currentLocalID = 1; float[] heightmap = new float[256 * 256]; - public event ObjectAddedCallback OnObjectAdded; - public event ObjectRemovedCallback OnObjectRemoved; - public event ObjectUpdatedCallback OnObjectUpdated; + public event ObjectAddCallback OnObjectAdd; + public event ObjectRemoveCallback OnObjectRemove; + public event ObjectTransformCallback OnObjectTransform; + public event ObjectFlagsCallback OnObjectFlags; + public event ObjectModifyCallback OnObjectModify; public event TerrainUpdatedCallback OnTerrainUpdated; public float[] Heightmap @@ -49,11 +51,16 @@ namespace Simian.Extensions { } - public void AddObject(object sender, Agent creator, SimulationObject obj) + public bool ObjectAdd(object sender, Agent creator, SimulationObject obj) { // Assign a unique LocalID to this object obj.Prim.LocalID = (uint)Interlocked.Increment(ref currentLocalID); + if (OnObjectAdd != null) + { + OnObjectAdd(sender, creator, obj); + } + // Add the object to the scene dictionary sceneObjects.Add(obj.Prim.LocalID, obj.Prim.ID, obj); @@ -74,14 +81,16 @@ namespace Simian.Extensions } } - if (OnObjectAdded != null) - { - OnObjectAdded(sender, obj); - } + return true; } - public void RemoveObject(object sender, SimulationObject obj) + public bool ObjectRemove(object sender, SimulationObject obj) { + if (OnObjectRemove != null) + { + OnObjectRemove(sender, obj); + } + sceneObjects.Remove(obj.Prim.LocalID, obj.Prim.ID); KillObjectPacket kill = new KillObjectPacket(); @@ -91,10 +100,57 @@ namespace Simian.Extensions server.UDP.BroadcastPacket(kill, PacketCategory.State); - if (OnObjectRemoved != null) + return true; + } + + public void ObjectTransform(object sender, SimulationObject obj, Vector3 position, + Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 angularVelocity, + Vector3 scale) + { + if (OnObjectTransform != null) { - OnObjectRemoved(sender, obj); + OnObjectTransform(sender, obj, position, rotation, velocity, + acceleration, angularVelocity, scale); } + + // Update the object + obj.Prim.Position = position; + obj.Prim.Rotation = rotation; + obj.Prim.Velocity = velocity; + obj.Prim.Acceleration = acceleration; + obj.Prim.AngularVelocity = angularVelocity; + obj.Prim.Scale = scale; + + // Inform clients + BroadcastObjectUpdate(obj); + } + + public void ObjectFlags(object sender, SimulationObject obj, PrimFlags flags) + { + if (OnObjectFlags != null) + { + OnObjectFlags(sender, obj, flags); + } + + // Update the object + obj.Prim.Flags = flags; + + // Inform clients + BroadcastObjectUpdate(obj); + } + + public void ObjectModify(object sender, SimulationObject obj, Primitive.ConstructionData data) + { + if (OnObjectModify != null) + { + OnObjectModify(sender, obj, data); + } + + // Update the object + obj.Prim.PrimData = data; + + // Inform clients + BroadcastObjectUpdate(obj); } public bool TryGetObject(uint localID, out SimulationObject obj) @@ -107,19 +163,12 @@ namespace Simian.Extensions return sceneObjects.TryGetValue(id, out obj); } - public void ObjectUpdate(object sender, SimulationObject obj, byte state, PrimFlags flags) + void BroadcastObjectUpdate(SimulationObject obj) { - // Something changed, build an update ObjectUpdatePacket update = - SimulationObject.BuildFullUpdate(obj.Prim, server.RegionHandle, state, flags); + SimulationObject.BuildFullUpdate(obj.Prim, server.RegionHandle, 0, obj.Prim.Flags); server.UDP.BroadcastPacket(update, PacketCategory.State); - - // Fire the callback - if (OnObjectUpdated != null) - { - OnObjectUpdated(sender, obj); - } } void CompleteAgentMovementHandler(Packet packet, Agent agent) diff --git a/Programs/Simian/Interfaces/ISceneProvider.cs b/Programs/Simian/Interfaces/ISceneProvider.cs index 996b3fd9..7044ddff 100644 --- a/Programs/Simian/Interfaces/ISceneProvider.cs +++ b/Programs/Simian/Interfaces/ISceneProvider.cs @@ -3,24 +3,37 @@ using OpenMetaverse; namespace Simian { - public delegate bool ObjectAddedCallback(object sender, SimulationObject obj); - public delegate bool ObjectRemovedCallback(object sender, SimulationObject obj); - public delegate void ObjectUpdatedCallback(object sender, SimulationObject obj); + public delegate void ObjectAddCallback(object sender, Agent creator, SimulationObject obj); + public delegate void ObjectRemoveCallback(object sender, SimulationObject obj); + public delegate void ObjectTransformCallback(object sender, SimulationObject obj, + Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 acceleration, + Vector3 angularVelocity, Vector3 scale); + public delegate void ObjectFlagsCallback(object sender, SimulationObject obj, PrimFlags flags); + public delegate void ObjectModifyCallback(object sender, SimulationObject obj, + Primitive.ConstructionData data); + // TODO: Convert terrain to a patch-based system public delegate void TerrainUpdatedCallback(object sender); - // TODO: ObjectImpulseAppliedCallback public interface ISceneProvider { - event ObjectAddedCallback OnObjectAdded; - event ObjectRemovedCallback OnObjectRemoved; - event ObjectUpdatedCallback OnObjectUpdated; + event ObjectAddCallback OnObjectAdd; + event ObjectRemoveCallback OnObjectRemove; + event ObjectTransformCallback OnObjectTransform; + event ObjectFlagsCallback OnObjectFlags; + event ObjectModifyCallback OnObjectModify; event TerrainUpdatedCallback OnTerrainUpdated; + // TODO: Convert to a patch-based system, and expose terrain editing + // through functions instead of a property float[] Heightmap { get; set; } - void AddObject(object sender, Agent creator, SimulationObject obj); - void RemoveObject(object sender, SimulationObject obj); - void ObjectUpdate(object sender, SimulationObject obj, byte state, PrimFlags flags); + bool ObjectAdd(object sender, Agent creator, SimulationObject obj); + bool ObjectRemove(object sender, SimulationObject obj); + void ObjectTransform(object sender, SimulationObject obj, Vector3 position, + Quaternion rotation, Vector3 velocity, Vector3 acceleration, + Vector3 angularVelocity, Vector3 scale); + void ObjectFlags(object sender, SimulationObject obj, PrimFlags flags); + void ObjectModify(object sender, SimulationObject obj, Primitive.ConstructionData data); bool TryGetObject(uint localID, out SimulationObject obj); bool TryGetObject(UUID id, out SimulationObject obj); } diff --git a/Programs/Simian/SimulationObject.cs b/Programs/Simian/SimulationObject.cs index b2aef39d..dbf79627 100644 --- a/Programs/Simian/SimulationObject.cs +++ b/Programs/Simian/SimulationObject.cs @@ -19,8 +19,15 @@ namespace Simian protected Simian Server; protected SimpleMesh[] Meshes = new SimpleMesh[4]; protected SimpleMesh[] WorldTransformedMeshes = new SimpleMesh[4]; - protected Matrix4 WorldTransformation = Matrix4.Identity; - protected bool WorldTransformationSet = false; + + public SimulationObject(SimulationObject obj) + { + Prim = new Primitive(obj.Prim); + Server = obj.Server; + LinkNumber = obj.LinkNumber; + Frozen = obj.Frozen; + // Skip everything else because it can be lazily reconstructed + } public SimulationObject(Primitive prim, Simian server) { @@ -112,7 +119,8 @@ namespace Simian return update; } - public static byte[] BuildObjectData(Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 angularVelocity) + public static byte[] BuildObjectData(Vector3 position, Quaternion rotation, Vector3 velocity, + Vector3 acceleration, Vector3 angularVelocity) { byte[] objectData = new byte[60]; int pos = 0; @@ -131,7 +139,8 @@ namespace Simian public static ObjectUpdatePacket.ObjectDataBlock BuildUpdateBlock(Primitive obj, ulong regionHandle, byte state, PrimFlags flags) { - byte[] objectData = BuildObjectData(obj.Position, obj.Rotation, obj.Velocity, obj.Acceleration, obj.AngularVelocity); + byte[] objectData = BuildObjectData(obj.Position, obj.Rotation, obj.Velocity, + obj.Acceleration, obj.AngularVelocity); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); update.ClickAction = (byte)obj.ClickAction; @@ -183,6 +192,5 @@ namespace Simian return update; } - } }