From 333b741e30a494dfae5a22c2fd48d6a891d48847 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Fri, 27 Jun 2008 19:21:15 +0000 Subject: run NArrange on SOP to stack together the attributes, properties, private methods, public methods, etc. --- .../Region/Environment/Scenes/SceneObjectPart.cs | 4463 ++++++++++---------- 1 file changed, 2205 insertions(+), 2258 deletions(-) (limited to 'OpenSim/Region/Environment/Scenes') diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index af535cc..d7aa962 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -1,3 +1,5 @@ +#region Header + /* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. @@ -25,6 +27,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#endregion Header + using System; using System.Collections.Generic; using System.Drawing; @@ -32,15 +36,33 @@ using System.Runtime.Serialization; using System.Security.Permissions; using System.Xml; using System.Xml.Serialization; + using Axiom.Math; + using libsecondlife; using libsecondlife.Packets; + using OpenSim.Framework; using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Environment.Scenes { + #region Enumerations + + [Flags] + public enum Changed : uint + { + INVENTORY = 1, + COLOR = 2, + SHAPE = 4, + SCALE = 8, + TEXTURE = 16, + LINK = 32, + ALLOWED_DROP = 64, + OWNER = 128 + } + // I don't really know where to put this except here. // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants [Flags] @@ -56,18 +78,7 @@ namespace OpenSim.Region.Environment.Scenes Something5 = 64, Something6 = 128 } - [Flags] - public enum Changed : uint - { - INVENTORY = 1, - COLOR = 2, - SHAPE = 4, - SCALE = 8, - TEXTURE = 16, - LINK = 32, - ALLOWED_DROP = 64, - OWNER = 128 - } + [Flags] public enum TextureAnimFlags : byte { @@ -81,74 +92,96 @@ namespace OpenSim.Region.Environment.Scenes SCALE = 0x40 } + #endregion Enumerations [Serializable] public partial class SceneObjectPart : IScriptHost, ISerializable { - [XmlIgnore] public PhysicsActor PhysActor = null; + #region Fields + [XmlIgnore] + public bool AllowedDrop = false; + public uint BaseMask = (uint)PermissionMask.All; + public uint Category; + public Int32 CreationDate; + public LLUUID CreatorID; + [XmlIgnore] + public bool DIE_AT_EDGE = false; + public uint EveryoneMask = (uint)PermissionMask.None; + public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None; + public LLUUID GroupID; + public uint GroupMask = (uint)PermissionMask.None; public LLUUID LastOwnerID; + public uint NextOwnerMask = (uint)PermissionMask.All; + public byte ObjectSaleType; public LLUUID OwnerID; - public LLUUID GroupID; + public uint OwnerMask = (uint)PermissionMask.All; public int OwnershipCost; - public byte ObjectSaleType; - public int SalePrice; - public uint Category; + public uint ParentID = 0; // TODO: This needs to be persisted in next XML version update! - [XmlIgnore] public int[] PayPrice = {-2,-2,-2,-2,-2}; - [XmlIgnore] public bool AllowedDrop = false; - [XmlIgnore] private Dictionary m_scriptEvents = new Dictionary(); - [XmlIgnore] public scriptEvents m_aggregateScriptEvents=0; - [XmlIgnore] private LLObject.ObjectFlags LocalFlags = LLObject.ObjectFlags.None; - [XmlIgnore] public bool DIE_AT_EDGE = false; - [XmlIgnore] private int m_scriptAccessPin = 0; - - [XmlIgnore] public bool m_IsAttachment = false; - [XmlIgnore] public uint m_attachmentPoint = (byte)0; - [XmlIgnore] public LLUUID m_attachedAvatar = LLUUID.Zero; - [XmlIgnore] public LLVector3 m_attachedPos = LLVector3.Zero; - [XmlIgnore] public LLUUID fromAssetID = LLUUID.Zero; - - [XmlIgnore] public bool m_undoing = false; + [XmlIgnore] + public int[] PayPrice = {-2,-2,-2,-2,-2}; + [XmlIgnore] + public PhysicsActor PhysActor = null; + public int SalePrice; - public Int32 CreationDate; - public uint ParentID = 0; + //Xantor 20080528 Sound stuff: + // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. + // Not a big problem as long as the script that sets it remains in the prim on startup. + // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script) + [XmlIgnore] + public LLUUID Sound; + [XmlIgnore] + public byte SoundFlags; + [XmlIgnore] + public double SoundGain; + [XmlIgnore] + public double SoundRadius; + [XmlIgnore] + public uint TimeStampFull = 0; + [XmlIgnore] + public uint TimeStampLastActivity = 0; // Will be used for AutoReturn + [XmlIgnore] + public uint TimeStampTerse = 0; + [XmlIgnore] + public LLUUID fromAssetID = LLUUID.Zero; + [XmlIgnore] + public bool m_IsAttachment = false; + [XmlIgnore] + public scriptEvents m_aggregateScriptEvents = 0; + [XmlIgnore] + public LLUUID m_attachedAvatar = LLUUID.Zero; + [XmlIgnore] + public LLVector3 m_attachedPos = LLVector3.Zero; + [XmlIgnore] + public uint m_attachmentPoint = (byte)0; + [XmlIgnore] + public PhysicsVector m_rotationAxis = new PhysicsVector(1f,1f,1f); + public LLUUID m_sitTargetAvatar = LLUUID.Zero; + [XmlIgnore] + public bool m_undoing = false; + [XmlIgnore] + private LLObject.ObjectFlags LocalFlags = LLObject.ObjectFlags.None; + private byte[] m_TextureAnimation; + private byte m_clickAction = 0; + private Color m_color = Color.Black; + private string m_description = String.Empty; private List m_lastColliders = new List(); - private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero; - private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0); + private int m_linkNum = 0; + [XmlIgnore] + private int m_scriptAccessPin = 0; + [XmlIgnore] + private Dictionary m_scriptEvents = new Dictionary(); + private string m_sitName = String.Empty; private Quaternion m_sitTargetOrientation = new Quaternion(0, 0, 0, 1); - public LLUUID m_sitTargetAvatar = LLUUID.Zero; - [XmlIgnore] public PhysicsVector m_rotationAxis = new PhysicsVector(1f,1f,1f); - - #region Permissions - - public uint BaseMask = (uint)PermissionMask.All; - public uint OwnerMask = (uint)PermissionMask.All; - public uint GroupMask = (uint)PermissionMask.None; - public uint EveryoneMask = (uint)PermissionMask.None; - public uint NextOwnerMask = (uint)PermissionMask.All; - + private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0); + private string m_text = String.Empty; + private string m_touchName = String.Empty; private UndoStack m_undo = new UndoStack(5); - public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None; - - public uint ObjectFlags - { - get { return (uint)Flags; } - set { Flags = (LLObject.ObjectFlags)value; } - } - - #endregion - - protected byte[] m_particleSystem = new byte[0]; - - [XmlIgnore] public uint TimeStampFull = 0; - [XmlIgnore] public uint TimeStampTerse = 0; - [XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn - /// /// Only used internally to schedule client updates. /// 0 - no update is scheduled @@ -159,174 +192,213 @@ namespace OpenSim.Region.Environment.Scenes /// private byte m_updateFlag; - #region Properties - - public LLUUID CreatorID; - - public LLUUID ObjectCreator - { - get { return CreatorID; } - } - - protected LLUUID m_uuid; - - public LLUUID UUID - { - get { return m_uuid; } - set { m_uuid = value; } - } + protected LLVector3 m_acceleration; + protected LLVector3 m_angularVelocity; + //unkown if this will be kept, added as a way of removing the group position from the group class + protected LLVector3 m_groupPosition; protected uint m_localId; - - public uint LocalId - { - get { return m_localId; } - set { m_localId = value; } - } - + protected LLObject.MaterialType m_material = 0; protected string m_name; + protected LLVector3 m_offsetPosition; - public virtual string Name - { - get { return m_name; } - set { m_name = value; } - } - - public scriptEvents ScriptEvents - { - get { return m_aggregateScriptEvents; } - } - - protected LLObject.MaterialType m_material = 0; + // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out. + protected SceneObjectGroup m_parentGroup; + protected byte[] m_particleSystem = new byte[0]; + protected ulong m_regionHandle; + protected LLQuaternion m_rotationOffset; + protected LLVector3 m_rotationalvelocity; + protected PrimitiveBaseShape m_shape; + protected LLUUID m_uuid; + protected LLVector3 m_velocity; - public byte Material - { - get { return (byte) m_material; } - set { m_material = (LLObject.MaterialType) value; } - } + #endregion Fields - protected ulong m_regionHandle; + #region Constructors - public ulong RegionHandle + /// + /// No arg constructor called by region restore db code + /// + public SceneObjectPart() { - get { return m_regionHandle; } - set { m_regionHandle = value; } + // It's not necessary to persist this + m_TextureAnimation = new byte[0]; } - - public int ScriptAccessPin - { - get { return m_scriptAccessPin; } - set { m_scriptAccessPin = (int)value; } - } - public uint GetEffectiveObjectFlags() + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, + PrimitiveBaseShape shape, LLVector3 groupPosition, LLVector3 offsetPosition) + : this(regionHandle, parent, ownerID, localID, shape, groupPosition, LLQuaternion.Identity, offsetPosition) { - LLObject.ObjectFlags f = Flags; - if (m_parentGroup == null || m_parentGroup.RootPart == this) - f &= ~(LLObject.ObjectFlags.Touch | LLObject.ObjectFlags.Money); - - return (uint)Flags | (uint)LocalFlags; } - //unkown if this will be kept, added as a way of removing the group position from the group class - protected LLVector3 m_groupPosition; - /// - /// Method for a prim to get it's world position from the group. - /// Remember, the Group Position simply gives the position of the group itself + /// Create a completely new SceneObjectPart (prim) /// - /// A Linked Child Prim objects position in world - public LLVector3 GetWorldPosition() + /// + /// + /// + /// + /// + /// + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, + PrimitiveBaseShape shape, LLVector3 groupPosition, LLQuaternion rotationOffset, + LLVector3 offsetPosition) { + m_name = "Primitive"; + m_regionHandle = regionHandle; + m_parentGroup = parent; - Quaternion parentRot = new Quaternion( - ParentGroup.RootPart.RotationOffset.W, - ParentGroup.RootPart.RotationOffset.X, - ParentGroup.RootPart.RotationOffset.Y, - ParentGroup.RootPart.RotationOffset.Z); + CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + OwnerID = ownerID; + CreatorID = OwnerID; + LastOwnerID = LLUUID.Zero; + UUID = LLUUID.Random(); + LocalId = (uint) (localID); + Shape = shape; + // Todo: Add More Object Parameter from above! + OwnershipCost = 0; + ObjectSaleType = (byte) 0; + SalePrice = 0; + Category = (uint) 0; + LastOwnerID = CreatorID; + // End Todo: /// + GroupPosition = groupPosition; + OffsetPosition = offsetPosition; + RotationOffset = rotationOffset; + Velocity = new LLVector3(0, 0, 0); + m_rotationalvelocity = new LLVector3(0, 0, 0); + AngularVelocity = new LLVector3(0, 0, 0); + Acceleration = new LLVector3(0, 0, 0); + m_TextureAnimation = new byte[0]; - Vector3 axPos - = new Vector3( - OffsetPosition.X, - OffsetPosition.Y, - OffsetPosition.Z); + // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol, + // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from + // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log - axPos = parentRot * axPos; - LLVector3 translationOffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); - return GroupPosition + translationOffsetPosition; + Flags = 0; + Flags |= LLObject.ObjectFlags.CreateSelected; - //return (new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z) + AbsolutePosition); + TrimPermissions(); + //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); + + ScheduleFullUpdate(); } /// - /// Gets the rotation of this prim offset by the group rotation + /// Re/create a SceneObjectPart (prim) + /// currently not used, and maybe won't be /// - /// - public LLQuaternion GetWorldRotation() - { - - Quaternion newRot; + /// + /// + /// + /// + /// + /// + public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, int creationDate, LLUUID ownerID, + LLUUID creatorID, LLUUID lastOwnerID, uint localID, PrimitiveBaseShape shape, + LLVector3 position, LLQuaternion rotation, uint flags) + { + m_regionHandle = regionHandle; + m_parentGroup = parent; + TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); + CreationDate = creationDate; + OwnerID = ownerID; + CreatorID = creatorID; + LastOwnerID = lastOwnerID; + UUID = LLUUID.Random(); + LocalId = (uint) (localID); + Shape = shape; + OwnershipCost = 0; + ObjectSaleType = (byte) 0; + SalePrice = 0; + Category = (uint) 0; + LastOwnerID = CreatorID; + OffsetPosition = position; + RotationOffset = rotation; + ObjectFlags = flags; - if (this.LinkNum == 0) - { - newRot = new Quaternion(RotationOffset.W,RotationOffset.X,RotationOffset.Y,RotationOffset.Z); + // Since we don't store script state, this is only a 'temporary' objectflag now + // If the object is scripted, the script will get loaded and this will be set again + ObjectFlags &= ~(uint)(LLObject.ObjectFlags.Scripted | LLObject.ObjectFlags.Touch); - } - else - { - Quaternion parentRot = new Quaternion( - ParentGroup.RootPart.RotationOffset.W, - ParentGroup.RootPart.RotationOffset.X, - ParentGroup.RootPart.RotationOffset.Y, - ParentGroup.RootPart.RotationOffset.Z); + TrimPermissions(); + // ApplyPhysics(); - Quaternion oldRot - = new Quaternion( - RotationOffset.W, - RotationOffset.X, - RotationOffset.Y, - RotationOffset.Z); + ScheduleFullUpdate(); + } - newRot = parentRot * oldRot; + protected SceneObjectPart(SerializationInfo info, StreamingContext context) + { + //System.Console.WriteLine("SceneObjectPart Deserialize BGN"); + + if (info == null) + { + throw new ArgumentNullException("info"); } - return new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); - //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); + /* + m_queue = (Queue)info.GetValue("m_queue", typeof(Queue)); + m_ids = (List)info.GetValue("m_ids", typeof(List)); + */ + //System.Console.WriteLine("SceneObjectPart Deserialize END"); } - public void StoreUndoState() + #endregion Constructors + + #region Public Properties + + public LLVector3 AbsolutePosition { - if (!m_undoing) - { - if (m_parentGroup != null) - { - if (m_undo.Count > 0) - { - UndoState last = m_undo.Peek(); - if (last != null) - { - if (last.Compare(this)) - return; - } - } + get { + if (m_IsAttachment) + return GroupPosition; + return m_offsetPosition + m_groupPosition; } + } - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this); + /// + public LLVector3 Acceleration + { + get { return m_acceleration; } + set { m_acceleration = value; } + } - m_undo.Push(nUndo); + /// + public LLVector3 AngularVelocity + { + get { return m_angularVelocity; } + set { m_angularVelocity = value; } + } - } - } + public byte ClickAction + { + get { return m_clickAction; } + set + { + m_clickAction = value; } } - public void ClearUndoState() + public Color Color { - m_undo.Clear(); - StoreUndoState(); + get { return m_color; } + set + { + m_color = value; + TriggerScriptChangedEvent(Changed.COLOR); + + /* ScheduleFullUpdate() need not be called b/c after + * setting the color, the text will be set, so then + * ScheduleFullUpdate() will be called. */ + //ScheduleFullUpdate(); + } + } + + public string Description + { + get { return m_description; } + set { m_description = value; } } public LLVector3 GroupPosition @@ -391,9 +463,50 @@ namespace OpenSim.Region.Environment.Scenes } } - private byte[] m_TextureAnimation; + public int LinkNum + { + get { return m_linkNum; } + set + { + m_linkNum = value; + TriggerScriptChangedEvent(Changed.LINK); - protected LLVector3 m_offsetPosition; + } + } + + public uint LocalId + { + get { return m_localId; } + set { m_localId = value; } + } + + public byte Material + { + get { return (byte) m_material; } + set { m_material = (LLObject.MaterialType) value; } + } + + public virtual string Name + { + get { return m_name; } + set { m_name = value; } + } + + public LLUUID ObjectCreator + { + get { return CreatorID; } + } + + public uint ObjectFlags + { + get { return (uint)Flags; } + set { Flags = (LLObject.ObjectFlags)value; } + } + + public LLUUID ObjectOwner + { + get { return OwnerID; } + } public LLVector3 OffsetPosition { @@ -416,16 +529,16 @@ namespace OpenSim.Region.Environment.Scenes } } - public LLVector3 AbsolutePosition + public SceneObjectGroup ParentGroup { - get { - if (m_IsAttachment) - return GroupPosition; - - return m_offsetPosition + m_groupPosition; } + get { return m_parentGroup; } } - protected LLQuaternion m_rotationOffset; + public ulong RegionHandle + { + get { return m_regionHandle; } + set { m_regionHandle = value; } + } public LLQuaternion RotationOffset { @@ -479,11 +592,7 @@ namespace OpenSim.Region.Environment.Scenes } } - protected LLVector3 m_velocity; - protected LLVector3 m_rotationalvelocity; - - /// - public LLVector3 Velocity + public LLVector3 RotationalVelocity { get { @@ -494,103 +603,86 @@ namespace OpenSim.Region.Environment.Scenes { if (PhysActor.IsPhysical) { - m_velocity.X = PhysActor.Velocity.X; - m_velocity.Y = PhysActor.Velocity.Y; - m_velocity.Z = PhysActor.Velocity.Z; + m_rotationalvelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(),0); } } - return m_velocity; - } - - set - { - m_velocity = value; - if (PhysActor != null) - { - if (PhysActor.IsPhysical) - { - PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z); - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } - } + return m_rotationalvelocity; } + set { m_rotationalvelocity = value; } } - public LLVector3 RotationalVelocity + public LLVector3 Scale { - get + get { return m_shape.Scale; } + set { - //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0 - //|| PhysActor.Velocity.z != 0) - //{ - if (PhysActor != null) + StoreUndoState(); + m_shape.Scale = value; + + if (PhysActor != null && m_parentGroup != null) { - if (PhysActor.IsPhysical) + if (m_parentGroup.Scene != null) { - m_rotationalvelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(),0); + if (m_parentGroup.Scene.PhysicsScene != null) + { + PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z); + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } } } - - return m_rotationalvelocity; + TriggerScriptChangedEvent(Changed.SCALE); } - set { m_rotationalvelocity = value; } } - - protected LLVector3 m_angularVelocity; - - /// - public LLVector3 AngularVelocity + public int ScriptAccessPin { - get { return m_angularVelocity; } - set { m_angularVelocity = value; } + get { return m_scriptAccessPin; } + set { m_scriptAccessPin = (int)value; } } - protected LLVector3 m_acceleration; - - /// - public LLVector3 Acceleration + public scriptEvents ScriptEvents { - get { return m_acceleration; } - set { m_acceleration = value; } + get { return m_aggregateScriptEvents; } } - private string m_description = String.Empty; - - public string Description - { - get { return m_description; } - set { m_description = value; } - } - - private Color m_color = Color.Black; - - public Color Color + public PrimitiveBaseShape Shape { - get { return m_color; } + get { return m_shape; } set { - m_color = value; - TriggerScriptChangedEvent(Changed.COLOR); - - /* ScheduleFullUpdate() need not be called b/c after - * setting the color, the text will be set, so then - * ScheduleFullUpdate() will be called. */ - //ScheduleFullUpdate(); + m_shape = value; + TriggerScriptChangedEvent(Changed.SHAPE); } } - private string m_text = String.Empty; + public string SitName + { + get { return m_sitName; } + set { m_sitName = value; } + } + + public Quaternion SitTargetOrientation + { + get { return m_sitTargetOrientation; } + } public Vector3 SitTargetPosition { get { return m_sitTargetPosition; } } - public Quaternion SitTargetOrientation + public bool Stopped { - get { return m_sitTargetOrientation; } + get { + double threshold = 0.02; + return (Math.Abs(Velocity.X) < threshold && + Math.Abs(Velocity.Y) < threshold && + Math.Abs(Velocity.Z) < threshold && + Math.Abs(AngularVelocity.X) < threshold && + Math.Abs(AngularVelocity.Y) < threshold && + Math.Abs(AngularVelocity.Z) < threshold); + } } public string Text @@ -610,315 +702,239 @@ namespace OpenSim.Region.Environment.Scenes } } - //Xantor 20080528 Sound stuff: - // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. - // Not a big problem as long as the script that sets it remains in the prim on startup. - // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script) - [XmlIgnore] - public LLUUID Sound; - [XmlIgnore] - public byte SoundFlags; - [XmlIgnore] - public double SoundGain; - [XmlIgnore] - public double SoundRadius; - - - private string m_sitName = String.Empty; - - public string SitName - { - get { return m_sitName; } - set { m_sitName = value; } - } - - private string m_touchName = String.Empty; - public string TouchName { get { return m_touchName; } set { m_touchName = value; } } - private int m_linkNum = 0; - - public int LinkNum + public LLUUID UUID { - get { return m_linkNum; } - set - { - m_linkNum = value; - TriggerScriptChangedEvent(Changed.LINK); - - } + get { return m_uuid; } + set { m_uuid = value; } } - private byte m_clickAction = 0; - - public byte ClickAction + public byte UpdateFlag { - get { return m_clickAction; } - set - { - m_clickAction = value; - } + get { return m_updateFlag; } + set { m_updateFlag = value; } } - protected PrimitiveBaseShape m_shape; - - /// - /// hook to the physics scene to apply impulse - /// This is sent up to the group, which then finds the root prim - /// and applies the force on the root prim of the group - /// - /// Vector force - /// true for the local frame, false for the global frame - public void ApplyImpulse(LLVector3 impulsei, bool localGlobalTF) + /// + public LLVector3 Velocity { - PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z); - - if (localGlobalTF) + get { + //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0 + //|| PhysActor.Velocity.z != 0) + //{ + if (PhysActor != null) + { + if (PhysActor.IsPhysical) + { + m_velocity.X = PhysActor.Velocity.X; + m_velocity.Y = PhysActor.Velocity.Y; + m_velocity.Z = PhysActor.Velocity.Z; + } + } - LLQuaternion grot = GetWorldRotation(); - Quaternion AXgrot = new Quaternion(grot.W,grot.X,grot.Y,grot.Z); - Vector3 AXimpulsei = new Vector3(impulsei.X, impulsei.Y, impulsei.Z); - Vector3 newimpulse = AXgrot * AXimpulsei; - impulse = new PhysicsVector(newimpulse.x, newimpulse.y, newimpulse.z); - + return m_velocity; } - else - { - if (m_parentGroup != null) + set + { + m_velocity = value; + if (PhysActor != null) { - m_parentGroup.applyImpulse(impulse); + if (PhysActor.IsPhysical) + { + PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z); + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } } } } - public void MoveToTarget(LLVector3 target, float tau) + #endregion Public Properties + + #region Private Methods + + private uint ApplyMask(uint val, bool set, uint mask) { - if (tau > 0) + if (set) { - m_parentGroup.moveToTarget(target, tau); + return val |= mask; } else { - StopMoveToTarget(); + return val &= ~mask; } - - } - - public void StopMoveToTarget() - { - m_parentGroup.stopMoveToTarget(); } - public void TriggerScriptChangedEvent(Changed val) + /// + /// Clear all pending updates + /// + private void ClearUpdateSchedule() { - if (m_parentGroup != null) - { - if (m_parentGroup.Scene != null) - m_parentGroup.Scene.TriggerObjectChanged(LocalId, (uint)val); - } - + m_updateFlag = 0; } - public PrimitiveBaseShape Shape + private void SendObjectPropertiesToClient(LLUUID AgentID) { - get { return m_shape; } - set + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) { - m_shape = value; - TriggerScriptChangedEvent(Changed.SHAPE); + // Ugly reference :( + if (avatars[i].UUID == AgentID) + { + m_parentGroup.GetProperties(avatars[i].ControllingClient); + } } } - public LLVector3 Scale + private void handleTimerAccounting(uint localID, double interval) { - get { return m_shape.Scale; } - set + if (localID == LocalId) { - StoreUndoState(); - m_shape.Scale = value; - if (PhysActor != null && m_parentGroup != null) + float sec = (float)interval; + if (m_parentGroup != null) { - if (m_parentGroup.Scene != null) + if (sec == 0) { - if (m_parentGroup.Scene.PhysicsScene != null) - { - PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z); - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } + if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001) + m_parentGroup.scriptScore = 0; + + m_parentGroup.scriptScore += 0.001f; + return; } + + if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec)) + m_parentGroup.scriptScore = 0; + m_parentGroup.scriptScore += (0.001f / sec); } - TriggerScriptChangedEvent(Changed.SCALE); + } } - public bool Stopped + #endregion Private Methods + + #region Public Methods + + public void AddFlag(LLObject.ObjectFlags flag) { - get { - double threshold = 0.02; - return (Math.Abs(Velocity.X) < threshold && - Math.Abs(Velocity.Y) < threshold && - Math.Abs(Velocity.Z) < threshold && - Math.Abs(AngularVelocity.X) < threshold && - Math.Abs(AngularVelocity.Y) < threshold && - Math.Abs(AngularVelocity.Z) < threshold); + LLObject.ObjectFlags prevflag = Flags; + //uint objflags = Flags; + if ((ObjectFlags & (uint) flag) == 0) + { + //Console.WriteLine("Adding flag: " + ((LLObject.ObjectFlags) flag).ToString()); + Flags |= flag; } + //uint currflag = (uint)Flags; + //System.Console.WriteLine("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString()); + //ScheduleFullUpdate(); } - #endregion - - public LLUUID ObjectOwner + /// + /// Tell all scene presences that they should send updates for this part to their clients + /// + public void AddFullUpdateToAllAvatars() { - get { return OwnerID; } + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + avatars[i].QueuePartForUpdate(this); + } } - // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out. - protected SceneObjectGroup m_parentGroup; - - public SceneObjectGroup ParentGroup + public void AddFullUpdateToAvatar(ScenePresence presence) { - get { return m_parentGroup; } + presence.QueuePartForUpdate(this); } - public byte UpdateFlag + public void AddNewParticleSystem(Primitive.ParticleSystem pSystem) { - get { return m_updateFlag; } - set { m_updateFlag = value; } + m_particleSystem = pSystem.GetBytes(); } - #region Constructors - - /// - /// No arg constructor called by region restore db code - /// - public SceneObjectPart() + /// Terse updates + public void AddTerseUpdateToAllAvatars() { - // It's not necessary to persist this - m_TextureAnimation = new byte[0]; + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + avatars[i].QueuePartForUpdate(this); + } } - public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, - PrimitiveBaseShape shape, LLVector3 groupPosition, LLVector3 offsetPosition) - : this(regionHandle, parent, ownerID, localID, shape, groupPosition, LLQuaternion.Identity, offsetPosition) + public void AddTerseUpdateToAvatar(ScenePresence presence) { + presence.QueuePartForUpdate(this); } - /// - /// Create a completely new SceneObjectPart (prim) - /// - /// - /// - /// - /// - /// - /// - public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, - PrimitiveBaseShape shape, LLVector3 groupPosition, LLQuaternion rotationOffset, - LLVector3 offsetPosition) + public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) { - m_name = "Primitive"; - m_regionHandle = regionHandle; - m_parentGroup = parent; - - CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; - OwnerID = ownerID; - CreatorID = OwnerID; - LastOwnerID = LLUUID.Zero; - UUID = LLUUID.Random(); - LocalId = (uint) (localID); - Shape = shape; - // Todo: Add More Object Parameter from above! - OwnershipCost = 0; - ObjectSaleType = (byte) 0; - SalePrice = 0; - Category = (uint) 0; - LastOwnerID = CreatorID; - // End Todo: /// - GroupPosition = groupPosition; - OffsetPosition = offsetPosition; - RotationOffset = rotationOffset; - Velocity = new LLVector3(0, 0, 0); - m_rotationalvelocity = new LLVector3(0, 0, 0); - AngularVelocity = new LLVector3(0, 0, 0); - Acceleration = new LLVector3(0, 0, 0); - m_TextureAnimation = new byte[0]; + byte[] data = new byte[16]; + int pos = 0; - // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol, - // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from - // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log + // The flags don't like conversion from uint to byte, so we have to do + // it the crappy way. See the above function :( - Flags = 0; - Flags |= LLObject.ObjectFlags.CreateSelected; + data[pos] = ConvertScriptUintToByte(pTexAnim.Flags); pos++; + data[pos] = (byte)pTexAnim.Face; pos++; + data[pos] = (byte)pTexAnim.SizeX; pos++; + data[pos] = (byte)pTexAnim.SizeY; pos++; - TrimPermissions(); - //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); + Helpers.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); + Helpers.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); + Helpers.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); - ScheduleFullUpdate(); + m_TextureAnimation = data; } - /// - /// Re/create a SceneObjectPart (prim) - /// currently not used, and maybe won't be - /// - /// - /// - /// - /// - /// - /// - public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, int creationDate, LLUUID ownerID, - LLUUID creatorID, LLUUID lastOwnerID, uint localID, PrimitiveBaseShape shape, - LLVector3 position, LLQuaternion rotation, uint flags) + public void AdjustSoundGain(double volume) { - m_regionHandle = regionHandle; - m_parentGroup = parent; - TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); - CreationDate = creationDate; - OwnerID = ownerID; - CreatorID = creatorID; - LastOwnerID = lastOwnerID; - UUID = LLUUID.Random(); - LocalId = (uint) (localID); - Shape = shape; - OwnershipCost = 0; - ObjectSaleType = (byte) 0; - SalePrice = 0; - Category = (uint) 0; - LastOwnerID = CreatorID; - OffsetPosition = position; - RotationOffset = rotation; - ObjectFlags = flags; - - // Since we don't store script state, this is only a 'temporary' objectflag now - // If the object is scripted, the script will get loaded and this will be set again - ObjectFlags &= ~(uint)(LLObject.ObjectFlags.Scripted | LLObject.ObjectFlags.Touch); - - TrimPermissions(); - // ApplyPhysics(); + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; - ScheduleFullUpdate(); + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) + { + p.ControllingClient.SendAttachedSoundGainChange(UUID, (float)volume); + } } - #endregion - /// - /// Restore this part from the serialized xml representation. + /// hook to the physics scene to apply impulse + /// This is sent up to the group, which then finds the root prim + /// and applies the force on the root prim of the group /// - /// - /// - public static SceneObjectPart FromXml(XmlReader xmlReader) + /// Vector force + /// true for the local frame, false for the global frame + public void ApplyImpulse(LLVector3 impulsei, bool localGlobalTF) { - // It's not necessary to persist this + PhysicsVector impulse = new PhysicsVector(impulsei.X, impulsei.Y, impulsei.Z); - XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); - SceneObjectPart newobject = (SceneObjectPart) serializer.Deserialize(xmlReader); - return newobject; + if (localGlobalTF) + { + + LLQuaternion grot = GetWorldRotation(); + Quaternion AXgrot = new Quaternion(grot.W,grot.X,grot.Y,grot.Z); + Vector3 AXimpulsei = new Vector3(impulsei.X, impulsei.Y, impulsei.Z); + Vector3 newimpulse = AXgrot * AXimpulsei; + impulse = new PhysicsVector(newimpulse.x, newimpulse.y, newimpulse.z); + + } + else + { + + if (m_parentGroup != null) + { + m_parentGroup.applyImpulse(impulse); + } + } } /// @@ -955,135 +971,173 @@ namespace OpenSim.Region.Environment.Scenes } } - public void TrimPermissions() + public void ClearUndoState() { + m_undo.Clear(); + StoreUndoState(); + } - BaseMask &= (uint)PermissionMask.All; - OwnerMask &= (uint)PermissionMask.All; - GroupMask &= (uint)PermissionMask.All; - EveryoneMask &= (uint)PermissionMask.All; - NextOwnerMask &= (uint)PermissionMask.All; - + public byte ConvertScriptUintToByte(uint indata) + { + byte outdata = (byte)TextureAnimFlags.NONE; + if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON; + if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP; + if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE; + if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG; + if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH; + if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE; + if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE; + return outdata; } /// - /// Serialize this part to xml. + /// Duplicates this part. /// - /// - public void ToXml(XmlWriter xmlWriter) + /// + public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum, bool userExposed) { - XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); - serializer.Serialize(xmlWriter, this); - } + SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); + dupe.m_shape = m_shape.Copy(); + dupe.m_regionHandle = m_regionHandle; + if (userExposed) + dupe.UUID = LLUUID.Random(); - public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) - { - // In this case we're using a sphere with a radius of the largest dimention of the prim - // TODO: Change to take shape into account + dupe.LocalId = localID; + dupe.OwnerID = AgentID; + dupe.GroupID = GroupID; + dupe.GroupPosition = new LLVector3(GroupPosition.X, GroupPosition.Y, GroupPosition.Z); + dupe.OffsetPosition = new LLVector3(OffsetPosition.X, OffsetPosition.Y, OffsetPosition.Z); + dupe.RotationOffset = + new LLQuaternion(RotationOffset.X, RotationOffset.Y, RotationOffset.Z, RotationOffset.W); + dupe.Velocity = new LLVector3(0, 0, 0); + dupe.Acceleration = new LLVector3(0, 0, 0); + dupe.AngularVelocity = new LLVector3(0, 0, 0); + dupe.ObjectFlags = ObjectFlags; + dupe.OwnershipCost = OwnershipCost; + dupe.ObjectSaleType = ObjectSaleType; + dupe.SalePrice = SalePrice; + dupe.Category = Category; - EntityIntersection returnresult = new EntityIntersection(); - Vector3 vAbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); - Vector3 vScale = new Vector3(Scale.X, Scale.Y, Scale.Z); - Quaternion qRotation = - new Quaternion(RotationOffset.W, RotationOffset.X, RotationOffset.Y, RotationOffset.Z); + if (userExposed) + dupe.ResetIDs(linkNum); + // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. + dupe.LastOwnerID = ObjectOwner; - //Quaternion worldRotation = (qRotation*parentrot); - //Matrix3 worldRotM = worldRotation.ToRotationMatrix(); + byte[] extraP = new byte[Shape.ExtraParams.Length]; + Array.Copy(Shape.ExtraParams, extraP, extraP.Length); + dupe.Shape.ExtraParams = extraP; + if (userExposed) + { + if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero) + { + m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true); + } + bool UsePhysics = ((dupe.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0); + dupe.DoPhysicsPropertyUpdate(UsePhysics, true); + } + return dupe; + } - Vector3 rOrigin = iray.Origin; - Vector3 rDirection = iray.Direction; + public static SceneObjectPart Create() + { + SceneObjectPart part = new SceneObjectPart(); + part.UUID = LLUUID.Random(); + PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); + part.Shape = shape; + part.Name = "Primitive"; + part.OwnerID = LLUUID.Random(); - //rDirection = rDirection.Normalize(); - // Buidling the first part of the Quadratic equation - Vector3 r2ndDirection = rDirection*rDirection; - float itestPart1 = r2ndDirection.x + r2ndDirection.y + r2ndDirection.z; + return part; + } - // Buidling the second part of the Quadratic equation - Vector3 tmVal2 = rOrigin - vAbsolutePosition; - Vector3 r2Direction = rDirection*2.0f; - Vector3 tmVal3 = r2Direction*tmVal2; - - float itestPart2 = tmVal3.x + tmVal3.y + tmVal3.z; - - // Buidling the third part of the Quadratic equation - Vector3 tmVal4 = rOrigin*rOrigin; - Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition; - - Vector3 tmVal6 = vAbsolutePosition*rOrigin; - - - // Set Radius to the largest dimention of the prim - float radius = 0f; - if (vScale.x > radius) - radius = vScale.x; - if (vScale.y > radius) - radius = vScale.y; - if (vScale.z > radius) - radius = vScale.z; + public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) + { + if (PhysActor != null) + { + if (UsePhysics != PhysActor.IsPhysical || isNew) + { + if (PhysActor.IsPhysical) + { + if (!isNew) + ParentGroup.Scene.RemovePhysicalPrim(1); - // the second part of this is the default prim size - // once we factor in the aabb of the prim we're adding we can - // change this to; - // radius = (radius / 2) - 0.01f; - // - radius = (radius / 2) + (0.5f / 2) - 0.1f; + PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; + PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; + PhysActor.delink(); + } - //radius = radius; + PhysActor.IsPhysical = UsePhysics; - float itestPart3 = tmVal4.x + tmVal4.y + tmVal4.z + tmVal5.x + tmVal5.y + tmVal5.z - - (2.0f*(tmVal6.x + tmVal6.y + tmVal6.z + (radius*radius))); - // Yuk Quadradrics.. Solve first - float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3); - if (rootsqr < 0.0f) - { - // No intersection - return returnresult; - } - float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); + // If we're not what we're supposed to be in the physics scene, recreate ourselves. + //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); + /// that's not wholesome. Had to make Scene public + //PhysActor = null; - if (root < 0.0f) - { - // perform second quadratic root solution - root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); + if ((ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) + { + //PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + //Name, + //Shape, + //new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + //AbsolutePosition.Z), + //new PhysicsVector(Scale.X, Scale.Y, Scale.Z), + //new Quaternion(RotationOffset.W, RotationOffset.X, + //RotationOffset.Y, RotationOffset.Z), UsePhysics); + if (UsePhysics) + { + ParentGroup.Scene.AddPhysicalPrim(1); - // is there any intersection? - if (root < 0.0f) - { - // nope, no intersection - return returnresult; + PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; + PhysActor.OnOutOfBounds += PhysicsOutOfBounds; + if (ParentID != 0 && ParentID != LocalId) + { + if (ParentGroup.RootPart.PhysActor != null) + { + PhysActor.link(ParentGroup.RootPart.PhysActor); + } + } + } + } } + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } + } - // We got an intersection. putting together an EntityIntersection object with the - // intersection information - Vector3 ipoint = - new Vector3(iray.Origin.x + (iray.Direction.x*root), iray.Origin.y + (iray.Direction.y*root), - iray.Origin.z + (iray.Direction.z*root)); - - returnresult.HitTF = true; - returnresult.ipoint = ipoint; - - // Normal is calculated by the difference and then normalizing the result - Vector3 normalpart = ipoint - vAbsolutePosition; - returnresult.normal = normalpart / normalpart.Length; + /// + /// Restore this part from the serialized xml representation. + /// + /// + /// + public static SceneObjectPart FromXml(XmlReader xmlReader) + { + // It's not necessary to persist this - // It's funny how the LLVector3 object has a Distance function, but the Axiom.Math object doesn't. - // I can write a function to do it.. but I like the fact that this one is Static. + XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); + SceneObjectPart newobject = (SceneObjectPart) serializer.Deserialize(xmlReader); + return newobject; + } - LLVector3 distanceConvert1 = new LLVector3(iray.Origin.x, iray.Origin.y, iray.Origin.z); - LLVector3 distanceConvert2 = new LLVector3(ipoint.x, ipoint.y, ipoint.z); - float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2); + public LLUUID GetAvatarOnSitTarget() + { + return m_sitTargetAvatar; + } - returnresult.distance = distance; + public bool GetDieAtEdge() + { + if (m_parentGroup == null) + return false; + if (m_parentGroup.RootPart == null) + return false; - return returnresult; + return m_parentGroup.RootPart.DIE_AT_EDGE; } public double GetDistanceTo(Vector3 a, Vector3 b) @@ -1094,608 +1148,562 @@ namespace OpenSim.Region.Environment.Scenes return Math.Sqrt(dx * dx + dy * dy + dz * dz); } - public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) + public uint GetEffectiveObjectFlags() { - // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes - // This breaks down into the ray---> plane equation. - // TODO: Change to take shape into account - Vector3[] vertexes = new Vector3[8]; - - float[] distance = new float[6]; - Vector3[] FaceA = new Vector3[6]; // vertex A for Facei - Vector3[] FaceB = new Vector3[6]; // vertex B for Facei - Vector3[] FaceC = new Vector3[6]; // vertex C for Facei - Vector3[] FaceD = new Vector3[6]; // vertex D for Facei + LLObject.ObjectFlags f = Flags; + if (m_parentGroup == null || m_parentGroup.RootPart == this) + f &= ~(LLObject.ObjectFlags.Touch | LLObject.ObjectFlags.Money); - Vector3[] normals = new Vector3[6]; // Normal for Facei - Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals + return (uint)Flags | (uint)LocalFlags; + } - AAfacenormals[0] = new Vector3(1, 0, 0); - AAfacenormals[1] = new Vector3(0, 1, 0); - AAfacenormals[2] = new Vector3(-1, 0, 0); - AAfacenormals[3] = new Vector3(0, -1, 0); - AAfacenormals[4] = new Vector3(0, 0, 1); - AAfacenormals[5] = new Vector3(0, 0, -1); + public LLVector3 GetGeometricCenter() + { + if (PhysActor != null) + { + return new LLVector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); + } + else + { + return new LLVector3(0, 0, 0); + } + } - Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B - Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C - Vector3 cross = new Vector3(); + public float GetMass() + { + if (PhysActor != null) + { + return PhysActor.Mass; + } + else + { + return 0; + } + } - LLVector3 pos = GetWorldPosition(); - LLQuaternion rot = GetWorldRotation(); + [SecurityPermission(SecurityAction.LinkDemand, + Flags = SecurityPermissionFlag.SerializationFormatter)] + public virtual void GetObjectData( + SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException("info"); + } - // Variables prefixed with AX are Axiom.Math copies of the LL variety. + info.AddValue("m_inventoryFileName", GetInventoryFileName()); + info.AddValue("m_folderID", UUID); + info.AddValue("PhysActor", PhysActor); - Quaternion AXrot = new Quaternion(rot.W,rot.X,rot.Y,rot.Z); - AXrot.Normalize(); + Dictionary TaskInventory_work = new Dictionary(); - Vector3 AXpos = new Vector3(pos.X, pos.Y, pos.Z); + foreach (LLUUID id in TaskInventory.Keys) + { + TaskInventory_work.Add(id.UUID, TaskInventory[id]); + } - // tScale is the offset to derive the vertex based on the scale. - // it's different for each vertex because we've got to rotate it - // to get the world position of the vertex to produce the Oriented Bounding Box + info.AddValue("TaskInventory", TaskInventory_work); - Vector3 tScale = new Vector3(); + info.AddValue("LastOwnerID", LastOwnerID.UUID); + info.AddValue("OwnerID", OwnerID.UUID); + info.AddValue("GroupID", GroupID.UUID); - Vector3 AXscale = new Vector3(m_shape.Scale.X * 0.5f, m_shape.Scale.Y * 0.5f, m_shape.Scale.Z * 0.5f); + info.AddValue("OwnershipCost", OwnershipCost); + info.AddValue("ObjectSaleType", ObjectSaleType); + info.AddValue("SalePrice", SalePrice); + info.AddValue("Category", Category); - //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale)); - //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1)); + info.AddValue("CreationDate", CreationDate); + info.AddValue("ParentID", ParentID); - // rScale is the rotated offset to find a vertex based on the scale and the world rotation. - Vector3 rScale = new Vector3(); + info.AddValue("OwnerMask", OwnerMask); + info.AddValue("NextOwnerMask", NextOwnerMask); + info.AddValue("GroupMask", GroupMask); + info.AddValue("EveryoneMask", EveryoneMask); + info.AddValue("BaseMask", BaseMask); - // Get Vertexes for Faces Stick them into ABCD for each Face - // Form: Face[face] that corresponds to the below diagram - #region ABCD Face Vertex Map Comment Diagram - // A _________ B - // | | - // | 4 top | - // |_________| - // C D + info.AddValue("m_particleSystem", m_particleSystem); - // A _________ B - // | Back | - // | 3 | - // |_________| - // C D + info.AddValue("TimeStampFull", TimeStampFull); + info.AddValue("TimeStampTerse", TimeStampTerse); + info.AddValue("TimeStampLastActivity", TimeStampLastActivity); - // A _________ B B _________ A - // | Left | | Right | - // | 0 | | 2 | - // |_________| |_________| - // C D D C + info.AddValue("m_updateFlag", m_updateFlag); + info.AddValue("CreatorID", CreatorID.UUID); - // A _________ B - // | Front | - // | 1 | - // |_________| - // C D - - // C _________ D - // | | - // | 5 bot | - // |_________| - // A B - #endregion + info.AddValue("m_inventorySerial", m_inventorySerial); + info.AddValue("m_uuid", m_uuid.UUID); + info.AddValue("m_localID", m_localId); + info.AddValue("m_name", m_name); + info.AddValue("m_flags", Flags); + info.AddValue("m_material", m_material); + info.AddValue("m_regionHandle", m_regionHandle); - #region Plane Decomposition of Oriented Bounding Box - tScale = new Vector3(AXscale.x, -AXscale.y, AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[0] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - // vertexes[0].x = pos.X + vertexes[0].x; - //vertexes[0].y = pos.Y + vertexes[0].y; - //vertexes[0].z = pos.Z + vertexes[0].z; + info.AddValue("m_groupPosition.X", m_groupPosition.X); + info.AddValue("m_groupPosition.Y", m_groupPosition.Y); + info.AddValue("m_groupPosition.Z", m_groupPosition.Z); - FaceA[0] = vertexes[0]; - FaceB[3] = vertexes[0]; - FaceA[4] = vertexes[0]; + info.AddValue("m_offsetPosition.X", m_offsetPosition.X); + info.AddValue("m_offsetPosition.Y", m_offsetPosition.Y); + info.AddValue("m_offsetPosition.Z", m_offsetPosition.Z); - tScale = AXscale; - rScale = ((AXrot * tScale)); - vertexes[1] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + info.AddValue("m_rotationOffset.W", m_rotationOffset.W); + info.AddValue("m_rotationOffset.X", m_rotationOffset.X); + info.AddValue("m_rotationOffset.Y", m_rotationOffset.Y); + info.AddValue("m_rotationOffset.Z", m_rotationOffset.Z); - // vertexes[1].x = pos.X + vertexes[1].x; - // vertexes[1].y = pos.Y + vertexes[1].y; - //vertexes[1].z = pos.Z + vertexes[1].z; + info.AddValue("m_velocity.X", m_velocity.X); + info.AddValue("m_velocity.Y", m_velocity.Y); + info.AddValue("m_velocity.Z", m_velocity.Z); - FaceB[0] = vertexes[1]; - FaceA[1] = vertexes[1]; - FaceC[4] = vertexes[1]; + info.AddValue("m_rotationalvelocity.X", m_rotationalvelocity.X); + info.AddValue("m_rotationalvelocity.Y", m_rotationalvelocity.Y); + info.AddValue("m_rotationalvelocity.Z", m_rotationalvelocity.Z); - tScale = new Vector3(AXscale.x, -AXscale.y, -AXscale.z); - rScale = ((AXrot * tScale)); + info.AddValue("m_angularVelocity.X", m_angularVelocity.X); + info.AddValue("m_angularVelocity.Y", m_angularVelocity.Y); + info.AddValue("m_angularVelocity.Z", m_angularVelocity.Z); - vertexes[2] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + info.AddValue("m_acceleration.X", m_acceleration.X); + info.AddValue("m_acceleration.Y", m_acceleration.Y); + info.AddValue("m_acceleration.Z", m_acceleration.Z); - //vertexes[2].x = pos.X + vertexes[2].x; - //vertexes[2].y = pos.Y + vertexes[2].y; - //vertexes[2].z = pos.Z + vertexes[2].z; + info.AddValue("m_description", m_description); + info.AddValue("m_color", m_color); + info.AddValue("m_text", m_text); + info.AddValue("m_sitName", m_sitName); + info.AddValue("m_touchName", m_touchName); + info.AddValue("m_clickAction", m_clickAction); + info.AddValue("m_shape", m_shape); + info.AddValue("m_parentGroup", m_parentGroup); + info.AddValue("PayPrice", PayPrice); + } - FaceC[0] = vertexes[2]; - FaceD[3] = vertexes[2]; - FaceC[5] = vertexes[2]; + public void GetProperties(IClientAPI client) + { + client.SendObjectPropertiesReply(LLUUID.Zero, (ulong)CreationDate, CreatorID, LLUUID.Zero, LLUUID.Zero, + GroupID, (short)InventorySerial, LastOwnerID, UUID, OwnerID, + ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description, + ParentGroup.RootPart.OwnerMask, ParentGroup.RootPart.NextOwnerMask, ParentGroup.RootPart.GroupMask, ParentGroup.RootPart.EveryoneMask, + ParentGroup.RootPart.BaseMask); + } - tScale = new Vector3(AXscale.x, AXscale.y, -AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[3] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + public LLUUID GetRootPartUUID() + { + if (m_parentGroup != null) + { + return m_parentGroup.UUID; + } + return LLUUID.Zero; + } - //vertexes[3].x = pos.X + vertexes[3].x; - // vertexes[3].y = pos.Y + vertexes[3].y; - // vertexes[3].z = pos.Z + vertexes[3].z; + public Quaternion GetSitTargetOrientation() + { + return m_sitTargetOrientation; + } - FaceD[0] = vertexes[3]; - FaceC[1] = vertexes[3]; - FaceA[5] = vertexes[3]; + public LLQuaternion GetSitTargetOrientationLL() + { + return + new LLQuaternion(m_sitTargetOrientation.x, m_sitTargetOrientation.y, m_sitTargetOrientation.z, + m_sitTargetOrientation.w); + } - tScale = new Vector3(-AXscale.x, AXscale.y, AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[4] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + public Vector3 GetSitTargetPosition() + { + return m_sitTargetPosition; + } - // vertexes[4].x = pos.X + vertexes[4].x; - // vertexes[4].y = pos.Y + vertexes[4].y; - // vertexes[4].z = pos.Z + vertexes[4].z; + public LLVector3 GetSitTargetPositionLL() + { + return new LLVector3(m_sitTargetPosition.x, m_sitTargetPosition.y, m_sitTargetPosition.z); + } - FaceB[1] = vertexes[4]; - FaceA[2] = vertexes[4]; - FaceD[4] = vertexes[4]; + /// + /// Method for a prim to get it's world position from the group. + /// Remember, the Group Position simply gives the position of the group itself + /// + /// A Linked Child Prim objects position in world + public LLVector3 GetWorldPosition() + { + Quaternion parentRot = new Quaternion( + ParentGroup.RootPart.RotationOffset.W, + ParentGroup.RootPart.RotationOffset.X, + ParentGroup.RootPart.RotationOffset.Y, + ParentGroup.RootPart.RotationOffset.Z); - tScale = new Vector3(-AXscale.x, AXscale.y, -AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[5] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + Vector3 axPos + = new Vector3( + OffsetPosition.X, + OffsetPosition.Y, + OffsetPosition.Z); - // vertexes[5].x = pos.X + vertexes[5].x; - // vertexes[5].y = pos.Y + vertexes[5].y; - // vertexes[5].z = pos.Z + vertexes[5].z; + axPos = parentRot * axPos; + LLVector3 translationOffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); + return GroupPosition + translationOffsetPosition; - FaceD[1] = vertexes[5]; - FaceC[2] = vertexes[5]; - FaceB[5] = vertexes[5]; + //return (new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z) + AbsolutePosition); + } - tScale = new Vector3(-AXscale.x, -AXscale.y, AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[6] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + /// + /// Gets the rotation of this prim offset by the group rotation + /// + /// + public LLQuaternion GetWorldRotation() + { + Quaternion newRot; - // vertexes[6].x = pos.X + vertexes[6].x; - // vertexes[6].y = pos.Y + vertexes[6].y; - // vertexes[6].z = pos.Z + vertexes[6].z; + if (this.LinkNum == 0) + { + newRot = new Quaternion(RotationOffset.W,RotationOffset.X,RotationOffset.Y,RotationOffset.Z); - FaceB[2] = vertexes[6]; - FaceA[3] = vertexes[6]; - FaceB[4] = vertexes[6]; + } + else + { + Quaternion parentRot = new Quaternion( + ParentGroup.RootPart.RotationOffset.W, + ParentGroup.RootPart.RotationOffset.X, + ParentGroup.RootPart.RotationOffset.Y, + ParentGroup.RootPart.RotationOffset.Z); - tScale = new Vector3(-AXscale.x, -AXscale.y, -AXscale.z); - rScale = ((AXrot * tScale)); - vertexes[7] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + Quaternion oldRot + = new Quaternion( + RotationOffset.W, + RotationOffset.X, + RotationOffset.Y, + RotationOffset.Z); - // vertexes[7].x = pos.X + vertexes[7].x; - // vertexes[7].y = pos.Y + vertexes[7].y; - // vertexes[7].z = pos.Z + vertexes[7].z; + newRot = parentRot * oldRot; + } + return new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); - FaceD[2] = vertexes[7]; - FaceC[3] = vertexes[7]; - FaceD[5] = vertexes[7]; - #endregion + //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); + } - // Get our plane normals - for (int i = 0; i < 6; i++) + public void MoveToTarget(LLVector3 target, float tau) + { + if (tau > 0) { - //m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]); - - // Our Plane direction - AmBa = FaceA[i] - FaceB[i]; - AmBb = FaceB[i] - FaceC[i]; - - cross = AmBb.Cross(AmBa); + m_parentGroup.moveToTarget(target, tau); + } + else + { + StopMoveToTarget(); + } + } - // normalize the cross product to get the normal. - normals[i] = cross / cross.Length; + public virtual void OnGrab(LLVector3 offsetPos, IClientAPI remoteClient) + { + } - //m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString()); - //distance[i] = (normals[i].x * AmBa.x + normals[i].y * AmBa.y + normals[i].z * AmBa.z) * -1; + public void PhysicsCollision(EventArgs e) + { + // single threaded here + if (e == null) + { + return; } - EntityIntersection returnresult = new EntityIntersection(); - - returnresult.distance = 1024; - float c = 0; - float a = 0; - float d = 0; - Vector3 q = new Vector3(); + CollisionEventUpdate a = (CollisionEventUpdate)e; + Dictionary collissionswith = a.m_objCollisionList; + List thisHitColliders = new List(); + List endedColliders = new List(); + List startedColliders = new List(); - #region OBB Version 2 Experiment - //float fmin = 999999; - //float fmax = -999999; - //float s = 0; + // calculate things that started colliding this time + // and build up list of colliders this time + foreach (uint localid in collissionswith.Keys) + { + if (localid != 0) + { + thisHitColliders.Add(localid); + if (!m_lastColliders.Contains(localid)) + { + startedColliders.Add(localid); + } - //for (int i=0;i<6;i++) - //{ - //s = iray.Direction.Dot(normals[i]); - //d = normals[i].Dot(FaceB[i]); + //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); + } + } - //if (s == 0) - //{ - //if (iray.Origin.Dot(normals[i]) > d) - //{ - //return returnresult; - //} - // else - //{ - //continue; - //} - //} - //a = (d - iray.Origin.Dot(normals[i])) / s; - //if (iray.Direction.Dot(normals[i]) < 0) - //{ - //if (a > fmax) - //{ - //if (a > fmin) - //{ - //return returnresult; - //} - //fmax = a; - //} - - //} - //else - //{ - //if (a < fmin) - //{ - //if (a < 0 || a < fmax) - //{ - //return returnresult; - //} - //fmin = a; - //} - //} - //} - //if (fmax > 0) - // a= fmax; - //else - // a=fmin; - - //q = iray.Origin + a * iray.Direction; - #endregion - - // Loop over faces (6 of them) - for (int i = 0; i < 6; i++) + // calculate things that ended colliding + foreach (uint localID in m_lastColliders) { - AmBa = FaceA[i] - FaceB[i]; - AmBb = FaceB[i] - FaceC[i]; - d = normals[i].Dot(FaceB[i]); - - //if (faceCenters) - //{ - // c = normals[i].Dot(normals[i]); - //} - //else - //{ - c = iray.Direction.Dot(normals[i]); - //} - if (c == 0) - continue; - - a = (d - iray.Origin.Dot(normals[i])) / c; - - if (a < 0) - continue; - - // If the normal is pointing outside the object - - - - if (iray.Direction.Dot(normals[i]) < 0 || !frontFacesOnly) + if (!thisHitColliders.Contains(localID)) { + endedColliders.Add(localID); + } + } - //if (faceCenters) - //{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f; - // q = iray.Origin + a * normals[i]; - //} - //else - //{ - q = iray.Origin + a * iray.Direction; - //} - - float distance2 = (float)GetDistanceTo(q, AXpos); - // Is this the closest hit to the object's origin? - //if (faceCenters) - //{ - // distance2 = (float)GetDistanceTo(q, iray.Origin); - //} + //add the items that started colliding this time to the last colliders list. + foreach (uint localID in startedColliders) + { + m_lastColliders.Add(localID); + } + // remove things that ended colliding from the last colliders list + foreach (uint localID in endedColliders) + { + m_lastColliders.Remove(localID); + } + if (m_parentGroup == null) + return; + if (m_parentGroup.RootPart == null) + return; - if (distance2 < returnresult.distance) + if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0) + { + // do event notification + if (startedColliders.Count > 0) + { + ColliderArgs StartCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in startedColliders) { - returnresult.distance = distance2; - returnresult.HitTF = true; - returnresult.ipoint = q; - //m_log.Info("[FACE]:" + i.ToString()); - //m_log.Info("[POINT]: " + q.ToString()); - //m_log.Info("[DIST]: " + distance2.ToString()); - if (faceCenters) + // always running this check because if the user deletes the object it would return a null reference. + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); + if (obj != null) { - returnresult.normal = (AXrot * AAfacenormals[i]); - - Vector3 scaleComponent = AAfacenormals[i]; - float ScaleOffset = 0.5f; - if (scaleComponent.x != 0) ScaleOffset = AXscale.x; - if (scaleComponent.y != 0) ScaleOffset = AXscale.y; - if (scaleComponent.z != 0) ScaleOffset = AXscale.z; - ScaleOffset = Math.Abs(ScaleOffset); - Vector3 offset = returnresult.normal * ScaleOffset; - returnresult.ipoint = AXpos + offset; - - ///pos = (intersectionpoint + offset); + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); } else { - returnresult.normal = normals[i]; + List avlist = m_parentGroup.Scene.GetScenePresences(); + if (avlist != null) + { + foreach (ScenePresence av in avlist) + { + if (av.LocalId == localId) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = av.UUID; + detobj.nameStr = av.ControllingClient.Name; + detobj.ownerUUID = av.UUID; + detobj.posVector = av.AbsolutePosition; + detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); + detobj.velVector = av.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = av.ControllingClient.ActiveGroupId; + colliding.Add(detobj); + } + } + } } - returnresult.AAfaceNormal = AAfacenormals[i]; + } + if (colliding.Count > 0) + { + StartCollidingMessage.Colliders = colliding; + // always running this check because if the user deletes the object it would return a null reference. + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage); } } } - return returnresult; - } - - // Use this for attachments! LocalID should be avatar's localid - public void SetParentLocalId(uint localID) - { - ParentID = localID; - } - - public void SetAttachmentPoint(uint AttachmentPoint) - { - m_attachmentPoint = AttachmentPoint; - - // save the attachment point. - //if (AttachmentPoint != 0) - //{ - m_shape.State = (byte)AttachmentPoint; - //} - } - - /// - /// - /// - public void SetParent(SceneObjectGroup parent) - { - m_parentGroup = parent; - } - - public void SetSitTarget(Vector3 offset, Quaternion orientation) - { - m_sitTargetPosition = offset; - m_sitTargetOrientation = orientation; - } - - public void SetBuoyancy(float fvalue) - { - if (PhysActor != null) - { - PhysActor.Buoyancy = fvalue; - } - } - - public void SetAxisRotation(int axis, int rotate) - { - if (m_parentGroup != null) - { - m_parentGroup.SetAxisRotation(axis, rotate); - } - } - - public void SetPhysicsAxisRotation() - { - PhysActor.LockAngularMotion(m_rotationAxis); - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } - - public void SetFloatOnWater(int floatYN) - { - if (PhysActor != null) + if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0) { - if (floatYN == 1) - { - PhysActor.FloatOnWater = true; - } - else + if (m_lastColliders.Count > 0) { - PhysActor.FloatOnWater = false; - } - } - } + ColliderArgs CollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in m_lastColliders) + { + // always running this check because if the user deletes the object it would return a null reference. + if (localId == 0) + continue; - public LLVector3 GetSitTargetPositionLL() - { - return new LLVector3(m_sitTargetPosition.x, m_sitTargetPosition.y, m_sitTargetPosition.z); - } + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + else + { + List avlist = m_parentGroup.Scene.GetScenePresences(); + if (avlist != null) + { + foreach (ScenePresence av in avlist) + { + if (av.LocalId == localId) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = av.UUID; + detobj.nameStr = av.Name; + detobj.ownerUUID = av.UUID; + detobj.posVector = av.AbsolutePosition; + detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); + detobj.velVector = av.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = av.ControllingClient.ActiveGroupId; + colliding.Add(detobj); + } + } - public LLQuaternion GetSitTargetOrientationLL() - { - return - new LLQuaternion(m_sitTargetOrientation.x, m_sitTargetOrientation.y, m_sitTargetOrientation.z, - m_sitTargetOrientation.w); - } + } + } + } + if (colliding.Count > 0) + { + CollidingMessage.Colliders = colliding; + // always running this check because if the user deletes the object it would return a null reference. + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + m_parentGroup.Scene.EventManager.TriggerScriptColliding(LocalId, CollidingMessage); + } - // Utility function so the databases don't have to reference axiom.math - public void SetSitTargetLL(LLVector3 offset, LLQuaternion orientation) - { - if ( - !(offset.X == 0 && offset.Y == 0 && offset.Z == 0 && (orientation.W == 0 || orientation.W == 1) && - orientation.X == 0 && orientation.Y == 0 && orientation.Z == 0)) - { - m_sitTargetPosition = new Vector3(offset.X, offset.Y, offset.Z); - m_sitTargetOrientation = new Quaternion(orientation.W, orientation.X, orientation.Y, orientation.Z); + } } - } - - public Vector3 GetSitTargetPosition() - { - return m_sitTargetPosition; - } - - public Quaternion GetSitTargetOrientation() - { - return m_sitTargetOrientation; - } - - public void SetAvatarOnSitTarget(LLUUID avatarID) - { - m_sitTargetAvatar = avatarID; - TriggerScriptChangedEvent(Changed.LINK); - } - - public LLUUID GetAvatarOnSitTarget() - { - return m_sitTargetAvatar; - } - - public LLUUID GetRootPartUUID() - { - if (m_parentGroup != null) + if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0) { - return m_parentGroup.UUID; - } - return LLUUID.Zero; - } - - public static SceneObjectPart Create() - { - SceneObjectPart part = new SceneObjectPart(); - part.UUID = LLUUID.Random(); - - PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); - part.Shape = shape; - - part.Name = "Primitive"; - part.OwnerID = LLUUID.Random(); - - return part; - } - - #region Copying - - /// - /// Duplicates this part. - /// - /// - public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum, bool userExposed) - { - SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); - dupe.m_shape = m_shape.Copy(); - dupe.m_regionHandle = m_regionHandle; - if (userExposed) - dupe.UUID = LLUUID.Random(); - - dupe.LocalId = localID; - dupe.OwnerID = AgentID; - dupe.GroupID = GroupID; - dupe.GroupPosition = new LLVector3(GroupPosition.X, GroupPosition.Y, GroupPosition.Z); - dupe.OffsetPosition = new LLVector3(OffsetPosition.X, OffsetPosition.Y, OffsetPosition.Z); - dupe.RotationOffset = - new LLQuaternion(RotationOffset.X, RotationOffset.Y, RotationOffset.Z, RotationOffset.W); - dupe.Velocity = new LLVector3(0, 0, 0); - dupe.Acceleration = new LLVector3(0, 0, 0); - dupe.AngularVelocity = new LLVector3(0, 0, 0); - dupe.ObjectFlags = ObjectFlags; - - dupe.OwnershipCost = OwnershipCost; - dupe.ObjectSaleType = ObjectSaleType; - dupe.SalePrice = SalePrice; - dupe.Category = Category; - - dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); - - if (userExposed) - dupe.ResetIDs(linkNum); + if (endedColliders.Count > 0) + { + ColliderArgs EndCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in endedColliders) + { + if (localId == 0) + continue; - // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. - dupe.LastOwnerID = ObjectOwner; + // always running this check because if the user deletes the object it would return a null reference. + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + else + { + List avlist = m_parentGroup.Scene.GetScenePresences(); + if (avlist != null) + { + foreach (ScenePresence av in avlist) + { + if (av.LocalId == localId) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = av.UUID; + detobj.nameStr = av.Name; + detobj.ownerUUID = av.UUID; + detobj.posVector = av.AbsolutePosition; + detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); + detobj.velVector = av.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = av.ControllingClient.ActiveGroupId; + colliding.Add(detobj); + } + } - byte[] extraP = new byte[Shape.ExtraParams.Length]; - Array.Copy(Shape.ExtraParams, extraP, extraP.Length); - dupe.Shape.ExtraParams = extraP; + } + } + } + if (colliding.Count > 0) + { + EndCollidingMessage.Colliders = colliding; + // always running this check because if the user deletes the object it would return a null reference. + if (m_parentGroup == null) + return; + if (m_parentGroup.Scene == null) + return; + m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(LocalId, EndCollidingMessage); + } - if (userExposed) - { - if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero) - { - m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true); } - bool UsePhysics = ((dupe.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0); - dupe.DoPhysicsPropertyUpdate(UsePhysics, true); } - return dupe; - } - - #endregion - - /// - /// Reset LLUUIDs for this part. This involves generate this part's own LLUUID and - /// generating new LLUUIDs for all the items in the inventory. - /// - /// Link number for the part - public void ResetIDs(int linkNum) - { - UUID = LLUUID.Random(); - LinkNum = linkNum; - - ResetInventoryIDs(); } - #region Update Scheduling - - /// - /// Clear all pending updates - /// - private void ClearUpdateSchedule() + public void PhysicsOutOfBounds(PhysicsVector pos) { - m_updateFlag = 0; + m_log.Info("[PHYSICS]: Physical Object went out of bounds."); + RemFlag(LLObject.ObjectFlags.Physics); + DoPhysicsPropertyUpdate(false, true); + //m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } - /// - /// Schedules this prim for a full update - /// - public void ScheduleFullUpdate() + public void PhysicsRequestingTerseUpdate() { - if (m_parentGroup != null) + if (PhysActor != null) { - m_parentGroup.QueueForUpdateCheck(); + LLVector3 newpos = new LLVector3(PhysActor.Position.GetBytes(), 0); + if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f) + { + m_parentGroup.AbsolutePosition = newpos; + return; + } } + ScheduleTerseUpdate(); - int timeNow = Util.UnixTimeSinceEpoch(); + //SendTerseUpdateToAllClients(); + } - // If multiple updates are scheduled on the same second, we still need to perform all of them - // So we'll force the issue by bumping up the timestamp so that later processing sees these need - // to be performed. - if (timeNow <= TimeStampFull) - { - TimeStampFull += 1; - } - else + public void PreloadSound(string sound) + { + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID soundID = LLUUID.Zero; + + if (!LLUUID.TryParse(sound, out soundID)) { - TimeStampFull = (uint)timeNow; + //Trys to fetch sound id from prim's inventory. + //Prim's inventory doesn't support non script items yet + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } } - m_updateFlag = 2; - -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", -// UUID, Name, TimeStampFull); - } - - public void AddFlag(LLObject.ObjectFlags flag) - { - LLObject.ObjectFlags prevflag = Flags; - //uint objflags = Flags; - if ((ObjectFlags & (uint) flag) == 0) + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) { - //Console.WriteLine("Adding flag: " + ((LLObject.ObjectFlags) flag).ToString()); - Flags |= flag; + // TODO: some filtering by distance of avatar + + p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); } - //uint currflag = (uint)Flags; - //System.Console.WriteLine("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString()); - //ScheduleFullUpdate(); } public void RemFlag(LLObject.ObjectFlags flag) @@ -1710,1471 +1718,1410 @@ namespace OpenSim.Region.Environment.Scenes //ScheduleFullUpdate(); } - /// - /// Schedule a terse update for this prim. Terse updates only send position, - /// rotation, velocity, rotational velocity and shape information. - /// - public void ScheduleTerseUpdate() + public void RemoveScriptEvents(LLUUID scriptid) { - if (m_updateFlag < 1) + lock (m_scriptEvents) { - if (m_parentGroup != null) + if (m_scriptEvents.ContainsKey(scriptid)) { - m_parentGroup.HasGroupChanged = true; - m_parentGroup.QueueForUpdateCheck(); - } - TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); - m_updateFlag = 1; + scriptEvents oldparts = scriptEvents.None; + oldparts = (scriptEvents) m_scriptEvents[scriptid]; -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", -// UUID, Name, TimeStampTerse); + // remove values from aggregated script events + m_aggregateScriptEvents &= ~oldparts; + m_scriptEvents.Remove(scriptid); + } } + aggregateScriptEvents(); } /// - /// Tell all the prims which have had updates scheduled + /// Reset LLUUIDs for this part. This involves generate this part's own LLUUID and + /// generating new LLUUIDs for all the items in the inventory. /// - public void SendScheduledUpdates() + /// Link number for the part + public void ResetIDs(int linkNum) { - if (m_updateFlag == 1) //some change has been made so update the clients - { - AddTerseUpdateToAllAvatars(); - ClearUpdateSchedule(); + UUID = LLUUID.Random(); + LinkNum = linkNum; - // This causes the Scene to 'poll' physical objects every couple of frames - // bad, so it's been replaced by an event driven method. - //if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0) - //{ - // Only send the constant terse updates on physical objects! - //ScheduleTerseUpdate(); - //} - } - else - { - if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes - { - AddFullUpdateToAllAvatars(); - ClearUpdateSchedule(); - } - } + ResetInventoryIDs(); } - #endregion - - #region Shape - /// - /// Update the shape of this part. + /// Resize this part. /// - /// - public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock) + /// + public void Resize(LLVector3 scale) { - m_shape.PathBegin = shapeBlock.PathBegin; - m_shape.PathEnd = shapeBlock.PathEnd; - m_shape.PathScaleX = shapeBlock.PathScaleX; - m_shape.PathScaleY = shapeBlock.PathScaleY; - m_shape.PathShearX = shapeBlock.PathShearX; - m_shape.PathShearY = shapeBlock.PathShearY; - m_shape.PathSkew = shapeBlock.PathSkew; - m_shape.ProfileBegin = shapeBlock.ProfileBegin; - m_shape.ProfileEnd = shapeBlock.ProfileEnd; - m_shape.PathCurve = shapeBlock.PathCurve; - m_shape.ProfileCurve = shapeBlock.ProfileCurve; - m_shape.ProfileHollow = shapeBlock.ProfileHollow; - m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset; - m_shape.PathRevolutions = shapeBlock.PathRevolutions; - m_shape.PathTaperX = shapeBlock.PathTaperX; - m_shape.PathTaperY = shapeBlock.PathTaperY; - m_shape.PathTwist = shapeBlock.PathTwist; - m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; - if (PhysActor != null) - { - PhysActor.Shape = m_shape; - } - + StoreUndoState(); + m_shape.Scale = scale; + ParentGroup.HasGroupChanged = true; ScheduleFullUpdate(); } - #endregion - - #region ExtraParams - - public void UpdatePrimFlags(ushort type, bool inUse, byte[] data) + /// + /// Schedules this prim for a full update + /// + public void ScheduleFullUpdate() { - //m_log.Info("TSomething1:" + ((type & (ushort)ExtraParamType.Something1) == (ushort)ExtraParamType.Something1)); - //m_log.Info("TSomething2:" + ((type & (ushort)ExtraParamType.Something2) == (ushort)ExtraParamType.Something2)); - //m_log.Info("TSomething3:" + ((type & (ushort)ExtraParamType.Something3) == (ushort)ExtraParamType.Something3)); - //m_log.Info("TSomething4:" + ((type & (ushort)ExtraParamType.Something4) == (ushort)ExtraParamType.Something4)); - //m_log.Info("TSomething5:" + ((type & (ushort)ExtraParamType.Something5) == (ushort)ExtraParamType.Something5)); - //m_log.Info("TSomething6:" + ((type & (ushort)ExtraParamType.Something6) == (ushort)ExtraParamType.Something6)); - - bool usePhysics = false; - bool IsTemporary = false; - bool IsPhantom = false; - bool castsShadows = false; - bool wasUsingPhysics = ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0); - //bool IsLocked = false; - int i = 0; - - try - { - i += 46; - //IsLocked = (data[i++] != 0) ? true : false; - usePhysics = ((data[i++] != 0) && m_parentGroup.Scene.m_physicalPrim) ? true : false; - //System.Console.WriteLine("U" + packet.ToBytes().Length.ToString()); - IsTemporary = (data[i++] != 0) ? true : false; - IsPhantom = (data[i++] != 0) ? true : false; - castsShadows = (data[i++] != 0) ? true : false; - } - catch (Exception) + if (m_parentGroup != null) { - Console.WriteLine("Ignoring invalid Packet:"); - //Silently ignore it - TODO: FIXME Quick + m_parentGroup.QueueForUpdateCheck(); } - if (usePhysics) - { - AddFlag(LLObject.ObjectFlags.Physics); - if (!wasUsingPhysics) - { - DoPhysicsPropertyUpdate(usePhysics, false); - if (m_parentGroup != null) - { - if (m_parentGroup.RootPart != null) - { - if (LocalId == m_parentGroup.RootPart.LocalId) - { - m_parentGroup.CheckSculptAndLoad(); - } - } - } - } + int timeNow = Util.UnixTimeSinceEpoch(); + + // If multiple updates are scheduled on the same second, we still need to perform all of them + // So we'll force the issue by bumping up the timestamp so that later processing sees these need + // to be performed. + if (timeNow <= TimeStampFull) + { + TimeStampFull += 1; } else { - RemFlag(LLObject.ObjectFlags.Physics); - if (wasUsingPhysics) - { - DoPhysicsPropertyUpdate(usePhysics, false); - } + TimeStampFull = (uint)timeNow; } - if (IsPhantom) + m_updateFlag = 2; + + // m_log.DebugFormat( + // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", + // UUID, Name, TimeStampFull); + } + + /// + /// Schedule a terse update for this prim. Terse updates only send position, + /// rotation, velocity, rotational velocity and shape information. + /// + public void ScheduleTerseUpdate() + { + if (m_updateFlag < 1) { - AddFlag(LLObject.ObjectFlags.Phantom); - if (PhysActor != null) + if (m_parentGroup != null) { - m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); - /// that's not wholesome. Had to make Scene public - PhysActor = null; + m_parentGroup.HasGroupChanged = true; + m_parentGroup.QueueForUpdateCheck(); } + TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); + m_updateFlag = 1; + + // m_log.DebugFormat( + // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", + // UUID, Name, TimeStampTerse); } - else + } + + public void ScriptSetPhantomStatus(bool Phantom) + { + if (m_parentGroup != null) { - RemFlag(LLObject.ObjectFlags.Phantom); - if (PhysActor == null) - { - PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( - Name, - Shape, - new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, - AbsolutePosition.Z), - new PhysicsVector(Scale.X, Scale.Y, Scale.Z), - new Quaternion(RotationOffset.W, RotationOffset.X, - RotationOffset.Y, RotationOffset.Z), usePhysics); + m_parentGroup.ScriptSetPhantomStatus(Phantom); + } + } - if (PhysActor != null) - { - PhysActor.LocalID = LocalId; - DoPhysicsPropertyUpdate(usePhysics, true); - if (m_parentGroup != null) - { - if (m_parentGroup.RootPart != null) - { - if (LocalId == m_parentGroup.RootPart.LocalId) - { - m_parentGroup.CheckSculptAndLoad(); - } - } - } - } - } - else + public void ScriptSetPhysicsStatus(bool UsePhysics) + { + if (m_parentGroup != null) + { + m_parentGroup.ScriptSetPhysicsStatus(UsePhysics); + } + } + + public void SculptTextureCallback(LLUUID textureID, AssetBase texture) + { + if (m_shape.SculptEntry) + { + if (texture != null) { - PhysActor.IsPhysical = usePhysics; - DoPhysicsPropertyUpdate(usePhysics, false); - if (m_parentGroup != null) + m_shape.SculptData = texture.Data; + if (PhysActor != null) { - if (m_parentGroup.RootPart != null) - { - if (LocalId == m_parentGroup.RootPart.LocalId) - { - m_parentGroup.CheckSculptAndLoad(); - } - } + // Tricks physics engine into thinking we've changed the part shape. + PrimitiveBaseShape m_newshape = m_shape.Copy(); + PhysActor.Shape = m_newshape; + m_shape = m_newshape; } } } + } - if (IsTemporary) - { - AddFlag(LLObject.ObjectFlags.TemporaryOnRez); - } - else - { - RemFlag(LLObject.ObjectFlags.TemporaryOnRez); - } - // System.Console.WriteLine("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); - ScheduleFullUpdate(); + /// + /// + /// + /// + public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) + { + m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); } - public void ScriptSetPhysicsStatus(bool UsePhysics) + /// + /// + /// + public void SendFullUpdateToAllClients() { - if (m_parentGroup != null) + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) { - m_parentGroup.ScriptSetPhysicsStatus(UsePhysics); + // Ugly reference :( + m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, + avatars[i].GenerateClientFlags(UUID)); } } - public void ScriptSetPhantomStatus(bool Phantom) + public void SendFullUpdateToAllClientsExcept(LLUUID agentID) { - if (m_parentGroup != null) + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) { - m_parentGroup.ScriptSetPhantomStatus(Phantom); + // Ugly reference :( + if (avatars[i].UUID != agentID) + { + m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, + avatars[i].GenerateClientFlags(UUID)); + } } } - public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) + /// + /// Sends a full update to the client + /// + /// + /// + public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags) { - if (PhysActor != null) + LLVector3 lPos; + lPos = OffsetPosition; + SendFullUpdateToClient(remoteClient, lPos, clientflags); + } + + /// + /// Sends a full update to the client + /// + /// + /// + /// + public void SendFullUpdateToClient(IClientAPI remoteClient, LLVector3 lPos, uint clientFlags) + { + clientFlags &= ~(uint) LLObject.ObjectFlags.CreateSelected; + + if (remoteClient.AgentId == OwnerID) { - if (UsePhysics != PhysActor.IsPhysical || isNew) + if ((uint) (Flags & LLObject.ObjectFlags.CreateSelected) != 0) { - if (PhysActor.IsPhysical) - { - if (!isNew) - ParentGroup.Scene.RemovePhysicalPrim(1); + clientFlags |= (uint) LLObject.ObjectFlags.CreateSelected; + Flags &= ~LLObject.ObjectFlags.CreateSelected; + } + } - PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; - PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; - PhysActor.delink(); - } + byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; + remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape, + lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, OwnerID, + m_text, color, ParentID, m_particleSystem, m_clickAction, m_TextureAnimation, m_IsAttachment, + m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius); + } - PhysActor.IsPhysical = UsePhysics; + /// + /// Tell all the prims which have had updates scheduled + /// + public void SendScheduledUpdates() + { + if (m_updateFlag == 1) //some change has been made so update the clients + { + AddTerseUpdateToAllAvatars(); + ClearUpdateSchedule(); + // This causes the Scene to 'poll' physical objects every couple of frames + // bad, so it's been replaced by an event driven method. + //if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0) + //{ + // Only send the constant terse updates on physical objects! + //ScheduleTerseUpdate(); + //} + } + else + { + if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes + { + AddFullUpdateToAllAvatars(); + ClearUpdateSchedule(); + } + } + } - // If we're not what we're supposed to be in the physics scene, recreate ourselves. - //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); - /// that's not wholesome. Had to make Scene public - //PhysActor = null; + public void SendSound(string sound, double volume, bool triggered, byte flags) + { + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; - if ((ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0) - { - //PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( - //Name, - //Shape, - //new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, - //AbsolutePosition.Z), - //new PhysicsVector(Scale.X, Scale.Y, Scale.Z), - //new Quaternion(RotationOffset.W, RotationOffset.X, - //RotationOffset.Y, RotationOffset.Z), UsePhysics); - if (UsePhysics) - { - ParentGroup.Scene.AddPhysicalPrim(1); + LLUUID ownerID = OwnerID; + LLUUID objectID = UUID; + LLUUID parentID = GetRootPartUUID(); + LLUUID soundID = LLUUID.Zero; + LLVector3 position = AbsolutePosition; // region local + ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle; - PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; - PhysActor.OnOutOfBounds += PhysicsOutOfBounds; - if (ParentID != 0 && ParentID != LocalId) - { - if (ParentGroup.RootPart.PhysActor != null) - { - PhysActor.link(ParentGroup.RootPart.PhysActor); - } - } - } + //byte flags = 0; + + if (!LLUUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + SceneObjectPart op = this; + foreach (KeyValuePair item in op.TaskInventory) + { + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + { + soundID = item.Value.ItemID; + break; } } - m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); } - } - public void UpdateExtraParam(ushort type, bool inUse, byte[] data) - { - m_shape.ReadInUpdateExtraParam(type, inUse, data); - - if (type == 0x30) + if (soundID == LLUUID.Zero) + return; + + List avatarts = m_parentGroup.Scene.GetAvatars(); + foreach (ScenePresence p in avatarts) { - if (m_shape.SculptEntry && m_shape.SculptTexture != LLUUID.Zero) + double dis=Util.GetDistanceTo(p.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance + continue; + + // Scale by distance + volume*=((100.0-dis)/100.0); + + if (triggered) { - //AssetBase tx = m_parentGroup.Scene.getase - m_parentGroup.Scene.AssetCache.GetAsset(m_shape.SculptTexture, SculptTextureCallback, true); + p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); } - } - - ParentGroup.HasGroupChanged = true; - ScheduleFullUpdate(); - } - - public void SculptTextureCallback(LLUUID textureID, AssetBase texture) - { - if (m_shape.SculptEntry) - { - if (texture != null) + else { - m_shape.SculptData = texture.Data; - if (PhysActor != null) - { - // Tricks physics engine into thinking we've changed the part shape. - PrimitiveBaseShape m_newshape = m_shape.Copy(); - PhysActor.Shape = m_newshape; - m_shape = m_newshape; - } + p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); } } } - #endregion + /// + /// Send a terse update to the client. + /// + /// + public void SendTerseUpdate(IClientAPI remoteClient) + { + m_parentGroup.SendPartTerseUpdate(remoteClient, this); + } - #region Physics + /// + /// + /// + public void SendTerseUpdateToAllClients() + { + List avatars = m_parentGroup.Scene.GetScenePresences(); + for (int i = 0; i < avatars.Count; i++) + { + m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this); + } + } - public float GetMass() + public void SendTerseUpdateToClient(IClientAPI remoteClient) { - if (PhysActor != null) + LLVector3 lPos; + lPos = OffsetPosition; + LLQuaternion mRot = RotationOffset; + // TODO: I have no idea why we are making this check. This should be sorted out + if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) { - return PhysActor.Mass; + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID); } else { - return 0; + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, + RotationalVelocity); + //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); } } - public LLVector3 GetGeometricCenter() + public void SendTerseUpdateToClient(IClientAPI remoteClient, LLVector3 lPos) { - if (PhysActor != null) + LLQuaternion mRot = RotationOffset; + if (m_IsAttachment) { - return new LLVector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, (byte)((m_attachmentPoint % 16) * 16 + (m_attachmentPoint / 16)),fromAssetID); } else { - return new LLVector3(0, 0, 0); + if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == 0) + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID); + } + else + { + remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, + RotationalVelocity); + //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); + } } } - #endregion - - #region Texture - - /// - /// Update the texture entry for this part. - /// - /// - public void UpdateTextureEntry(byte[] textureEntry) + public void SetAttachmentPoint(uint AttachmentPoint) { - m_shape.TextureEntry = textureEntry; - TriggerScriptChangedEvent(Changed.TEXTURE); - - ParentGroup.HasGroupChanged = true; - ScheduleFullUpdate(); - } + m_attachmentPoint = AttachmentPoint; - // Added to handle bug in libsecondlife's TextureEntry.ToBytes() - // not handling RGBA properly. Cycles through, and "fixes" the color - // info - public void UpdateTexture(LLObject.TextureEntry tex) - { - //LLColor tmpcolor; - //for (uint i = 0; i < 32; i++) + // save the attachment point. + //if (AttachmentPoint != 0) //{ - // if (tex.FaceTextures[i] != null) - // { - // tmpcolor = tex.GetFace((uint) i).RGBA; - // tmpcolor.A = tmpcolor.A*255; - // tmpcolor.R = tmpcolor.R*255; - // tmpcolor.G = tmpcolor.G*255; - // tmpcolor.B = tmpcolor.B*255; - // tex.FaceTextures[i].RGBA = tmpcolor; - // } + m_shape.State = (byte)AttachmentPoint; //} - //tmpcolor = tex.DefaultTexture.RGBA; - //tmpcolor.A = tmpcolor.A*255; - //tmpcolor.R = tmpcolor.R*255; - //tmpcolor.G = tmpcolor.G*255; - //tmpcolor.B = tmpcolor.B*255; - //tex.DefaultTexture.RGBA = tmpcolor; - UpdateTextureEntry(tex.ToBytes()); } - public byte ConvertScriptUintToByte(uint indata) + public void SetAvatarOnSitTarget(LLUUID avatarID) { - byte outdata = (byte)TextureAnimFlags.NONE; - if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON; - if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP; - if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE; - if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG; - if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH; - if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE; - if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE; - return outdata; + m_sitTargetAvatar = avatarID; + TriggerScriptChangedEvent(Changed.LINK); } - public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) + public void SetAxisRotation(int axis, int rotate) { - byte[] data = new byte[16]; - int pos = 0; - - // The flags don't like conversion from uint to byte, so we have to do - // it the crappy way. See the above function :( - - data[pos] = ConvertScriptUintToByte(pTexAnim.Flags); pos++; - data[pos] = (byte)pTexAnim.Face; pos++; - data[pos] = (byte)pTexAnim.SizeX; pos++; - data[pos] = (byte)pTexAnim.SizeY; pos++; - - Helpers.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); - Helpers.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); - Helpers.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); + if (m_parentGroup != null) + { + m_parentGroup.SetAxisRotation(axis, rotate); + } + } - m_TextureAnimation = data; + public void SetBuoyancy(float fvalue) + { + if (PhysActor != null) + { + PhysActor.Buoyancy = fvalue; + } } - #endregion + public void SetDieAtEdge(bool p) + { + if (m_parentGroup == null) + return; + if (m_parentGroup.RootPart == null) + return; - #region ParticleSystem + m_parentGroup.RootPart.DIE_AT_EDGE = p; + } - public void AddNewParticleSystem(Primitive.ParticleSystem pSystem) + public void SetFloatOnWater(int floatYN) { - m_particleSystem = pSystem.GetBytes(); + if (PhysActor != null) + { + if (floatYN == 1) + { + PhysActor.FloatOnWater = true; + } + else + { + PhysActor.FloatOnWater = false; + } + } } - #endregion - - #region Position + public void SetGroup(LLUUID groupID, IClientAPI client) + { + GroupID = groupID; + GetProperties(client); + m_updateFlag = 2; + } /// /// /// - /// - public void UpdateOffSet(LLVector3 pos) + public void SetParent(SceneObjectGroup parent) { - if ((pos.X != OffsetPosition.X) || - (pos.Y != OffsetPosition.Y) || - (pos.Z != OffsetPosition.Z)) + m_parentGroup = parent; + } + + // Use this for attachments! LocalID should be avatar's localid + public void SetParentLocalId(uint localID) + { + ParentID = localID; + } + + public void SetPhysicsAxisRotation() + { + PhysActor.LockAngularMotion(m_rotationAxis); + m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + + public void SetScriptEvents(LLUUID scriptid, int events) + { + scriptEvents oldparts; + lock (m_scriptEvents) { - LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); - OffsetPosition = newPos; - ScheduleTerseUpdate(); + if (m_scriptEvents.ContainsKey(scriptid)) + { + oldparts = m_scriptEvents[scriptid]; + + // remove values from aggregated script events + m_scriptEvents[scriptid] = (scriptEvents) events; + } + else + { + m_scriptEvents.Add(scriptid, (scriptEvents) events); + } } + aggregateScriptEvents(); + } + + public void SetSitTarget(Vector3 offset, Quaternion orientation) + { + m_sitTargetPosition = offset; + m_sitTargetOrientation = orientation; } - public void UpdateGroupPosition(LLVector3 pos) + // Utility function so the databases don't have to reference axiom.math + public void SetSitTargetLL(LLVector3 offset, LLQuaternion orientation) { - if ((pos.X != GroupPosition.X) || - (pos.Y != GroupPosition.Y) || - (pos.Z != GroupPosition.Z)) + if ( + !(offset.X == 0 && offset.Y == 0 && offset.Z == 0 && (orientation.W == 0 || orientation.W == 1) && + orientation.X == 0 && orientation.Y == 0 && orientation.Z == 0)) { - LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); - GroupPosition = newPos; - ScheduleTerseUpdate(); + m_sitTargetPosition = new Vector3(offset.X, offset.Y, offset.Z); + m_sitTargetOrientation = new Quaternion(orientation.W, orientation.X, orientation.Y, orientation.Z); } } - #endregion + /// + /// Set the text displayed for this part. + /// + /// + public void SetText(string text) + { + Text = text; - #region rotation + ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); + } - public void UpdateRotation(LLQuaternion rot) + /// + /// Set the text displayed for this part. + /// + /// + /// + /// + public void SetText(string text, Vector3 color, double alpha) { - if ((rot.X != RotationOffset.X) || - (rot.Y != RotationOffset.Y) || - (rot.Z != RotationOffset.Z) || - (rot.W != RotationOffset.W)) - { - //StoreUndoState(); - RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W); - ParentGroup.HasGroupChanged = true; - ScheduleTerseUpdate(); - } + Color = Color.FromArgb(0xff - (int) (alpha*0xff), + (int) (color.x*0xff), + (int) (color.y*0xff), + (int) (color.z*0xff)); + SetText(text); } - #endregion - - #region Sound - public void PreloadSound(string sound) + public void StopMoveToTarget() { - LLUUID ownerID = OwnerID; - LLUUID objectID = UUID; - LLUUID soundID = LLUUID.Zero; + m_parentGroup.stopMoveToTarget(); + } - if (!LLUUID.TryParse(sound, out soundID)) + public void StoreUndoState() + { + if (!m_undoing) { - //Trys to fetch sound id from prim's inventory. - //Prim's inventory doesn't support non script items yet - SceneObjectPart op = this; - foreach (KeyValuePair item in op.TaskInventory) + if (m_parentGroup != null) { - if (item.Value.Name == sound) + if (m_undo.Count > 0) { - soundID = item.Value.ItemID; - break; + UndoState last = m_undo.Peek(); + if (last != null) + { + if (last.Compare(this)) + return; + } } - } - } - List avatarts = m_parentGroup.Scene.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - } - } + if (m_parentGroup.GetSceneMaxUndo() > 0) + { + UndoState nUndo = new UndoState(this); - public void AdjustSoundGain(double volume) - { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; + m_undo.Push(nUndo); - List avatarts = m_parentGroup.Scene.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - p.ControllingClient.SendAttachedSoundGainChange(UUID, (float)volume); + } + } } } - public void SendSound(string sound, double volume, bool triggered, byte flags) + public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; + // In this case we're using a sphere with a radius of the largest dimention of the prim + // TODO: Change to take shape into account - LLUUID ownerID = OwnerID; - LLUUID objectID = UUID; - LLUUID parentID = GetRootPartUUID(); - LLUUID soundID = LLUUID.Zero; - LLVector3 position = AbsolutePosition; // region local - ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle; - //byte flags = 0; + EntityIntersection returnresult = new EntityIntersection(); + Vector3 vAbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); - if (!LLUUID.TryParse(sound, out soundID)) - { - // search sound file from inventory - SceneObjectPart op = this; - foreach (KeyValuePair item in op.TaskInventory) - { - if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) - { - soundID = item.Value.ItemID; - break; - } - } - } + Vector3 vScale = new Vector3(Scale.X, Scale.Y, Scale.Z); + Quaternion qRotation = + new Quaternion(RotationOffset.W, RotationOffset.X, RotationOffset.Y, RotationOffset.Z); - if (soundID == LLUUID.Zero) - return; - List avatarts = m_parentGroup.Scene.GetAvatars(); - foreach (ScenePresence p in avatarts) + //Quaternion worldRotation = (qRotation*parentrot); + //Matrix3 worldRotM = worldRotation.ToRotationMatrix(); + + + Vector3 rOrigin = iray.Origin; + Vector3 rDirection = iray.Direction; + + + + //rDirection = rDirection.Normalize(); + // Buidling the first part of the Quadratic equation + Vector3 r2ndDirection = rDirection*rDirection; + float itestPart1 = r2ndDirection.x + r2ndDirection.y + r2ndDirection.z; + + // Buidling the second part of the Quadratic equation + Vector3 tmVal2 = rOrigin - vAbsolutePosition; + Vector3 r2Direction = rDirection*2.0f; + Vector3 tmVal3 = r2Direction*tmVal2; + + float itestPart2 = tmVal3.x + tmVal3.y + tmVal3.z; + + // Buidling the third part of the Quadratic equation + Vector3 tmVal4 = rOrigin*rOrigin; + Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition; + + Vector3 tmVal6 = vAbsolutePosition*rOrigin; + + + // Set Radius to the largest dimention of the prim + float radius = 0f; + if (vScale.x > radius) + radius = vScale.x; + if (vScale.y > radius) + radius = vScale.y; + if (vScale.z > radius) + radius = vScale.z; + + // the second part of this is the default prim size + // once we factor in the aabb of the prim we're adding we can + // change this to; + // radius = (radius / 2) - 0.01f; + // + radius = (radius / 2) + (0.5f / 2) - 0.1f; + + //radius = radius; + + float itestPart3 = tmVal4.x + tmVal4.y + tmVal4.z + tmVal5.x + tmVal5.y + tmVal5.z - + (2.0f*(tmVal6.x + tmVal6.y + tmVal6.z + (radius*radius))); + + // Yuk Quadradrics.. Solve first + float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3); + if (rootsqr < 0.0f) { - double dis=Util.GetDistanceTo(p.AbsolutePosition, position); - if (dis > 100.0) // Max audio distance - continue; + // No intersection + return returnresult; + } + float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); - // Scale by distance - volume*=((100.0-dis)/100.0); + if (root < 0.0f) + { + // perform second quadratic root solution + root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); - if (triggered) - { - p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); - } - else + // is there any intersection? + if (root < 0.0f) { - p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); + // nope, no intersection + return returnresult; } } - } - #endregion + // We got an intersection. putting together an EntityIntersection object with the + // intersection information + Vector3 ipoint = + new Vector3(iray.Origin.x + (iray.Direction.x*root), iray.Origin.y + (iray.Direction.y*root), + iray.Origin.z + (iray.Direction.z*root)); - #region Resizing/Scale + returnresult.HitTF = true; + returnresult.ipoint = ipoint; - /// - /// Resize this part. - /// - /// - public void Resize(LLVector3 scale) + // Normal is calculated by the difference and then normalizing the result + Vector3 normalpart = ipoint - vAbsolutePosition; + returnresult.normal = normalpart / normalpart.Length; + + // It's funny how the LLVector3 object has a Distance function, but the Axiom.Math object doesn't. + // I can write a function to do it.. but I like the fact that this one is Static. + + LLVector3 distanceConvert1 = new LLVector3(iray.Origin.x, iray.Origin.y, iray.Origin.z); + LLVector3 distanceConvert2 = new LLVector3(ipoint.x, ipoint.y, ipoint.z); + float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2); + + returnresult.distance = distance; + + return returnresult; + } + + public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) { - StoreUndoState(); - m_shape.Scale = scale; + // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes + // This breaks down into the ray---> plane equation. + // TODO: Change to take shape into account + Vector3[] vertexes = new Vector3[8]; + + float[] distance = new float[6]; + Vector3[] FaceA = new Vector3[6]; // vertex A for Facei + Vector3[] FaceB = new Vector3[6]; // vertex B for Facei + Vector3[] FaceC = new Vector3[6]; // vertex C for Facei + Vector3[] FaceD = new Vector3[6]; // vertex D for Facei + + Vector3[] normals = new Vector3[6]; // Normal for Facei + Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals - ParentGroup.HasGroupChanged = true; - ScheduleFullUpdate(); - } + AAfacenormals[0] = new Vector3(1, 0, 0); + AAfacenormals[1] = new Vector3(0, 1, 0); + AAfacenormals[2] = new Vector3(-1, 0, 0); + AAfacenormals[3] = new Vector3(0, -1, 0); + AAfacenormals[4] = new Vector3(0, 0, 1); + AAfacenormals[5] = new Vector3(0, 0, -1); - #endregion + Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B + Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C + Vector3 cross = new Vector3(); - public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF) - { - bool set = addRemTF == 1; + LLVector3 pos = GetWorldPosition(); + LLQuaternion rot = GetWorldRotation(); - // Are we the owner? - if (AgentID == OwnerID) - { - switch (field) - { - case 2: - OwnerMask = ApplyMask(OwnerMask, set, mask); - break; - case 4: - GroupMask = ApplyMask(GroupMask, set, mask); - break; - case 8: - EveryoneMask = ApplyMask(EveryoneMask, set, mask); - break; - case 16: - NextOwnerMask = ApplyMask(NextOwnerMask, set, mask); - break; - } - SendFullUpdateToAllClients(); + // Variables prefixed with AX are Axiom.Math copies of the LL variety. - SendObjectPropertiesToClient(AgentID); + Quaternion AXrot = new Quaternion(rot.W,rot.X,rot.Y,rot.Z); + AXrot.Normalize(); - } - } + Vector3 AXpos = new Vector3(pos.X, pos.Y, pos.Z); - private void SendObjectPropertiesToClient(LLUUID AgentID) - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - // Ugly reference :( - if (avatars[i].UUID == AgentID) - { - m_parentGroup.GetProperties(avatars[i].ControllingClient); - } - } - } + // tScale is the offset to derive the vertex based on the scale. + // it's different for each vertex because we've got to rotate it + // to get the world position of the vertex to produce the Oriented Bounding Box - private uint ApplyMask(uint val, bool set, uint mask) - { - if (set) - { - return val |= mask; - } - else - { - return val &= ~mask; - } - } + Vector3 tScale = new Vector3(); - #region Client Update Methods + Vector3 AXscale = new Vector3(m_shape.Scale.X * 0.5f, m_shape.Scale.Y * 0.5f, m_shape.Scale.Z * 0.5f); - /// - /// Tell all scene presences that they should send updates for this part to their clients - /// - public void AddFullUpdateToAllAvatars() - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - avatars[i].QueuePartForUpdate(this); - } - } + //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale)); + //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1)); - public void SendFullUpdateToAllClientsExcept(LLUUID agentID) - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - // Ugly reference :( - if (avatars[i].UUID != agentID) - { - m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, - avatars[i].GenerateClientFlags(UUID)); - } - } - } + // rScale is the rotated offset to find a vertex based on the scale and the world rotation. + Vector3 rScale = new Vector3(); - public void AddFullUpdateToAvatar(ScenePresence presence) - { - presence.QueuePartForUpdate(this); - } + // Get Vertexes for Faces Stick them into ABCD for each Face + // Form: Face[face] that corresponds to the below diagram + #region ABCD Face Vertex Map Comment Diagram + // A _________ B + // | | + // | 4 top | + // |_________| + // C D - /// - /// - /// - public void SendFullUpdateToAllClients() - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - // Ugly reference :( - m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this, - avatars[i].GenerateClientFlags(UUID)); - } - } + // A _________ B + // | Back | + // | 3 | + // |_________| + // C D - /// - /// - /// - /// - public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) - { - m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); - } + // A _________ B B _________ A + // | Left | | Right | + // | 0 | | 2 | + // |_________| |_________| + // C D D C - /// - /// Sends a full update to the client - /// - /// - /// - public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags) - { - LLVector3 lPos; - lPos = OffsetPosition; - SendFullUpdateToClient(remoteClient, lPos, clientflags); - } + // A _________ B + // | Front | + // | 1 | + // |_________| + // C D - /// - /// Sends a full update to the client - /// - /// - /// - /// - public void SendFullUpdateToClient(IClientAPI remoteClient, LLVector3 lPos, uint clientFlags) - { - clientFlags &= ~(uint) LLObject.ObjectFlags.CreateSelected; + // C _________ D + // | | + // | 5 bot | + // |_________| + // A B + #endregion - if (remoteClient.AgentId == OwnerID) - { - if ((uint) (Flags & LLObject.ObjectFlags.CreateSelected) != 0) - { - clientFlags |= (uint) LLObject.ObjectFlags.CreateSelected; - Flags &= ~LLObject.ObjectFlags.CreateSelected; - } - } + #region Plane Decomposition of Oriented Bounding Box + tScale = new Vector3(AXscale.x, -AXscale.y, AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[0] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); + // vertexes[0].x = pos.X + vertexes[0].x; + //vertexes[0].y = pos.Y + vertexes[0].y; + //vertexes[0].z = pos.Z + vertexes[0].z; - byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; - remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape, - lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, OwnerID, - m_text, color, ParentID, m_particleSystem, m_clickAction, m_TextureAnimation, m_IsAttachment, - m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius); - } + FaceA[0] = vertexes[0]; + FaceB[3] = vertexes[0]; + FaceA[4] = vertexes[0]; - /// Terse updates - public void AddTerseUpdateToAllAvatars() - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - avatars[i].QueuePartForUpdate(this); - } - } + tScale = AXscale; + rScale = ((AXrot * tScale)); + vertexes[1] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - public void AddTerseUpdateToAvatar(ScenePresence presence) - { - presence.QueuePartForUpdate(this); - } + // vertexes[1].x = pos.X + vertexes[1].x; + // vertexes[1].y = pos.Y + vertexes[1].y; + //vertexes[1].z = pos.Z + vertexes[1].z; - /// - /// - /// - public void SendTerseUpdateToAllClients() - { - List avatars = m_parentGroup.Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) - { - m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this); - } - } + FaceB[0] = vertexes[1]; + FaceA[1] = vertexes[1]; + FaceC[4] = vertexes[1]; - /// - /// Send a terse update to the client. - /// - /// - public void SendTerseUpdate(IClientAPI remoteClient) - { - m_parentGroup.SendPartTerseUpdate(remoteClient, this); - } + tScale = new Vector3(AXscale.x, -AXscale.y, -AXscale.z); + rScale = ((AXrot * tScale)); - public void SendTerseUpdateToClient(IClientAPI remoteClient) - { - LLVector3 lPos; - lPos = OffsetPosition; - LLQuaternion mRot = RotationOffset; - // TODO: I have no idea why we are making this check. This should be sorted out - if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0) - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID); - } - else - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, - RotationalVelocity); - //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); - } - } + vertexes[2] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - public void SendTerseUpdateToClient(IClientAPI remoteClient, LLVector3 lPos) - { - LLQuaternion mRot = RotationOffset; - if (m_IsAttachment) - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, (byte)((m_attachmentPoint % 16) * 16 + (m_attachmentPoint / 16)),fromAssetID); - } - else - { - if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == 0) - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID); - } - else - { - remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, - RotationalVelocity); - //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString()); - } - } - } + //vertexes[2].x = pos.X + vertexes[2].x; + //vertexes[2].y = pos.Y + vertexes[2].y; + //vertexes[2].z = pos.Z + vertexes[2].z; - #endregion + FaceC[0] = vertexes[2]; + FaceD[3] = vertexes[2]; + FaceC[5] = vertexes[2]; - public virtual void UpdateMovement() - { - } + tScale = new Vector3(AXscale.x, AXscale.y, -AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[3] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - #region Events + //vertexes[3].x = pos.X + vertexes[3].x; + // vertexes[3].y = pos.Y + vertexes[3].y; + // vertexes[3].z = pos.Z + vertexes[3].z; - public void PhysicsRequestingTerseUpdate() - { - if (PhysActor != null) - { - LLVector3 newpos = new LLVector3(PhysActor.Position.GetBytes(), 0); - if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f) - { - m_parentGroup.AbsolutePosition = newpos; - return; - } - } - ScheduleTerseUpdate(); + FaceD[0] = vertexes[3]; + FaceC[1] = vertexes[3]; + FaceA[5] = vertexes[3]; - //SendTerseUpdateToAllClients(); - } + tScale = new Vector3(-AXscale.x, AXscale.y, AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[4] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - #endregion + // vertexes[4].x = pos.X + vertexes[4].x; + // vertexes[4].y = pos.Y + vertexes[4].y; + // vertexes[4].z = pos.Z + vertexes[4].z; - public void PhysicsOutOfBounds(PhysicsVector pos) - { - m_log.Info("[PHYSICS]: Physical Object went out of bounds."); - RemFlag(LLObject.ObjectFlags.Physics); - DoPhysicsPropertyUpdate(false, true); - //m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } + FaceB[1] = vertexes[4]; + FaceA[2] = vertexes[4]; + FaceD[4] = vertexes[4]; - public virtual void OnGrab(LLVector3 offsetPos, IClientAPI remoteClient) - { - } + tScale = new Vector3(-AXscale.x, AXscale.y, -AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[5] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - /// - /// Set the text displayed for this part. - /// - /// - public void SetText(string text) - { - Text = text; - - ParentGroup.HasGroupChanged = true; - ScheduleFullUpdate(); - } + // vertexes[5].x = pos.X + vertexes[5].x; + // vertexes[5].y = pos.Y + vertexes[5].y; + // vertexes[5].z = pos.Z + vertexes[5].z; - /// - /// Set the text displayed for this part. - /// - /// - /// - /// - public void SetText(string text, Vector3 color, double alpha) - { - Color = Color.FromArgb(0xff - (int) (alpha*0xff), - (int) (color.x*0xff), - (int) (color.y*0xff), - (int) (color.z*0xff)); - SetText(text); - } + FaceD[1] = vertexes[5]; + FaceC[2] = vertexes[5]; + FaceB[5] = vertexes[5]; - public int registerTargetWaypoint(LLVector3 target, float tolerance) - { - if (m_parentGroup != null) - { - return m_parentGroup.registerTargetWaypoint(target, tolerance); - } - return 0; - } - public void unregisterTargetWaypoint(int handle) - { - if (m_parentGroup != null) - { - m_parentGroup.unregisterTargetWaypoint(handle); - } - } - protected SceneObjectPart(SerializationInfo info, StreamingContext context) - { - //System.Console.WriteLine("SceneObjectPart Deserialize BGN"); + tScale = new Vector3(-AXscale.x, -AXscale.y, AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[6] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - if (info == null) - { - throw new ArgumentNullException("info"); - } + // vertexes[6].x = pos.X + vertexes[6].x; + // vertexes[6].y = pos.Y + vertexes[6].y; + // vertexes[6].z = pos.Z + vertexes[6].z; - /* - m_queue = (Queue)info.GetValue("m_queue", typeof(Queue)); - m_ids = (List)info.GetValue("m_ids", typeof(List)); - */ + FaceB[2] = vertexes[6]; + FaceA[3] = vertexes[6]; + FaceB[4] = vertexes[6]; - //System.Console.WriteLine("SceneObjectPart Deserialize END"); - } + tScale = new Vector3(-AXscale.x, -AXscale.y, -AXscale.z); + rScale = ((AXrot * tScale)); + vertexes[7] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); - [SecurityPermission(SecurityAction.LinkDemand, - Flags = SecurityPermissionFlag.SerializationFormatter)] - public virtual void GetObjectData( - SerializationInfo info, StreamingContext context) - { - if (info == null) + // vertexes[7].x = pos.X + vertexes[7].x; + // vertexes[7].y = pos.Y + vertexes[7].y; + // vertexes[7].z = pos.Z + vertexes[7].z; + + FaceD[2] = vertexes[7]; + FaceC[3] = vertexes[7]; + FaceD[5] = vertexes[7]; + #endregion + + // Get our plane normals + for (int i = 0; i < 6; i++) { - throw new ArgumentNullException("info"); - } + //m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]); - info.AddValue("m_inventoryFileName", GetInventoryFileName()); - info.AddValue("m_folderID", UUID); - info.AddValue("PhysActor", PhysActor); + // Our Plane direction + AmBa = FaceA[i] - FaceB[i]; + AmBb = FaceB[i] - FaceC[i]; - Dictionary TaskInventory_work = new Dictionary(); + cross = AmBb.Cross(AmBa); - foreach (LLUUID id in TaskInventory.Keys) - { - TaskInventory_work.Add(id.UUID, TaskInventory[id]); + // normalize the cross product to get the normal. + normals[i] = cross / cross.Length; + + //m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString()); + //distance[i] = (normals[i].x * AmBa.x + normals[i].y * AmBa.y + normals[i].z * AmBa.z) * -1; } - info.AddValue("TaskInventory", TaskInventory_work); + EntityIntersection returnresult = new EntityIntersection(); - info.AddValue("LastOwnerID", LastOwnerID.UUID); - info.AddValue("OwnerID", OwnerID.UUID); - info.AddValue("GroupID", GroupID.UUID); + returnresult.distance = 1024; + float c = 0; + float a = 0; + float d = 0; + Vector3 q = new Vector3(); - info.AddValue("OwnershipCost", OwnershipCost); - info.AddValue("ObjectSaleType", ObjectSaleType); - info.AddValue("SalePrice", SalePrice); - info.AddValue("Category", Category); + #region OBB Version 2 Experiment + //float fmin = 999999; + //float fmax = -999999; + //float s = 0; - info.AddValue("CreationDate", CreationDate); - info.AddValue("ParentID", ParentID); + //for (int i=0;i<6;i++) + //{ + //s = iray.Direction.Dot(normals[i]); + //d = normals[i].Dot(FaceB[i]); - info.AddValue("OwnerMask", OwnerMask); - info.AddValue("NextOwnerMask", NextOwnerMask); - info.AddValue("GroupMask", GroupMask); - info.AddValue("EveryoneMask", EveryoneMask); - info.AddValue("BaseMask", BaseMask); + //if (s == 0) + //{ + //if (iray.Origin.Dot(normals[i]) > d) + //{ + //return returnresult; + //} + // else + //{ + //continue; + //} + //} + //a = (d - iray.Origin.Dot(normals[i])) / s; + //if (iray.Direction.Dot(normals[i]) < 0) + //{ + //if (a > fmax) + //{ + //if (a > fmin) + //{ + //return returnresult; + //} + //fmax = a; + //} - info.AddValue("m_particleSystem", m_particleSystem); + //} + //else + //{ + //if (a < fmin) + //{ + //if (a < 0 || a < fmax) + //{ + //return returnresult; + //} + //fmin = a; + //} + //} + //} + //if (fmax > 0) + // a= fmax; + //else + // a=fmin; - info.AddValue("TimeStampFull", TimeStampFull); - info.AddValue("TimeStampTerse", TimeStampTerse); - info.AddValue("TimeStampLastActivity", TimeStampLastActivity); + //q = iray.Origin + a * iray.Direction; + #endregion + + // Loop over faces (6 of them) + for (int i = 0; i < 6; i++) + { + AmBa = FaceA[i] - FaceB[i]; + AmBb = FaceB[i] - FaceC[i]; + d = normals[i].Dot(FaceB[i]); + + //if (faceCenters) + //{ + // c = normals[i].Dot(normals[i]); + //} + //else + //{ + c = iray.Direction.Dot(normals[i]); + //} + if (c == 0) + continue; - info.AddValue("m_updateFlag", m_updateFlag); - info.AddValue("CreatorID", CreatorID.UUID); + a = (d - iray.Origin.Dot(normals[i])) / c; - info.AddValue("m_inventorySerial", m_inventorySerial); - info.AddValue("m_uuid", m_uuid.UUID); - info.AddValue("m_localID", m_localId); - info.AddValue("m_name", m_name); - info.AddValue("m_flags", Flags); - info.AddValue("m_material", m_material); - info.AddValue("m_regionHandle", m_regionHandle); + if (a < 0) + continue; - info.AddValue("m_groupPosition.X", m_groupPosition.X); - info.AddValue("m_groupPosition.Y", m_groupPosition.Y); - info.AddValue("m_groupPosition.Z", m_groupPosition.Z); + // If the normal is pointing outside the object - info.AddValue("m_offsetPosition.X", m_offsetPosition.X); - info.AddValue("m_offsetPosition.Y", m_offsetPosition.Y); - info.AddValue("m_offsetPosition.Z", m_offsetPosition.Z); - info.AddValue("m_rotationOffset.W", m_rotationOffset.W); - info.AddValue("m_rotationOffset.X", m_rotationOffset.X); - info.AddValue("m_rotationOffset.Y", m_rotationOffset.Y); - info.AddValue("m_rotationOffset.Z", m_rotationOffset.Z); - info.AddValue("m_velocity.X", m_velocity.X); - info.AddValue("m_velocity.Y", m_velocity.Y); - info.AddValue("m_velocity.Z", m_velocity.Z); + if (iray.Direction.Dot(normals[i]) < 0 || !frontFacesOnly) + { - info.AddValue("m_rotationalvelocity.X", m_rotationalvelocity.X); - info.AddValue("m_rotationalvelocity.Y", m_rotationalvelocity.Y); - info.AddValue("m_rotationalvelocity.Z", m_rotationalvelocity.Z); + //if (faceCenters) + //{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f; + // q = iray.Origin + a * normals[i]; + //} + //else + //{ + q = iray.Origin + a * iray.Direction; + //} - info.AddValue("m_angularVelocity.X", m_angularVelocity.X); - info.AddValue("m_angularVelocity.Y", m_angularVelocity.Y); - info.AddValue("m_angularVelocity.Z", m_angularVelocity.Z); + float distance2 = (float)GetDistanceTo(q, AXpos); + // Is this the closest hit to the object's origin? + //if (faceCenters) + //{ + // distance2 = (float)GetDistanceTo(q, iray.Origin); + //} - info.AddValue("m_acceleration.X", m_acceleration.X); - info.AddValue("m_acceleration.Y", m_acceleration.Y); - info.AddValue("m_acceleration.Z", m_acceleration.Z); + if (distance2 < returnresult.distance) + { + returnresult.distance = distance2; + returnresult.HitTF = true; + returnresult.ipoint = q; + //m_log.Info("[FACE]:" + i.ToString()); + //m_log.Info("[POINT]: " + q.ToString()); + //m_log.Info("[DIST]: " + distance2.ToString()); + if (faceCenters) + { + returnresult.normal = (AXrot * AAfacenormals[i]); - info.AddValue("m_description", m_description); - info.AddValue("m_color", m_color); - info.AddValue("m_text", m_text); - info.AddValue("m_sitName", m_sitName); - info.AddValue("m_touchName", m_touchName); - info.AddValue("m_clickAction", m_clickAction); - info.AddValue("m_shape", m_shape); - info.AddValue("m_parentGroup", m_parentGroup); - info.AddValue("PayPrice", PayPrice); + Vector3 scaleComponent = AAfacenormals[i]; + float ScaleOffset = 0.5f; + if (scaleComponent.x != 0) ScaleOffset = AXscale.x; + if (scaleComponent.y != 0) ScaleOffset = AXscale.y; + if (scaleComponent.z != 0) ScaleOffset = AXscale.z; + ScaleOffset = Math.Abs(ScaleOffset); + Vector3 offset = returnresult.normal * ScaleOffset; + returnresult.ipoint = AXpos + offset; + + ///pos = (intersectionpoint + offset); + } + else + { + returnresult.normal = normals[i]; + } + returnresult.AAfaceNormal = AAfacenormals[i]; + } + } + } + return returnresult; } - public void Undo() + /// + /// Serialize this part to xml. + /// + /// + public void ToXml(XmlWriter xmlWriter) { - if (m_undo.Count > 0) - { - UndoState goback = m_undo.Pop(); - if (goback != null) - goback.PlaybackState(this); - } + XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); + serializer.Serialize(xmlWriter, this); } - public void SetScriptEvents(LLUUID scriptid, int events) + public void TriggerScriptChangedEvent(Changed val) { - scriptEvents oldparts; - lock (m_scriptEvents) + if (m_parentGroup != null) { - if (m_scriptEvents.ContainsKey(scriptid)) - { - oldparts = m_scriptEvents[scriptid]; - - // remove values from aggregated script events - m_scriptEvents[scriptid] = (scriptEvents) events; - } - else - { - m_scriptEvents.Add(scriptid, (scriptEvents) events); - } + if (m_parentGroup.Scene != null) + m_parentGroup.Scene.TriggerObjectChanged(LocalId, (uint)val); } - aggregateScriptEvents(); } - public void RemoveScriptEvents(LLUUID scriptid) + public void TrimPermissions() { - lock (m_scriptEvents) - { - 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); - } - } - aggregateScriptEvents(); + BaseMask &= (uint)PermissionMask.All; + OwnerMask &= (uint)PermissionMask.All; + GroupMask &= (uint)PermissionMask.All; + EveryoneMask &= (uint)PermissionMask.All; + NextOwnerMask &= (uint)PermissionMask.All; } - public void aggregateScriptEvents() + public void Undo() { - // Aggregate script events - lock (m_scriptEvents) - { - foreach (scriptEvents s in m_scriptEvents.Values) - { - m_aggregateScriptEvents |= s; - } - } - - uint objectflagupdate = 0; - - if ( - ((m_aggregateScriptEvents & scriptEvents.touch) != 0) || - ((m_aggregateScriptEvents & scriptEvents.touch_end) != 0) || - ((m_aggregateScriptEvents & scriptEvents.touch_start) != 0) - ) - { - objectflagupdate |= (uint) LLObject.ObjectFlags.Touch; - } - - if ((m_aggregateScriptEvents & scriptEvents.money) != 0) - { - objectflagupdate |= (uint) LLObject.ObjectFlags.Money; - } - - if (AllowedDrop) + if (m_undo.Count > 0) { - objectflagupdate |= (uint) LLObject.ObjectFlags.AllowInventoryDrop; + UndoState goback = m_undo.Pop(); + if (goback != null) + goback.PlaybackState(this); } + } - if ( - ((m_aggregateScriptEvents & scriptEvents.collision) != 0) || - ((m_aggregateScriptEvents & scriptEvents.collision_end) != 0) || - ((m_aggregateScriptEvents & scriptEvents.collision_start) != 0) - ) - { - // subscribe to physics updates. - if (PhysActor != null) - { - PhysActor.OnCollisionUpdate += PhysicsCollision; - PhysActor.SubscribeEvents(1000); + public void UpdateExtraParam(ushort type, bool inUse, byte[] data) + { + m_shape.ReadInUpdateExtraParam(type, inUse, data); - } - } - else + if (type == 0x30) { - if (PhysActor != null) + if (m_shape.SculptEntry && m_shape.SculptTexture != LLUUID.Zero) { - PhysActor.UnSubscribeEvents(); - PhysActor.OnCollisionUpdate -= PhysicsCollision; + //AssetBase tx = m_parentGroup.Scene.getase + m_parentGroup.Scene.AssetCache.GetAsset(m_shape.SculptTexture, SculptTextureCallback, true); } } - if ((GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Scripted) != 0) - { - m_parentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; - } - else - { - m_parentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting; - } - LocalFlags=(LLObject.ObjectFlags)objectflagupdate; - - if (m_parentGroup != null && m_parentGroup.RootPart == this) - m_parentGroup.aggregateScriptEvents(); - else - ScheduleFullUpdate(); + ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); } - public void PhysicsCollision(EventArgs e) + public void UpdateGroupPosition(LLVector3 pos) { - // single threaded here - if (e == null) + if ((pos.X != GroupPosition.X) || + (pos.Y != GroupPosition.Y) || + (pos.Z != GroupPosition.Z)) { - return; + LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); + GroupPosition = newPos; + ScheduleTerseUpdate(); } - - CollisionEventUpdate a = (CollisionEventUpdate)e; - Dictionary collissionswith = a.m_objCollisionList; - List thisHitColliders = new List(); - List endedColliders = new List(); - List startedColliders = new List(); + } - // calculate things that started colliding this time - // and build up list of colliders this time - foreach (uint localid in collissionswith.Keys) - { - if (localid != 0) - { - thisHitColliders.Add(localid); - if (!m_lastColliders.Contains(localid)) - { - startedColliders.Add(localid); - } + public virtual void UpdateMovement() + { + } - //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); - } + /// + /// + /// + /// + public void UpdateOffSet(LLVector3 pos) + { + if ((pos.X != OffsetPosition.X) || + (pos.Y != OffsetPosition.Y) || + (pos.Z != OffsetPosition.Z)) + { + LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z); + OffsetPosition = newPos; + ScheduleTerseUpdate(); } + } - // calculate things that ended colliding - foreach (uint localID in m_lastColliders) + public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF) + { + bool set = addRemTF == 1; + + // Are we the owner? + if (AgentID == OwnerID) { - if (!thisHitColliders.Contains(localID)) + switch (field) { - endedColliders.Add(localID); + case 2: + OwnerMask = ApplyMask(OwnerMask, set, mask); + break; + case 4: + GroupMask = ApplyMask(GroupMask, set, mask); + break; + case 8: + EveryoneMask = ApplyMask(EveryoneMask, set, mask); + break; + case 16: + NextOwnerMask = ApplyMask(NextOwnerMask, set, mask); + break; } + SendFullUpdateToAllClients(); + + SendObjectPropertiesToClient(AgentID); + } + } - //add the items that started colliding this time to the last colliders list. - foreach (uint localID in startedColliders) + public void UpdatePrimFlags(ushort type, bool inUse, byte[] data) + { + //m_log.Info("TSomething1:" + ((type & (ushort)ExtraParamType.Something1) == (ushort)ExtraParamType.Something1)); + //m_log.Info("TSomething2:" + ((type & (ushort)ExtraParamType.Something2) == (ushort)ExtraParamType.Something2)); + //m_log.Info("TSomething3:" + ((type & (ushort)ExtraParamType.Something3) == (ushort)ExtraParamType.Something3)); + //m_log.Info("TSomething4:" + ((type & (ushort)ExtraParamType.Something4) == (ushort)ExtraParamType.Something4)); + //m_log.Info("TSomething5:" + ((type & (ushort)ExtraParamType.Something5) == (ushort)ExtraParamType.Something5)); + //m_log.Info("TSomething6:" + ((type & (ushort)ExtraParamType.Something6) == (ushort)ExtraParamType.Something6)); + + bool usePhysics = false; + bool IsTemporary = false; + bool IsPhantom = false; + bool castsShadows = false; + bool wasUsingPhysics = ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0); + //bool IsLocked = false; + int i = 0; + + try { - m_lastColliders.Add(localID); + i += 46; + //IsLocked = (data[i++] != 0) ? true : false; + usePhysics = ((data[i++] != 0) && m_parentGroup.Scene.m_physicalPrim) ? true : false; + //System.Console.WriteLine("U" + packet.ToBytes().Length.ToString()); + IsTemporary = (data[i++] != 0) ? true : false; + IsPhantom = (data[i++] != 0) ? true : false; + castsShadows = (data[i++] != 0) ? true : false; } - // remove things that ended colliding from the last colliders list - foreach (uint localID in endedColliders) + catch (Exception) { - m_lastColliders.Remove(localID); + Console.WriteLine("Ignoring invalid Packet:"); + //Silently ignore it - TODO: FIXME Quick } - if (m_parentGroup == null) - return; - if (m_parentGroup.RootPart == null) - return; - if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0) + if (usePhysics) { - // do event notification - if (startedColliders.Count > 0) + AddFlag(LLObject.ObjectFlags.Physics); + if (!wasUsingPhysics) { - ColliderArgs StartCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in startedColliders) + DoPhysicsPropertyUpdate(usePhysics, false); + if (m_parentGroup != null) { - // always running this check because if the user deletes the object it would return a null reference. - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - else + if (m_parentGroup.RootPart != null) { - List avlist = m_parentGroup.Scene.GetScenePresences(); - if (avlist != null) + if (LocalId == m_parentGroup.RootPart.LocalId) { - foreach (ScenePresence av in avlist) - { - if (av.LocalId == localId) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = av.UUID; - detobj.nameStr = av.ControllingClient.Name; - detobj.ownerUUID = av.UUID; - detobj.posVector = av.AbsolutePosition; - detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); - detobj.velVector = av.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = av.ControllingClient.ActiveGroupId; - colliding.Add(detobj); - } - } + m_parentGroup.CheckSculptAndLoad(); } } } - if (colliding.Count > 0) - { - StartCollidingMessage.Colliders = colliding; - // always running this check because if the user deletes the object it would return a null reference. - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage); - } } } - if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0) + else { - if (m_lastColliders.Count > 0) + RemFlag(LLObject.ObjectFlags.Physics); + if (wasUsingPhysics) { - ColliderArgs CollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in m_lastColliders) - { - // always running this check because if the user deletes the object it would return a null reference. - if (localId == 0) - continue; - - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - else - { - List avlist = m_parentGroup.Scene.GetScenePresences(); - if (avlist != null) - { - foreach (ScenePresence av in avlist) - { - if (av.LocalId == localId) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = av.UUID; - detobj.nameStr = av.Name; - detobj.ownerUUID = av.UUID; - detobj.posVector = av.AbsolutePosition; - detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); - detobj.velVector = av.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = av.ControllingClient.ActiveGroupId; - colliding.Add(detobj); - } - } - - } - } - } - if (colliding.Count > 0) - { - CollidingMessage.Colliders = colliding; - // always running this check because if the user deletes the object it would return a null reference. - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - m_parentGroup.Scene.EventManager.TriggerScriptColliding(LocalId, CollidingMessage); - } + DoPhysicsPropertyUpdate(usePhysics, false); + } + } + if (IsPhantom) + { + AddFlag(LLObject.ObjectFlags.Phantom); + if (PhysActor != null) + { + m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); + /// that's not wholesome. Had to make Scene public + PhysActor = null; } } - if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0) + else { - if (endedColliders.Count > 0) + RemFlag(LLObject.ObjectFlags.Phantom); + if (PhysActor == null) { - ColliderArgs EndCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in endedColliders) - { - if (localId == 0) - continue; - - // always running this check because if the user deletes the object it would return a null reference. - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId); - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - else + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + Name, + Shape, + new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, + AbsolutePosition.Z), + new PhysicsVector(Scale.X, Scale.Y, Scale.Z), + new Quaternion(RotationOffset.W, RotationOffset.X, + RotationOffset.Y, RotationOffset.Z), usePhysics); + + if (PhysActor != null) + { + PhysActor.LocalID = LocalId; + DoPhysicsPropertyUpdate(usePhysics, true); + if (m_parentGroup != null) { - List avlist = m_parentGroup.Scene.GetScenePresences(); - if (avlist != null) + if (m_parentGroup.RootPart != null) { - foreach (ScenePresence av in avlist) + if (LocalId == m_parentGroup.RootPart.LocalId) { - if (av.LocalId == localId) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = av.UUID; - detobj.nameStr = av.Name; - detobj.ownerUUID = av.UUID; - detobj.posVector = av.AbsolutePosition; - detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w); - detobj.velVector = av.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = av.ControllingClient.ActiveGroupId; - colliding.Add(detobj); - } + m_parentGroup.CheckSculptAndLoad(); } - } } } - if (colliding.Count > 0) + } + else + { + PhysActor.IsPhysical = usePhysics; + DoPhysicsPropertyUpdate(usePhysics, false); + if (m_parentGroup != null) { - EndCollidingMessage.Colliders = colliding; - // always running this check because if the user deletes the object it would return a null reference. - if (m_parentGroup == null) - return; - if (m_parentGroup.Scene == null) - return; - m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(LocalId, EndCollidingMessage); + if (m_parentGroup.RootPart != null) + { + if (LocalId == m_parentGroup.RootPart.LocalId) + { + m_parentGroup.CheckSculptAndLoad(); + } + } } - } } - } - + if (IsTemporary) + { + AddFlag(LLObject.ObjectFlags.TemporaryOnRez); + } + else + { + RemFlag(LLObject.ObjectFlags.TemporaryOnRez); + } + // System.Console.WriteLine("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); + ScheduleFullUpdate(); + } - public void SetDieAtEdge(bool p) + public void UpdateRotation(LLQuaternion rot) { - if (m_parentGroup == null) - return; - if (m_parentGroup.RootPart == null) - return; - - m_parentGroup.RootPart.DIE_AT_EDGE = p; + if ((rot.X != RotationOffset.X) || + (rot.Y != RotationOffset.Y) || + (rot.Z != RotationOffset.Z) || + (rot.W != RotationOffset.W)) + { + //StoreUndoState(); + RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W); + ParentGroup.HasGroupChanged = true; + ScheduleTerseUpdate(); + } } - public bool GetDieAtEdge() + + /// + /// Update the shape of this part. + /// + /// + public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock) { - if (m_parentGroup == null) - return false; - if (m_parentGroup.RootPart == null) - return false; + m_shape.PathBegin = shapeBlock.PathBegin; + m_shape.PathEnd = shapeBlock.PathEnd; + m_shape.PathScaleX = shapeBlock.PathScaleX; + m_shape.PathScaleY = shapeBlock.PathScaleY; + m_shape.PathShearX = shapeBlock.PathShearX; + m_shape.PathShearY = shapeBlock.PathShearY; + m_shape.PathSkew = shapeBlock.PathSkew; + m_shape.ProfileBegin = shapeBlock.ProfileBegin; + m_shape.ProfileEnd = shapeBlock.ProfileEnd; + m_shape.PathCurve = shapeBlock.PathCurve; + m_shape.ProfileCurve = shapeBlock.ProfileCurve; + m_shape.ProfileHollow = shapeBlock.ProfileHollow; + m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset; + m_shape.PathRevolutions = shapeBlock.PathRevolutions; + m_shape.PathTaperX = shapeBlock.PathTaperX; + m_shape.PathTaperY = shapeBlock.PathTaperY; + m_shape.PathTwist = shapeBlock.PathTwist; + m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; + if (PhysActor != null) + { + PhysActor.Shape = m_shape; + } - return m_parentGroup.RootPart.DIE_AT_EDGE; + ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); } - public void GetProperties(IClientAPI client) + // Added to handle bug in libsecondlife's TextureEntry.ToBytes() + // not handling RGBA properly. Cycles through, and "fixes" the color + // info + public void UpdateTexture(LLObject.TextureEntry tex) { - - client.SendObjectPropertiesReply(LLUUID.Zero, (ulong)CreationDate, CreatorID, LLUUID.Zero, LLUUID.Zero, - GroupID, (short)InventorySerial, LastOwnerID, UUID, OwnerID, - ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description, - ParentGroup.RootPart.OwnerMask, ParentGroup.RootPart.NextOwnerMask, ParentGroup.RootPart.GroupMask, ParentGroup.RootPart.EveryoneMask, - ParentGroup.RootPart.BaseMask); - + //LLColor tmpcolor; + //for (uint i = 0; i < 32; i++) + //{ + // if (tex.FaceTextures[i] != null) + // { + // tmpcolor = tex.GetFace((uint) i).RGBA; + // tmpcolor.A = tmpcolor.A*255; + // tmpcolor.R = tmpcolor.R*255; + // tmpcolor.G = tmpcolor.G*255; + // tmpcolor.B = tmpcolor.B*255; + // tex.FaceTextures[i].RGBA = tmpcolor; + // } + //} + //tmpcolor = tex.DefaultTexture.RGBA; + //tmpcolor.A = tmpcolor.A*255; + //tmpcolor.R = tmpcolor.R*255; + //tmpcolor.G = tmpcolor.G*255; + //tmpcolor.B = tmpcolor.B*255; + //tex.DefaultTexture.RGBA = tmpcolor; + UpdateTextureEntry(tex.ToBytes()); } - - public void SetGroup(LLUUID groupID, IClientAPI client) + + /// + /// Update the texture entry for this part. + /// + /// + public void UpdateTextureEntry(byte[] textureEntry) { - GroupID = groupID; - GetProperties(client); - m_updateFlag = 2; + m_shape.TextureEntry = textureEntry; + TriggerScriptChangedEvent(Changed.TEXTURE); + + ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); } - - private void handleTimerAccounting(uint localID, double interval) + + public void aggregateScriptEvents() { - if (localID == LocalId) + // Aggregate script events + lock (m_scriptEvents) { - - float sec = (float)interval; - if (m_parentGroup != null) + foreach (scriptEvents s in m_scriptEvents.Values) { - if (sec == 0) - { - if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001) - m_parentGroup.scriptScore = 0; + m_aggregateScriptEvents |= s; + } + } - m_parentGroup.scriptScore += 0.001f; - return; - } + uint objectflagupdate = 0; - if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec)) - m_parentGroup.scriptScore = 0; - m_parentGroup.scriptScore += (0.001f / sec); + if ( + ((m_aggregateScriptEvents & scriptEvents.touch) != 0) || + ((m_aggregateScriptEvents & scriptEvents.touch_end) != 0) || + ((m_aggregateScriptEvents & scriptEvents.touch_start) != 0) + ) + { + objectflagupdate |= (uint) LLObject.ObjectFlags.Touch; + } + + if ((m_aggregateScriptEvents & scriptEvents.money) != 0) + { + objectflagupdate |= (uint) LLObject.ObjectFlags.Money; + } + + if (AllowedDrop) + { + objectflagupdate |= (uint) LLObject.ObjectFlags.AllowInventoryDrop; + } + + if ( + ((m_aggregateScriptEvents & scriptEvents.collision) != 0) || + ((m_aggregateScriptEvents & scriptEvents.collision_end) != 0) || + ((m_aggregateScriptEvents & scriptEvents.collision_start) != 0) + ) + { + // subscribe to physics updates. + if (PhysActor != null) + { + PhysActor.OnCollisionUpdate += PhysicsCollision; + PhysActor.SubscribeEvents(1000); + + } + } + else + { + if (PhysActor != null) + { + PhysActor.UnSubscribeEvents(); + PhysActor.OnCollisionUpdate -= PhysicsCollision; } + } + if ((GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Scripted) != 0) + { + m_parentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; + } + else + { + m_parentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting; + } + + LocalFlags=(LLObject.ObjectFlags)objectflagupdate; + + if (m_parentGroup != null && m_parentGroup.RootPart == this) + m_parentGroup.aggregateScriptEvents(); + else + ScheduleFullUpdate(); + } + + public int registerTargetWaypoint(LLVector3 target, float tolerance) + { + if (m_parentGroup != null) + { + return m_parentGroup.registerTargetWaypoint(target, tolerance); + } + return 0; + } + public void unregisterTargetWaypoint(int handle) + { + if (m_parentGroup != null) + { + m_parentGroup.unregisterTargetWaypoint(handle); } } + #endregion Public Methods } -} +} \ No newline at end of file -- cgit v1.1