From a4b3439025f7ae8cf3a795f540675714d6324122 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 7 Oct 2010 05:12:39 +0200
Subject: Implement rezzing coalesced objects

---
 .../InventoryAccess/InventoryAccessModule.cs       | 277 +++++++++++++--------
 1 file changed, 172 insertions(+), 105 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 88dff02..a7d59c7 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -458,7 +458,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
                     item.Folder = folder.ID;
                     item.Owner = userID;
                     if (objlist.Count > 1)
+                    {
                         item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
+                    }
+                    else
+                    {
+                        item.SaleType = objlist[0].RootPart.ObjectSaleType;
+                        item.SalePrice = objlist[0].RootPart.SalePrice;
+                    }
                 }
 
                 AssetBase asset = CreateAsset(
@@ -522,7 +529,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
                                  7); // Preserve folded permissions
                     }
 
-                    // TODO: add the new fields (Flags, Sale info, etc)
                     item.CreationDate = Util.UnixTimeSinceEpoch();
                     item.Description = asset.Description;
                     item.Name = asset.Name;
@@ -598,6 +604,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
 
                 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
 
+                SceneObjectGroup group = null;
+
                 if (rezAsset != null)
                 {
                     UUID itemId = UUID.Zero;
@@ -606,34 +614,78 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
                     // item that it came from.  This allows us to enable 'save object to inventory'
                     if (!m_Scene.Permissions.BypassPermissions())
                     {
-                        if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
+                        if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
                         {
                             itemId = item.ID;
                         }
                     }
                     else
                     {
-                        // Brave new fullperm world
-                        //
-                        itemId = item.ID;
+                        if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
+                        {
+                            // Brave new fullperm world
+                            itemId = item.ID;
+                        }
                     }
 
                     string xmlData = Utils.BytesToString(rezAsset.Data);
-                    SceneObjectGroup group
-                        = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData);
+                    List<SceneObjectGroup> objlist =
+                            new List<SceneObjectGroup>();
+                    List<Vector3> veclist = new List<Vector3>();
+
+                    XmlDocument doc = new XmlDocument();
+                    doc.LoadXml(xmlData);
+                    XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
+                    if (e == null || attachment) // Single
+                    {
+                        SceneObjectGroup g =
+                                SceneObjectSerializer.FromOriginalXmlFormat(
+                                itemId, xmlData);
+                        objlist.Add(g);
+                        veclist.Add(new Vector3(0, 0, 0));
 
-                    Util.FireAndForget(delegate { AddUserData(group); });
- 
-                    group.RootPart.FromFolderID = item.Folder;
+                        float offsetHeight = 0;
+                        pos = m_Scene.GetNewRezLocation(
+                            RayStart, RayEnd, RayTargetID, Quaternion.Identity,
+                            BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false);
+                        pos.Z += offsetHeight;
+                    }
+                    else
+                    {
+                        XmlElement coll = (XmlElement)e;
+                        float bx = Convert.ToSingle(coll.GetAttribute("x"));
+                        float by = Convert.ToSingle(coll.GetAttribute("y"));
+                        float bz = Convert.ToSingle(coll.GetAttribute("z"));
+                        Vector3 bbox = new Vector3(bx, by, bz);
 
-                    // If it's rezzed in world, select it. Much easier to 
-                    // find small items.
-                    //
-                    if (!attachment)
-                        group.RootPart.CreateSelected = true;
+                        pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
+                                RayTargetID, Quaternion.Identity,
+                                BypassRayCast, bRayEndIsIntersection, true,
+                                bbox, false);
+
+                        pos -= bbox / 2;
+
+                        XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
+                        foreach (XmlNode n in groups)
+                        {
+                            SceneObjectGroup g =
+                                    SceneObjectSerializer.FromOriginalXmlFormat(
+                                    itemId, n.OuterXml);
+                            objlist.Add(g);
+                            XmlElement el = (XmlElement)n;
+                            float x = Convert.ToSingle(el.GetAttribute("offsetx"));
+                            float y = Convert.ToSingle(el.GetAttribute("offsety"));
+                            float z = Convert.ToSingle(el.GetAttribute("offsetz"));
+                            veclist.Add(new Vector3(x, y, z));
+                        }
+                    }
+
+                    int primcount = 0;
+                    foreach (SceneObjectGroup g in objlist)
+                        primcount += g.PrimCount;
 
                     if (!m_Scene.Permissions.CanRezObject(
-                        group.PrimCount, remoteClient.AgentId, pos)
+                        primcount, remoteClient.AgentId, pos)
                         && !attachment)
                     {
                         // The client operates in no fail mode. It will
@@ -646,121 +698,137 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
                         return null;
                     }
 
