Fixed rezzing coalesced objects from a prim's inventory

Previously only the first object in the Coalesced Object was rezzed. Now all the objects are rezzed.
link-sitting
Oren Hurvitz 2013-09-25 10:56:05 +03:00 committed by Justin Clark-Casey (justincc)
parent acfe603a5f
commit d0c1780839
5 changed files with 198 additions and 144 deletions

View File

@ -757,64 +757,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
SceneObjectGroup group = null; SceneObjectGroup group = null;
string xmlData = Utils.BytesToString(rezAsset.Data); List<SceneObjectGroup> objlist;
List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); List<Vector3> veclist;
List<Vector3> veclist = new List<Vector3>(); Vector3 bbox;
float offsetHeight;
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
Vector3 pos; Vector3 pos;
XmlDocument doc = new XmlDocument(); bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
doc.LoadXml(xmlData);
XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); if (single)
if (e == null || attachment) // Single
{ {
SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
objlist.Add(g);
veclist.Add(Vector3.Zero);
float offsetHeight = 0;
pos = m_Scene.GetNewRezLocation( pos = m_Scene.GetNewRezLocation(
RayStart, RayEnd, RayTargetID, Quaternion.Identity, RayStart, RayEnd, RayTargetID, Quaternion.Identity,
BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); BypassRayCast, bRayEndIsIntersection, true, bbox, false);
pos.Z += offsetHeight; pos.Z += offsetHeight;
} }
else 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);
pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
RayTargetID, Quaternion.Identity, RayTargetID, Quaternion.Identity,
BypassRayCast, bRayEndIsIntersection, true, BypassRayCast, bRayEndIsIntersection, true,
bbox, false); bbox, false);
pos -= bbox / 2; pos -= bbox / 2;
XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
foreach (XmlNode n in groups)
{
SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
objlist.Add(g);
XmlElement el = (XmlElement)n;
string rawX = el.GetAttribute("offsetx");
string rawY = el.GetAttribute("offsety");
string rawZ = el.GetAttribute("offsetz");
//
// m_log.DebugFormat(
// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
// g.Name, rawX, rawY, rawZ);
float x = Convert.ToSingle(rawX);
float y = Convert.ToSingle(rawY);
float z = Convert.ToSingle(rawZ);
veclist.Add(new Vector3(x, y, z));
}
} }
if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))

View File

@ -234,15 +234,17 @@ namespace OpenSim.Region.Framework.Interfaces
List<TaskInventoryItem> GetInventoryItems(InventoryType type); List<TaskInventoryItem> GetInventoryItems(InventoryType type);
/// <summary> /// <summary>
/// Get the scene object referenced by an inventory item. /// Get the scene object(s) referenced by an inventory item.
/// </summary> /// </summary>
/// ///
/// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
/// been adjusted to reflect the part and item from which it originates. /// been adjusted to reflect the part and item from which it originates.
/// ///
/// <param name="item"></param> /// <param name="item">Inventory item</param>
/// <returns>The scene object. Null if the scene object asset couldn't be found</returns> /// <param name="objlist">The scene objects</param>
SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); /// <param name="veclist">Relative offsets for each object</param>
/// <returns>true = success, false = the scene object asset couldn't be found</returns>
bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
/// <summary> /// <summary>
/// Update an existing inventory item. /// Update an existing inventory item.

View File

