diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index e7f5f56c24..42d8c27e12 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -459,7 +459,7 @@ namespace OpenSim.Region.Environment.Scenes { AddEntityFromStorage(prim); } - MainLog.Instance.Verbose("Loaded " + PrimsFromDB.Count.ToString() + " object(s)"); + MainLog.Instance.Verbose("Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); } /// @@ -520,6 +520,7 @@ namespace OpenSim.Region.Environment.Scenes { part.LocalID = this.PrimIDAllocate(); } + sceneObject.UpdateParentIDs(); this.AddEntity(sceneObject); } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 39b7fb0347..dae4b5f073 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -1,5 +1,9 @@ using System.Collections.Generic; using System.Text; +using System.Xml; +using System.Xml.Serialization; +using System.IO; +using System; using Axiom.Math; using libsecondlife; using libsecondlife.Packets; @@ -22,6 +26,7 @@ namespace OpenSim.Region.Environment.Scenes public event PrimCountTaintedDelegate OnPrimCountTainted; + #region Properties /// /// /// @@ -111,6 +116,9 @@ namespace OpenSim.Region.Environment.Scenes set { m_isSelected = value; } } + #endregion + + #region Constructors /// /// /// @@ -119,6 +127,31 @@ namespace OpenSim.Region.Environment.Scenes } + /// + /// + /// + public SceneObjectGroup(Scene scene, ulong regionHandle, string xmlData) + { + m_scene = scene; + m_regionHandle = regionHandle; + + StringReader sr = new StringReader(xmlData); + XmlTextReader reader = new XmlTextReader(sr); + reader.ReadStartElement("SceneObjectGroup"); + reader.ReadStartElement("RootPart"); + this.m_rootPart = SceneObjectPart.FromXml(reader); + reader.ReadEndElement(); + //TODO: read and create rest of the parts + reader.ReadEndElement(); + reader.Close(); + sr.Close(); + + this.m_parts.Add(m_rootPart.UUID, m_rootPart); + this.m_rootPart.LocalID = m_scene.PrimIDAllocate(); + this.m_rootPart.RegionHandle = m_regionHandle; + m_scene.EventManager.OnBackup += this.ProcessBackup; + } + /// /// /// @@ -142,7 +175,25 @@ namespace OpenSim.Region.Environment.Scenes this.SetPartAsRoot(newPart); m_scene.EventManager.OnBackup += this.ProcessBackup; } + #endregion + public string ToXmlString() + { + StringWriter sw = new StringWriter(); + //StreamWriter st = new StreamWriter("testxml.txt"); + XmlTextWriter writer = new XmlTextWriter(sw); + writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + writer.WriteStartElement(String.Empty, "RootPart", String.Empty); + m_rootPart.ToXml(writer); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.Close(); + // System.Console.WriteLine("prim: " + sw.ToString()); + return sw.ToString(); + // st.Close(); + // return ""; + + } #region Copying /// @@ -169,23 +220,6 @@ namespace OpenSim.Region.Environment.Scenes return dupe; } - /// - /// Added as a way for the storage provider to reset the scene, - /// most likely a better way to do this sort of thing but for now... - /// - /// - public void SetScene(Scene scene) - { - m_scene = scene; - m_scene.EventManager.OnBackup += this.ProcessBackup; - } - - public void AddPart(SceneObjectPart part) - { - part.SetParent(this); - this.m_parts.Add(part.UUID, part); - } - /// /// /// @@ -209,6 +243,7 @@ namespace OpenSim.Region.Environment.Scenes } #endregion + #region Scheduling /// /// /// @@ -264,15 +299,9 @@ namespace OpenSim.Region.Environment.Scenes } } - /// - /// - /// - /// - public void LinkToGroup(SceneObjectGroup objectGroup) - { - - } + #endregion + #region SceneGroupPart Methods /// /// /// @@ -339,26 +368,37 @@ namespace OpenSim.Region.Environment.Scenes } return false; } + #endregion + #region Packet Handlers /// /// /// - public void TriggerTainted() + /// + public void LinkToGroup(SceneObjectGroup objectGroup) { - if (OnPrimCountTainted != null) - { - this.OnPrimCountTainted(); - } - } - - /// - /// Processes backup - /// - /// - public void ProcessBackup(OpenSim.Region.Interfaces.IRegionDataStore datastore) - { - datastore.StoreObject(this); + SceneObjectPart linkPart = objectGroup.m_rootPart; + linkPart.OffsetPosition = linkPart.GroupPosition - this.Pos; + linkPart.GroupPosition = this.Pos; + + Vector3 axPos = new Vector3(linkPart.OffsetPosition.X, linkPart.OffsetPosition.Y, linkPart.OffsetPosition.Z); + Quaternion parentRot = new Quaternion(this.m_rootPart.RotationOffset.W, this.m_rootPart.RotationOffset.X, this.m_rootPart.RotationOffset.Y, this.m_rootPart.RotationOffset.Z); + axPos = parentRot.Inverse() * axPos; + linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + Quaternion oldRot = new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y, linkPart.RotationOffset.Z); + Quaternion newRot = parentRot * oldRot; + linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); + linkPart.ParentID = this.m_rootPart.LocalID; + this.m_parts.Add(linkPart.UUID, linkPart); + linkPart.SetParent(this); + + //TODO: rest of parts + + m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup; + m_scene.DeleteEntity(objectGroup.UUID); + this.ScheduleGroupForFullUpdate(); } + /// /// /// @@ -469,6 +509,7 @@ namespace OpenSim.Region.Environment.Scenes part.UpdateTextureEntry(textureEntry); } } + #endregion #region Shape /// @@ -485,6 +526,7 @@ namespace OpenSim.Region.Environment.Scenes } #endregion + #region Resize /// /// /// @@ -498,6 +540,7 @@ namespace OpenSim.Region.Environment.Scenes part.Resize(scale); } } + #endregion #region Position /// @@ -636,8 +679,6 @@ namespace OpenSim.Region.Environment.Scenes private void SetPartAsRoot(SceneObjectPart part) { this.m_rootPart = part; - //this.m_uuid= part.UUID; - // this.m_localId = part.LocalID; } /// @@ -658,6 +699,29 @@ namespace OpenSim.Region.Environment.Scenes return m_scene.RequestAvatarList(); } + #region Events + /// + /// + /// + public void TriggerTainted() + { + if (OnPrimCountTainted != null) + { + this.OnPrimCountTainted(); + } + } + + /// + /// Processes backup + /// + /// + public void ProcessBackup(OpenSim.Region.Interfaces.IRegionDataStore datastore) + { + datastore.StoreObject(this); + } + #endregion + + #region Client Updating public void SendFullUpdateToClient(IClientAPI remoteClient) { lock (this.m_parts) @@ -702,5 +766,41 @@ namespace OpenSim.Region.Environment.Scenes part.SendTerseUpdateToClient(remoteClient); } } + #endregion + + /// + /// Added as a way for the storage provider to reset the scene, + /// most likely a better way to do this sort of thing but for now... + /// + /// + public void SetScene(Scene scene) + { + m_scene = scene; + m_scene.EventManager.OnBackup += this.ProcessBackup; + } + + /// + /// + /// + /// + public void AddPart(SceneObjectPart part) + { + part.SetParent(this); + this.m_parts.Add(part.UUID, part); + } + + /// + /// + /// + public void UpdateParentIDs() + { + foreach (SceneObjectPart part in this.m_parts.Values) + { + if (part.UUID != this.m_rootPart.UUID) + { + part.ParentID = this.m_rootPart.LocalID; + } + } + } } } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 1b373aa896..c1348c7979 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -1,5 +1,8 @@ using System.Collections.Generic; using System.Text; +using System.Xml; +using System.Xml.Serialization; +using System.IO; using System; using Axiom.Math; using libsecondlife; @@ -249,6 +252,27 @@ namespace OpenSim.Region.Environment.Scenes } #endregion + /// + /// + /// + /// + /// + public static SceneObjectPart FromXml(XmlReader xmlReader) + { + XmlSerializer serializer = new XmlSerializer(typeof(SceneObjectPart)); + return (SceneObjectPart)serializer.Deserialize(xmlReader); + } + + /// + /// + /// + /// + public void ToXml(XmlWriter xmlWriter) + { + XmlSerializer serializer = new XmlSerializer(typeof(SceneObjectPart)); + serializer.Serialize(xmlWriter, this); + } + /// /// /// diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs index 5d1592c0c7..bd6658c674 100644 --- a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs +++ b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs @@ -308,7 +308,6 @@ namespace OpenSim.DataStore.MonoSqliteStorage private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID) { - Console.WriteLine("scene Group for this prim is " + sceneGroupID); row["UUID"] = prim.UUID; row["ParentID"] = prim.ParentID; row["CreationDate"] = prim.CreationDate; @@ -481,37 +480,54 @@ namespace OpenSim.DataStore.MonoSqliteStorage public List LoadObjects() { + Dictionary createdObjects = new Dictionary(); List retvals = new List(); DataTable prims = ds.Tables["prims"]; DataTable shapes = ds.Tables["primshapes"]; - // This only supports 1 prim per SceneObjectGroup. Need to fix later foreach (DataRow primRow in prims.Rows) { - SceneObjectGroup group = new SceneObjectGroup(); - SceneObjectPart prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID); - if (shapeRow != null) + string uuid = (string)primRow["UUID"]; + string objID = (string)primRow["SceneGroupID"]; + if (uuid == objID) //is new SceneObjectGroup ? { - prim.Shape = buildShape(shapeRow); + SceneObjectGroup group = new SceneObjectGroup(); + SceneObjectPart prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + Console.WriteLine("No shape found for prim in storage, so setting default box shape"); + prim.Shape = BoxShape.Default; + } + group.AddPart(prim); + group.RootPart = prim; + + createdObjects.Add(group.UUID, group); + retvals.Add(group); } else { - Console.WriteLine("No shape found for prim in storage, so setting default box shape"); - prim.Shape = BoxShape.Default; + SceneObjectPart prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + Console.WriteLine("No shape found for prim in storage, so setting default box shape"); + prim.Shape = BoxShape.Default; + } + createdObjects[new LLUUID(objID)].AddPart(prim); } - group.AddPart(prim); - // TODO: there are a couple of known issues to get this to work - // * While we can add Children, we can't set the root part (or - // or even figure out which should be the root part) - // * region handle may need to be persisted, it isn't now - group.RootPart = prim; - - retvals.Add(group); } - MainLog.Instance.Verbose("DATASTORE", "Sqlite - LoadObjects found " + prims.Rows.Count + " objects"); + MainLog.Instance.Verbose("DATASTORE", "Sqlite - LoadObjects found " + prims.Rows.Count + " primitives"); return retvals; }