-                    group.ResetIDs();
-
-                    if (attachment)
+                    for (int i = 0 ; i < objlist.Count ; i++ )
                     {
-                        group.RootPart.Flags |= PrimFlags.Phantom;
-                        group.RootPart.IsAttachment = true;
+                        group = objlist[i];
+
+                        Vector3 storedPosition = group.AbsolutePosition;
+                        if (group.UUID == UUID.Zero)
+                        {
+                            m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3");
+                        }
+                        group.RootPart.FromFolderID = item.Folder;
+
+                        // If it's rezzed in world, select it. Much easier to 
+                        // find small items.
+                        //
+                        if (!attachment)
+                        {
+                            group.RootPart.CreateSelected = true;
+                            foreach (SceneObjectPart child in group.Parts)
+                                child.CreateSelected = true;
+                        }
+                        group.ResetIDs();
+
+                        if (attachment)
+                        {
+                            group.RootPart.Flags |= PrimFlags.Phantom;
+                            group.RootPart.IsAttachment = true;
+                        }
 
                         // If we're rezzing an attachment then don't ask
                         // AddNewSceneObject() to update the client since
-                        // we'll be doing that later on.  Scheduling more
-                        // than one full update during the attachment
-                        // process causes some clients to fail to display
-                        // the attachment properly.
-                        // Also, don't persist attachments.
-                        m_Scene.AddNewSceneObject(group, false, false);
-                    }
-                    else
-                    {
+                        // we'll be doing that later on.  Scheduling more than
+                        // one full update during the attachment
+                        // process causes some clients to fail to display the
+                        // attachment properly.
                         m_Scene.AddNewSceneObject(group, true, false);
-                    }
 
-                    //  m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z);
-                    // if attachment we set it's asset id so object updates can reflect that
-                    // if not, we set it's position in world.
-                    if (!attachment)
-                    {
-                        group.ScheduleGroupForFullUpdate();
-                        
-                        float offsetHeight = 0;
-                        pos = m_Scene.GetNewRezLocation(
-                            RayStart, RayEnd, RayTargetID, Quaternion.Identity,
-                            BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false);
-                        pos.Z += offsetHeight;
-                        group.AbsolutePosition = pos;
-                        //   m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2}  and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight);
-
-                    }
-                    else
-                    {
-                        group.SetFromItemID(itemID);
-                    }
+                        // if attachment we set it's asset id so object updates
+                        // can reflect that, if not, we set it's position in world.
+                        if (!attachment)
+                        {
+                            group.ScheduleGroupForFullUpdate();
+                            
+                            group.AbsolutePosition = pos + veclist[i];
+                        }
+                        else
+                        {
+                            group.SetFromItemID(itemID);
+                        }
 
-                    SceneObjectPart rootPart = null;
-                    try
-                    {
-                        rootPart = group.GetChildPart(group.UUID);
-                    }
-                    catch (NullReferenceException)
-                    {
-                        string isAttachment = "";
+                        SceneObjectPart rootPart = null;
 
-                        if (attachment)
-                            isAttachment = " Object was an attachment";
+                        try
+                        {
+                            rootPart = group.GetChildPart(group.UUID);
+                        }
+                        catch (NullReferenceException)
+                        {
+                            string isAttachment = "";
 
-                        m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
-                    }
+                            if (attachment)
+                                isAttachment = " Object was an attachment";
 
-                    // Since renaming the item in the inventory does not affect the name stored
-                    // in the serialization, transfer the correct name from the inventory to the
-                    // object itself before we rez.
-                    rootPart.Name = item.Name;
-                    rootPart.Description = item.Description;
+                            m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
+                        }
 