@ -31,6 +31,7 @@ using System.Collections;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Timers; using System.Timers;
using System.Xml;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using log4net; using log4net;
@ -2134,6 +2135,69 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Returns the list of Scene Objects in an asset.
/// </summary>
/// <remarks>
/// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
/// </remarks>
/// <param name="assetData">Asset data</param>
/// <param name="attachment">Whether the item is an attachment</param>
/// <param name="objlist">The objects included in the asset</param>
/// <param name="veclist">Relative positions of the objects</param>
/// <param name="bbox">Bounding box of all the objects</param>
/// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
/// to the centre of the root prim (relevant only when returning a single object)</param>
/// <returns>true = returning a single object; false = multiple objects</returns>
public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
out Vector3 bbox, out float offsetHeight)
{
objlist = new List<SceneObjectGroup>();
veclist = new List<Vector3>();
XmlDocument doc = new XmlDocument();
string xmlData = Utils.BytesToString(assetData);
doc.LoadXml(xmlData);
XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
if (e == null || attachment) // Single
{
SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
objlist.Add(g);
veclist.Add(new Vector3(0, 0, 0));
bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
return true;
}
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"));
bbox = new Vector3(bx, by, bz);
offsetHeight = 0;
XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
foreach (XmlNode n in groups)
{
SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
objlist.Add(g);
XmlElement el = (XmlElement)n;
string rawX = el.GetAttribute("offsetx");
string rawY = el.GetAttribute("offsety");
string rawZ = el.GetAttribute("offsetz");
float x = Convert.ToSingle(rawX);
float y = Convert.ToSingle(rawY);
float z = Convert.ToSingle(rawZ);
veclist.Add(new Vector3(x, y, z));
}
}
return false;
}
/// <summary> /// <summary>
/// Event Handler Rez an object into a scene /// Event Handler Rez an object into a scene
/// Calls the non-void event handler /// Calls the non-void event handler
@ -2209,19 +2273,25 @@ namespace OpenSim.Region.Framework.Scenes
/// will be used if it exists.</param> /// will be used if it exists.</param>
/// <param name="vel">The velocity of the rezzed object.</param> /// <param name="vel">The velocity of the rezzed object.</param>
/// <param name="param"></param> /// <param name="param"></param>
/// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
public virtual SceneObjectGroup RezObject( public virtual List<SceneObjectGroup> RezObject(
SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
{ {
if (null == item) if (null == item)
return null; return null;
SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); List<SceneObjectGroup> objlist;
List<Vector3> veclist;
if (null == group) bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
if (!success)
return null; return null;
if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) int totalPrims = 0;
foreach (SceneObjectGroup group in objlist)
totalPrims += group.PrimCount;
if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
return null; return null;
if (!Permissions.BypassPermissions()) if (!Permissions.BypassPermissions())
@ -2230,6 +2300,10 @@ namespace OpenSim.Region.Framework.Scenes
sourcePart.Inventory.RemoveInventoryItem(item.ItemID); sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
} }
for (int i = 0; i < objlist.Count; i++)
{
SceneObjectGroup group = objlist[i];
Vector3 curpos = pos + veclist[i];
if (group.IsAttachment == false && group.RootPart.Shape.State != 0) if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
{ {
@ -2238,15 +2312,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
group.FromPartID = sourcePart.UUID; group.FromPartID = sourcePart.UUID;
AddNewSceneObject(group, true, pos, rot, vel); AddNewSceneObject(group, true, curpos, rot, vel);
// We can only call this after adding the scene object, since the scene object references the scene // We can only call this after adding the scene object, since the scene object references the scene
// to find out if scripts should be activated at all. // to find out if scripts should be activated at all.
group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
group.ScheduleGroupForFullUpdate(); group.ScheduleGroupForFullUpdate();
}
return group; return objlist;
} }
public virtual bool returnObjects(SceneObjectGroup[] returnobjects, public virtual bool returnObjects(SceneObjectGroup[] returnobjects,

View File

@ -734,7 +734,7 @@ namespace OpenSim.Region.Framework.Scenes
return items; return items;
} }
public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
{ {
AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
@ -743,11 +743,19 @@ namespace OpenSim.Region.Framework.Scenes
m_log.WarnFormat( m_log.WarnFormat(
"[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
item.AssetID, item.Name, m_part.Name); item.AssetID, item.Name, m_part.Name);
return null; objlist = null;
veclist = null;
return false;
} }
string xmlData = Utils.BytesToString(rezAsset.Data); Vector3 bbox;
SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); float offsetHeight;
bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
for (int i = 0; i < objlist.Count; i++)
{
SceneObjectGroup group = objlist[i];
group.ResetIDs(); group.ResetIDs();
@ -801,8 +809,9 @@ namespace OpenSim.Region.Framework.Scenes
} }
rootPart.TrimPermissions(); rootPart.TrimPermissions();
}
return group; return true;
} }
/// <summary> /// <summary>

View File

@ -2970,26 +2970,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// need the magnitude later // need the magnitude later
// float velmag = (float)Util.GetMagnitude(llvel); // float velmag = (float)Util.GetMagnitude(llvel);
SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
// If either of these are null, then there was an unknown error. // If either of these are null, then there was an unknown error.
if (new_group == null) if (new_groups == null)
return; return;
foreach (SceneObjectGroup group in new_groups)
{
// objects rezzed with this method are die_at_edge by default. // objects rezzed with this method are die_at_edge by default.
new_group.RootPart.SetDieAtEdge(true); group.RootPart.SetDieAtEdge(true);
new_group.ResumeScripts(); group.ResumeScripts();
m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
"object_rez", new Object[] { "object_rez", new Object[] {
new LSL_String( new LSL_String(
new_group.RootPart.UUID.ToString()) }, group.RootPart.UUID.ToString()) },
new DetectParams[0])); new DetectParams[0]));
float groupmass = new_group.GetMass(); float groupmass = group.GetMass();
PhysicsActor pa = new_group.RootPart.PhysActor; PhysicsActor pa = group.RootPart.PhysActor;
//Recoil. //Recoil.
if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
@ -3001,6 +3003,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
// Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
}
}); });
//ScriptSleep((int)((groupmass * velmag) / 10)); //ScriptSleep((int)((groupmass * velmag) / 10));