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;
}
-
}
}