-                    if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
-                    {
+                        // Since renaming the item in the inventory does not
+                        // affect the name stored in the serialization, transfer
+                        // the correct name from the inventory to the
+                        // object itself before we rez.
+                        rootPart.Name = item.Name;
+                        rootPart.Description = item.Description;
                         rootPart.ObjectSaleType = item.SaleType;
                         rootPart.SalePrice = item.SalePrice;
-                    }
 
-                    group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
-                    if ((rootPart.OwnerID != item.Owner) ||
-                            (item.CurrentPermissions & 16) != 0 || // Magic number
-                            (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
-                    {
-                        //Need to kill the for sale here
-                        rootPart.ObjectSaleType = 0;
-                        rootPart.SalePrice = 10;
-
-                        if (m_Scene.Permissions.PropagatePermissions())
+                        group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
+                        if ((rootPart.OwnerID != item.Owner) ||
+                            (item.CurrentPermissions & 16) != 0)
                         {
-                            foreach (SceneObjectPart part in group.Parts)
+                            //Need to kill the for sale here
+                            rootPart.ObjectSaleType = 0;
+                            rootPart.SalePrice = 10;
+
+                            if (m_Scene.Permissions.PropagatePermissions())
                             {
-                                if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
-                                    part.EveryoneMask = item.EveryOnePermissions;
-                                if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
-                                    part.NextOwnerMask = item.NextPermissions;
-                                if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
-                                    part.GroupMask = item.GroupPermissions;
+                                foreach (SceneObjectPart part in group.Parts)
+                                {
+                                    if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
+                                    {
+                                        part.EveryoneMask = item.EveryOnePermissions;
+                                        part.NextOwnerMask = item.NextPermissions;
+                                    }
+                                    part.GroupMask = 0; // DO NOT propagate here
+                                }
+                                
+                                group.ApplyNextOwnerPermissions();
                             }
+                        }
 
-                            foreach (SceneObjectPart part in group.Parts)
+                        foreach (SceneObjectPart part in group.Parts)
+                        {
+                            if ((part.OwnerID != item.Owner) ||
+                                (item.CurrentPermissions & 16) != 0)
                             {
                                 part.LastOwnerID = part.OwnerID;
                                 part.OwnerID = item.Owner;
                                 part.Inventory.ChangeInventoryOwner(item.Owner);
+                                part.GroupMask = 0; // DO NOT propagate here
                             }
-                            
-                            group.ApplyNextOwnerPermissions();
+                            part.EveryoneMask = item.EveryOnePermissions;
+                            part.NextOwnerMask = item.NextPermissions;
                         }
-                    }
 
-                    rootPart.TrimPermissions();
+                        rootPart.TrimPermissions();
 
-                    if (!attachment)
-                    {
-                        if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
+                        if (!attachment)
                         {
-                            group.ClearPartAttachmentData();
-                        }
-                        
-                        // Fire on_rez
-                        group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
-                        rootPart.ParentGroup.ResumeScripts();
+                            if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
+                            {
+                                // Save attachment data
+                                group.RootPart.AttachPoint = group.RootPart.Shape.State;
+                                group.RootPart.AttachOffset = storedPosition;
 
-                        rootPart.ScheduleFullUpdate();
+                                group.ClearPartAttachmentData();
+                            }
+                            
+                            // Fire on_rez
+                            group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1);
+                            rootPart.ParentGroup.ResumeScripts();
+
+                            rootPart.ScheduleFullUpdate();
+                        }
                     }
 
                     if (!m_Scene.Permissions.BypassPermissions())
@@ -778,9 +846,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
                             }
                         }
                     }
-
-                    return rootPart.ParentGroup;
                 }
+                return group;
             }
 
             return null;
-- 
cgit v1.1