From 385c1f51846197f03a535fe80c3fed131d03df5d Mon Sep 17 00:00:00 2001
From: Adam Frisby
Date: Mon, 21 Apr 2008 14:11:36 +0000
Subject: * Added missing reference to OpenSim.Framework.Communications to
RemoteAdminPlugin to fix a compile error introduced by the Radmin patch.
---
.../Region/Environment/Scenes/SceneObjectGroup.cs | 2436 ++++++++++----------
1 file changed, 1218 insertions(+), 1218 deletions(-)
(limited to 'OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs')
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index ac35e46..6af7662 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -39,9 +39,8 @@ using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Environment.Scenes
{
-
[Flags]
- public enum scriptEvents : int
+ public enum scriptEvents
{
None = 0,
attach = 1,
@@ -77,16 +76,6 @@ namespace OpenSim.Region.Environment.Scenes
public partial class SceneObjectGroup : EntityBase
{
- protected SceneObjectPart m_rootPart;
-
- ///
- /// The constituent parts of this group
- ///
- protected Dictionary m_parts = new Dictionary();
-
- protected ulong m_regionHandle;
-
- public event PrimCountTaintedDelegate OnPrimCountTainted;
private PrimCountTaintedDelegate handlerPrimCountTainted = null;
///
@@ -94,17 +83,34 @@ namespace OpenSim.Region.Environment.Scenes
/// since the group's last persistent backup
///
public bool HasGroupChanged = false;
-
+
private LLVector3 lastPhysGroupPos;
private LLQuaternion lastPhysGroupRot;
- private Dictionary m_scriptEvents = new Dictionary();
private scriptEvents m_aggregateScriptEvents = scriptEvents.None;
+ ///
+ /// The constituent parts of this group
+ ///
+ protected Dictionary m_parts = new Dictionary();
+
+ protected ulong m_regionHandle;
+ protected SceneObjectPart m_rootPart;
+ private Dictionary m_scriptEvents = new Dictionary();
+
#region Properties
///
+ /// Added because the Parcel code seems to use it
+ /// but not sure a object should have this
+ /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
+ /// think really there should be a list (or whatever) in each scenepresence
+ /// saying what prim(s) that user has selected.
+ ///
+ protected bool m_isSelected = false;
+
+ ///
///
///
public int PrimCount
@@ -116,11 +122,13 @@ namespace OpenSim.Region.Environment.Scenes
{
get { return m_rootPart.RotationOffset; }
}
+
public LLUUID GroupID
{
get { return m_rootPart.GroupID; }
set { m_rootPart.GroupID = value; }
}
+
///
///
///
@@ -161,7 +169,7 @@ namespace OpenSim.Region.Environment.Scenes
{
get
{
- if( m_rootPart == null )
+ if (m_rootPart == null)
{
throw new NullReferenceException(
string.Format("[SCENE OBJECT GROUP]: Object {0} has no root part.", m_uuid));
@@ -176,7 +184,7 @@ namespace OpenSim.Region.Environment.Scenes
{
m_scene.CrossPrimGroupIntoNewRegion(val, this);
}
-
+
lock (m_parts)
{
@@ -187,24 +195,26 @@ namespace OpenSim.Region.Environment.Scenes
}
//if (m_rootPart.PhysActor != null)
//{
- //m_rootPart.PhysActor.Position =
- //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
- //m_rootPart.GroupPosition.Z);
- //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ //m_rootPart.PhysActor.Position =
+ //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
+ //m_rootPart.GroupPosition.Z);
+ //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
//}
}
}
public override uint LocalId
{
- get {
+ get
+ {
if (m_rootPart == null)
{
m_log.Error("[SCENE OBJECT GROUP]: Unable to find the rootpart for a LocalId Request!");
return 0;
}
-
- return m_rootPart.LocalId; }
+
+ return m_rootPart.LocalId;
+ }
set { m_rootPart.LocalId = value; }
}
@@ -216,11 +226,12 @@ namespace OpenSim.Region.Environment.Scenes
public LLUUID OwnerID
{
- get {
+ get
+ {
if (m_rootPart == null)
return LLUUID.Zero;
- return m_rootPart.OwnerID;
+ return m_rootPart.OwnerID;
}
set { m_rootPart.OwnerID = value; }
}
@@ -237,15 +248,6 @@ namespace OpenSim.Region.Environment.Scenes
set { m_rootPart.Text = value; }
}
- ///
- /// Added because the Parcel code seems to use it
- /// but not sure a object should have this
- /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
- /// think really there should be a list (or whatever) in each scenepresence
- /// saying what prim(s) that user has selected.
- ///
- protected bool m_isSelected = false;
-
protected virtual bool InSceneBackup
{
get { return true; }
@@ -254,7 +256,8 @@ namespace OpenSim.Region.Environment.Scenes
public bool IsSelected
{
get { return m_isSelected; }
- set {
+ set
+ {
m_isSelected = value;
// Tell physics engine that group is selected
if (m_rootPart.PhysActor != null)
@@ -304,11 +307,11 @@ namespace OpenSim.Region.Environment.Scenes
public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
{
m_scene = scene;
-
+
part.SetParent(this);
part.ParentID = 0;
part.LinkNum = 0;
-
+
m_parts.Add(part.UUID, part);
SetPartAsRoot(part);
@@ -329,7 +332,7 @@ namespace OpenSim.Region.Environment.Scenes
{
m_scene = scene;
m_regionHandle = regionHandle;
-
+
StringReader sr = new StringReader(xmlData);
XmlTextReader reader = new XmlTextReader(sr);
try
@@ -339,11 +342,11 @@ namespace OpenSim.Region.Environment.Scenes
reader.ReadStartElement("RootPart");
m_rootPart = SceneObjectPart.FromXml(reader);
AddPart(m_rootPart);
-
- m_log.DebugFormat("[SCENE OBJECT GROUP]: Current node {0}", reader.Name);
-
+
+ m_log.DebugFormat("[SCENE OBJECT GROUP]: Current node {0}", reader.Name);
+
reader.ReadEndElement();
-
+
while (reader.Read())
{
switch (reader.NodeType)
@@ -356,7 +359,7 @@ namespace OpenSim.Region.Environment.Scenes
part.LocalId = m_scene.PrimIDAllocate();
AddPart(part);
part.RegionHandle = m_regionHandle;
-
+
part.TrimPermissions();
}
break;
@@ -368,10 +371,10 @@ namespace OpenSim.Region.Environment.Scenes
catch (XmlException)
{
m_log.ErrorFormat("[SCENE OBJECT GROUP]: Deserialization of following xml failed, {0}", xmlData);
-
+
// Let's see if carrying on does anything for us
}
-
+
reader.Close();
sr.Close();
@@ -436,6 +439,37 @@ namespace OpenSim.Region.Environment.Scenes
}
///
+ ///
+ ///
+ public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
+ LLQuaternion rot, PrimitiveBaseShape shape)
+ {
+ m_regionHandle = regionHandle;
+ m_scene = scene;
+
+ // this.Pos = pos;
+ LLVector3 rootOffset = new LLVector3(0, 0, 0);
+ SceneObjectPart newPart =
+ new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rot, rootOffset);
+ newPart.LinkNum = m_parts.Count;
+ m_parts.Add(newPart.UUID, newPart);
+ SetPartAsRoot(newPart);
+
+ AttachToBackup();
+
+ //ApplyPhysics(scene.m_physicalPrim);
+ }
+
+ ///
+ ///
+ ///
+ public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
+ PrimitiveBaseShape shape)
+ : this(scene, regionHandle, ownerID, localID, pos, LLQuaternion.Identity, shape)
+ {
+ }
+
+ ///
/// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes.
///
private void AttachToBackup()
@@ -473,7 +507,7 @@ namespace OpenSim.Region.Environment.Scenes
// This may need to be updated to the maximum draw distance possible..
// We might (and probably will) be checking for prim creation from other sims
// when the camera crosses the border.
- float idist = (float)Constants.RegionSize;
+ float idist = Constants.RegionSize;
if (inter.HitTF)
@@ -481,7 +515,6 @@ namespace OpenSim.Region.Environment.Scenes
// We need to find the closest prim to return to the testcaller along the ray
if (inter.distance < idist)
{
- idist = inter.distance;
returnresult.HitTF = true;
returnresult.ipoint = inter.ipoint;
returnresult.obj = part;
@@ -494,39 +527,10 @@ namespace OpenSim.Region.Environment.Scenes
return returnresult;
}
- ///
- ///
- ///
- public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
- LLQuaternion rot, PrimitiveBaseShape shape)
- {
- m_regionHandle = regionHandle;
- m_scene = scene;
-
- // this.Pos = pos;
- LLVector3 rootOffset = new LLVector3(0, 0, 0);
- SceneObjectPart newPart =
- new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rot, rootOffset);
- newPart.LinkNum = m_parts.Count;
- m_parts.Add(newPart.UUID, newPart);
- SetPartAsRoot(newPart);
-
- AttachToBackup();
-
- //ApplyPhysics(scene.m_physicalPrim);
- }
-
- ///
- ///
- ///
- public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
- PrimitiveBaseShape shape)
- : this(scene, regionHandle, ownerID, localID, pos, LLQuaternion.Identity, shape)
- {
- }
-
#endregion
+ public event PrimCountTaintedDelegate OnPrimCountTainted;
+
public string ToXmlString()
{
using (StringWriter sw = new StringWriter())
@@ -547,7 +551,7 @@ namespace OpenSim.Region.Environment.Scenes
m_rootPart.ToXml(writer);
writer.WriteEndElement();
writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
-
+
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
@@ -560,7 +564,7 @@ namespace OpenSim.Region.Environment.Scenes
}
}
}
-
+
writer.WriteEndElement();
writer.WriteEndElement();
}
@@ -583,7 +587,7 @@ namespace OpenSim.Region.Environment.Scenes
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
m_rootPart.ToXml(writer);
writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
-
+
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
@@ -594,1060 +598,771 @@ namespace OpenSim.Region.Environment.Scenes
}
}
}
-
+
writer.WriteEndElement();
writer.WriteEndElement();
}
- #region Copying
-
///
- /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
+ ///
///
- ///
- public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID)
+ ///
+ private void SetPartAsRoot(SceneObjectPart part)
{
- SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
- dupe.m_parts = new Dictionary();
- dupe.m_parts.Clear();
- //dupe.OwnerID = AgentID;
- //dupe.GroupID = GroupID;
- dupe.AbsolutePosition = new LLVector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
- dupe.m_scene = m_scene;
- dupe.m_regionHandle = m_regionHandle;
-
- dupe.CopyRootPart(m_rootPart, OwnerID, GroupID);
- dupe.m_rootPart.TrimPermissions();
-
- /// may need to create a new Physics actor.
- if (dupe.RootPart.PhysActor != null)
- {
- PrimitiveBaseShape pbs = dupe.RootPart.Shape;
-
- dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
- dupe.RootPart.Name,
- pbs,
- new PhysicsVector(dupe.RootPart.AbsolutePosition.X, dupe.RootPart.AbsolutePosition.Y,
- dupe.RootPart.AbsolutePosition.Z),
- new PhysicsVector(dupe.RootPart.Scale.X, dupe.RootPart.Scale.Y, dupe.RootPart.Scale.Z),
- new Quaternion(dupe.RootPart.RotationOffset.W, dupe.RootPart.RotationOffset.X,
- dupe.RootPart.RotationOffset.Y, dupe.RootPart.RotationOffset.Z),
- dupe.RootPart.PhysActor.IsPhysical);
-
- dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
-
- dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
- }
- // Now we've made a copy that replaces this one, we need to
- // switch the owner to the person who did the copying
- // Second Life copies an object and duplicates the first one in it's place
- // So, we have to make a copy of this one, set it in it's place then set the owner on this one
-
- SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
+ m_rootPart = part;
+ }
+ ///
+ ///
+ ///
+ ///
+ private void SetPartAsNonRoot(SceneObjectPart part)
+ {
+ part.ParentID = m_rootPart.LocalId;
+ }
- m_rootPart.ScheduleFullUpdate();
+ ///
+ ///
+ ///
+ ///
+ public List GetScenePresences()
+ {
+ return m_scene.GetScenePresences();
+ }
- List partList = new List(m_parts.Values);
- foreach (SceneObjectPart part in partList)
+ public override void UpdateMovement()
+ {
+ lock (m_parts)
{
- if (part.UUID != m_rootPart.UUID)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- dupe.CopyPart(part, OwnerID, GroupID);
- SetPartOwner(part, cAgentID, cGroupID);
- part.ScheduleFullUpdate();
+ part.UpdateMovement();
}
}
- dupe.UpdateParentIDs();
+ }
- dupe.AttachToBackup();
- ScheduleGroupForFullUpdate();
+ public float GetTimeDilation()
+ {
+ return m_scene.TimeDilation;
+ }
- 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;
+ AttachToBackup();
}
///
///
///
///
- public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
+ public void AddPart(SceneObjectPart part)
{
- SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
- newPart.SetParent(this);
-
lock (m_parts)
{
- m_parts.Add(newPart.UUID, newPart);
- }
-
- SetPartAsRoot(newPart);
- }
+ part.SetParent(this);
+ part.LinkNum = m_parts.Count;
- public void ScriptSetPhysicsStatus(bool UsePhysics)
- {
- if (m_scene.m_physicalPrim)
- {
- lock (m_parts)
+ try
{
- foreach (SceneObjectPart part in m_parts.Values)
- {
- if (UsePhysics)
- part.AddFlag(LLObject.ObjectFlags.Physics);
- else
- part.RemFlag(LLObject.ObjectFlags.Physics);
-
- part.DoPhysicsPropertyUpdate(UsePhysics, false);
- IsSelected = false;
- }
+ m_parts.Add(part.UUID, part);
+ }
+ catch (Exception e)
+ {
+ m_log.Error("Failed to add scened object part", e);
}
}
-
}
- public void ScriptSetPhantomStatus(bool PhantomStatus)
+ ///
+ ///
+ ///
+ public void UpdateParentIDs()
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
- if (PhantomStatus)
+ if (part.UUID != m_rootPart.UUID)
{
- part.AddFlag(LLObject.ObjectFlags.Phantom);
- if (part.PhysActor != null)
- {
- m_scene.PhysicsScene.RemovePrim(part.PhysActor);
- }
- }
- else
- {
- part.RemFlag(LLObject.ObjectFlags.Phantom);
- if ((part.ObjectFlags & (int)LLObject.ObjectFlags.Physics) != 0)
- {
- part.DoPhysicsPropertyUpdate(true, false);
- }
+ part.ParentID = m_rootPart.LocalId;
}
}
}
}
- public void applyImpulse(PhysicsVector impulse)
+ public void RegenerateFullIDs()
{
- // We check if rootpart is null here because scripts don't delete if you delete the host.
- // This means that unfortunately, we can pass a null physics actor to Simulate!
- // Make sure we don't do that!
- SceneObjectPart rootpart = m_rootPart;
- if (rootpart != null)
+ lock (m_parts)
{
- if (rootpart.PhysActor != null)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- rootpart.PhysActor.AddForce(impulse);
- m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
+ part.UUID = LLUUID.Random();
}
}
}
- public void moveToTarget(LLVector3 target, float tau)
- {
- SceneObjectPart rootpart = m_rootPart;
- if (rootpart != null)
- {
- rootpart.PhysActor.PIDTarget = new PhysicsVector(target.X, target.Y, target.Z);
- rootpart.PhysActor.PIDTau = tau;
- rootpart.PhysActor.PIDActive = true;
- }
- }
- public void stopMoveToTarget()
+ public void ResetChildPrimPhysicsPositions()
{
- SceneObjectPart rootpart = m_rootPart;
- if (rootpart != null)
- {
- rootpart.PhysActor.PIDActive = false;
- }
+ AbsolutePosition = AbsolutePosition;
+ HasGroupChanged = false;
}
- public void SetRootPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
+ public LLUUID GetPartsFullID(uint localID)
{
- part.LastOwnerID = part.OwnerID;
- part.OwnerID = cAgentID;
- part.GroupID = cGroupID;
-
-
- if (part.OwnerID != cAgentID)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- // Apply Next Owner Permissions if we're not bypassing permissions
- if (!m_scene.PermissionsMngr.BypassPermissions)
- m_rootPart.ApplyNextOwnerPermissions();
+ return part.UUID;
}
-
- part.ScheduleFullUpdate();
+ return null;
}
- ///
- ///
- ///
- ///
- public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
+ public void ObjectGrabHandler(uint localId, LLVector3 offsetPos, IClientAPI remoteClient)
{
- SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
- newPart.SetParent(this);
-
- lock (m_parts)
+ if (m_rootPart.LocalId == localId)
{
- m_parts.Add(newPart.UUID, newPart);
+ OnGrabGroup(offsetPos, remoteClient);
}
-
- SetPartAsNonRoot(newPart);
- }
-
- ///
- /// Reset the LLUUIDs for all the prims that make up this group.
- ///
- /// This is called by methods which want to add a new group to an existing scene, in order
- /// to ensure that there are no clashes with groups already present.
- ///
- public void ResetIDs()
- {
- // As this is only ever called for prims which are not currently part of the scene (and hence
- // not accessible by clients), there should be no need to lock
- List partsList = new List(m_parts.Values);
- m_parts.Clear();
- foreach (SceneObjectPart part in partsList)
+ else
{
- part.ResetIDs(m_parts.Count);
- m_parts.Add(part.UUID, part);
+ SceneObjectPart part = GetChildPart(localId);
+ OnGrabPart(part, offsetPos, remoteClient);
}
}
- ///
- ///
- ///
- ///
- public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags)
+ public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient)
{
- //RootPart.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
- ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket) PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
- // TODO: don't create new blocks if recycling an old packet
-
- ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
- objPropDB.RequestFlags = RequestFlags;
- objPropDB.ObjectID = RootPart.UUID;
- objPropDB.OwnerID = RootPart.ObjectOwner;
- objPropDB.GroupID = RootPart.GroupID;
- objPropDB.BaseMask = RootPart.BaseMask;
- objPropDB.OwnerMask = RootPart.OwnerMask;
- objPropDB.GroupMask = RootPart.GroupMask;
- objPropDB.EveryoneMask = RootPart.EveryoneMask;
- objPropDB.NextOwnerMask = RootPart.NextOwnerMask;
-
- // TODO: More properties are needed in SceneObjectPart!
- objPropDB.OwnershipCost = RootPart.OwnershipCost;
- objPropDB.SaleType = RootPart.ObjectSaleType;
- objPropDB.SalePrice = RootPart.SalePrice;
- objPropDB.Category = RootPart.Category;
- objPropDB.LastOwnerID = RootPart.CreatorID;
- objPropDB.Name = Helpers.StringToField(RootPart.Name);
- objPropDB.Description = Helpers.StringToField(RootPart.Description);
- objPropFamilyPack.ObjectData = objPropDB;
- remoteClient.OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
+ part.OnGrab(offsetPos, remoteClient);
}
- public void SetPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
+ public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient)
{
- part.OwnerID = cAgentID;
- part.GroupID = cGroupID;
+ m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
}
- #endregion
-
- #region Scheduling
-
///
- /// Examine this object's parts to see if they've changed sufficiently to warrant an update
+ /// Completely delete this group and tell all the scene presences about that deletion.
///
- public override void Update()
+ public void DeleteGroup()
{
+ DetachFromBackup(this);
+
lock (m_parts)
{
- if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02)
- {
- foreach (SceneObjectPart part in m_parts.Values)
- {
- if (part.UpdateFlag == 0) part.UpdateFlag = 1;
- }
-
- lastPhysGroupPos = AbsolutePosition;
- }
-
- if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
- || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
- || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
- || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1))
+ foreach (SceneObjectPart part in m_parts.Values)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ List avatars = GetScenePresences();
+ for (int i = 0; i < avatars.Count; i++)
{
- if (part.UpdateFlag == 0) part.UpdateFlag = 1;
+ if (avatars[i].ParentID == LocalId)
+ {
+ avatars[i].StandUp();
+ }
+
+ avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
-
- lastPhysGroupRot = GroupRotation;
- }
-
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.SendScheduledUpdates();
}
}
}
- public void ScheduleFullUpdateToAvatar(ScenePresence presence)
+ ///
+ /// Delete all the parts in this group.
+ ///
+ public void DeleteParts()
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
- part.AddFullUpdateToAvatar(presence);
+ part.StopScripts();
}
+
+ m_rootPart = null;
+ m_parts.Clear();
}
}
- public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
+ public void AddScriptLPS(int count)
{
- lock (m_parts)
- {
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.AddTerseUpdateToAvatar(presence);
- }
- }
+ InnerScene d = m_scene.m_innerScene;
+ d.AddToScriptLPS(count);
}
- ///
- /// Schedule a full update for every part in this object
- ///
- public void ScheduleGroupForFullUpdate()
+ public void AddActiveScriptCount(int count)
{
- HasGroupChanged = true;
-
- lock (m_parts)
- {
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.ScheduleFullUpdate();
- }
- }
+ InnerScene d = m_scene.m_innerScene;
+ d.AddActiveScripts(count);
}
- ///
- ///
- ///
- public void ScheduleGroupForTerseUpdate()
+ public void RemoveScriptEvents(LLUUID scriptid)
{
- HasGroupChanged = true;
-
- lock (m_parts)
+ lock (m_scriptEvents)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ if (m_scriptEvents.ContainsKey(scriptid))
{
- part.ScheduleTerseUpdate();
+ scriptEvents oldparts = scriptEvents.None;
+ oldparts = (scriptEvents) m_scriptEvents[scriptid];
+
+ // remove values from aggregated script events
+ m_aggregateScriptEvents &= ~oldparts;
+ m_scriptEvents.Remove(scriptid);
}
}
+ aggregateScriptEvents();
}
- ///
- ///
- ///
- public void SendGroupFullUpdate()
+ public void SetScriptEvents(LLUUID scriptid, int events)
{
- HasGroupChanged = true;
-
- lock (m_parts)
+ scriptEvents oldparts;
+ lock (m_scriptEvents)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ if (m_scriptEvents.ContainsKey(scriptid))
{
- part.SendFullUpdateToAllClients();
+ oldparts = m_scriptEvents[scriptid];
+
+ // remove values from aggregated script events
+ m_aggregateScriptEvents &= ~oldparts;
+ m_scriptEvents[scriptid] = (scriptEvents) events;
+ }
+ else
+ {
+ m_scriptEvents.Add(scriptid, (scriptEvents) events);
}
}
- }
- public void QueueForUpdateCheck()
- {
- m_scene.m_innerScene.AddToUpdateList(this);
+ aggregateScriptEvents();
}
- ///
- ///
- ///
- public void SendGroupTerseUpdate()
+ public void aggregateScriptEvents()
{
- HasGroupChanged = true;
-
- lock (m_parts)
+ // Aggregate script events
+ lock (m_scriptEvents)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ foreach (scriptEvents s in m_scriptEvents.Values)
{
- part.SendTerseUpdateToAllClients();
+ m_aggregateScriptEvents |= s;
}
}
- }
+ uint objectflagupdate = m_rootPart.ObjectFlags;
- #endregion
+ if (
+ ((m_aggregateScriptEvents & scriptEvents.touch) != 0) ||
+ ((m_aggregateScriptEvents & scriptEvents.touch_end) != 0) ||
+ ((m_aggregateScriptEvents & scriptEvents.touch_start) != 0)
+ )
+ {
+ objectflagupdate |= (uint) LLObject.ObjectFlags.Touch;
+ }
+ else
+ {
+ objectflagupdate &= ~(uint) LLObject.ObjectFlags.Touch;
+ }
- #region SceneGroupPart Methods
+ if ((m_aggregateScriptEvents & scriptEvents.money) != 0)
+ {
+ objectflagupdate |= (uint) LLObject.ObjectFlags.Money;
+ }
+ else
+ {
+ objectflagupdate &= ~(uint) LLObject.ObjectFlags.Money;
+ }
- ///
- /// Get the child part by LinkNum
- ///
- ///
- /// null if no child part with that linknum or child part
- public SceneObjectPart GetLinkNumPart(int linknum)
- {
+ if (
+ ((m_aggregateScriptEvents & scriptEvents.collision) != 0) ||
+ ((m_aggregateScriptEvents & scriptEvents.collision_end) != 0) ||
+ ((m_aggregateScriptEvents & scriptEvents.collision_start) != 0)
+ )
+ {
+ // subscribe to physics updates.
+ }
+ else
+ {
+ // unsubscribe to physics updates.
+ }
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
- if (part.LinkNum == linknum)
- {
- return part;
- }
+ part.ObjectFlags = objectflagupdate;
}
}
-
- return null;
+ ScheduleGroupForFullUpdate();
}
- ///
- /// Get a child part with a given UUID
- ///
- ///
- /// null if a child part with the primID was not found
- public SceneObjectPart GetChildPart(LLUUID primID)
+ public override void SetText(string text, Vector3 color, double alpha)
{
- SceneObjectPart childPart = null;
- if (m_parts.ContainsKey(primID))
- {
- childPart = m_parts[primID];
- }
- return childPart;
+ Color = Color.FromArgb(0xff - (int) (alpha * 0xff),
+ (int) (color.x * 0xff),
+ (int) (color.y * 0xff),
+ (int) (color.z * 0xff));
+ Text = text;
+
+ m_rootPart.ScheduleFullUpdate();
}
- ///
- /// Get a child part with a given local ID
- ///
- ///
- /// null if a child part with the local ID was not found
- public SceneObjectPart GetChildPart(uint localID)
+ public void ApplyPhysics(bool m_physicalPrim)
{
lock (m_parts)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ if (m_parts.Count > 1)
{
- if (part.LocalId == localID)
+ m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
+ foreach (SceneObjectPart part in m_parts.Values)
{
- return part;
+ if (part.LocalId != m_rootPart.LocalId)
+ {
+ part.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
+ }
+ // Hack to get the physics scene geometries in the right spot
+ ResetChildPrimPhysicsPositions();
}
}
+ else
+ {
+ m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
+ }
}
-
- return null;
}
- ///
- /// Does this group contain the child prim
- /// should be able to remove these methods once we have a entity index in scene
- ///
- ///
- ///
- public bool HasChildPrim(LLUUID primID)
+ public void SetOwnerId(LLUUID userId)
{
- if (m_parts.ContainsKey(primID))
- {
- return true;
- }
- return false;
+ ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; });
}
- ///
- /// Does this group contain the child prim
- /// should be able to remove these methods once we have a entity index in scene
- ///
- ///
- ///
- public bool HasChildPrim(uint localID)
+ public void ForEachPart(Action whatToDo)
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
- if (part.LocalId == localID)
- {
- return true;
- }
+ whatToDo(part);
}
}
- return false;
}
-
- #endregion
- #region Packet Handlers
+ #region Events
///
- /// Link the prims in a given group to this group
+ ///
///
- /// The group of prims which should be linked to this group
- public void LinkToGroup(SceneObjectGroup objectGroup)
+ public void TriggerTainted()
{
- if (objectGroup.RootPart.UpdateFlag > 0)
+ handlerPrimCountTainted = OnPrimCountTainted;
+ if (handlerPrimCountTainted != null)
{
- // I've never actually seen this happen, though I think it's theoretically possible
- m_log.WarnFormat(
- "[SCENE OBJECT GROUP]: Aborted linking {0}, {1} to {2}, {3} as it has yet to finish delinking",
- objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
-
- return;
+ handlerPrimCountTainted();
}
-
-// m_log.DebugFormat(
-// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
-// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
-
- SceneObjectPart linkPart = objectGroup.m_rootPart;
-
- Vector3 oldGroupPosition =
- new Vector3(linkPart.GroupPosition.X, linkPart.GroupPosition.Y, linkPart.GroupPosition.Z);
- Quaternion oldRootRotation =
- new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y,
- linkPart.RotationOffset.Z);
+ }
- linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
- linkPart.GroupPosition = AbsolutePosition;
- Vector3 axPos = new Vector3(linkPart.OffsetPosition.X, linkPart.OffsetPosition.Y, linkPart.OffsetPosition.Z);
-
- Quaternion parentRot =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- 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.Inverse()*oldRot;
- linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
-
- linkPart.ParentID = m_rootPart.LocalId;
-
- linkPart.LinkNum = m_parts.Count;
-
- lock (m_parts)
+ ///
+ /// Processes backup
+ ///
+ ///
+ public void ProcessBackup(IRegionDataStore datastore)
+ {
+ if (HasGroupChanged)
{
- m_parts.Add(linkPart.UUID, linkPart);
+ datastore.StoreObject(this, m_scene.RegionInfo.RegionID);
+ HasGroupChanged = false;
}
-
- linkPart.SetParent(this);
- //if (linkPart.PhysActor != null)
- //{
- // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
+ ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
+ }
- //linkPart.PhysActor = null;
- //}
+ #endregion
- //TODO: rest of parts
- foreach (SceneObjectPart part in objectGroup.Children.Values)
+ #region Client Updating
+
+ public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientFlags)
+ {
+ lock (m_parts)
{
- if (part.UUID != objectGroup.m_rootPart.UUID)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- LinkNonRootPart(part, oldGroupPosition, oldRootRotation);
+ SendPartFullUpdate(remoteClient, part, clientFlags);
}
}
+ }
- DetachFromBackup(objectGroup);
+ ///
+ /// Send a full update to the client for the given part
+ ///
+ ///
+ ///
+ internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags)
+ {
+ if (m_rootPart.UUID == part.UUID)
+ {
+ part.SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags);
+ }
+ else
+ {
+ part.SendFullUpdateToClient(remoteClient, clientFlags);
+ }
+ }
- m_scene.DeleteEntity(objectGroup.UUID);
+ ///
+ /// Send a terse update to the client for the given part
+ ///
+ ///
+ ///
+ internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part)
+ {
+ if (m_rootPart.UUID == part.UUID)
+ {
+ part.SendTerseUpdateToClient(remoteClient, AbsolutePosition);
+ }
+ else
+ {
+ part.SendTerseUpdateToClient(remoteClient);
+ }
+ }
- // TODO Deleting the parts may cause problems later on if they have already
- // made it into the update queue. However, sending out updates for those parts is now
- // spurious, so it would be good not to send them at some point.
- // The traffic caused is always going to be pretty minor, so it's not high priority
- //objectGroup.DeleteParts();
+ #endregion
- ScheduleGroupForFullUpdate();
- }
+ #region Copying
///
- /// Delink the given prim from this group. The delinked prim is established as
- /// an independent SceneObjectGroup.
+ /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
///
- ///
- public void DelinkFromGroup(uint partID)
- {
- SceneObjectPart linkPart = GetChildPart(partID);
+ ///
+ public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID)
+ {
+ SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
+ dupe.m_parts = new Dictionary();
+ dupe.m_parts.Clear();
+ //dupe.OwnerID = AgentID;
+ //dupe.GroupID = GroupID;
+ dupe.AbsolutePosition = new LLVector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
+ dupe.m_scene = m_scene;
+ dupe.m_regionHandle = m_regionHandle;
- if (null != linkPart)
- {
-// m_log.DebugFormat(
-// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
-// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
-
- LLQuaternion worldRot = linkPart.GetWorldRotation();
-
- // Remove the part from this object
- lock (m_parts)
- {
- m_parts.Remove(linkPart.UUID);
- }
-
- linkPart.ParentID = 0;
+ dupe.CopyRootPart(m_rootPart, OwnerID, GroupID);
+ dupe.m_rootPart.TrimPermissions();
- if (linkPart.PhysActor != null)
- {
- m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
- }
-
- // We need to reset the child part's position
- // ready for life as a separate object after being a part of another object
- Quaternion parentRot
- = new Quaternion(
- m_rootPart.RotationOffset.W,
- m_rootPart.RotationOffset.X,
- m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
-
- Vector3 axPos
- = new Vector3(
- linkPart.OffsetPosition.X,
- linkPart.OffsetPosition.Y,
- linkPart.OffsetPosition.Z);
+ /// may need to create a new Physics actor.
+ if (dupe.RootPart.PhysActor != null)
+ {
+ PrimitiveBaseShape pbs = dupe.RootPart.Shape;
- axPos = parentRot*axPos;
- linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
- linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
- linkPart.OffsetPosition = new LLVector3(0, 0, 0);
+ dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
+ dupe.RootPart.Name,
+ pbs,
+ new PhysicsVector(dupe.RootPart.AbsolutePosition.X, dupe.RootPart.AbsolutePosition.Y,
+ dupe.RootPart.AbsolutePosition.Z),
+ new PhysicsVector(dupe.RootPart.Scale.X, dupe.RootPart.Scale.Y, dupe.RootPart.Scale.Z),
+ new Quaternion(dupe.RootPart.RotationOffset.W, dupe.RootPart.RotationOffset.X,
+ dupe.RootPart.RotationOffset.Y, dupe.RootPart.RotationOffset.Z),
+ dupe.RootPart.PhysActor.IsPhysical);
- linkPart.RotationOffset = worldRot;
+ dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
- // This chunk is probably unnecesary now - delete later on
- /*
- 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);
- */
+ dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
+ }
+ // Now we've made a copy that replaces this one, we need to
+ // switch the owner to the person who did the copying
+ // Second Life copies an object and duplicates the first one in it's place
+ // So, we have to make a copy of this one, set it in it's place then set the owner on this one
- // Add physics information back to delinked part if appropriate
- // XXX This is messy and should be refactorable with the similar section in
- // SceneObjectPart.UpdatePrimFlags()
- //if (m_rootPart.PhysActor != null)
- //{
- //linkPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
- //linkPart.Name,
- //linkPart.Shape,
- //new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y,
- //linkPart.AbsolutePosition.Z),
- //new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z),
- //new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X,
- //linkPart.RotationOffset.Y, linkPart.RotationOffset.Z),
- //m_rootPart.PhysActor.IsPhysical);
- //m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true);
- //}
+ SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
- SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
- m_scene.AddEntity(objectGroup);
+ m_rootPart.ScheduleFullUpdate();
- ScheduleGroupForFullUpdate();
- }
- else
+ List partList = new List(m_parts.Values);
+ foreach (SceneObjectPart part in partList)
{
- m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
- "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
- partID, LocalId, UUID);
+ if (part.UUID != m_rootPart.UUID)
+ {
+ dupe.CopyPart(part, OwnerID, GroupID);
+ SetPartOwner(part, cAgentID, cGroupID);
+ part.ScheduleFullUpdate();
+ }
}
- }
+ dupe.UpdateParentIDs();
- private void DetachFromBackup(SceneObjectGroup objectGroup)
- {
- m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup;
+ dupe.AttachToBackup();
+ ScheduleGroupForFullUpdate();
+
+ return dupe;
}
- private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{
- part.SetParent(this);
- part.ParentID = m_rootPart.LocalId;
- part.LinkNum = m_parts.Count;
-
+ SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
+ newPart.SetParent(this);
+
lock (m_parts)
{
- m_parts.Add(part.UUID, part);
+ m_parts.Add(newPart.UUID, newPart);
}
- Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
- axiomOldPos = oldGroupRotation*axiomOldPos;
- axiomOldPos += oldGroupPosition;
- LLVector3 oldAbsolutePosition = new LLVector3(axiomOldPos.x, axiomOldPos.y, axiomOldPos.z);
- part.OffsetPosition = oldAbsolutePosition - AbsolutePosition;
-
- Quaternion axiomRootRotation =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
-
- Vector3 axiomPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
- axiomPos = axiomRootRotation.Inverse()*axiomPos;
- part.OffsetPosition = new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z);
+ SetPartAsRoot(newPart);
+ }
- Quaternion axiomPartRotation =
- new Quaternion(part.RotationOffset.W, part.RotationOffset.X, part.RotationOffset.Y,
- part.RotationOffset.Z);
+ public void ScriptSetPhysicsStatus(bool UsePhysics)
+ {
+ if (m_scene.m_physicalPrim)
+ {
+ lock (m_parts)
+ {
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ if (UsePhysics)
+ part.AddFlag(LLObject.ObjectFlags.Physics);
+ else
+ part.RemFlag(LLObject.ObjectFlags.Physics);
- axiomPartRotation = oldGroupRotation*axiomPartRotation;
- axiomPartRotation = axiomRootRotation.Inverse()*axiomPartRotation;
- part.RotationOffset =
- new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
+ part.DoPhysicsPropertyUpdate(UsePhysics, false);
+ IsSelected = false;
+ }
+ }
+ }
}
- ///
- /// If object is physical, apply force to move it around
- /// If object is not physical, just put it at the resulting location
- ///
- /// Always seems to be 0,0,0, so ignoring
- /// New position. We do the math here to turn it into a force
- ///
- public void GrabMovement(LLVector3 offset, LLVector3 pos, IClientAPI remoteClient)
+ public void ScriptSetPhantomStatus(bool PhantomStatus)
{
-
- if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
+ lock (m_parts)
{
-
- if (m_rootPart.PhysActor != null)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- if (m_rootPart.PhysActor.IsPhysical)
+ if (PhantomStatus)
{
- LLVector3 llmoveforce = pos - AbsolutePosition;
- PhysicsVector grabforce = new PhysicsVector(llmoveforce.X, llmoveforce.Y, llmoveforce.Z);
- grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass;
- m_rootPart.PhysActor.AddForce(grabforce);
- m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ part.AddFlag(LLObject.ObjectFlags.Phantom);
+ if (part.PhysActor != null)
+ {
+ m_scene.PhysicsScene.RemovePrim(part.PhysActor);
+ }
}
else
{
- //NonPhysicalGrabMovement(pos);
+ part.RemFlag(LLObject.ObjectFlags.Phantom);
+ if ((part.ObjectFlags & (int) LLObject.ObjectFlags.Physics) != 0)
+ {
+ part.DoPhysicsPropertyUpdate(true, false);
+ }
}
}
- else
- {
- //NonPhysicalGrabMovement(pos);
- }
}
}
- public void NonPhysicalGrabMovement(LLVector3 pos)
- {
- AbsolutePosition = pos;
- m_rootPart.SendTerseUpdateToAllClients();
- }
- ///
- ///
- ///
- ///
- public void GetProperties(IClientAPI client)
+ public void applyImpulse(PhysicsVector impulse)
{
- ObjectPropertiesPacket proper = (ObjectPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
- // TODO: don't create new blocks if recycling an old packet
-
- proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
- proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
- proper.ObjectData[0].ItemID = LLUUID.Zero;
- proper.ObjectData[0].CreationDate = (ulong) m_rootPart.CreationDate;
- proper.ObjectData[0].CreatorID = m_rootPart.CreatorID;
- proper.ObjectData[0].FolderID = LLUUID.Zero;
- proper.ObjectData[0].FromTaskID = LLUUID.Zero;
- proper.ObjectData[0].GroupID = LLUUID.Zero;
- proper.ObjectData[0].InventorySerial = (short) m_rootPart.InventorySerial;
- proper.ObjectData[0].LastOwnerID = m_rootPart.LastOwnerID;
- proper.ObjectData[0].ObjectID = UUID;
- proper.ObjectData[0].OwnerID = m_rootPart.OwnerID;
- proper.ObjectData[0].TouchName = Helpers.StringToField(m_rootPart.TouchName);
- proper.ObjectData[0].TextureID = new byte[0];
- proper.ObjectData[0].SitName = Helpers.StringToField(m_rootPart.SitName);
- proper.ObjectData[0].Name = Helpers.StringToField(m_rootPart.Name);
- proper.ObjectData[0].Description = Helpers.StringToField(m_rootPart.Description);
- proper.ObjectData[0].OwnerMask = m_rootPart.OwnerMask;
- proper.ObjectData[0].NextOwnerMask = m_rootPart.NextOwnerMask;
- proper.ObjectData[0].GroupMask = m_rootPart.GroupMask;
- proper.ObjectData[0].EveryoneMask = m_rootPart.EveryoneMask;
- proper.ObjectData[0].BaseMask = m_rootPart.BaseMask;
-
- client.OutPacket(proper, ThrottleOutPacketType.Task);
+ // We check if rootpart is null here because scripts don't delete if you delete the host.
+ // This means that unfortunately, we can pass a null physics actor to Simulate!
+ // Make sure we don't do that!
+ SceneObjectPart rootpart = m_rootPart;
+ if (rootpart != null)
+ {
+ if (rootpart.PhysActor != null)
+ {
+ rootpart.PhysActor.AddForce(impulse);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
+ }
+ }
}
- ///
- /// Set the name of a prim
- ///
- ///
- ///
- public void SetPartName(string name, uint localID)
+ public void moveToTarget(LLVector3 target, float tau)
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ SceneObjectPart rootpart = m_rootPart;
+ if (rootpart != null)
{
- part.Name = name;
+ rootpart.PhysActor.PIDTarget = new PhysicsVector(target.X, target.Y, target.Z);
+ rootpart.PhysActor.PIDTau = tau;
+ rootpart.PhysActor.PIDActive = true;
}
}
- public void SetPartDescription(string des, uint localID)
+ public void stopMoveToTarget()
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ SceneObjectPart rootpart = m_rootPart;
+ if (rootpart != null)
{
- part.Description = des;
+ rootpart.PhysActor.PIDActive = false;
}
}
- public void SetPartText(string text, uint localID)
+ public void SetRootPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ part.LastOwnerID = part.OwnerID;
+ part.OwnerID = cAgentID;
+ part.GroupID = cGroupID;
+
+
+ if (part.OwnerID != cAgentID)
{
- part.SetText( text );
- }
+ // Apply Next Owner Permissions if we're not bypassing permissions
+ if (!m_scene.PermissionsMngr.BypassPermissions)
+ m_rootPart.ApplyNextOwnerPermissions();
+ }
+
+ part.ScheduleFullUpdate();
}
- public void SetPartText(string text, LLUUID partID)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{
- SceneObjectPart part = GetChildPart(partID);
- if (part != null)
- {
- part.SetText( text );
- }
- }
+ SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
+ newPart.SetParent(this);
- public string GetPartName(uint localID)
- {
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ lock (m_parts)
{
- return part.Name;
+ m_parts.Add(newPart.UUID, newPart);
}
- return String.Empty;
- }
- public string GetPartDescription(uint localID)
- {
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
- {
- return part.Description;
- }
- return String.Empty;
+ SetPartAsNonRoot(newPart);
}
///
+ /// Reset the LLUUIDs for all the prims that make up this group.
///
+ /// This is called by methods which want to add a new group to an existing scene, in order
+ /// to ensure that there are no clashes with groups already present.
///
- ///
- ///
- ///
- ///
- ///
- public void UpdatePrimFlags(uint localID, ushort type, bool inUse, byte[] data)
+ public void ResetIDs()
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ // As this is only ever called for prims which are not currently part of the scene (and hence
+ // not accessible by clients), there should be no need to lock
+ List partsList = new List(m_parts.Values);
+ m_parts.Clear();
+ foreach (SceneObjectPart part in partsList)
{
- // If we have children
- lock (m_parts)
- {
- if (m_parts.Count > 1)
- {
- foreach (SceneObjectPart parts in m_parts.Values)
- {
- parts.UpdatePrimFlags(type, inUse, data);
- }
- }
- else
- {
- part.UpdatePrimFlags(type, inUse, data);
- }
- }
+ part.ResetIDs(m_parts.Count);
+ m_parts.Add(part.UUID, part);
}
}
- public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
- {
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
- {
- part.UpdateExtraParam(type, inUse, data);
- }
- }
- public SceneObjectPart[] GetParts()
- {
- int numParts = Children.Count;
- SceneObjectPart[] partArray = new SceneObjectPart[numParts];
- Children.Values.CopyTo(partArray, 0);
- return partArray;
- }
-
///
///
///
- ///
- ///
- public void UpdateTextureEntry(uint localID, byte[] textureEntry)
+ ///
+ public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags)
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
- {
- part.UpdateTextureEntry(textureEntry);
- }
+ //RootPart.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
+ ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket) PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
+ // TODO: don't create new blocks if recycling an old packet
+
+ ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
+ objPropDB.RequestFlags = RequestFlags;
+ objPropDB.ObjectID = RootPart.UUID;
+ objPropDB.OwnerID = RootPart.ObjectOwner;
+ objPropDB.GroupID = RootPart.GroupID;
+ objPropDB.BaseMask = RootPart.BaseMask;
+ objPropDB.OwnerMask = RootPart.OwnerMask;
+ objPropDB.GroupMask = RootPart.GroupMask;
+ objPropDB.EveryoneMask = RootPart.EveryoneMask;
+ objPropDB.NextOwnerMask = RootPart.NextOwnerMask;
+
+ // TODO: More properties are needed in SceneObjectPart!
+ objPropDB.OwnershipCost = RootPart.OwnershipCost;
+ objPropDB.SaleType = RootPart.ObjectSaleType;
+ objPropDB.SalePrice = RootPart.SalePrice;
+ objPropDB.Category = RootPart.Category;
+ objPropDB.LastOwnerID = RootPart.CreatorID;
+ objPropDB.Name = Helpers.StringToField(RootPart.Name);
+ objPropDB.Description = Helpers.StringToField(RootPart.Description);
+ objPropFamilyPack.ObjectData = objPropDB;
+ remoteClient.OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
}
- public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
+ public void SetPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
{
- SceneObjectPart updatePart = GetChildPart(localID);
- updatePart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
- HasGroupChanged = true;
+ part.OwnerID = cAgentID;
+ part.GroupID = cGroupID;
}
#endregion
- #region Shape
+ #region Scheduling
///
- ///
+ /// Examine this object's parts to see if they've changed sufficiently to warrant an update
///
- ///
- public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
+ public override void Update()
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ lock (m_parts)
{
- part.UpdateShape(shapeBlock);
+ if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02)
+ {
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ if (part.UpdateFlag == 0) part.UpdateFlag = 1;
+ }
- if (part.PhysActor != null)
- m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
- }
-
- }
+ lastPhysGroupPos = AbsolutePosition;
+ }
- #endregion
+ if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
+ || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
+ || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
+ || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1))
+ {
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ if (part.UpdateFlag == 0) part.UpdateFlag = 1;
+ }
- #region Resize
+ lastPhysGroupRot = GroupRotation;
+ }
- ///
- ///
- ///
- ///
- ///
- public void Resize(LLVector3 scale, uint localID)
- {
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
- {
- part.Resize(scale);
- if (part.PhysActor != null)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- part.PhysActor.Size =
- new PhysicsVector(scale.X, scale.Y, scale.Z);
- m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
+ part.SendScheduledUpdates();
}
- //if (part.UUID != m_rootPart.UUID)
- ScheduleGroupForFullUpdate();
-
- //if (part.UUID == m_rootPart.UUID)
- //{
- //if (m_rootPart.PhysActor != null)
- //{
- //m_rootPart.PhysActor.Size =
- //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
- //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
- //}
- //}
}
}
- public void GroupResize(LLVector3 scale, uint localID)
+
+ public void ScheduleFullUpdateToAvatar(ScenePresence presence)
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ lock (m_parts)
{
- float x = (scale.X / part.Scale.X);
- float y = (scale.Y / part.Scale.Y);
- float z = (scale.Z / part.Scale.Z);
- part.Resize(scale);
-
- lock (m_parts)
- {
- foreach (SceneObjectPart obPart in m_parts.Values)
- {
- if (obPart.UUID != m_rootPart.UUID)
- {
-
- LLVector3 currentpos = new LLVector3(obPart.OffsetPosition);
- currentpos.X *= x;
- currentpos.Y *= y;
- currentpos.Z *= z;
- LLVector3 newSize = new LLVector3(obPart.Scale);
- newSize.X *= x;
- newSize.Y *= y;
- newSize.Z *= z;
- obPart.Resize(newSize);
- obPart.UpdateOffSet(currentpos);
- }
- }
- }
-
- if (part.PhysActor != null)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- part.PhysActor.Size =
- new PhysicsVector(scale.X, scale.Y, scale.Z);
- m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
+ part.AddFullUpdateToAvatar(presence);
}
-
-
- ScheduleGroupForTerseUpdate();
}
}
- #endregion
-
- #region Position
-
- ///
- ///
- ///
- ///
- public void UpdateGroupPosition(LLVector3 pos)
+ public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
{
- if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
+ lock (m_parts)
{
- AbsolutePosition = pos;
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ part.AddTerseUpdateToAvatar(presence);
+ }
}
- //we need to do a terse update even if the move wasn't allowed
- // so that the position is reset in the client (the object snaps back)
- ScheduleGroupForTerseUpdate();
}
///
- ///
+ /// Schedule a full update for every part in this object
///
- ///
- ///
- public void UpdateSinglePosition(LLVector3 pos, uint localID)
+ public void ScheduleGroupForFullUpdate()
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ HasGroupChanged = true;
+
+ lock (m_parts)
{
- if (part.UUID == m_rootPart.UUID)
- {
- UpdateRootPosition(pos);
- }
- else
+ foreach (SceneObjectPart part in m_parts.Values)
{
- part.UpdateOffSet(pos);
+ part.ScheduleFullUpdate();
}
}
}
@@ -1655,579 +1370,864 @@ namespace OpenSim.Region.Environment.Scenes
///
///
///
- ///
- private void UpdateRootPosition(LLVector3 pos)
+ public void ScheduleGroupForTerseUpdate()
{
- LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
- LLVector3 oldPos =
- new LLVector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
- AbsolutePosition.Y + m_rootPart.OffsetPosition.Y,
- AbsolutePosition.Z + m_rootPart.OffsetPosition.Z);
- LLVector3 diff = oldPos - newPos;
- Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
- Quaternion partRotation =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
- axDiff = partRotation.Inverse()*axDiff;
- diff.X = axDiff.x;
- diff.Y = axDiff.y;
- diff.Z = axDiff.z;
+ HasGroupChanged = true;
lock (m_parts)
{
- foreach (SceneObjectPart obPart in m_parts.Values)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- if (obPart.UUID != m_rootPart.UUID)
- {
- obPart.OffsetPosition = obPart.OffsetPosition + diff;
- }
+ part.ScheduleTerseUpdate();
}
}
-
- AbsolutePosition = newPos;
- ScheduleGroupForTerseUpdate();
}
- public void OffsetForNewRegion(LLVector3 offset)
+ ///
+ ///
+ ///
+ public void SendGroupFullUpdate()
{
- m_rootPart.GroupPosition = offset;
+ HasGroupChanged = true;
+
+ lock (m_parts)
+ {
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ part.SendFullUpdateToAllClients();
+ }
+ }
+ }
+
+ public void QueueForUpdateCheck()
+ {
+ m_scene.m_innerScene.AddToUpdateList(this);
+ }
+
+ ///
+ ///
+ ///
+ public void SendGroupTerseUpdate()
+ {
+ HasGroupChanged = true;
+
+ lock (m_parts)
+ {
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ part.SendTerseUpdateToAllClients();
+ }
+ }
}
#endregion
- #region Rotation
+ #region SceneGroupPart Methods
///
- ///
+ /// Get the child part by LinkNum
///
- ///
- public void UpdateGroupRotation(LLQuaternion rot)
+ ///
+ /// null if no child part with that linknum or child part
+ public SceneObjectPart GetLinkNumPart(int linknum)
{
- m_rootPart.UpdateRotation(rot);
- if (m_rootPart.PhysActor != null)
+ lock (m_parts)
{
- m_rootPart.PhysActor.Orientation =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
- m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ if (part.LinkNum == linknum)
+ {
+ return part;
+ }
+ }
}
- ScheduleGroupForTerseUpdate();
+
+ return null;
}
///
- ///
+ /// Get a child part with a given UUID
///
- ///
- ///
- public void UpdateGroupRotation(LLVector3 pos, LLQuaternion rot)
+ ///
+ /// null if a child part with the primID was not found
+ public SceneObjectPart GetChildPart(LLUUID primID)
{
- m_rootPart.UpdateRotation(rot);
- if (m_rootPart.PhysActor != null)
+ SceneObjectPart childPart = null;
+ if (m_parts.ContainsKey(primID))
{
- m_rootPart.PhysActor.Orientation =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
- m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ childPart = m_parts[primID];
}
- AbsolutePosition = pos;
- ScheduleGroupForTerseUpdate();
+ return childPart;
}
///
- ///
+ /// Get a child part with a given local ID
///
- ///
///
- public void UpdateSingleRotation(LLQuaternion rot, uint localID)
+ /// null if a child part with the local ID was not found
+ public SceneObjectPart GetChildPart(uint localID)
{
- SceneObjectPart part = GetChildPart(localID);
- if (part != null)
+ lock (m_parts)
{
- if (part.UUID == m_rootPart.UUID)
- {
- UpdateRootRotation(rot);
- }
- else
+ foreach (SceneObjectPart part in m_parts.Values)
{
- part.UpdateRotation(rot);
+ if (part.LocalId == localID)
+ {
+ return part;
+ }
}
}
+
+ return null;
}
///
- ///
+ /// Does this group contain the child prim
+ /// should be able to remove these methods once we have a entity index in scene
///
- ///
- private void UpdateRootRotation(LLQuaternion rot)
+ ///
+ ///
+ public bool HasChildPrim(LLUUID primID)
{
- Quaternion axRot = new Quaternion(rot.W, rot.X, rot.Y, rot.Z);
- Quaternion oldParentRot =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
-
- m_rootPart.UpdateRotation(rot);
- if (m_rootPart.PhysActor != null)
+ if (m_parts.ContainsKey(primID))
{
- m_rootPart.PhysActor.Orientation =
- new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
- m_rootPart.RotationOffset.Z);
- m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ return true;
}
+ return false;
+ }
+ ///
+ /// Does this group contain the child prim
+ /// should be able to remove these methods once we have a entity index in scene
+ ///
+ ///
+ ///
+ public bool HasChildPrim(uint localID)
+ {
lock (m_parts)
{
- foreach (SceneObjectPart prim in m_parts.Values)
+ foreach (SceneObjectPart part in m_parts.Values)
{
- if (prim.UUID != m_rootPart.UUID)
+ if (part.LocalId == localID)
{
- Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z);
- axPos = oldParentRot*axPos;
- axPos = axRot.Inverse()*axPos;
- prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
- Quaternion primsRot =
- new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y,
- prim.RotationOffset.Z);
- Quaternion newRot = oldParentRot*primsRot;
- newRot = axRot.Inverse()*newRot;
- prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
- prim.ScheduleTerseUpdate();
+ return true;
}
}
}
-
- m_rootPart.ScheduleTerseUpdate();
+ return false;
}
#endregion
+ #region Packet Handlers
+
///
- ///
+ /// Link the prims in a given group to this group
///
- ///
- private void SetPartAsRoot(SceneObjectPart part)
+ /// The group of prims which should be linked to this group
+ public void LinkToGroup(SceneObjectGroup objectGroup)
{
- m_rootPart = part;
+ if (objectGroup.RootPart.UpdateFlag > 0)
+ {
+ // I've never actually seen this happen, though I think it's theoretically possible
+ m_log.WarnFormat(
+ "[SCENE OBJECT GROUP]: Aborted linking {0}, {1} to {2}, {3} as it has yet to finish delinking",
+ objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
+
+ return;
+ }
+
+// m_log.DebugFormat(
+// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
+// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
+
+ SceneObjectPart linkPart = objectGroup.m_rootPart;
+
+ Vector3 oldGroupPosition =
+ new Vector3(linkPart.GroupPosition.X, linkPart.GroupPosition.Y, linkPart.GroupPosition.Z);
+ Quaternion oldRootRotation =
+ new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y,
+ linkPart.RotationOffset.Z);
+
+ linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
+ linkPart.GroupPosition = AbsolutePosition;
+ Vector3 axPos = new Vector3(linkPart.OffsetPosition.X, linkPart.OffsetPosition.Y, linkPart.OffsetPosition.Z);
+
+ Quaternion parentRot =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ 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.Inverse() * oldRot;
+ linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
+
+ linkPart.ParentID = m_rootPart.LocalId;
+
+ linkPart.LinkNum = m_parts.Count;
+
+ lock (m_parts)
+ {
+ m_parts.Add(linkPart.UUID, linkPart);
+ }
+
+ linkPart.SetParent(this);
+
+ //if (linkPart.PhysActor != null)
+ //{
+ // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
+
+ //linkPart.PhysActor = null;
+ //}
+
+ //TODO: rest of parts
+ foreach (SceneObjectPart part in objectGroup.Children.Values)
+ {
+ if (part.UUID != objectGroup.m_rootPart.UUID)
+ {
+ LinkNonRootPart(part, oldGroupPosition, oldRootRotation);
+ }
+ }
+
+ DetachFromBackup(objectGroup);
+
+ m_scene.DeleteEntity(objectGroup.UUID);
+
+ // TODO Deleting the parts may cause problems later on if they have already
+ // made it into the update queue. However, sending out updates for those parts is now
+ // spurious, so it would be good not to send them at some point.
+ // The traffic caused is always going to be pretty minor, so it's not high priority
+ //objectGroup.DeleteParts();
+
+ ScheduleGroupForFullUpdate();
}
///
- ///
+ /// Delink the given prim from this group. The delinked prim is established as
+ /// an independent SceneObjectGroup.
///
- ///
- private void SetPartAsNonRoot(SceneObjectPart part)
+ ///
+ public void DelinkFromGroup(uint partID)
+ {
+ SceneObjectPart linkPart = GetChildPart(partID);
+
+ if (null != linkPart)
+ {
+// m_log.DebugFormat(
+// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
+// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
+
+ LLQuaternion worldRot = linkPart.GetWorldRotation();
+
+ // Remove the part from this object
+ lock (m_parts)
+ {
+ m_parts.Remove(linkPart.UUID);
+ }
+
+ linkPart.ParentID = 0;
+
+ if (linkPart.PhysActor != null)
+ {
+ m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
+ }
+
+ // We need to reset the child part's position
+ // ready for life as a separate object after being a part of another object
+ Quaternion parentRot
+ = new Quaternion(
+ m_rootPart.RotationOffset.W,
+ m_rootPart.RotationOffset.X,
+ m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+
+ Vector3 axPos
+ = new Vector3(
+ linkPart.OffsetPosition.X,
+ linkPart.OffsetPosition.Y,
+ linkPart.OffsetPosition.Z);
+
+ axPos = parentRot * axPos;
+ linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
+ linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
+ linkPart.OffsetPosition = new LLVector3(0, 0, 0);
+
+ linkPart.RotationOffset = worldRot;
+
+ // This chunk is probably unnecesary now - delete later on
+ /*
+ 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);
+ */
+
+ // Add physics information back to delinked part if appropriate
+ // XXX This is messy and should be refactorable with the similar section in
+ // SceneObjectPart.UpdatePrimFlags()
+ //if (m_rootPart.PhysActor != null)
+ //{
+ //linkPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
+ //linkPart.Name,
+ //linkPart.Shape,
+ //new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y,
+ //linkPart.AbsolutePosition.Z),
+ //new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z),
+ //new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X,
+ //linkPart.RotationOffset.Y, linkPart.RotationOffset.Z),
+ //m_rootPart.PhysActor.IsPhysical);
+ //m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true);
+ //}
+
+ SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
+
+ m_scene.AddEntity(objectGroup);
+
+ ScheduleGroupForFullUpdate();
+ }
+ else
+ {
+ m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
+ "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
+ partID, LocalId, UUID);
+ }
+ }
+
+ private void DetachFromBackup(SceneObjectGroup objectGroup)
{
+ m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup;
+ }
+
+ private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation)
+ {
+ part.SetParent(this);
part.ParentID = m_rootPart.LocalId;
+ part.LinkNum = m_parts.Count;
+
+ lock (m_parts)
+ {
+ m_parts.Add(part.UUID, part);
+ }
+
+ Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
+ axiomOldPos = oldGroupRotation * axiomOldPos;
+ axiomOldPos += oldGroupPosition;
+ LLVector3 oldAbsolutePosition = new LLVector3(axiomOldPos.x, axiomOldPos.y, axiomOldPos.z);
+ part.OffsetPosition = oldAbsolutePosition - AbsolutePosition;
+
+ Quaternion axiomRootRotation =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+
+ Vector3 axiomPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
+ axiomPos = axiomRootRotation.Inverse() * axiomPos;
+ part.OffsetPosition = new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z);
+
+ Quaternion axiomPartRotation =
+ new Quaternion(part.RotationOffset.W, part.RotationOffset.X, part.RotationOffset.Y,
+ part.RotationOffset.Z);
+
+ axiomPartRotation = oldGroupRotation * axiomPartRotation;
+ axiomPartRotation = axiomRootRotation.Inverse() * axiomPartRotation;
+ part.RotationOffset =
+ new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
}
///
- ///
+ /// If object is physical, apply force to move it around
+ /// If object is not physical, just put it at the resulting location
///
- ///
- public List GetScenePresences()
+ /// Always seems to be 0,0,0, so ignoring
+ /// New position. We do the math here to turn it into a force
+ ///
+ public void GrabMovement(LLVector3 offset, LLVector3 pos, IClientAPI remoteClient)
{
- return m_scene.GetScenePresences();
+ if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
+ {
+ if (m_rootPart.PhysActor != null)
+ {
+ if (m_rootPart.PhysActor.IsPhysical)
+ {
+ LLVector3 llmoveforce = pos - AbsolutePosition;
+ PhysicsVector grabforce = new PhysicsVector(llmoveforce.X, llmoveforce.Y, llmoveforce.Z);
+ grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass;
+ m_rootPart.PhysActor.AddForce(grabforce);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ }
+ else
+ {
+ //NonPhysicalGrabMovement(pos);
+ }
+ }
+ else
+ {
+ //NonPhysicalGrabMovement(pos);
+ }
+ }
}
- #region Events
+ public void NonPhysicalGrabMovement(LLVector3 pos)
+ {
+ AbsolutePosition = pos;
+ m_rootPart.SendTerseUpdateToAllClients();
+ }
///
///
///
- public void TriggerTainted()
+ ///
+ public void GetProperties(IClientAPI client)
{
- handlerPrimCountTainted = OnPrimCountTainted;
- if (handlerPrimCountTainted != null)
- {
- handlerPrimCountTainted();
- }
+ ObjectPropertiesPacket proper = (ObjectPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
+ // TODO: don't create new blocks if recycling an old packet
+
+ proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
+ proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
+ proper.ObjectData[0].ItemID = LLUUID.Zero;
+ proper.ObjectData[0].CreationDate = (ulong) m_rootPart.CreationDate;
+ proper.ObjectData[0].CreatorID = m_rootPart.CreatorID;
+ proper.ObjectData[0].FolderID = LLUUID.Zero;
+ proper.ObjectData[0].FromTaskID = LLUUID.Zero;
+ proper.ObjectData[0].GroupID = LLUUID.Zero;
+ proper.ObjectData[0].InventorySerial = (short) m_rootPart.InventorySerial;
+ proper.ObjectData[0].LastOwnerID = m_rootPart.LastOwnerID;
+ proper.ObjectData[0].ObjectID = UUID;
+ proper.ObjectData[0].OwnerID = m_rootPart.OwnerID;
+ proper.ObjectData[0].TouchName = Helpers.StringToField(m_rootPart.TouchName);
+ proper.ObjectData[0].TextureID = new byte[0];
+ proper.ObjectData[0].SitName = Helpers.StringToField(m_rootPart.SitName);
+ proper.ObjectData[0].Name = Helpers.StringToField(m_rootPart.Name);
+ proper.ObjectData[0].Description = Helpers.StringToField(m_rootPart.Description);
+ proper.ObjectData[0].OwnerMask = m_rootPart.OwnerMask;
+ proper.ObjectData[0].NextOwnerMask = m_rootPart.NextOwnerMask;
+ proper.ObjectData[0].GroupMask = m_rootPart.GroupMask;
+ proper.ObjectData[0].EveryoneMask = m_rootPart.EveryoneMask;
+ proper.ObjectData[0].BaseMask = m_rootPart.BaseMask;
+
+ client.OutPacket(proper, ThrottleOutPacketType.Task);
}
///
- /// Processes backup
+ /// Set the name of a prim
///
- ///
- public void ProcessBackup(IRegionDataStore datastore)
+ ///
+ ///
+ public void SetPartName(string name, uint localID)
{
- if (HasGroupChanged)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- datastore.StoreObject(this, m_scene.RegionInfo.RegionID);
- HasGroupChanged = false;
+ part.Name = name;
}
-
- ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
}
- #endregion
-
- #region Client Updating
-
- public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientFlags)
+ public void SetPartDescription(string des, uint localID)
{
- lock (m_parts)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
- {
- SendPartFullUpdate(remoteClient, part, clientFlags);
- }
+ part.Description = des;
}
}
- ///
- /// Send a full update to the client for the given part
- ///
- ///
- ///
- internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags)
+ public void SetPartText(string text, uint localID)
{
- if (m_rootPart.UUID == part.UUID)
- {
- part.SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags);
- }
- else
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- part.SendFullUpdateToClient(remoteClient, clientFlags);
+ part.SetText(text);
}
}
- ///
- /// Send a terse update to the client for the given part
- ///
- ///
- ///
- internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part)
+ public void SetPartText(string text, LLUUID partID)
{
- if (m_rootPart.UUID == part.UUID)
- {
- part.SendTerseUpdateToClient(remoteClient, AbsolutePosition);
- }
- else
+ SceneObjectPart part = GetChildPart(partID);
+ if (part != null)
{
- part.SendTerseUpdateToClient(remoteClient);
+ part.SetText(text);
}
}
- #endregion
-
- public override void UpdateMovement()
+ public string GetPartName(uint localID)
{
- lock (m_parts)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.UpdateMovement();
- }
+ return part.Name;
}
- }
-
- public float GetTimeDilation()
- {
- return m_scene.TimeDilation;
- }
-
- ///
- /// 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;
- AttachToBackup();
+ return String.Empty;
}
- ///
- ///
- ///
- ///
- public void AddPart(SceneObjectPart part)
+ public string GetPartDescription(uint localID)
{
- lock (m_parts)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- part.SetParent(this);
- part.LinkNum = m_parts.Count;
-
- try
- {
- m_parts.Add(part.UUID, part);
- }
- catch (Exception e)
- {
- m_log.Error("Failed to add scened object part", e);
- }
+ return part.Description;
}
+ return String.Empty;
}
///
///
///
- public void UpdateParentIDs()
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UpdatePrimFlags(uint localID, ushort type, bool inUse, byte[] data)
{
- lock (m_parts)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ // If we have children
+ lock (m_parts)
{
- if (part.UUID != m_rootPart.UUID)
+ if (m_parts.Count > 1)
{
- part.ParentID = m_rootPart.LocalId;
+ foreach (SceneObjectPart parts in m_parts.Values)
+ {
+ parts.UpdatePrimFlags(type, inUse, data);
+ }
+ }
+ else
+ {
+ part.UpdatePrimFlags(type, inUse, data);
}
}
}
}
- public void RegenerateFullIDs()
+ public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
{
- lock (m_parts)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.UUID = LLUUID.Random();
- }
+ part.UpdateExtraParam(type, inUse, data);
}
}
- public void ResetChildPrimPhysicsPositions()
+ public SceneObjectPart[] GetParts()
{
- AbsolutePosition = AbsolutePosition;
- HasGroupChanged = false;
+ int numParts = Children.Count;
+ SceneObjectPart[] partArray = new SceneObjectPart[numParts];
+ Children.Values.CopyTo(partArray, 0);
+ return partArray;
}
- public LLUUID GetPartsFullID(uint localID)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UpdateTextureEntry(uint localID, byte[] textureEntry)
{
SceneObjectPart part = GetChildPart(localID);
if (part != null)
{
- return part.UUID;
+ part.UpdateTextureEntry(textureEntry);
}
- return null;
}
- public void ObjectGrabHandler(uint localId, LLVector3 offsetPos, IClientAPI remoteClient)
+ public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
{
- if (m_rootPart.LocalId == localId)
- {
- OnGrabGroup(offsetPos, remoteClient);
- }
- else
- {
- SceneObjectPart part = GetChildPart(localId);
- OnGrabPart(part, offsetPos, remoteClient);
- }
+ SceneObjectPart updatePart = GetChildPart(localID);
+ updatePart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
+ HasGroupChanged = true;
}
- public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient)
- {
- part.OnGrab(offsetPos, remoteClient);
- }
+ #endregion
- public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient)
+ #region Shape
+
+ ///
+ ///
+ ///
+ ///
+ public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
{
- m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
+ {
+ part.UpdateShape(shapeBlock);
+
+ if (part.PhysActor != null)
+ m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
+ }
}
+ #endregion
+
+ #region Resize
+
///
- /// Completely delete this group and tell all the scene presences about that deletion.
+ ///
///
- public void DeleteGroup()
- {
- DetachFromBackup(this);
-
- lock (m_parts)
+ ///
+ ///
+ public void Resize(LLVector3 scale, uint localID)
+ {
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ part.Resize(scale);
+ if (part.PhysActor != null)
{
- List avatars = GetScenePresences();
- for (int i = 0; i < avatars.Count; i++)
+ part.PhysActor.Size =
+ new PhysicsVector(scale.X, scale.Y, scale.Z);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
+ }
+ //if (part.UUID != m_rootPart.UUID)
+ ScheduleGroupForFullUpdate();
+
+ //if (part.UUID == m_rootPart.UUID)
+ //{
+ //if (m_rootPart.PhysActor != null)
+ //{
+ //m_rootPart.PhysActor.Size =
+ //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
+ //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ //}
+ //}
+ }
+ }
+
+ public void GroupResize(LLVector3 scale, uint localID)
+ {
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
+ {
+ float x = (scale.X / part.Scale.X);
+ float y = (scale.Y / part.Scale.Y);
+ float z = (scale.Z / part.Scale.Z);
+ part.Resize(scale);
+
+ lock (m_parts)
+ {
+ foreach (SceneObjectPart obPart in m_parts.Values)
{
- if (avatars[i].ParentID == LocalId)
+ if (obPart.UUID != m_rootPart.UUID)
{
- avatars[i].StandUp();
+ LLVector3 currentpos = new LLVector3(obPart.OffsetPosition);
+ currentpos.X *= x;
+ currentpos.Y *= y;
+ currentpos.Z *= z;
+ LLVector3 newSize = new LLVector3(obPart.Scale);
+ newSize.X *= x;
+ newSize.Y *= y;
+ newSize.Z *= z;
+ obPart.Resize(newSize);
+ obPart.UpdateOffSet(currentpos);
}
-
- avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
}
- }
- }
- ///
- /// Delete all the parts in this group.
- ///
- public void DeleteParts()
- {
- lock (m_parts)
- {
- foreach (SceneObjectPart part in m_parts.Values)
+ if (part.PhysActor != null)
{
- part.StopScripts();
+ part.PhysActor.Size =
+ new PhysicsVector(scale.X, scale.Y, scale.Z);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
}
-
- m_rootPart = null;
- m_parts.Clear();
+
+
+ ScheduleGroupForTerseUpdate();
}
}
- public void AddScriptLPS(int count)
- {
- InnerScene d = m_scene.m_innerScene;
- d.AddToScriptLPS(count);
- }
+ #endregion
- public void AddActiveScriptCount(int count)
- {
- InnerScene d = m_scene.m_innerScene;
- d.AddActiveScripts(count);
- }
+ #region Position
- public void RemoveScriptEvents(LLUUID scriptid)
+ ///
+ ///
+ ///
+ ///
+ public void UpdateGroupPosition(LLVector3 pos)
{
- lock (m_scriptEvents)
+ if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
{
- if (m_scriptEvents.ContainsKey(scriptid))
- {
- scriptEvents oldparts = scriptEvents.None;
- oldparts = (scriptEvents)m_scriptEvents[scriptid];
-
- // remove values from aggregated script events
- m_aggregateScriptEvents &= ~oldparts;
- m_scriptEvents.Remove(scriptid);
- }
-
+ AbsolutePosition = pos;
}
- aggregateScriptEvents();
+ //we need to do a terse update even if the move wasn't allowed
+ // so that the position is reset in the client (the object snaps back)
+ ScheduleGroupForTerseUpdate();
}
- public void SetScriptEvents(LLUUID scriptid, int events)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UpdateSinglePosition(LLVector3 pos, uint localID)
{
-
- scriptEvents oldparts = scriptEvents.None;
- lock (m_scriptEvents)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
{
- if (m_scriptEvents.ContainsKey(scriptid))
+ if (part.UUID == m_rootPart.UUID)
{
- oldparts = (scriptEvents)m_scriptEvents[scriptid];
-
- // remove values from aggregated script events
- m_aggregateScriptEvents &= ~oldparts;
- m_scriptEvents[scriptid] = (scriptEvents)events;
+ UpdateRootPosition(pos);
}
else
{
- m_scriptEvents.Add(scriptid, (scriptEvents)events);
+ part.UpdateOffSet(pos);
}
-
}
-
- aggregateScriptEvents();
}
- public void aggregateScriptEvents()
+
+ ///
+ ///
+ ///
+ ///
+ private void UpdateRootPosition(LLVector3 pos)
{
- // Aggregate script events
- lock (m_scriptEvents)
+ LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
+ LLVector3 oldPos =
+ new LLVector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
+ AbsolutePosition.Y + m_rootPart.OffsetPosition.Y,
+ AbsolutePosition.Z + m_rootPart.OffsetPosition.Z);
+ LLVector3 diff = oldPos - newPos;
+ Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
+ Quaternion partRotation =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+ axDiff = partRotation.Inverse() * axDiff;
+ diff.X = axDiff.x;
+ diff.Y = axDiff.y;
+ diff.Z = axDiff.z;
+
+ lock (m_parts)
{
- foreach (scriptEvents s in m_scriptEvents.Values)
+ foreach (SceneObjectPart obPart in m_parts.Values)
{
- m_aggregateScriptEvents |= s;
+ if (obPart.UUID != m_rootPart.UUID)
+ {
+ obPart.OffsetPosition = obPart.OffsetPosition + diff;
+ }
}
}
- uint objectflagupdate = m_rootPart.ObjectFlags;
- if (
- ((m_aggregateScriptEvents & scriptEvents.touch) != 0) ||
- ((m_aggregateScriptEvents & scriptEvents.touch_end) != 0) ||
- ((m_aggregateScriptEvents & scriptEvents.touch_start) != 0)
- )
- {
- objectflagupdate |= (uint)LLObject.ObjectFlags.Touch;
- }
- else
- {
- objectflagupdate &= ~(uint)LLObject.ObjectFlags.Touch;
- }
+ AbsolutePosition = newPos;
+ ScheduleGroupForTerseUpdate();
+ }
- if ((m_aggregateScriptEvents & scriptEvents.money) != 0)
- {
- objectflagupdate |= (uint)LLObject.ObjectFlags.Money;
- }
- else
- {
- objectflagupdate &= ~(uint)LLObject.ObjectFlags.Money;
- }
+ public void OffsetForNewRegion(LLVector3 offset)
+ {
+ m_rootPart.GroupPosition = offset;
+ }
- if (
- ((m_aggregateScriptEvents & scriptEvents.collision) != 0) ||
- ((m_aggregateScriptEvents & scriptEvents.collision_end) != 0) ||
- ((m_aggregateScriptEvents & scriptEvents.collision_start) != 0)
- )
- {
- // subscribe to physics updates.
- }
- else
- {
- // unsubscribe to physics updates.
- }
- lock (m_parts)
+ #endregion
+
+ #region Rotation
+
+ ///
+ ///
+ ///
+ ///
+ public void UpdateGroupRotation(LLQuaternion rot)
+ {
+ m_rootPart.UpdateRotation(rot);
+ if (m_rootPart.PhysActor != null)
{
- foreach (SceneObjectPart part in m_parts.Values)
- {
- part.ObjectFlags = objectflagupdate;
- }
+ m_rootPart.PhysActor.Orientation =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
}
- ScheduleGroupForFullUpdate();
-
+ ScheduleGroupForTerseUpdate();
}
- public override void SetText(string text, Vector3 color, double alpha)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UpdateGroupRotation(LLVector3 pos, LLQuaternion rot)
{
- Color = Color.FromArgb(0xff - (int) (alpha*0xff),
- (int) (color.x*0xff),
- (int) (color.y*0xff),
- (int) (color.z*0xff));
- Text = text;
-
- m_rootPart.ScheduleFullUpdate();
+ m_rootPart.UpdateRotation(rot);
+ if (m_rootPart.PhysActor != null)
+ {
+ m_rootPart.PhysActor.Orientation =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ }
+ AbsolutePosition = pos;
+ ScheduleGroupForTerseUpdate();
}
- public void ApplyPhysics(bool m_physicalPrim)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void UpdateSingleRotation(LLQuaternion rot, uint localID)
{
- lock (m_parts)
- {
- if (m_parts.Count > 1)
+ SceneObjectPart part = GetChildPart(localID);
+ if (part != null)
+ {
+ if (part.UUID == m_rootPart.UUID)
{
- m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
- foreach (SceneObjectPart part in m_parts.Values)
- {
- if (part.LocalId != m_rootPart.LocalId)
- {
- part.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
- }
- // Hack to get the physics scene geometries in the right spot
- ResetChildPrimPhysicsPositions();
-
- }
+ UpdateRootRotation(rot);
}
else
{
- m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
- }
+ part.UpdateRotation(rot);
+ }
}
}
- public void SetOwnerId(LLUUID userId)
+ ///
+ ///
+ ///
+ ///
+ private void UpdateRootRotation(LLQuaternion rot)
{
- ForEachPart(delegate(SceneObjectPart part)
- { part.OwnerID = userId; });
- }
+ Quaternion axRot = new Quaternion(rot.W, rot.X, rot.Y, rot.Z);
+ Quaternion oldParentRot =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+
+ m_rootPart.UpdateRotation(rot);
+ if (m_rootPart.PhysActor != null)
+ {
+ m_rootPart.PhysActor.Orientation =
+ new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
+ m_rootPart.RotationOffset.Z);
+ m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
+ }
- public void ForEachPart(Action whatToDo)
- {
lock (m_parts)
{
- foreach (SceneObjectPart part in m_parts.Values)
+ foreach (SceneObjectPart prim in m_parts.Values)
{
- whatToDo(part);
+ if (prim.UUID != m_rootPart.UUID)
+ {
+ Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z);
+ axPos = oldParentRot * axPos;
+ axPos = axRot.Inverse() * axPos;
+ prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
+ Quaternion primsRot =
+ new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y,
+ prim.RotationOffset.Z);
+ Quaternion newRot = oldParentRot * primsRot;
+ newRot = axRot.Inverse() * newRot;
+ prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
+ prim.ScheduleTerseUpdate();
+ }
}
}
+
+ m_rootPart.ScheduleTerseUpdate();
}
-
+ #endregion
}
-}
+}
\ No newline at end of file
--
cgit v1.1