diff --git a/OpenSim/Framework/General/Interfaces/IClientAPI.cs b/OpenSim/Framework/General/Interfaces/IClientAPI.cs index acacabe19f..206122d7a6 100644 --- a/OpenSim/Framework/General/Interfaces/IClientAPI.cs +++ b/OpenSim/Framework/General/Interfaces/IClientAPI.cs @@ -59,6 +59,7 @@ namespace OpenSim.Framework.Interfaces public delegate void UpdatePrimRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient); public delegate void UpdatePrimSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient); public delegate void UpdatePrimGroupRotation(uint localID,LLVector3 pos, LLQuaternion rot, IClientAPI remoteClient); + public delegate void ObjectDuplicate(uint localID, LLVector3 offset, uint dupeFlags); public delegate void StatusChange(bool status); public delegate void NewAvatar(IClientAPI remoteClient, LLUUID agentID, bool status); public delegate void UpdateAgent(IClientAPI remoteClient, uint flags, LLQuaternion bodyRotation); @@ -92,6 +93,7 @@ namespace OpenSim.Framework.Interfaces event UpdateAgent OnAgentUpdate; event GenericCall OnRequestAvatarsData; event GenericCall4 OnAddPrim; + event ObjectDuplicate OnObjectDuplicate; event UpdateVector OnGrapObject; event ObjectSelect OnDeGrapObject; event MoveObject OnGrapUpdate; diff --git a/OpenSim/Region/ClientStack/ClientView.API.cs b/OpenSim/Region/ClientStack/ClientView.API.cs index cefe85685b..3c1df75f63 100644 --- a/OpenSim/Region/ClientStack/ClientView.API.cs +++ b/OpenSim/Region/ClientStack/ClientView.API.cs @@ -55,6 +55,7 @@ namespace OpenSim.Region.ClientStack public event LinkObjects OnLinkObjects; public event UpdateVector OnGrapObject; public event ObjectSelect OnDeGrapObject; + public event ObjectDuplicate OnObjectDuplicate; public event MoveObject OnGrapUpdate; public event GenericCall4 OnAddPrim; public event UpdateShape OnUpdatePrimShape; diff --git a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs index def14c73d3..982ae5071b 100644 --- a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs +++ b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs @@ -233,6 +233,18 @@ namespace OpenSim.Region.ClientStack } } break; + case PacketType.ObjectDuplicate: + ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack; + for (int i = 0; i < dupe.ObjectData.Length; i++) + { + if (OnObjectDuplicate != null) + { + OnObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, dupe.SharedData.DuplicateFlags); + } + } + + break; + case PacketType.ObjectSelect: ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack; for (int i = 0; i < incomingselect.ObjectData.Length; i++) diff --git a/OpenSim/Region/Environment/Scenes/EntityBase.cs b/OpenSim/Region/Environment/Scenes/EntityBase.cs index 99ca021839..7914bab588 100644 --- a/OpenSim/Region/Environment/Scenes/EntityBase.cs +++ b/OpenSim/Region/Environment/Scenes/EntityBase.cs @@ -74,6 +74,7 @@ namespace OpenSim.Region.Environment.Scenes public uint LocalId { get { return m_localId; } + set { m_localId = value; } } /// @@ -121,6 +122,15 @@ namespace OpenSim.Region.Environment.Scenes } + /// + /// Copies the entity + /// + /// + public virtual EntityBase Copy() + { + return (EntityBase)this.MemberwiseClone(); + } + /// /// Infoms the entity that the land (heightmap) has changed /// diff --git a/OpenSim/Region/Environment/Scenes/Primitive.cs b/OpenSim/Region/Environment/Scenes/Primitive.cs index 9d016182e9..8d31d63c13 100644 --- a/OpenSim/Region/Environment/Scenes/Primitive.cs +++ b/OpenSim/Region/Environment/Scenes/Primitive.cs @@ -141,8 +141,43 @@ namespace OpenSim.Region.Environment.Scenes this.CreateFromPacket(addPacket, ownerID, localID); this.rotation = Axiom.Math.Quaternion.Identity; } + + /// + /// + /// + /// Empty constructor for duplication + public Primitive() + { + + } + #endregion + #region Duplication + + public Primitive Copy(EntityBase parent, SceneObject rootParent) + { + Primitive dupe = (Primitive)this.MemberwiseClone(); + // TODO: Copy this properly. + dupe.inventoryItems = this.inventoryItems; + dupe.m_Parent = parent; + dupe.m_RootParent = rootParent; + // TODO: Copy this properly. + dupe.m_Shape = this.m_Shape; + + uint newLocalID = this.m_world.PrimIDAllocate(); + dupe.LocalId = newLocalID; + + dupe.Scale = new LLVector3(this.Scale.X, this.Scale.Y, this.Scale.Z); + dupe.rotation = new Quaternion(this.rotation.w, this.rotation.x, this.rotation.y, this.rotation.z); + dupe.Pos = new LLVector3(this.Pos.X, this.Pos.Y, this.Pos.Z); + + return dupe; + } + + #endregion + + #region Override from EntityBase /// /// diff --git a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs index e07834853e..35e0ea6bfd 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.PacketHandlers.cs @@ -212,6 +212,39 @@ namespace OpenSim.Region.Environment.Scenes } + /// + /// + /// + /// + /// + /// + public void DuplicateObject(uint originalPrim, LLVector3 offset, uint flags) + { + SceneObject originPrim = null; + foreach (EntityBase ent in Entities.Values) + { + if (ent is SceneObject) + { + if (((SceneObject)ent).rootLocalID == originalPrim) + { + originPrim = (SceneObject)ent; + break; + } + } + } + + if (originPrim != null) + { + //SceneObject copy = originPrim.Copy(); + + } + else + { + OpenSim.Framework.Console.MainLog.Instance.Warn("Attempted to duplicate nonexistant prim"); + } + + } + /// /// /// diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index fdf3cc8ab0..1798cba787 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -57,6 +57,7 @@ namespace OpenSim.Region.Environment.Scenes private float timeStep = 0.1f; private Random Rand = new Random(); private uint _primCount = 702000; + private System.Threading.Mutex _primAllocateMutex = new Mutex(false); private int storageCount; private Mutex updateLock; @@ -396,6 +397,22 @@ namespace OpenSim.Region.Environment.Scenes } + /// + /// Returns a new unallocated primitive ID + /// + /// A brand new primitive ID + public uint PrimIDAllocate() + { + uint myID; + + _primAllocateMutex.WaitOne(); + ++_primCount; + myID = _primCount; + _primAllocateMutex.ReleaseMutex(); + + return myID; + } + /// /// /// @@ -415,9 +432,8 @@ namespace OpenSim.Region.Environment.Scenes { try { - SceneObject sceneOb = new SceneObject(m_regionHandle, this, addPacket, ownerID, this._primCount); + SceneObject sceneOb = new SceneObject(m_regionHandle, this, addPacket, ownerID, this.PrimIDAllocate()); this.Entities.Add(sceneOb.rootUUID, sceneOb); - this._primCount++; // Trigger event for listeners // eventManager.TriggerOnNewPrimitive(prim); @@ -468,6 +484,7 @@ namespace OpenSim.Region.Environment.Scenes client.OnObjectDescription += this.PrimDescription; client.OnObjectName += this.PrimName; client.OnLinkObjects += this.LinkObjects; + client.OnObjectDuplicate += this.DuplicateObject; /* remoteClient.OnParcelPropertiesRequest += new ParcelPropertiesRequest(parcelManager.handleParcelPropertiesRequest); remoteClient.OnParcelDivideRequest += new ParcelDivideRequest(parcelManager.handleParcelDivideRequest); diff --git a/OpenSim/Region/Environment/Scenes/SceneObject.cs b/OpenSim/Region/Environment/Scenes/SceneObject.cs index 452502ba8b..2b80d57c68 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObject.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObject.cs @@ -75,6 +75,15 @@ namespace OpenSim.Region.Environment.Scenes this.CreateRootFromPacket(addPacket, ownerID, localID); } + /// + /// + /// + /// Need a null constructor for duplication + public SceneObject() + { + + } + /// /// /// @@ -97,6 +106,25 @@ namespace OpenSim.Region.Environment.Scenes } + /// + /// + /// + /// A complete copy of the object + public SceneObject Copy() + { + SceneObject dupe = new SceneObject(); + + Primitive newRoot = this.rootPrimitive.Copy((EntityBase)dupe, dupe); + + foreach (EntityBase child in this.children) + { + EntityBase newChild = child.Copy(); + dupe.children.Add(newChild); + } + + return dupe; + } + /// /// ///