2007-10-15 07:10:21 +00:00
/ *
2008-03-18 05:16:43 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2007-10-15 07:10:21 +00:00
2007-09-19 00:30:55 +00:00
using System ;
2007-07-30 20:11:40 +00:00
using System.Collections.Generic ;
2007-12-27 21:41:48 +00:00
using System.Drawing ;
2011-07-11 02:35:29 +00:00
using System.IO ;
2008-11-21 21:16:42 +00:00
using System.Reflection ;
2008-04-21 07:09:17 +00:00
using System.Runtime.Serialization ;
using System.Security.Permissions ;
2007-08-13 13:36:42 +00:00
using System.Xml ;
using System.Xml.Serialization ;
2008-11-21 21:16:42 +00:00
using log4net ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
using OpenMetaverse.Packets ;
2010-08-16 19:38:20 +00:00
using OpenMetaverse.StructuredData ;
2007-10-29 21:46:25 +00:00
using OpenSim.Framework ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Interfaces ;
using OpenSim.Region.Framework.Scenes.Scripting ;
2010-10-17 17:35:38 +00:00
using OpenSim.Region.Framework.Scenes.Serialization ;
2007-08-28 18:40:40 +00:00
using OpenSim.Region.Physics.Manager ;
2007-07-30 20:11:40 +00:00
2009-02-06 16:55:34 +00:00
namespace OpenSim.Region.Framework.Scenes
2009-09-30 16:00:09 +00:00
{
2008-06-27 19:21:15 +00:00
#region Enumerations
[Flags]
public enum Changed : uint
{
INVENTORY = 1 ,
COLOR = 2 ,
SHAPE = 4 ,
SCALE = 8 ,
TEXTURE = 16 ,
LINK = 32 ,
ALLOWED_DROP = 64 ,
2008-09-09 14:51:41 +00:00
OWNER = 128 ,
2010-08-06 14:11:18 +00:00
REGION = 256 ,
TELEPORT = 512 ,
REGION_RESTART = 1024 ,
2010-08-06 17:28:53 +00:00
MEDIA = 2048 ,
2010-08-06 14:11:18 +00:00
ANIMATION = 16384
2008-06-27 19:21:15 +00:00
}
2008-05-16 01:22:11 +00:00
// I don't really know where to put this except here.
2008-01-17 02:23:48 +00:00
// Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants
2008-02-10 10:55:57 +00:00
[Flags]
public enum ExtraParamType
{
Something1 = 1 ,
Something2 = 2 ,
Something3 = 4 ,
Something4 = 8 ,
Flexible = 16 ,
Light = 32 ,
Sculpt = 48 ,
Something5 = 64 ,
Something6 = 128
}
2008-06-27 19:21:15 +00:00
2008-02-02 08:11:14 +00:00
[Flags]
public enum TextureAnimFlags : byte
{
NONE = 0x00 ,
ANIM_ON = 0x01 ,
LOOP = 0x02 ,
REVERSE = 0x04 ,
PING_PONG = 0x08 ,
SMOOTH = 0x10 ,
ROTATE = 0x20 ,
SCALE = 0x40
}
2008-01-17 02:23:48 +00:00
2010-02-01 21:35:05 +00:00
public enum PrimType : int
{
BOX = 0 ,
CYLINDER = 1 ,
PRISM = 2 ,
SPHERE = 3 ,
TORUS = 4 ,
TUBE = 5 ,
RING = 6 ,
SCULPT = 7
}
2011-11-02 21:59:00 +00:00
public enum UpdateRequired : byte
{
NONE = 0 ,
TERSE = 1 ,
FULL = 2
}
2008-06-27 19:21:15 +00:00
#endregion Enumerations
2008-05-16 01:22:11 +00:00
2010-05-12 22:59:48 +00:00
public class SceneObjectPart : IScriptHost , ISceneEntity
2007-07-30 20:11:40 +00:00
{
2010-02-01 21:35:05 +00:00
/// <value>
/// Denote all sides of the prim
/// </value>
public const int ALL_SIDES = - 1 ;
2008-11-21 21:16:42 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2009-01-02 17:22:24 +00:00
2010-08-16 19:38:20 +00:00
/// <summary>
/// Dynamic attributes can be created and deleted as required.
/// </summary>
2010-08-16 21:21:46 +00:00
public DAMap DynAttrs { get ; set ; }
2010-08-16 19:38:20 +00:00
2010-02-03 16:40:21 +00:00
/// <value>
2012-04-06 21:41:35 +00:00
/// Is this a root part?
2010-02-03 16:40:21 +00:00
/// </value>
2012-04-06 21:41:35 +00:00
/// <remarks>
/// This will return true even if the whole object is attached to an avatar.
/// </remarks>
2010-02-03 16:40:21 +00:00
public bool IsRoot
{
2012-04-06 21:41:35 +00:00
get { return ParentGroup . RootPart = = this ; }
2010-02-03 16:40:21 +00:00
}
2012-07-10 22:19:52 +00:00
/// <summary>
/// Is an explicit sit target set for this part?
/// </summary>
public bool IsSitTargetSet
{
get
{
return
! ( SitTargetPosition = = Vector3 . Zero
& & ( SitTargetOrientation = = Quaternion . Identity // Valid Zero Rotation quaternion
| | SitTargetOrientation . X = = 0f & & SitTargetOrientation . Y = = 0f & & SitTargetOrientation . Z = = 1f & & SitTargetOrientation . W = = 0f // W-Z Mapping was invalid at one point
| | SitTargetOrientation . X = = 0f & & SitTargetOrientation . Y = = 0f & & SitTargetOrientation . Z = = 0f & & SitTargetOrientation . W = = 0f ) ) ; // Invalid Quaternion
}
}
2008-06-27 19:21:15 +00:00
#region Fields
2008-05-16 01:22:11 +00:00
2009-10-25 07:40:21 +00:00
public bool AllowedDrop ;
2010-10-17 17:41:38 +00:00
2009-10-25 07:40:21 +00:00
public bool DIE_AT_EDGE ;
2010-10-17 17:41:38 +00:00
2010-02-14 21:41:57 +00:00
public bool RETURN_AT_EDGE ;
2010-10-17 17:41:38 +00:00
2010-02-14 21:41:57 +00:00
public bool BlockGrab ;
public bool StatusSandbox ;
public Vector3 StatusSandboxPos ;
2011-05-25 11:17:46 +00:00
[XmlIgnore]
public int [ ] PayPrice = { - 2 , - 2 , - 2 , - 2 , - 2 } ;
[XmlIgnore]
2012-04-03 04:50:13 +00:00
/// <summary>
/// The representation of this part in the physics scene.
/// </summary>
/// <remarks>
/// If you use this property more than once in a section of code then you must take a reference and use that.
/// If another thread is simultaneously turning physics off on this part then this refernece could become
/// null at any time.
/// </remarks>
2012-04-06 22:49:23 +00:00
public PhysicsActor PhysActor { get ; set ; }
2008-06-29 02:04:44 +00:00
2008-06-27 19:21:15 +00:00
//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)
2010-10-17 17:41:38 +00:00
2008-09-06 07:52:41 +00:00
public UUID Sound ;
2011-10-15 01:54:43 +00:00
2008-06-27 19:21:15 +00:00
public byte SoundFlags ;
2011-10-15 01:54:43 +00:00
2008-06-27 19:21:15 +00:00
public double SoundGain ;
2011-10-15 01:54:43 +00:00
2008-06-27 19:21:15 +00:00
public double SoundRadius ;
2011-10-15 01:54:43 +00:00
2009-10-25 07:40:21 +00:00
public uint TimeStampFull ;
2011-10-15 01:54:43 +00:00
2009-10-25 07:40:21 +00:00
public uint TimeStampLastActivity ; // Will be used for AutoReturn
2011-10-15 01:54:43 +00:00
public uint TimeStampTerse ;
2010-01-10 19:58:44 +00:00
public int STATUS_ROTATE_X ;
public int STATUS_ROTATE_Y ;
2010-01-07 03:19:00 +00:00
public int STATUS_ROTATE_Z ;
2011-10-15 01:54:43 +00:00
2009-12-31 17:41:07 +00:00
private Dictionary < int , string > m_CollisionFilter = new Dictionary < int , string > ( ) ;
2008-12-17 16:11:03 +00:00
/// <value>
2009-10-01 00:38:36 +00:00
/// The UUID of the user inventory item from which this object was rezzed if this is a root part.
2008-12-17 16:11:03 +00:00
/// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item.
/// </value>
2009-10-25 07:40:21 +00:00
private UUID m_fromUserInventoryItemID ;
2008-12-17 16:11:03 +00:00
public UUID FromUserInventoryItemID
{
get { return m_fromUserInventoryItemID ; }
2011-09-01 23:41:21 +00:00
set { m_fromUserInventoryItemID = value ; }
2008-12-17 16:11:03 +00:00
}
2011-09-01 23:41:21 +00:00
2009-10-25 07:40:21 +00:00
public scriptEvents AggregateScriptEvents ;
public Vector3 AttachedPos ;
2009-10-26 06:16:12 +00:00
public Vector3 RotationAxis = Vector3 . One ;
2008-12-20 21:36:42 +00:00
2009-10-25 07:40:21 +00:00
public bool VolumeDetectActive ; // XmlIgnore set to avoid problems with persistance until I come to care for this
// Certainly this must be a persistant setting finally
2008-12-20 21:36:42 +00:00
2009-10-25 07:40:21 +00:00
public bool IsWaitingForFirstSpinUpdatePacket ;
public Quaternion SpinOldOrientation = Quaternion . Identity ;
2009-04-10 06:39:52 +00:00
2012-01-13 22:48:56 +00:00
protected int m_APIDIterations = 0 ;
protected Quaternion m_APIDTarget = Quaternion . Identity ;
protected float m_APIDDamp = 0 ;
protected float m_APIDStrength = 0 ;
2010-02-14 21:41:57 +00:00
2008-11-21 21:16:42 +00:00
/// <summary>
/// This part's inventory
2011-10-15 01:54:43 +00:00
/// </summary>
2008-11-25 17:01:18 +00:00
public IEntityInventory Inventory
{
get { return m_inventory ; }
2009-09-30 16:00:09 +00:00
}
2008-11-25 17:01:18 +00:00
protected SceneObjectPartInventory m_inventory ;
2008-08-18 00:39:10 +00:00
2009-10-25 07:40:21 +00:00
public bool Undoing ;
2010-10-17 17:41:38 +00:00
2010-02-14 21:41:57 +00:00
public bool IgnoreUndoUpdate = false ;
2010-10-17 17:41:38 +00:00
2012-01-19 11:03:22 +00:00
public PrimFlags LocalFlags ;
2010-10-17 17:41:38 +00:00
2009-07-15 00:10:01 +00:00
private float m_damage = - 1.0f ;
2008-06-27 19:21:15 +00:00
private byte [ ] m_TextureAnimation ;
2009-10-25 07:40:21 +00:00
private byte m_clickAction ;
2008-06-27 19:21:15 +00:00
private Color m_color = Color . Black ;
2008-07-26 21:22:15 +00:00
private readonly List < uint > m_lastColliders = new List < uint > ( ) ;
2009-10-25 07:40:21 +00:00
private int m_linkNum ;
2010-10-17 17:41:38 +00:00
2009-10-25 07:40:21 +00:00
private int m_scriptAccessPin ;
2010-10-17 17:41:38 +00:00
2008-09-06 07:52:41 +00:00
private readonly Dictionary < UUID , scriptEvents > m_scriptEvents = new Dictionary < UUID , scriptEvents > ( ) ;
2008-06-27 19:21:15 +00:00
private string m_sitName = String . Empty ;
2008-09-06 07:52:41 +00:00
private Quaternion m_sitTargetOrientation = Quaternion . Identity ;
2009-10-25 07:40:21 +00:00
private Vector3 m_sitTargetPosition ;
2008-11-04 16:39:28 +00:00
private string m_sitAnimation = "SIT" ;
2008-06-27 19:21:15 +00:00
private string m_text = String . Empty ;
private string m_touchName = String . Empty ;
2012-09-26 21:49:44 +00:00
private readonly List < UndoState > m_undo = new List < UndoState > ( 5 ) ;
private readonly List < UndoState > m_redo = new List < UndoState > ( 5 ) ;
2008-05-01 18:04:42 +00:00
2012-05-15 00:02:38 +00:00
private bool m_passTouches = false ;
private bool m_passCollisions = false ;
2009-05-27 18:01:06 +00:00
2008-09-06 07:52:41 +00:00
protected Vector3 m_acceleration ;
protected Vector3 m_angularVelocity ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
//unkown if this will be kept, added as a way of removing the group position from the group class
2008-09-06 07:52:41 +00:00
protected Vector3 m_groupPosition ;
2008-05-01 18:04:42 +00:00
protected uint m_localId ;
2009-10-25 07:40:21 +00:00
protected Material m_material = OpenMetaverse . Material . Wood ;
2008-05-01 18:04:42 +00:00
protected string m_name ;
2008-09-06 07:52:41 +00:00
protected Vector3 m_offsetPosition ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
protected SceneObjectGroup m_parentGroup ;
2009-10-25 07:40:21 +00:00
protected byte [ ] m_particleSystem = Utils . EmptyBytes ;
2008-06-27 19:21:15 +00:00
protected ulong m_regionHandle ;
2009-11-05 00:19:56 +00:00
protected Quaternion m_rotationOffset = Quaternion . Identity ;
2009-10-25 07:40:21 +00:00
protected PrimitiveBaseShape m_shape ;
2008-09-06 07:52:41 +00:00
protected UUID m_uuid ;
protected Vector3 m_velocity ;
2008-05-01 18:04:42 +00:00
2009-10-27 01:22:32 +00:00
protected Vector3 m_lastPosition ;
protected Quaternion m_lastRotation ;
protected Vector3 m_lastVelocity ;
protected Vector3 m_lastAcceleration ;
protected Vector3 m_lastAngularVelocity ;
2009-10-28 10:21:53 +00:00
protected int m_lastTerseSent ;
2010-07-01 21:52:31 +00:00
/// <summary>
/// Stores media texture data
/// </summary>
protected string m_mediaUrl ;
2009-10-27 01:22:32 +00:00
2008-08-01 02:33:28 +00:00
// TODO: Those have to be changed into persistent properties at some later point,
2008-08-18 00:39:10 +00:00
// or sit-camera on vehicles will break on sim-crossing.
2009-10-25 07:40:21 +00:00
private Vector3 m_cameraEyeOffset ;
private Vector3 m_cameraAtOffset ;
private bool m_forceMouselook ;
2008-08-18 00:39:10 +00:00
2008-11-19 18:30:16 +00:00
// TODO: Collision sound should have default.
2009-10-25 07:40:21 +00:00
private UUID m_collisionSound ;
private float m_collisionSoundVolume ;
2008-11-19 18:30:16 +00:00
2008-06-27 19:21:15 +00:00
#endregion Fields
2007-08-01 18:04:31 +00:00
2011-06-10 19:40:14 +00:00
// ~SceneObjectPart()
// {
2012-02-15 01:45:25 +00:00
// Console.WriteLine(
// "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}",
// Name, LocalId, ParentGroup.Name, ParentGroup.LocalId);
2011-06-10 19:40:14 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}",
// Name, LocalId, ParentGroup.Name, ParentGroup.LocalId);
// }
2008-06-27 19:21:15 +00:00
#region Constructors
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// No arg constructor called by region restore db code
/// </summary>
public SceneObjectPart ( )
2007-08-01 16:50:20 +00:00
{
2009-10-25 07:40:21 +00:00
m_TextureAnimation = Utils . EmptyBytes ;
m_particleSystem = Utils . EmptyBytes ;
Rezzed = DateTime . UtcNow ;
2011-11-21 17:51:38 +00:00
Description = String . Empty ;
2010-08-16 21:21:46 +00:00
DynAttrs = new DAMap ( ) ;
2011-11-21 17:55:10 +00:00
// 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
2008-11-25 17:01:18 +00:00
m_inventory = new SceneObjectPartInventory ( this ) ;
2007-08-01 16:50:20 +00:00
}
2008-05-01 18:04:42 +00:00
/// <summary>
2008-11-10 18:10:00 +00:00
/// Create a completely new SceneObjectPart (prim). This will need to be added separately to a SceneObjectGroup
2008-05-01 18:04:42 +00:00
/// </summary>
2008-06-27 19:21:15 +00:00
/// <param name="ownerID"></param>
/// <param name="shape"></param>
/// <param name="position"></param>
2008-11-06 22:21:25 +00:00
/// <param name="rotationOffset"></param>
/// <param name="offsetPosition"></param>
2008-11-07 21:07:14 +00:00
public SceneObjectPart (
2008-11-10 18:10:00 +00:00
UUID ownerID , PrimitiveBaseShape shape , Vector3 groupPosition ,
2011-11-21 17:55:10 +00:00
Quaternion rotationOffset , Vector3 offsetPosition ) : this ( )
2008-05-01 18:04:42 +00:00
{
2008-06-27 19:21:15 +00:00
m_name = "Primitive" ;
2008-05-16 01:22:11 +00:00
2011-11-11 01:21:37 +00:00
CreationDate = ( int ) Utils . DateTimeToUnixTime ( Rezzed ) ;
LastOwnerID = CreatorID = OwnerID = ownerID ;
2008-09-06 07:52:41 +00:00
UUID = UUID . Random ( ) ;
2008-06-27 19:21:15 +00:00
Shape = shape ;
2011-11-11 01:21:37 +00:00
OwnershipCost = 0 ;
ObjectSaleType = 0 ;
SalePrice = 0 ;
Category = 0 ;
2008-06-27 19:21:15 +00:00
GroupPosition = groupPosition ;
OffsetPosition = offsetPosition ;
RotationOffset = rotationOffset ;
2009-10-25 07:40:21 +00:00
Velocity = Vector3 . Zero ;
AngularVelocity = Vector3 . Zero ;
Acceleration = Vector3 . Zero ;
2010-08-10 16:26:31 +00:00
Flags = 0 ;
2010-06-01 00:45:14 +00:00
CreateSelected = true ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
TrimPermissions ( ) ;
2008-05-01 18:04:42 +00:00
}
2008-06-27 19:21:15 +00:00
#endregion Constructors
2008-06-29 02:04:44 +00:00
#region XML Schema
2008-06-27 19:21:15 +00:00
2008-09-06 07:52:41 +00:00
private UUID _lastOwnerID ;
private UUID _ownerID ;
private UUID _groupID ;
2008-07-02 20:31:17 +00:00
private int _ownershipCost ;
private byte _objectSaleType ;
private int _salePrice ;
private uint _category ;
private Int32 _creationDate ;
private uint _parentID = 0 ;
private uint _baseMask = ( uint ) PermissionMask . All ;
private uint _ownerMask = ( uint ) PermissionMask . All ;
private uint _groupMask = ( uint ) PermissionMask . None ;
private uint _everyoneMask = ( uint ) PermissionMask . None ;
private uint _nextOwnerMask = ( uint ) PermissionMask . All ;
2010-08-10 16:26:31 +00:00
private PrimFlags _flags = PrimFlags . None ;
2008-10-03 15:32:44 +00:00
private DateTime m_expires ;
2008-10-18 05:51:36 +00:00
private DateTime m_rezzed ;
2010-06-01 00:45:14 +00:00
private bool m_createSelected = false ;
2008-08-18 00:39:10 +00:00
2011-11-11 01:21:37 +00:00
private UUID _creatorID ;
2008-11-06 22:21:25 +00:00
public UUID CreatorID
{
2011-11-11 01:21:37 +00:00
get { return _creatorID ; }
set { _creatorID = value ; }
2008-06-29 02:04:44 +00:00
}
2008-05-01 18:04:42 +00:00
2011-11-11 01:21:37 +00:00
private string m_creatorData = string . Empty ;
2010-12-02 00:01:22 +00:00
/// <summary>
2012-01-12 17:56:35 +00:00
/// Data about the creator in the form home_url;name
2010-12-02 00:01:22 +00:00
/// </summary>
public string CreatorData
2010-11-21 21:16:52 +00:00
{
get { return m_creatorData ; }
set { m_creatorData = value ; }
}
2010-11-22 01:19:24 +00:00
/// <summary>
/// Used by the DB layer to retrieve / store the entire user identification.
/// The identification can either be a simple UUID or a string of the form
2012-01-12 17:56:35 +00:00
/// uuid[;home_url[;name]]
2010-11-22 01:19:24 +00:00
/// </summary>
2010-11-21 21:16:52 +00:00
public string CreatorIdentification
{
get
{
2011-11-11 01:21:37 +00:00
if ( CreatorData ! = null & & CreatorData ! = string . Empty )
return CreatorID . ToString ( ) + ';' + CreatorData ;
2010-11-21 21:16:52 +00:00
else
2011-11-11 01:21:37 +00:00
return CreatorID . ToString ( ) ;
2010-11-21 21:16:52 +00:00
}
set
{
if ( ( value = = null ) | | ( value ! = null & & value = = string . Empty ) )
{
2011-11-11 01:21:37 +00:00
CreatorData = string . Empty ;
2010-11-21 21:16:52 +00:00
return ;
}
if ( ! value . Contains ( ";" ) ) // plain UUID
{
UUID uuid = UUID . Zero ;
UUID . TryParse ( value , out uuid ) ;
2011-11-11 01:21:37 +00:00
CreatorID = uuid ;
2010-11-21 21:16:52 +00:00
}
else // <uuid>[;<endpoint>[;name]]
{
string name = "Unknown User" ;
string [ ] parts = value . Split ( ';' ) ;
if ( parts . Length > = 1 )
{
UUID uuid = UUID . Zero ;
UUID . TryParse ( parts [ 0 ] , out uuid ) ;
2011-11-11 01:21:37 +00:00
CreatorID = uuid ;
2010-11-21 21:16:52 +00:00
}
if ( parts . Length > = 2 )
2011-11-11 01:21:37 +00:00
CreatorData = parts [ 1 ] ;
2010-11-21 21:16:52 +00:00
if ( parts . Length > = 3 )
name = parts [ 2 ] ;
2011-11-11 01:21:37 +00:00
CreatorData + = ';' + name ;
2010-11-21 21:16:52 +00:00
}
}
}
2008-06-29 02:04:44 +00:00
/// <summary>
2009-02-25 11:01:38 +00:00
/// A relic from when we we thought that prims contained folder objects. In
2009-10-01 00:38:36 +00:00
/// reality, prim == folder
2008-06-29 02:04:44 +00:00
/// Exposing this is not particularly good, but it's one of the least evils at the moment to see
/// folder id from prim inventory item data, since it's not (yet) actually stored with the prim.
/// </summary>
2008-09-06 07:52:41 +00:00
public UUID FolderID
2008-06-29 02:04:44 +00:00
{
get { return UUID ; }
2009-02-25 11:01:38 +00:00
set { } // Don't allow assignment, or legacy prims wil b0rk - but we need the setter for legacy serialization.
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2008-11-21 21:16:42 +00:00
/// <value>
/// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
/// </value>
2008-06-29 02:04:44 +00:00
public uint InventorySerial
2008-06-27 19:21:15 +00:00
{
2008-11-25 17:01:18 +00:00
get { return m_inventory . Serial ; }
set { m_inventory . Serial = value ; }
2008-06-27 19:21:15 +00:00
}
2008-05-16 01:22:11 +00:00
2008-11-21 21:16:42 +00:00
/// <value>
/// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
2009-09-30 16:00:09 +00:00
/// </value>
2008-06-29 02:04:44 +00:00
public TaskInventoryDictionary TaskInventory
2008-06-27 19:21:15 +00:00
{
2008-11-25 17:15:21 +00:00
get { return m_inventory . Items ; }
set { m_inventory . Items = value ; }
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2010-08-10 16:26:31 +00:00
/// <summary>
/// This is idential to the Flags property, except that the returned value is uint rather than PrimFlags
/// </summary>
[Obsolete("Use Flags property instead")]
2008-06-29 02:04:44 +00:00
public uint ObjectFlags
2008-06-27 19:21:15 +00:00
{
2010-08-10 16:26:31 +00:00
get { return ( uint ) Flags ; }
set { Flags = ( PrimFlags ) value ; }
2008-08-18 00:39:10 +00:00
}
2008-09-06 07:52:41 +00:00
public UUID UUID
2008-06-29 02:04:44 +00:00
{
get { return m_uuid ; }
2010-09-07 02:41:29 +00:00
set
{
m_uuid = value ;
// This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part
if ( Inventory ! = null )
2010-09-16 21:12:32 +00:00
Inventory . ResetObjectID ( ) ;
2010-09-07 02:41:29 +00:00
}
2008-05-01 18:04:42 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-29 02:04:44 +00:00
public uint LocalId
{
get { return m_localId ; }
2011-11-16 23:01:59 +00:00
set
{
m_localId = value ;
// m_log.DebugFormat("[SCENE OBJECT PART]: Set part {0} to local id {1}", Name, m_localId);
}
2008-06-27 23:22:14 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-29 02:04:44 +00:00
public virtual string Name
2008-05-01 18:04:42 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_name ; }
2008-12-26 12:58:02 +00:00
set
{
m_name = value ;
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . SOPName = value ;
2008-12-26 12:58:02 +00:00
}
2008-06-29 02:04:44 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-29 02:04:44 +00:00
public byte Material
{
get { return ( byte ) m_material ; }
2009-04-20 03:07:53 +00:00
set
{
m_material = ( Material ) value ;
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . SetMaterial ( ( int ) value ) ;
2009-04-20 03:07:53 +00:00
}
2008-06-29 02:04:44 +00:00
}
2008-06-27 19:21:15 +00:00
2012-05-15 00:02:38 +00:00
[XmlIgnore]
2009-05-27 18:01:06 +00:00
public bool PassTouches
{
get { return m_passTouches ; }
set
{
m_passTouches = value ;
2011-09-01 00:22:28 +00:00
2009-05-27 18:01:06 +00:00
if ( ParentGroup ! = null )
ParentGroup . HasGroupChanged = true ;
}
}
2012-05-15 00:02:38 +00:00
public bool PassCollisions
{
get { return m_passCollisions ; }
set
{
m_passCollisions = value ;
if ( ParentGroup ! = null )
ParentGroup . HasGroupChanged = true ;
}
}
2009-12-31 17:41:07 +00:00
public Dictionary < int , string > CollisionFilter
{
get { return m_CollisionFilter ; }
set
{
m_CollisionFilter = value ;
}
}
2012-01-13 22:48:56 +00:00
protected Quaternion APIDTarget
2010-02-14 21:41:57 +00:00
{
get { return m_APIDTarget ; }
set { m_APIDTarget = value ; }
}
2010-10-17 17:41:38 +00:00
2012-01-13 22:48:56 +00:00
protected float APIDDamp
2010-02-14 21:41:57 +00:00
{
get { return m_APIDDamp ; }
set { m_APIDDamp = value ; }
}
2010-10-17 17:41:38 +00:00
2012-01-13 22:48:56 +00:00
protected float APIDStrength
2010-02-14 21:41:57 +00:00
{
get { return m_APIDStrength ; }
set { m_APIDStrength = value ; }
}
2008-06-29 02:04:44 +00:00
public ulong RegionHandle
{
get { return m_regionHandle ; }
set { m_regionHandle = value ; }
2008-06-27 19:21:15 +00:00
}
2008-06-29 02:04:44 +00:00
public int ScriptAccessPin
2008-06-27 19:21:15 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_scriptAccessPin ; }
set { m_scriptAccessPin = ( int ) value ; }
2008-05-01 18:04:42 +00:00
}
2010-02-14 21:41:57 +00:00
private SceneObjectPart m_PlaySoundMasterPrim = null ;
public SceneObjectPart PlaySoundMasterPrim
{
get { return m_PlaySoundMasterPrim ; }
set { m_PlaySoundMasterPrim = value ; }
}
private List < SceneObjectPart > m_PlaySoundSlavePrims = new List < SceneObjectPart > ( ) ;
public List < SceneObjectPart > PlaySoundSlavePrims
{
2010-03-03 23:40:32 +00:00
get { return m_PlaySoundSlavePrims ; }
set { m_PlaySoundSlavePrims = value ; }
2010-02-14 21:41:57 +00:00
}
private SceneObjectPart m_LoopSoundMasterPrim = null ;
public SceneObjectPart LoopSoundMasterPrim
{
get { return m_LoopSoundMasterPrim ; }
set { m_LoopSoundMasterPrim = value ; }
}
private List < SceneObjectPart > m_LoopSoundSlavePrims = new List < SceneObjectPart > ( ) ;
public List < SceneObjectPart > LoopSoundSlavePrims
{
get { return m_LoopSoundSlavePrims ; }
set { m_LoopSoundSlavePrims = value ; }
}
2008-05-01 18:04:42 +00:00
2010-10-17 17:41:38 +00:00
2008-08-24 05:25:26 +00:00
public Byte [ ] TextureAnimation
{
get { return m_TextureAnimation ; }
set { m_TextureAnimation = value ; }
}
2010-10-17 17:41:38 +00:00
2008-09-08 02:40:20 +00:00
public Byte [ ] ParticleSystem
{
get { return m_particleSystem ; }
set { m_particleSystem = value ; }
}
2010-10-17 17:41:38 +00:00
2008-10-03 15:32:44 +00:00
public DateTime Expires
{
get { return m_expires ; }
set { m_expires = value ; }
}
2010-10-17 17:41:38 +00:00
2008-10-18 05:51:36 +00:00
public DateTime Rezzed
{
get { return m_rezzed ; }
set { m_rezzed = value ; }
}
2010-10-17 17:41:38 +00:00
2009-07-15 00:10:01 +00:00
public float Damage
{
get { return m_damage ; }
set { m_damage = value ; }
}
2008-09-12 00:37:59 +00:00
/// <summary>
/// The position of the entire group that this prim belongs to.
/// </summary>
2008-09-06 07:52:41 +00:00
public Vector3 GroupPosition
2007-08-07 17:22:15 +00:00
{
2007-12-04 13:46:18 +00:00
get
2007-11-03 19:33:00 +00:00
{
2008-01-15 14:39:35 +00:00
// If this is a linkset, we don't want the physics engine mucking up our group position here.
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
2012-07-11 23:07:14 +00:00
// If physical and the root prim of a linkset, the position of the group is what physics thinks.
2011-11-11 01:21:37 +00:00
if ( actor ! = null & & ParentID = = 0 )
2009-11-02 19:40:57 +00:00
m_groupPosition = actor . Position ;
2008-11-17 05:57:58 +00:00
2012-07-11 23:07:14 +00:00
// If I'm an attachment, my position is reported as the position of who I'm attached to
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsAttachment )
2008-04-25 21:41:55 +00:00
{
2011-11-11 01:21:37 +00:00
ScenePresence sp = ParentGroup . Scene . GetScenePresence ( ParentGroup . AttachedAvatar ) ;
2008-11-17 05:57:58 +00:00
if ( sp ! = null )
return sp . AbsolutePosition ;
2008-04-25 21:41:55 +00:00
}
2007-12-04 13:46:18 +00:00
return m_groupPosition ;
2007-11-03 19:33:00 +00:00
}
2007-12-04 13:46:18 +00:00
set
2008-04-28 01:48:21 +00:00
{
2008-01-14 18:29:04 +00:00
m_groupPosition = value ;
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
if ( actor ! = null )
2007-11-03 19:33:00 +00:00
{
try
{
2008-01-15 14:39:35 +00:00
// Root prim actually goes at Position
2011-11-11 01:21:37 +00:00
if ( ParentID = = 0 )
2008-01-14 18:29:04 +00:00
{
2009-11-02 19:40:57 +00:00
actor . Position = value ;
2008-01-14 18:29:04 +00:00
}
else
{
2012-07-11 23:07:14 +00:00
// The physics engine always sees all objects (root or linked) in world coordinates.
2009-11-02 19:40:57 +00:00
actor . Position = GetWorldPosition ( ) ;
actor . Orientation = GetWorldRotation ( ) ;
2008-01-14 18:29:04 +00:00
}
2008-05-16 01:22:11 +00:00
2008-01-15 14:39:35 +00:00
// Tell the physics engines that this prim changed.
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( actor ) ;
2007-11-03 19:33:00 +00:00
}
catch ( Exception e )
{
2012-08-15 23:39:00 +00:00
m_log . ErrorFormat ( "[SCENEOBJECTPART]: GROUP POSITION. {0}" , e ) ;
2007-11-03 19:33:00 +00:00
}
}
2008-09-13 18:42:09 +00:00
// TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
2012-07-10 22:39:05 +00:00
if ( SitTargetAvatar ! = UUID . Zero )
2008-09-13 22:07:07 +00:00
{
2011-09-01 00:22:28 +00:00
ScenePresence avatar ;
2011-11-11 01:21:37 +00:00
if ( ParentGroup . Scene . TryGetScenePresence ( SitTargetAvatar , out avatar ) )
2008-09-13 18:42:09 +00:00
{
2011-09-01 00:22:28 +00:00
avatar . ParentPosition = GetWorldPosition ( ) ;
2008-09-13 18:42:09 +00:00
}
}
2007-11-03 19:33:00 +00:00
}
2007-08-07 17:22:15 +00:00
}
2008-09-06 07:52:41 +00:00
public Vector3 OffsetPosition
2007-07-30 20:11:40 +00:00
{
2007-08-16 17:08:03 +00:00
get { return m_offsetPosition ; }
2008-04-28 01:48:21 +00:00
set
{
2011-07-19 04:46:17 +00:00
// StoreUndoState();
2008-04-28 01:48:21 +00:00
m_offsetPosition = value ;
2008-10-11 23:47:35 +00:00
2008-11-17 15:40:27 +00:00
if ( ParentGroup ! = null & & ! ParentGroup . IsDeleted )
2008-10-11 23:47:35 +00:00
{
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
2011-11-11 01:21:37 +00:00
if ( ParentID ! = 0 & & actor ! = null )
2008-10-11 23:59:46 +00:00
{
2009-11-02 19:40:57 +00:00
actor . Position = GetWorldPosition ( ) ;
actor . Orientation = GetWorldRotation ( ) ;
2008-10-11 23:47:35 +00:00
2008-10-11 23:59:46 +00:00
// Tell the physics engines that this prim changed.
2011-11-11 01:21:37 +00:00
if ( ParentGroup . Scene ! = null )
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( actor ) ;
2008-10-11 23:59:46 +00:00
}
2008-10-11 23:47:35 +00:00
}
2008-01-14 18:29:04 +00:00
}
2007-08-16 17:08:03 +00:00
}
2010-05-12 22:59:48 +00:00
public Vector3 RelativePosition
{
get
{
if ( IsRoot )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsAttachment )
2010-05-12 22:59:48 +00:00
return AttachedPos ;
else
return AbsolutePosition ;
}
else
{
return OffsetPosition ;
}
}
}
2008-09-06 07:52:41 +00:00
public Quaternion RotationOffset
2007-07-30 20:11:40 +00:00
{
2007-12-04 13:46:18 +00:00
get
2007-11-03 19:33:00 +00:00
{
2008-01-15 14:39:35 +00:00
// We don't want the physics engine mucking up the rotations in a linkset
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
2012-07-11 23:07:14 +00:00
// If this is a root of a linkset, the real rotation is what the physics engine thinks.
// If not a root prim, the offset rotation is computed by SOG and is relative to the root.
2011-11-11 01:21:37 +00:00
if ( ParentID = = 0 & & ( Shape . PCode ! = 9 | | Shape . State = = 0 ) & & actor ! = null )
2007-11-03 19:33:00 +00:00
{
2009-11-02 19:40:57 +00:00
if ( actor . Orientation . X ! = 0f | | actor . Orientation . Y ! = 0f
| | actor . Orientation . Z ! = 0f | | actor . Orientation . W ! = 0f )
2007-11-03 20:50:11 +00:00
{
2009-11-02 19:40:57 +00:00
m_rotationOffset = actor . Orientation ;
2007-11-03 20:50:11 +00:00
}
2007-11-03 19:33:00 +00:00
}
2011-10-28 22:15:51 +00:00
// float roll, pitch, yaw = 0;
// m_rotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
/ /
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Got euler {0} for RotationOffset on {1} {2}",
// new Vector3(roll, pitch, yaw), Name, LocalId);
2007-12-04 13:46:18 +00:00
return m_rotationOffset ;
2007-11-03 19:33:00 +00:00
}
2009-05-29 20:20:47 +00:00
2007-12-04 13:46:18 +00:00
set
2007-11-03 19:33:00 +00:00
{
2008-04-28 01:48:21 +00:00
StoreUndoState ( ) ;
2008-01-14 18:29:04 +00:00
m_rotationOffset = value ;
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
if ( actor ! = null )
2007-11-03 19:33:00 +00:00
{
try
{
2008-01-15 14:39:35 +00:00
// Root prim gets value directly
2011-11-11 01:21:37 +00:00
if ( ParentID = = 0 )
2008-01-14 18:29:04 +00:00
{
2009-11-02 19:40:57 +00:00
actor . Orientation = value ;
//m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
2008-01-14 18:29:04 +00:00
}
else
{
2008-01-16 02:48:39 +00:00
// Child prim we have to calculate it's world rotationwel
2008-09-06 07:52:41 +00:00
Quaternion resultingrotation = GetWorldRotation ( ) ;
2009-11-02 19:40:57 +00:00
actor . Orientation = resultingrotation ;
//m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
2008-01-14 18:29:04 +00:00
}
2011-09-01 00:22:28 +00:00
2011-11-11 01:21:37 +00:00
if ( ParentGroup ! = null )
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( actor ) ;
2007-11-03 19:33:00 +00:00
//}
}
catch ( Exception ex )
{
2009-02-22 20:52:55 +00:00
m_log . Error ( "[SCENEOBJECTPART]: ROTATIONOFFSET" + ex . Message ) ;
2007-11-03 19:33:00 +00:00
}
}
2011-10-28 22:15:51 +00:00
// float roll, pitch, yaw = 0;
// m_rotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
/ /
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Set euler {0} for RotationOffset on {1} {2}",
// new Vector3(roll, pitch, yaw), Name, LocalId);
2007-11-03 19:33:00 +00:00
}
2007-07-30 20:11:40 +00:00
}
2008-06-29 02:04:44 +00:00
/// <summary></summary>
2008-09-06 07:52:41 +00:00
public Vector3 Velocity
2007-08-01 16:50:20 +00:00
{
2007-12-04 13:46:18 +00:00
get
{
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
if ( actor ! = null )
2007-11-04 14:06:41 +00:00
{
2009-11-02 19:40:57 +00:00
if ( actor . IsPhysical )
2007-11-04 14:06:41 +00:00
{
2009-11-02 19:40:57 +00:00
m_velocity = actor . Velocity ;
2007-11-04 14:06:41 +00:00
}
}
2007-12-04 13:46:18 +00:00
2008-06-29 02:04:44 +00:00
return m_velocity ;
2008-02-12 07:32:32 +00:00
}
2007-12-27 21:41:48 +00:00
2008-06-27 19:21:15 +00:00
set
2007-11-08 00:10:40 +00:00
{
2008-06-29 02:04:44 +00:00
m_velocity = value ;
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
if ( actor ! = null )
2007-11-08 00:10:40 +00:00
{
2009-11-02 19:40:57 +00:00
if ( actor . IsPhysical )
2007-11-08 00:10:40 +00:00
{
2009-11-02 19:40:57 +00:00
actor . Velocity = value ;
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( actor ) ;
2007-11-08 00:10:40 +00:00
}
}
}
}
2011-11-02 21:59:00 +00:00
/// <summary>Update angular velocity and schedule terse update.</summary>
public void UpdateAngularVelocity ( Vector3 avel )
{
AngularVelocity = avel ;
ScheduleTerseUpdate ( ) ;
ParentGroup . HasGroupChanged = true ;
}
/// <summary>Get or set angular velocity. Does not schedule update.</summary>
2008-09-06 07:52:41 +00:00
public Vector3 AngularVelocity
2008-06-27 19:21:15 +00:00
{
2008-08-18 00:39:10 +00:00
get
{
2009-11-02 19:40:57 +00:00
PhysicsActor actor = PhysActor ;
if ( ( actor ! = null ) & & actor . IsPhysical )
2008-07-01 21:31:02 +00:00
{
2009-11-02 19:40:57 +00:00
m_angularVelocity = actor . RotationalVelocity ;
2008-07-01 21:31:02 +00:00
}
2008-08-18 00:39:10 +00:00
return m_angularVelocity ;
2008-07-01 21:31:02 +00:00
}
2008-06-29 02:04:44 +00:00
set { m_angularVelocity = value ; }
2008-06-27 19:21:15 +00:00
}
2008-06-29 02:04:44 +00:00
/// <summary></summary>
2008-09-06 07:52:41 +00:00
public Vector3 Acceleration
2008-06-27 19:21:15 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_acceleration ; }
set { m_acceleration = value ; }
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2011-11-21 17:51:38 +00:00
public string Description { get ; set ; }
2008-08-18 00:39:10 +00:00
2010-02-01 21:35:05 +00:00
/// <value>
/// Text color.
/// </value>
2008-06-29 02:04:44 +00:00
public Color Color
2007-12-27 05:37:48 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_color ; }
2012-01-19 11:03:22 +00:00
set { m_color = value ; }
2007-12-27 05:37:48 +00:00
}
2007-08-02 16:40:50 +00:00
public string Text
{
2008-05-29 16:21:41 +00:00
get
{
2012-01-19 11:03:22 +00:00
if ( m_text . Length > 255 )
return m_text . Substring ( 0 , 254 ) ;
return m_text ;
2008-05-01 18:04:42 +00:00
}
2012-01-19 11:03:22 +00:00
set { m_text = value ; }
2008-05-01 18:04:42 +00:00
}
2008-06-29 02:04:44 +00:00
public string SitName
{
get { return m_sitName ; }
set { m_sitName = value ; }
}
2008-05-01 18:04:42 +00:00
public string TouchName
{
get { return m_touchName ; }
set { m_touchName = value ; }
2007-08-02 16:40:50 +00:00
}
2008-06-29 02:04:44 +00:00
public int LinkNum
2007-12-17 02:30:03 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_linkNum ; }
2012-05-15 22:43:59 +00:00
set
{
// if (ParentGroup != null)
// {
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Setting linknum of {0}@{1} to {2} from {3}",
// Name, AbsolutePosition, value, m_linkNum);
// Util.PrintCallStack();
// }
m_linkNum = value ;
}
2007-12-17 02:30:03 +00:00
}
2008-06-29 02:04:44 +00:00
public byte ClickAction
2007-11-17 12:03:20 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_clickAction ; }
set
{
m_clickAction = value ;
}
2007-11-17 12:03:20 +00:00
}
2008-06-29 02:04:44 +00:00
public PrimitiveBaseShape Shape
2008-01-17 14:59:05 +00:00
{
2008-06-29 02:04:44 +00:00
get { return m_shape ; }
2011-11-04 00:06:08 +00:00
set { m_shape = value ; }
2008-06-29 02:04:44 +00:00
}
2011-07-18 03:54:21 +00:00
/// <summary>
/// Change the scale of this part.
/// </summary>
2008-09-06 07:52:41 +00:00
public Vector3 Scale
2008-06-29 02:04:44 +00:00
{
get { return m_shape . Scale ; }
set
2008-06-27 19:21:15 +00:00
{
2009-11-02 19:40:57 +00:00
if ( m_shape ! = null )
2008-03-24 22:48:34 +00:00
{
2011-07-18 03:54:21 +00:00
StoreUndoState ( ) ;
2009-11-02 19:40:57 +00:00
m_shape . Scale = value ;
PhysicsActor actor = PhysActor ;
2011-09-01 00:22:28 +00:00
if ( actor ! = null )
2008-06-27 19:21:15 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . Scene ! = null )
2008-06-29 02:04:44 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . Scene . PhysicsScene ! = null )
2009-11-02 19:40:57 +00:00
{
actor . Size = m_shape . Scale ;
2011-07-18 03:54:21 +00:00
2012-10-07 00:20:52 +00:00
// if (Shape.SculptEntry)
// CheckSculptAndLoad();
// else
2012-04-03 04:50:13 +00:00
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( actor ) ;
2009-11-02 19:40:57 +00:00
}
2008-06-29 02:04:44 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-03-24 22:48:34 +00:00
}
2011-07-18 03:54:21 +00:00
2008-06-29 02:04:44 +00:00
TriggerScriptChangedEvent ( Changed . SCALE ) ;
}
}
2011-11-02 21:59:00 +00:00
2011-12-14 05:37:17 +00:00
public UpdateRequired UpdateFlag { get ; set ; }
2010-07-01 18:25:46 +00:00
/// <summary>
2010-07-12 18:46:23 +00:00
/// Used for media on a prim.
2010-07-01 18:25:46 +00:00
/// </summary>
2010-07-12 18:46:23 +00:00
/// Do not change this value directly - always do it through an IMoapModule.
2010-07-01 21:52:31 +00:00
public string MediaUrl
{
get
{
return m_mediaUrl ;
}
2010-09-12 17:43:49 +00:00
set
{
2010-07-01 21:52:31 +00:00
m_mediaUrl = value ;
2011-09-01 00:22:28 +00:00
2010-07-01 21:52:31 +00:00
if ( ParentGroup ! = null )
2010-09-12 17:43:49 +00:00
ParentGroup . HasGroupChanged = true ;
2010-07-01 21:52:31 +00:00
}
}
2010-05-31 17:00:02 +00:00
public bool CreateSelected
{
get { return m_createSelected ; }
2010-08-10 19:15:44 +00:00
set
{
// m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID);
m_createSelected = value ;
}
2010-09-12 17:43:49 +00:00
}
2008-06-29 02:04:44 +00:00
# endregion
2008-08-18 00:39:10 +00:00
2008-06-29 02:04:44 +00:00
//---------------
2008-10-10 15:02:40 +00:00
#region Public Properties with only Get
2008-06-29 02:04:44 +00:00
2008-09-06 07:52:41 +00:00
public Vector3 AbsolutePosition
2008-06-29 02:04:44 +00:00
{
2011-06-24 20:54:01 +00:00
get
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsAttachment )
2008-06-29 02:04:44 +00:00
return GroupPosition ;
2011-06-24 20:54:01 +00:00
return m_offsetPosition + m_groupPosition ;
}
2008-06-29 02:04:44 +00:00
}
public SceneObjectGroup ParentGroup
{
get { return m_parentGroup ; }
2011-11-11 01:21:37 +00:00
private set { m_parentGroup = value ; }
2008-06-29 02:04:44 +00:00
}
public scriptEvents ScriptEvents
{
2008-07-26 21:22:15 +00:00
get { return AggregateScriptEvents ; }
2008-06-29 02:04:44 +00:00
}
public Quaternion SitTargetOrientation
{
get { return m_sitTargetOrientation ; }
2011-11-05 01:38:42 +00:00
set
{
m_sitTargetOrientation = value ;
// m_log.DebugFormat("[SCENE OBJECT PART]: Set sit target orientation {0} for {1} {2}", m_sitTargetOrientation, Name, LocalId);
}
2008-06-29 02:04:44 +00:00
}
public Vector3 SitTargetPosition
{
get { return m_sitTargetPosition ; }
2011-11-05 01:38:42 +00:00
set
{
m_sitTargetPosition = value ;
// m_log.DebugFormat("[SCENE OBJECT PART]: Set sit target position to {0} for {1} {2}", m_sitTargetPosition, Name, LocalId);
}
2008-07-03 18:25:18 +00:00
}
// This sort of sucks, but I'm adding these in to make some of
// the mappings more consistant.
2008-09-06 07:52:41 +00:00
public Vector3 SitTargetPositionLL
2008-07-03 18:25:18 +00:00
{
2008-09-06 07:52:41 +00:00
get { return new Vector3 ( m_sitTargetPosition . X , m_sitTargetPosition . Y , m_sitTargetPosition . Z ) ; }
set { m_sitTargetPosition = value ; }
2008-06-29 02:04:44 +00:00
}
2008-09-06 07:52:41 +00:00
public Quaternion SitTargetOrientationLL
2008-07-03 18:25:18 +00:00
{
2008-08-18 00:39:10 +00:00
get
{
2008-09-06 07:52:41 +00:00
return new Quaternion (
m_sitTargetOrientation . X ,
m_sitTargetOrientation . Y ,
m_sitTargetOrientation . Z ,
m_sitTargetOrientation . W
2008-07-03 18:25:18 +00:00
) ;
}
2008-09-08 19:57:28 +00:00
set { m_sitTargetOrientation = new Quaternion ( value . X , value . Y , value . Z , value . W ) ; }
2008-07-03 18:25:18 +00:00
}
2008-06-29 02:04:44 +00:00
public bool Stopped
{
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 ) ;
2008-01-17 14:59:05 +00:00
}
}
2012-04-06 21:41:35 +00:00
/// <summary>
/// The parent ID of this part.
/// </summary>
/// <remarks>
/// If this is a root part which is not attached to an avatar then the value will be 0.
/// If this is a root part which is attached to an avatar then the value is the local id of that avatar.
/// If this is a child part then the value is the local ID of the root part.
/// </remarks>
2008-08-18 00:39:10 +00:00
public uint ParentID
2008-07-12 21:43:35 +00:00
{
get { return _parentID ; }
set { _parentID = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public int CreationDate
2008-07-12 21:43:35 +00:00
{
get { return _creationDate ; }
set { _creationDate = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint Category
2008-07-12 21:43:35 +00:00
{
get { return _category ; }
set { _category = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public int SalePrice
2008-07-12 21:43:35 +00:00
{
get { return _salePrice ; }
set { _salePrice = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public byte ObjectSaleType
2008-07-12 21:43:35 +00:00
{
get { return _objectSaleType ; }
set { _objectSaleType = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public int OwnershipCost
2008-07-12 21:43:35 +00:00
{
get { return _ownershipCost ; }
set { _ownershipCost = value ; }
2008-07-02 20:31:17 +00:00
}
2008-09-06 07:52:41 +00:00
public UUID GroupID
2008-07-12 21:43:35 +00:00
{
get { return _groupID ; }
set { _groupID = value ; }
2008-07-02 20:31:17 +00:00
}
2008-09-06 07:52:41 +00:00
public UUID OwnerID
2008-07-12 21:43:35 +00:00
{
get { return _ownerID ; }
set { _ownerID = value ; }
2008-07-02 20:31:17 +00:00
}
2008-09-06 07:52:41 +00:00
public UUID LastOwnerID
2008-07-12 21:43:35 +00:00
{
get { return _lastOwnerID ; }
set { _lastOwnerID = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint BaseMask
2008-07-12 21:43:35 +00:00
{
get { return _baseMask ; }
set { _baseMask = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint OwnerMask
2008-07-12 21:43:35 +00:00
{
get { return _ownerMask ; }
set { _ownerMask = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint GroupMask
2008-07-12 21:43:35 +00:00
{
get { return _groupMask ; }
set { _groupMask = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint EveryoneMask
2008-07-12 21:43:35 +00:00
{
get { return _everyoneMask ; }
set { _everyoneMask = value ; }
2008-07-02 20:31:17 +00:00
}
2008-08-18 00:39:10 +00:00
public uint NextOwnerMask
2008-07-12 21:43:35 +00:00
{
get { return _nextOwnerMask ; }
set { _nextOwnerMask = value ; }
2008-07-02 20:31:17 +00:00
}
2010-08-06 23:45:04 +00:00
/// <summary>
/// Property flags. See OpenMetaverse.PrimFlags
2010-09-12 17:43:49 +00:00
/// </summary>
2011-07-11 01:09:11 +00:00
/// <remarks>
2010-08-06 23:45:04 +00:00
/// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge
2011-07-11 01:09:11 +00:00
/// </remarks>
2008-09-06 07:52:41 +00:00
public PrimFlags Flags
2008-07-12 21:43:35 +00:00
{
get { return _flags ; }
2010-08-10 16:26:31 +00:00
set
{
// m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
_flags = value ;
}
2008-07-02 20:31:17 +00:00
}
2011-10-17 01:04:20 +00:00
/// <summary>
2012-07-09 20:24:32 +00:00
/// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
2011-10-17 01:04:20 +00:00
/// </summary>
2012-07-09 20:24:32 +00:00
public UUID SitTargetAvatar { get ; set ; }
/// <summary>
2013-01-04 20:34:39 +00:00
/// IDs of all avatars sat on this part.
2012-07-09 20:24:32 +00:00
/// </summary>
/// <remarks>
/// We need to track this so that we can stop sat upon prims from being attached.
/// </remarks>
/// <value>
/// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
/// </value>
private HashSet < UUID > m_sittingAvatars ;
2008-07-14 21:39:30 +00:00
2008-09-06 07:52:41 +00:00
public virtual UUID RegionID
2008-07-14 21:39:30 +00:00
{
2008-08-18 00:39:10 +00:00
get
{
2011-09-01 00:22:28 +00:00
if ( ParentGroup . Scene ! = null )
2008-07-23 22:14:35 +00:00
return ParentGroup . Scene . RegionInfo . RegionID ;
else
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2008-07-23 22:14:35 +00:00
}
2008-07-16 21:27:52 +00:00
set { } // read only
2008-07-14 21:39:30 +00:00
}
2008-07-16 21:27:57 +00:00
2008-09-06 07:52:41 +00:00
private UUID _parentUUID = UUID . Zero ;
2010-10-17 17:41:38 +00:00
2008-09-06 07:52:41 +00:00
public UUID ParentUUID
2008-07-15 18:57:18 +00:00
{
2008-08-18 00:39:10 +00:00
get
2008-07-16 21:27:57 +00:00
{
2008-08-18 00:39:10 +00:00
if ( ParentGroup ! = null )
2008-07-16 21:27:57 +00:00
_parentUUID = ParentGroup . UUID ;
2011-09-01 00:22:28 +00:00
2008-07-16 21:27:57 +00:00
return _parentUUID ;
}
2011-09-01 00:22:28 +00:00
2008-07-16 21:27:57 +00:00
set { _parentUUID = value ; }
2008-07-15 18:57:18 +00:00
}
2010-10-17 17:41:38 +00:00
2008-11-04 16:39:28 +00:00
public string SitAnimation
{
get { return m_sitAnimation ; }
set { m_sitAnimation = value ; }
}
2008-11-19 18:30:16 +00:00
public UUID CollisionSound
{
get { return m_collisionSound ; }
set
{
m_collisionSound = value ;
aggregateScriptEvents ( ) ;
}
}
public float CollisionSoundVolume
{
get { return m_collisionSoundVolume ; }
set { m_collisionSoundVolume = value ; }
}
2008-06-29 02:04:44 +00:00
#endregion Public Properties with only Get
2008-06-27 19:21:15 +00:00
private uint ApplyMask ( uint val , bool set , uint mask )
2008-03-25 03:36:31 +00:00
{
2008-06-27 19:21:15 +00:00
if ( set )
2008-03-25 03:36:31 +00:00
{
2008-06-27 19:21:15 +00:00
return val | = mask ;
2008-03-25 03:36:31 +00:00
}
else
{
2008-06-27 19:21:15 +00:00
return val & = ~ mask ;
2008-03-25 03:36:31 +00:00
}
}
2008-06-27 19:21:15 +00:00
/// <summary>
2008-07-12 21:43:35 +00:00
/// Clear all pending updates of parts to clients
2008-06-27 19:21:15 +00:00
/// </summary>
2011-11-02 21:59:00 +00:00
public void ClearUpdateSchedule ( )
2008-01-17 02:23:48 +00:00
{
2011-11-02 21:59:00 +00:00
UpdateFlag = UpdateRequired . NONE ;
2008-05-01 18:04:42 +00:00
}
2008-05-01 16:35:00 +00:00
2011-09-15 17:58:58 +00:00
/// <summary>
/// Send this part's properties (name, description, inventory serial, base mask, etc.) to a client
/// </summary>
/// <param name="client"></param>
public void SendPropertiesToClient ( IClientAPI client )
{
client . SendObjectPropertiesReply ( this ) ;
}
2009-08-13 06:43:24 +00:00
// TODO: unused:
// private void handleTimerAccounting(uint localID, double interval)
// {
// if (localID == LocalId)
// {
// float sec = (float)interval;
// if (m_parentGroup != null)
// {
// if (sec == 0)
// {
// 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);
// }
// }
// }
2007-09-19 00:30:55 +00:00
2008-06-27 19:21:15 +00:00
#region Public Methods
2008-12-19 18:38:45 +00:00
public void ResetExpire ( )
{
Expires = DateTime . Now + new TimeSpan ( 600000000 ) ;
}
2008-09-06 07:52:41 +00:00
public void AddFlag ( PrimFlags flag )
2008-05-01 18:04:42 +00:00
{
2008-09-06 07:52:41 +00:00
// PrimFlags prevflag = Flags;
2010-08-13 19:23:53 +00:00
if ( ( Flags & flag ) = = 0 )
2008-06-27 19:21:15 +00:00
{
2009-02-22 20:52:55 +00:00
//m_log.Debug("Adding flag: " + ((PrimFlags) flag).ToString());
2010-08-10 16:26:31 +00:00
Flags | = flag ;
2008-10-03 15:32:44 +00:00
if ( flag = = PrimFlags . TemporaryOnRez )
2008-12-19 18:38:45 +00:00
ResetExpire ( ) ;
2008-05-01 18:04:42 +00:00
}
2009-02-22 20:52:55 +00:00
// m_log.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
2008-05-01 18:04:42 +00:00
}
2008-01-08 21:56:52 +00:00
2008-06-27 19:21:15 +00:00
public void AddNewParticleSystem ( Primitive . ParticleSystem pSystem )
2007-11-03 19:33:00 +00:00
{
2008-06-27 19:21:15 +00:00
m_particleSystem = pSystem . GetBytes ( ) ;
2007-09-11 14:18:34 +00:00
}
2008-08-08 15:16:30 +00:00
public void RemoveParticleSystem ( )
{
m_particleSystem = new byte [ 0 ] ;
}
2008-06-27 19:21:15 +00:00
public void AddTextureAnimation ( Primitive . TextureAnimation pTexAnim )
2007-09-19 00:30:55 +00:00
{
2008-06-27 19:21:15 +00:00
byte [ ] data = new byte [ 16 ] ;
int pos = 0 ;
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
// The flags don't like conversion from uint to byte, so we have to do
// it the crappy way. See the above function :(
2007-09-19 00:30:55 +00:00
2008-09-06 07:52:41 +00:00
data [ pos ] = ConvertScriptUintToByte ( ( uint ) pTexAnim . Flags ) ; pos + + ;
2008-06-27 19:21:15 +00:00
data [ pos ] = ( byte ) pTexAnim . Face ; pos + + ;
data [ pos ] = ( byte ) pTexAnim . SizeX ; pos + + ;
data [ pos ] = ( byte ) pTexAnim . SizeY ; pos + + ;
2008-02-07 01:52:39 +00:00
2008-11-19 06:25:34 +00:00
Utils . FloatToBytes ( pTexAnim . Start ) . CopyTo ( data , pos ) ;
Utils . FloatToBytes ( pTexAnim . Length ) . CopyTo ( data , pos + 4 ) ;
Utils . FloatToBytes ( pTexAnim . Rate ) . CopyTo ( data , pos + 8 ) ;
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
m_TextureAnimation = data ;
2007-07-30 20:11:40 +00:00
}
2007-09-19 00:30:55 +00:00
2008-06-27 19:21:15 +00:00
public void AdjustSoundGain ( double volume )
2007-08-03 11:44:30 +00:00
{
2008-06-27 19:21:15 +00:00
if ( volume > 1 )
volume = 1 ;
if ( volume < 0 )
volume = 0 ;
2008-05-16 01:22:11 +00:00
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . ForEachRootClient ( delegate ( IClientAPI client )
2008-06-27 19:21:15 +00:00
{
2011-11-04 00:06:08 +00:00
client . SendAttachedSoundGainChange ( UUID , ( float ) volume ) ;
2010-03-19 12:51:16 +00:00
} ) ;
2007-08-03 11:44:30 +00:00
}
2007-09-19 00:30:55 +00:00
2008-05-01 18:04:42 +00:00
/// <summary>
2008-06-27 19:21:15 +00:00
/// 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
2008-05-01 18:04:42 +00:00
/// </summary>
2008-06-27 19:21:15 +00:00
/// <param name="impulsei">Vector force</param>
/// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
2008-09-06 07:52:41 +00:00
public void ApplyImpulse ( Vector3 impulsei , bool localGlobalTF )
2008-05-01 16:35:00 +00:00
{
2009-10-26 06:16:12 +00:00
Vector3 impulse = impulsei ;
2008-05-15 19:28:10 +00:00
2008-06-27 19:21:15 +00:00
if ( localGlobalTF )
{
2008-09-06 07:52:41 +00:00
Quaternion grot = GetWorldRotation ( ) ;
Quaternion AXgrot = grot ;
Vector3 AXimpulsei = impulsei ;
Vector3 newimpulse = AXimpulsei * AXgrot ;
2009-10-26 06:16:12 +00:00
impulse = newimpulse ;
2008-06-27 19:21:15 +00:00
}
2011-11-11 01:21:37 +00:00
if ( ParentGroup ! = null )
2008-09-29 19:01:45 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . applyImpulse ( impulse ) ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 16:35:00 +00:00
}
2008-05-16 01:22:11 +00:00
2008-12-14 14:30:28 +00:00
/// <summary>
/// hook to the physics scene to apply angular 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
/// </summary>
/// <param name="impulsei">Vector force</param>
/// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
public void ApplyAngularImpulse ( Vector3 impulsei , bool localGlobalTF )
{
2009-10-26 06:16:12 +00:00
Vector3 impulse = impulsei ;
2008-12-14 14:30:28 +00:00
if ( localGlobalTF )
{
Quaternion grot = GetWorldRotation ( ) ;
Quaternion AXgrot = grot ;
Vector3 AXimpulsei = impulsei ;
Vector3 newimpulse = AXimpulsei * AXgrot ;
2009-10-26 06:16:12 +00:00
impulse = newimpulse ;
2008-12-14 14:30:28 +00:00
}
2011-11-11 01:21:37 +00:00
ParentGroup . applyAngularImpulse ( impulse ) ;
2008-12-14 14:30:28 +00:00
}
/// <summary>
/// hook to the physics scene to apply angular 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
/// </summary>
/// <param name="impulsei">Vector force</param>
/// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
public void SetAngularImpulse ( Vector3 impulsei , bool localGlobalTF )
{
2009-10-26 06:16:12 +00:00
Vector3 impulse = impulsei ;
2008-12-14 14:30:28 +00:00
if ( localGlobalTF )
{
Quaternion grot = GetWorldRotation ( ) ;
Quaternion AXgrot = grot ;
Vector3 AXimpulsei = impulsei ;
Vector3 newimpulse = AXimpulsei * AXgrot ;
2009-10-26 06:16:12 +00:00
impulse = newimpulse ;
2008-12-14 14:30:28 +00:00
}
2011-11-11 01:21:37 +00:00
ParentGroup . setAngularImpulse ( impulse ) ;
2008-12-14 14:30:28 +00:00
}
2008-06-17 17:23:00 +00:00
/// <summary>
/// Apply physics to this part.
/// </summary>
/// <param name="rootObjectFlags"></param>
2011-10-15 01:47:27 +00:00
/// <param name="VolumeDetectActive"></param>
public void ApplyPhysics ( uint rootObjectFlags , bool VolumeDetectActive )
2008-05-01 16:35:00 +00:00
{
2011-12-22 19:44:52 +00:00
if ( ! ParentGroup . Scene . CollidablePrims )
return ;
2011-10-15 01:42:43 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}",
// Name, LocalId, UUID, m_physicalPrim);
2011-07-08 16:58:01 +00:00
2011-10-15 01:47:27 +00:00
bool isPhysical = ( rootObjectFlags & ( uint ) PrimFlags . Physics ) ! = 0 ;
bool isPhantom = ( rootObjectFlags & ( uint ) PrimFlags . Phantom ) ! = 0 ;
2008-05-01 16:35:00 +00:00
2008-12-26 12:58:02 +00:00
if ( IsJoint ( ) )
{
DoPhysicsPropertyUpdate ( isPhysical , true ) ;
}
else
2008-05-01 16:35:00 +00:00
{
2008-12-26 12:58:02 +00:00
// Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
if ( VolumeDetectActive )
isPhantom = false ;
2008-05-16 01:22:11 +00:00
2008-12-26 12:58:02 +00:00
// The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
2009-10-04 09:54:36 +00:00
// or flexible
2011-11-11 01:21:37 +00:00
if ( ! isPhantom & & ! ParentGroup . IsAttachment & & ! ( Shape . PathCurve = = ( byte ) Extrusion . Flexible ) )
2008-03-16 18:55:56 +00:00
{
2012-04-03 08:28:17 +00:00
// Added clarification.. since A rigid body is an object that you can kick around, etc.
bool rigidBody = isPhysical & & ! isPhantom ;
2011-10-15 01:02:39 +00:00
2012-04-03 08:28:17 +00:00
PhysicsActor pa = AddToPhysics ( rigidBody ) ;
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
pa . SetVolumeDetect ( VolumeDetectActive ? 1 : 0 ) ;
2008-03-16 18:55:56 +00:00
}
2008-01-15 04:14:27 +00:00
}
2007-11-30 08:08:14 +00:00
}
2007-12-27 21:41:48 +00:00
2008-06-27 19:21:15 +00:00
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 ;
2007-08-13 13:36:42 +00:00
}
/// <summary>
2008-06-27 19:21:15 +00:00
/// Duplicates this part.
2007-08-13 13:36:42 +00:00
/// </summary>
2010-07-28 18:38:20 +00:00
/// <param name="localID"></param>
/// <param name="AgentID"></param>
/// <param name="GroupID"></param>
/// <param name="linkNum"></param>
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
2008-06-27 19:21:15 +00:00
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public SceneObjectPart Copy ( uint localID , UUID AgentID , UUID GroupID , int linkNum , bool userExposed )
2007-08-13 13:36:42 +00:00
{
2009-05-04 15:38:36 +00:00
SceneObjectPart dupe = ( SceneObjectPart ) MemberwiseClone ( ) ;
2008-06-27 19:21:15 +00:00
dupe . m_shape = m_shape . Copy ( ) ;
dupe . m_regionHandle = m_regionHandle ;
if ( userExposed )
2008-09-06 07:52:41 +00:00
dupe . UUID = UUID . Random ( ) ;
2007-08-13 13:36:42 +00:00
2012-03-07 01:03:26 +00:00
dupe . PhysActor = null ;
2008-12-07 04:03:09 +00:00
2011-11-11 01:21:37 +00:00
dupe . OwnerID = AgentID ;
dupe . GroupID = GroupID ;
2008-09-06 07:52:41 +00:00
dupe . GroupPosition = GroupPosition ;
dupe . OffsetPosition = OffsetPosition ;
dupe . RotationOffset = RotationOffset ;
2012-02-19 07:51:40 +00:00
dupe . Velocity = Velocity ;
dupe . Acceleration = Acceleration ;
dupe . AngularVelocity = AngularVelocity ;
2010-08-13 19:23:53 +00:00
dupe . Flags = Flags ;
2007-12-04 13:46:18 +00:00
2011-11-11 01:21:37 +00:00
dupe . OwnershipCost = OwnershipCost ;
dupe . ObjectSaleType = ObjectSaleType ;
dupe . SalePrice = SalePrice ;
dupe . Category = Category ;
2008-10-18 05:51:36 +00:00
dupe . m_rezzed = m_rezzed ;
2007-11-23 05:56:35 +00:00
2008-11-26 07:34:38 +00:00
dupe . m_inventory = new SceneObjectPartInventory ( dupe ) ;
dupe . m_inventory . Items = ( TaskInventoryDictionary ) m_inventory . Items . Clone ( ) ;
2007-12-28 05:25:21 +00:00
2008-06-27 19:21:15 +00:00
if ( userExposed )
2008-11-26 07:34:38 +00:00
{
2008-06-27 19:21:15 +00:00
dupe . ResetIDs ( linkNum ) ;
2008-11-26 07:34:38 +00:00
dupe . m_inventory . HasInventoryChanged = true ;
}
else
{
dupe . m_inventory . HasInventoryChanged = m_inventory . HasInventoryChanged ;
}
2007-11-23 05:56:35 +00:00
2008-11-21 18:44:48 +00:00
// Move afterwards ResetIDs as it clears the localID
2008-11-20 00:13:15 +00:00
dupe . LocalId = localID ;
2008-06-27 19:21:15 +00:00
// This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
2011-11-11 01:21:37 +00:00
dupe . LastOwnerID = OwnerID ;
2007-11-23 05:56:35 +00:00
2008-06-27 19:21:15 +00:00
byte [ ] extraP = new byte [ Shape . ExtraParams . Length ] ;
Array . Copy ( Shape . ExtraParams , extraP , extraP . Length ) ;
dupe . Shape . ExtraParams = extraP ;
2007-11-23 05:56:35 +00:00
2013-01-22 09:59:20 +00:00
dupe . DynAttrs . CopyFrom ( DynAttrs ) ;
2008-06-27 19:21:15 +00:00
if ( userExposed )
{
2012-10-07 00:20:52 +00:00
/ *
2008-09-06 07:52:41 +00:00
if ( dupe . m_shape . SculptEntry & & dupe . m_shape . SculptTexture ! = UUID . Zero )
2008-06-27 19:21:15 +00:00
{
2011-07-16 02:16:24 +00:00
ParentGroup . Scene . AssetService . Get (
dupe . m_shape . SculptTexture . ToString ( ) , dupe , dupe . AssetReceived ) ;
2008-06-27 19:21:15 +00:00
}
2012-10-07 00:20:52 +00:00
* /
2010-08-13 19:23:53 +00:00
bool UsePhysics = ( ( dupe . Flags & PrimFlags . Physics ) ! = 0 ) ;
2008-06-27 19:21:15 +00:00
dupe . DoPhysicsPropertyUpdate ( UsePhysics , true ) ;
}
2009-02-03 17:50:25 +00:00
2010-07-28 18:38:20 +00:00
ParentGroup . Scene . EventManager . TriggerOnSceneObjectPartCopy ( dupe , this , userExposed ) ;
2010-07-28 17:55:29 +00:00
// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
2010-09-12 17:43:49 +00:00
return dupe ;
2008-06-27 19:21:15 +00:00
}
2007-12-04 13:46:18 +00:00
2011-07-16 02:16:24 +00:00
/// <summary>
/// Called back by asynchronous asset fetch.
/// </summary>
/// <param name="id">ID of asset received</param>
/// <param name="sender">Register</param>
/// <param name="asset"></param>
2012-10-07 00:20:52 +00:00
/ *
2009-05-15 05:00:25 +00:00
protected void AssetReceived ( string id , Object sender , AssetBase asset )
{
if ( asset ! = null )
2011-07-16 02:16:24 +00:00
SculptTextureCallback ( asset ) ;
2011-07-16 02:24:36 +00:00
else
m_log . WarnFormat (
"[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data" ,
2012-06-19 23:05:48 +00:00
Name , UUID , id ) ;
2009-05-15 05:00:25 +00:00
}
2012-10-07 00:20:52 +00:00
* /
2011-07-31 01:50:50 +00:00
/// <summary>
/// Do a physics property update for a NINJA joint.
/// </summary>
/// <param name="UsePhysics"></param>
/// <param name="isNew"></param>
protected void DoPhysicsPropertyUpdateForNinjaJoint ( bool UsePhysics , bool isNew )
2008-06-27 19:21:15 +00:00
{
2011-07-31 01:50:50 +00:00
if ( UsePhysics )
2008-06-27 19:21:15 +00:00
{
2011-07-31 01:50:50 +00:00
// by turning a joint proxy object physical, we cause creation of a joint in the ODE scene.
// note that, as a special case, joints have no bodies or geoms in the physics scene, even though they are physical.
2008-12-26 12:58:02 +00:00
2011-07-31 01:50:50 +00:00
PhysicsJointType jointType ;
if ( IsHingeJoint ( ) )
{
jointType = PhysicsJointType . Hinge ;
}
else if ( IsBallJoint ( ) )
{
jointType = PhysicsJointType . Ball ;
}
else
{
jointType = PhysicsJointType . Ball ;
}
2007-11-23 05:56:35 +00:00
2011-07-31 01:50:50 +00:00
List < string > bodyNames = new List < string > ( ) ;
string RawParams = Description ;
string [ ] jointParams = RawParams . Split ( " " . ToCharArray ( ) , System . StringSplitOptions . RemoveEmptyEntries ) ;
string trackedBodyName = null ;
if ( jointParams . Length > = 2 )
{
for ( int iBodyName = 0 ; iBodyName < 2 ; iBodyName + + )
2008-12-26 12:58:02 +00:00
{
2011-07-31 01:50:50 +00:00
string bodyName = jointParams [ iBodyName ] ;
bodyNames . Add ( bodyName ) ;
if ( bodyName ! = "NULL" )
2008-12-26 12:58:02 +00:00
{
2011-07-31 01:50:50 +00:00
if ( trackedBodyName = = null )
2008-12-26 12:58:02 +00:00
{
2011-07-31 01:50:50 +00:00
trackedBodyName = bodyName ;
2008-12-26 12:58:02 +00:00
}
}
2008-06-27 19:21:15 +00:00
}
2011-07-31 01:50:50 +00:00
}
2008-03-21 05:54:56 +00:00
2011-11-11 01:21:37 +00:00
SceneObjectPart trackedBody = ParentGroup . Scene . GetSceneObjectPart ( trackedBodyName ) ; // FIXME: causes a sequential lookup
2011-07-31 01:50:50 +00:00
Quaternion localRotation = Quaternion . Identity ;
if ( trackedBody ! = null )
{
localRotation = Quaternion . Inverse ( trackedBody . RotationOffset ) * this . RotationOffset ;
}
else
{
// error, output it below
}
2008-12-26 12:58:02 +00:00
2011-07-31 01:50:50 +00:00
PhysicsJoint joint ;
2008-12-26 12:58:02 +00:00
2011-11-11 01:21:37 +00:00
joint = ParentGroup . Scene . PhysicsScene . RequestJointCreation ( Name , jointType ,
2011-07-31 01:50:50 +00:00
AbsolutePosition ,
this . RotationOffset ,
Description ,
bodyNames ,
trackedBodyName ,
localRotation ) ;
2008-12-26 12:58:02 +00:00
2011-07-31 01:50:50 +00:00
if ( trackedBody = = null )
{
ParentGroup . Scene . jointErrorMessage ( joint , "warning: tracked body name not found! joint location will not be updated properly. joint: " + Name ) ;
}
}
else
{
if ( isNew )
{
// if the joint proxy is new, and it is not physical, do nothing. There is no joint in ODE to
// delete, and if we try to delete it, due to asynchronous processing, the deletion request
// will get processed later at an indeterminate time, which could cancel a later-arriving
// joint creation request.
2008-12-26 12:58:02 +00:00
}
else
{
2011-07-31 01:50:50 +00:00
// here we turn off the joint object, so remove the joint from the physics scene
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . PhysicsScene . RequestJointDeletion ( Name ) ; // FIXME: what if the name changed?
2008-12-26 12:58:02 +00:00
2011-07-31 01:50:50 +00:00
// make sure client isn't interpolating the joint proxy object
Velocity = Vector3 . Zero ;
AngularVelocity = Vector3 . Zero ;
Acceleration = Vector3 . Zero ;
2008-12-26 12:58:02 +00:00
}
}
2011-07-31 01:50:50 +00:00
}
/// <summary>
/// Do a physics propery update for this part.
/// </summary>
/// <param name="UsePhysics"></param>
/// <param name="isNew"></param>
public void DoPhysicsPropertyUpdate ( bool UsePhysics , bool isNew )
{
2012-04-20 23:54:48 +00:00
if ( ParentGroup . Scene = = null )
return ;
2012-04-21 00:51:57 +00:00
2011-12-22 19:57:50 +00:00
if ( ! ParentGroup . Scene . PhysicalPrims & & UsePhysics )
2011-10-15 01:42:43 +00:00
return ;
2011-07-31 01:50:50 +00:00
if ( IsJoint ( ) )
{
DoPhysicsPropertyUpdateForNinjaJoint ( UsePhysics , isNew ) ;
}
2008-12-26 12:58:02 +00:00
else
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
2008-12-26 12:58:02 +00:00
{
2012-04-03 04:50:13 +00:00
if ( UsePhysics ! = pa . IsPhysical | | isNew )
2008-12-26 12:58:02 +00:00
{
2012-04-03 04:50:13 +00:00
if ( pa . IsPhysical ) // implies UsePhysics==false for this block
2008-12-26 12:58:02 +00:00
{
if ( ! isNew )
ParentGroup . Scene . RemovePhysicalPrim ( 1 ) ;
2008-12-19 21:06:07 +00:00
2012-04-03 04:50:13 +00:00
pa . OnRequestTerseUpdate - = PhysicsRequestingTerseUpdate ;
pa . OnOutOfBounds - = PhysicsOutOfBounds ;
pa . delink ( ) ;
2007-11-23 05:56:35 +00:00
2008-12-26 12:58:02 +00:00
if ( ParentGroup . Scene . PhysicsScene . SupportsNINJAJoints & & ( ! isNew ) )
{
// destroy all joints connected to this now deactivated body
2012-04-03 04:50:13 +00:00
ParentGroup . Scene . PhysicsScene . RemoveAllJointsConnectedToActorThreadLocked ( pa ) ;
2008-12-26 12:58:02 +00:00
}
2007-12-04 13:46:18 +00:00
2008-12-26 12:58:02 +00:00
// stop client-side interpolation of all joint proxy objects that have just been deleted
// this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback,
// which stops client-side interpolation of deactivated joint proxy objects.
}
2007-11-23 05:56:35 +00:00
2008-12-26 12:58:02 +00:00
if ( ! UsePhysics & & ! isNew )
2008-06-27 19:21:15 +00:00
{
2008-12-26 12:58:02 +00:00
// reset velocity to 0 on physics switch-off. Without that, the client thinks the
// prim still has velocity and continues to interpolate its position along the old
// velocity-vector.
Velocity = new Vector3 ( 0 , 0 , 0 ) ;
Acceleration = new Vector3 ( 0 , 0 , 0 ) ;
AngularVelocity = new Vector3 ( 0 , 0 , 0 ) ;
//RotationalVelocity = new Vector3(0, 0, 0);
}
2012-04-03 04:50:13 +00:00
pa . IsPhysical = UsePhysics ;
2008-12-26 12:58:02 +00:00
// 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;
2010-08-10 19:15:44 +00:00
if ( ( Flags & PrimFlags . Phantom ) = = 0 )
2008-12-26 12:58:02 +00:00
{
if ( UsePhysics )
2008-06-27 19:21:15 +00:00
{
2008-12-26 12:58:02 +00:00
ParentGroup . Scene . AddPhysicalPrim ( 1 ) ;
2012-04-03 04:50:13 +00:00
pa . OnRequestTerseUpdate + = PhysicsRequestingTerseUpdate ;
pa . OnOutOfBounds + = PhysicsOutOfBounds ;
2011-11-11 01:21:37 +00:00
if ( ParentID ! = 0 & & ParentID ! = LocalId )
2008-06-27 19:21:15 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor parentPa = ParentGroup . RootPart . PhysActor ;
if ( parentPa ! = null )
2008-12-26 12:58:02 +00:00
{
2012-04-03 04:50:13 +00:00
pa . link ( parentPa ) ;
2008-12-26 12:58:02 +00:00
}
2008-06-27 19:21:15 +00:00
}
}
}
}
2011-07-11 02:13:59 +00:00
2011-07-12 01:33:09 +00:00
// If this part is a sculpt then delay the physics update until we've asynchronously loaded the
// mesh data.
2012-10-07 00:20:52 +00:00
// if (Shape.SculptEntry)
// CheckSculptAndLoad();
// else
2012-04-03 04:50:13 +00:00
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( pa ) ;
2007-11-23 05:56:35 +00:00
}
}
2008-06-27 19:21:15 +00:00
}
2007-11-23 05:56:35 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Restore this part from the serialized xml representation.
/// </summary>
2008-12-17 16:11:03 +00:00
/// <param name="xmlReader"></param>
2008-06-27 19:21:15 +00:00
/// <returns></returns>
2010-10-17 17:35:38 +00:00
public static SceneObjectPart FromXml ( XmlTextReader xmlReader )
2008-12-17 16:11:03 +00:00
{
2010-10-17 17:35:38 +00:00
SceneObjectPart part = SceneObjectSerializer . Xml2ToSOP ( xmlReader ) ;
2008-12-19 18:38:45 +00:00
// for tempOnRez objects, we have to fix the Expire date.
2011-09-01 23:50:16 +00:00
if ( ( part . Flags & PrimFlags . TemporaryOnRez ) ! = 0 )
part . ResetExpire ( ) ;
2008-12-19 18:38:45 +00:00
2008-12-17 16:11:03 +00:00
return part ;
2008-12-19 18:38:45 +00:00
}
2007-11-30 16:29:23 +00:00
2008-06-27 19:21:15 +00:00
public bool GetDieAtEdge ( )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2008-06-27 19:21:15 +00:00
return false ;
2007-11-23 05:56:35 +00:00
2011-11-11 01:21:37 +00:00
return ParentGroup . RootPart . DIE_AT_EDGE ;
2010-01-10 19:58:44 +00:00
}
2010-02-14 21:41:57 +00:00
public bool GetReturnAtEdge ( )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return false ;
2011-11-11 01:21:37 +00:00
return ParentGroup . RootPart . RETURN_AT_EDGE ;
2010-02-14 21:41:57 +00:00
}
public void SetReturnAtEdge ( bool p )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return ;
2011-11-11 01:21:37 +00:00
ParentGroup . RootPart . RETURN_AT_EDGE = p ;
2010-02-14 21:41:57 +00:00
}
public bool GetBlockGrab ( )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return false ;
2011-11-11 01:21:37 +00:00
return ParentGroup . RootPart . BlockGrab ;
2010-02-14 21:41:57 +00:00
}
public void SetBlockGrab ( bool p )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return ;
2011-11-11 01:21:37 +00:00
ParentGroup . RootPart . BlockGrab = p ;
2010-02-14 21:41:57 +00:00
}
public void SetStatusSandbox ( bool p )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return ;
2011-11-11 01:21:37 +00:00
StatusSandboxPos = ParentGroup . RootPart . AbsolutePosition ;
ParentGroup . RootPart . StatusSandbox = p ;
2010-02-14 21:41:57 +00:00
}
public bool GetStatusSandbox ( )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
return false ;
2011-11-11 01:21:37 +00:00
return ParentGroup . RootPart . StatusSandbox ;
2010-02-14 21:41:57 +00:00
}
2010-01-10 19:58:44 +00:00
public int GetAxisRotation ( int axis )
{
//Cannot use ScriptBaseClass constants as no referance to it currently.
2012-12-18 22:59:41 +00:00
if ( axis = = ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_X )
2010-01-10 19:58:44 +00:00
return STATUS_ROTATE_X ;
2012-12-18 22:59:41 +00:00
if ( axis = = ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_Y )
2010-01-10 19:58:44 +00:00
return STATUS_ROTATE_Y ;
2012-12-18 22:59:41 +00:00
if ( axis = = ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_Z )
2010-01-10 19:58:44 +00:00
return STATUS_ROTATE_Z ;
return 0 ;
2007-11-23 05:56:35 +00:00
}
2008-03-23 06:24:59 +00:00
public double GetDistanceTo ( Vector3 a , Vector3 b )
{
2008-09-06 07:52:41 +00:00
float dx = a . X - b . X ;
float dy = a . Y - b . Y ;
float dz = a . Z - b . Z ;
2008-03-23 06:24:59 +00:00
return Math . Sqrt ( dx * dx + dy * dy + dz * dz ) ;
}
2008-06-27 19:21:15 +00:00
public uint GetEffectiveObjectFlags ( )
2010-09-12 17:43:49 +00:00
{
2010-08-10 16:26:31 +00:00
// Commenting this section of code out since it doesn't actually do anything, as enums are handled by
// value rather than reference
2010-09-12 17:43:49 +00:00
// PrimFlags f = _flags;
2010-08-10 16:26:31 +00:00
// if (m_parentGroup == null || m_parentGroup.RootPart == this)
// f &= ~(PrimFlags.Touch | PrimFlags.Money);
2008-03-23 06:24:59 +00:00
2010-08-10 16:26:31 +00:00
return ( uint ) Flags | ( uint ) LocalFlags ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 06:31:12 +00:00
2008-09-06 07:52:41 +00:00
public Vector3 GetGeometricCenter ( )
2008-06-27 19:21:15 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
2013-01-21 23:55:54 +00:00
if ( pa ! = null )
return new Vector3 ( pa . GeometricCenter . X , pa . GeometricCenter . Y , pa . GeometricCenter . Z ) ;
else
return new Vector3 ( 0 , 0 , 0 ) ;
}
public Vector3 GetCenterOfMass ( )
{
PhysicsActor pa = PhysActor ;
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
return new Vector3 ( pa . CenterOfMass . X , pa . CenterOfMass . Y , pa . CenterOfMass . Z ) ;
2008-06-27 19:21:15 +00:00
else
2008-09-06 07:52:41 +00:00
return new Vector3 ( 0 , 0 , 0 ) ;
2008-06-27 19:21:15 +00:00
}
2008-03-22 03:40:38 +00:00
2008-06-27 19:21:15 +00:00
public float GetMass ( )
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
return pa . Mass ;
2008-06-27 19:21:15 +00:00
else
return 0 ;
}
2008-03-22 03:40:38 +00:00
2009-10-26 06:16:12 +00:00
public Vector3 GetForce ( )
2008-07-24 07:45:58 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
return pa . Force ;
2008-07-24 07:45:58 +00:00
else
2009-10-26 06:16:12 +00:00
return Vector3 . Zero ;
2008-07-24 07:45:58 +00:00
}
2008-06-27 19:21:15 +00:00
/// <summary>
/// Method for a prim to get it's world position from the group.
/// </summary>
2011-09-01 00:41:53 +00:00
/// <remarks>
/// Remember, the Group Position simply gives the position of the group itself
/// </remarks>
2008-06-27 19:21:15 +00:00
/// <returns>A Linked Child Prim objects position in world</returns>
2008-09-06 07:52:41 +00:00
public Vector3 GetWorldPosition ( )
{
2012-07-11 23:07:14 +00:00
Vector3 ret ;
if ( _parentID = = 0 )
// if a root SOP, my position is what it is
ret = GroupPosition ;
2012-01-05 08:11:52 +00:00
else
2012-07-11 23:07:14 +00:00
{
// If a child SOP, my position is relative to the root SOP so take
// my info and add the root's position and rotation to
// get my world position.
Quaternion parentRot = ParentGroup . RootPart . RotationOffset ;
Vector3 translationOffsetPosition = OffsetPosition * parentRot ;
ret = ParentGroup . AbsolutePosition + translationOffsetPosition ;
}
return ret ;
2008-06-27 19:21:15 +00:00
}
2008-03-22 03:40:38 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Gets the rotation of this prim offset by the group rotation
/// </summary>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public Quaternion GetWorldRotation ( )
2008-06-27 19:21:15 +00:00
{
Quaternion newRot ;
2008-03-23 06:24:59 +00:00
2011-02-13 05:30:43 +00:00
if ( this . LinkNum = = 0 | | this . LinkNum = = 1 )
2008-06-27 19:21:15 +00:00
{
2008-09-06 07:52:41 +00:00
newRot = RotationOffset ;
2008-06-27 19:21:15 +00:00
}
else
{
2012-07-11 23:07:14 +00:00
// A child SOP's rotation is relative to the root SOP's rotation.
// Combine them to get my absolute rotation.
2008-09-06 07:52:41 +00:00
Quaternion parentRot = ParentGroup . RootPart . RotationOffset ;
Quaternion oldRot = RotationOffset ;
2008-06-27 19:21:15 +00:00
newRot = parentRot * oldRot ;
}
2008-03-22 03:40:38 +00:00
2008-09-06 07:52:41 +00:00
return newRot ;
2008-06-27 19:21:15 +00:00
}
2008-03-22 03:40:38 +00:00
2008-09-06 07:52:41 +00:00
public void MoveToTarget ( Vector3 target , float tau )
2008-06-27 19:21:15 +00:00
{
if ( tau > 0 )
2008-03-22 03:40:38 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . moveToTarget ( target , tau ) ;
2008-06-27 19:21:15 +00:00
}
else
{
StopMoveToTarget ( ) ;
}
}
2008-03-23 06:24:59 +00:00
2009-03-06 23:01:35 +00:00
/// <summary>
/// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
/// </summary>
/// <param name="height">Height to hover. Height of zero disables hover.</param>
/// <param name="hoverType">Determines what the height is relative to </param>
/// <param name="tau">Number of seconds over which to reach target</param>
public void SetHoverHeight ( float height , PIDHoverType hoverType , float tau )
{
2011-11-11 01:21:37 +00:00
ParentGroup . SetHoverHeight ( height , hoverType , tau ) ;
2009-03-06 23:01:35 +00:00
}
public void StopHover ( )
{
2011-11-11 01:21:37 +00:00
ParentGroup . SetHoverHeight ( 0f , PIDHoverType . Ground , 0f ) ;
2009-03-06 23:01:35 +00:00
}
2008-09-06 07:52:41 +00:00
public virtual void OnGrab ( Vector3 offsetPos , IClientAPI remoteClient )
2008-06-27 19:21:15 +00:00
{
}
2008-05-16 01:22:11 +00:00
2012-05-29 17:18:47 +00:00
public bool CollisionFilteredOut ( UUID objectID , string objectName )
2008-06-27 19:21:15 +00:00
{
2012-05-29 17:18:47 +00:00
if ( CollisionFilter . Count = = 0 )
2012-05-15 00:02:38 +00:00
return false ;
2008-03-23 06:24:59 +00:00
2012-05-29 17:18:47 +00:00
if ( CollisionFilter . ContainsValue ( objectID . ToString ( ) ) | |
CollisionFilter . ContainsValue ( objectID . ToString ( ) + objectName ) | |
CollisionFilter . ContainsValue ( UUID . Zero . ToString ( ) + objectName ) )
2008-03-23 06:24:59 +00:00
{
2012-05-29 17:18:47 +00:00
if ( CollisionFilter . ContainsKey ( 1 ) )
2012-05-15 00:02:38 +00:00
return false ;
return true ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2012-05-29 17:18:47 +00:00
if ( CollisionFilter . ContainsKey ( 1 ) )
2012-05-15 00:02:38 +00:00
return true ;
2008-05-16 01:22:11 +00:00
2012-05-15 00:02:38 +00:00
return false ;
}
2008-11-19 18:30:16 +00:00
2012-05-15 00:02:38 +00:00
private DetectedObject CreateDetObject ( SceneObjectPart obj )
{
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 ;
2011-11-11 01:21:37 +00:00
2012-05-15 00:02:38 +00:00
return detobj ;
}
2011-11-11 01:21:37 +00:00
2012-05-15 00:02:38 +00:00
private DetectedObject CreateDetObject ( ScenePresence av )
{
DetectedObject detobj = new DetectedObject ( ) ;
detobj . keyUUID = av . UUID ;
detobj . nameStr = av . ControllingClient . Name ;
detobj . ownerUUID = av . UUID ;
detobj . posVector = av . AbsolutePosition ;
detobj . rotQuat = av . Rotation ;
detobj . velVector = av . Velocity ;
detobj . colliderType = 0 ;
detobj . groupUUID = av . ControllingClient . ActiveGroupId ;
2009-12-31 17:41:07 +00:00
2012-05-15 00:02:38 +00:00
return detobj ;
}
2011-10-25 21:19:17 +00:00
2012-05-15 00:02:38 +00:00
private DetectedObject CreateDetObjectForGround ( )
{
DetectedObject detobj = new DetectedObject ( ) ;
detobj . keyUUID = UUID . Zero ;
detobj . nameStr = "" ;
detobj . ownerUUID = UUID . Zero ;
detobj . posVector = ParentGroup . RootPart . AbsolutePosition ;
detobj . rotQuat = Quaternion . Identity ;
detobj . velVector = Vector3 . Zero ;
detobj . colliderType = 0 ;
detobj . groupUUID = UUID . Zero ;
2011-11-11 01:21:37 +00:00
2012-05-15 00:02:38 +00:00
return detobj ;
}
2011-09-01 00:22:28 +00:00
2012-05-15 00:02:38 +00:00
private ColliderArgs CreateColliderArgs ( SceneObjectPart dest , List < uint > colliders )
{
ColliderArgs colliderArgs = new ColliderArgs ( ) ;
List < DetectedObject > colliding = new List < DetectedObject > ( ) ;
foreach ( uint localId in colliders )
{
if ( localId = = 0 )
continue ;
2011-10-25 21:19:17 +00:00
2012-05-15 00:02:38 +00:00
SceneObjectPart obj = ParentGroup . Scene . GetSceneObjectPart ( localId ) ;
if ( obj ! = null )
{
2012-05-29 17:18:47 +00:00
if ( ! dest . CollisionFilteredOut ( obj . UUID , obj . Name ) )
2012-05-15 00:02:38 +00:00
colliding . Add ( CreateDetObject ( obj ) ) ;
2008-03-23 06:24:59 +00:00
}
2012-05-15 00:02:38 +00:00
else
2008-03-10 05:56:58 +00:00
{
2012-05-15 00:02:38 +00:00
ScenePresence av = ParentGroup . Scene . GetScenePresence ( localId ) ;
if ( av ! = null & & ( ! av . IsChildAgent ) )
2008-06-27 19:21:15 +00:00
{
2012-05-29 17:18:47 +00:00
if ( ! dest . CollisionFilteredOut ( av . UUID , av . Name ) )
2012-05-15 00:02:38 +00:00
colliding . Add ( CreateDetObject ( av ) ) ;
2008-06-27 19:21:15 +00:00
}
}
2007-12-27 05:52:24 +00:00
}
2008-05-01 18:04:42 +00:00
2012-05-15 00:02:38 +00:00
colliderArgs . Colliders = colliding ;
2011-09-01 00:22:28 +00:00
2012-05-15 00:02:38 +00:00
return colliderArgs ;
}
2009-12-31 17:41:07 +00:00
2012-05-15 00:02:38 +00:00
private delegate void ScriptCollidingNotification ( uint localID , ColliderArgs message ) ;
private void SendCollisionEvent ( scriptEvents ev , List < uint > colliders , ScriptCollidingNotification notify )
{
bool sendToRoot = false ;
ColliderArgs CollidingMessage ;
2011-09-01 00:22:28 +00:00
2012-05-15 00:02:38 +00:00
if ( colliders . Count > 0 )
2010-01-10 20:28:53 +00:00
{
2012-05-15 00:02:38 +00:00
if ( ( ScriptEvents & ev ) ! = 0 )
2010-01-10 20:28:53 +00:00
{
2012-05-15 00:02:38 +00:00
CollidingMessage = CreateColliderArgs ( this , colliders ) ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
if ( CollidingMessage . Colliders . Count > 0 )
notify ( LocalId , CollidingMessage ) ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
if ( PassCollisions )
sendToRoot = true ;
}
else
{
if ( ( ParentGroup . RootPart . ScriptEvents & ev ) ! = 0 )
sendToRoot = true ;
}
if ( sendToRoot & & ParentGroup . RootPart ! = this )
{
CollidingMessage = CreateColliderArgs ( ParentGroup . RootPart , colliders ) ;
if ( CollidingMessage . Colliders . Count > 0 )
notify ( ParentGroup . RootPart . LocalId , CollidingMessage ) ;
2010-01-10 20:28:53 +00:00
}
}
2012-05-15 00:02:38 +00:00
}
2011-09-01 00:22:28 +00:00
2012-05-15 00:02:38 +00:00
private void SendLandCollisionEvent ( scriptEvents ev , ScriptCollidingNotification notify )
{
if ( ( ParentGroup . RootPart . ScriptEvents & ev ) ! = 0 )
2010-01-10 20:28:53 +00:00
{
2012-05-15 00:02:38 +00:00
ColliderArgs LandCollidingMessage = new ColliderArgs ( ) ;
List < DetectedObject > colliding = new List < DetectedObject > ( ) ;
colliding . Add ( CreateDetObjectForGround ( ) ) ;
LandCollidingMessage . Colliders = colliding ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
notify ( LocalId , LandCollidingMessage ) ;
}
}
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
public void PhysicsCollision ( EventArgs e )
{
if ( ParentGroup . Scene = = null | | ParentGroup . IsDeleted )
return ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
// single threaded here
CollisionEventUpdate a = ( CollisionEventUpdate ) e ;
Dictionary < uint , ContactPoint > collissionswith = a . m_objCollisionList ;
List < uint > thisHitColliders = new List < uint > ( ) ;
List < uint > endedColliders = new List < uint > ( ) ;
List < uint > startedColliders = new List < uint > ( ) ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
// calculate things that started colliding this time
// and build up list of colliders this time
foreach ( uint localid in collissionswith . Keys )
{
thisHitColliders . Add ( localid ) ;
if ( ! m_lastColliders . Contains ( localid ) )
startedColliders . Add ( localid ) ;
2010-01-10 20:28:53 +00:00
}
2011-09-01 00:22:28 +00:00
2012-05-15 00:02:38 +00:00
// calculate things that ended colliding
foreach ( uint localID in m_lastColliders )
2010-01-10 20:28:53 +00:00
{
2012-05-15 00:02:38 +00:00
if ( ! thisHitColliders . Contains ( localID ) )
endedColliders . Add ( localID ) ;
}
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
//add the items that started colliding this time to the last colliders list.
foreach ( uint localID in startedColliders )
m_lastColliders . Add ( localID ) ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
// remove things that ended colliding from the last colliders list
foreach ( uint localID in endedColliders )
m_lastColliders . Remove ( localID ) ;
2010-01-10 20:28:53 +00:00
2012-05-15 00:02:38 +00:00
// play the sound.
if ( startedColliders . Count > 0 & & CollisionSound ! = UUID . Zero & & CollisionSoundVolume > 0.0f )
2012-10-16 11:24:33 +00:00
{
ISoundModule soundModule = ParentGroup . Scene . RequestModuleInterface < ISoundModule > ( ) ;
if ( soundModule ! = null )
{
2012-10-16 11:40:21 +00:00
soundModule . SendSound ( UUID , CollisionSound ,
2012-10-16 11:24:33 +00:00
CollisionSoundVolume , true , ( byte ) 0 , 0 , false ,
false ) ;
}
}
2012-05-15 00:02:38 +00:00
SendCollisionEvent ( scriptEvents . collision_start , startedColliders , ParentGroup . Scene . EventManager . TriggerScriptCollidingStart ) ;
SendCollisionEvent ( scriptEvents . collision , m_lastColliders , ParentGroup . Scene . EventManager . TriggerScriptColliding ) ;
SendCollisionEvent ( scriptEvents . collision_end , endedColliders , ParentGroup . Scene . EventManager . TriggerScriptCollidingEnd ) ;
if ( startedColliders . Contains ( 0 ) )
{
if ( m_lastColliders . Contains ( 0 ) )
SendLandCollisionEvent ( scriptEvents . land_collision , ParentGroup . Scene . EventManager . TriggerScriptLandColliding ) ;
else
SendLandCollisionEvent ( scriptEvents . land_collision_start , ParentGroup . Scene . EventManager . TriggerScriptLandCollidingStart ) ;
2010-01-10 20:28:53 +00:00
}
2012-05-15 00:02:38 +00:00
if ( endedColliders . Contains ( 0 ) )
SendLandCollisionEvent ( scriptEvents . land_collision_end , ParentGroup . Scene . EventManager . TriggerScriptLandCollidingEnd ) ;
2008-01-16 18:35:34 +00:00
}
2007-08-03 14:47:38 +00:00
2009-10-26 06:16:12 +00:00
public void PhysicsOutOfBounds ( Vector3 pos )
2008-05-01 16:35:00 +00:00
{
2012-12-15 00:30:17 +00:00
// Note: This is only being called on the root prim at this time.
m_log . ErrorFormat (
"[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical." ,
Name , LocalId , pos , ParentGroup . Scene . Name , AbsolutePosition ) ;
2009-05-29 21:10:17 +00:00
2008-09-06 07:52:41 +00:00
RemFlag ( PrimFlags . Physics ) ;
2008-06-27 19:21:15 +00:00
DoPhysicsPropertyUpdate ( false , true ) ;
2008-05-01 16:35:00 +00:00
}
2008-06-27 19:21:15 +00:00
public void PhysicsRequestingTerseUpdate ( )
2008-05-01 16:35:00 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
2008-03-14 16:28:33 +00:00
{
2012-04-03 04:50:13 +00:00
Vector3 newpos = new Vector3 ( pa . Position . GetBytes ( ) , 0 ) ;
2009-08-30 01:47:28 +00:00
2011-11-11 01:21:37 +00:00
if ( ParentGroup . Scene . TestBorderCross ( newpos , Cardinals . N )
| ParentGroup . Scene . TestBorderCross ( newpos , Cardinals . S )
| ParentGroup . Scene . TestBorderCross ( newpos , Cardinals . E )
| ParentGroup . Scene . TestBorderCross ( newpos , Cardinals . W ) )
2008-06-27 19:21:15 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . AbsolutePosition = newpos ;
2008-06-27 19:21:15 +00:00
return ;
}
2011-11-11 01:21:37 +00:00
//ParentGroup.RootPart.m_groupPosition = newpos;
2008-03-14 16:28:33 +00:00
}
2012-04-03 04:50:13 +00:00
2008-06-27 19:21:15 +00:00
ScheduleTerseUpdate ( ) ;
}
2008-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
public void RemFlag ( PrimFlags flag )
2007-08-03 12:00:24 +00:00
{
2008-09-06 07:52:41 +00:00
// PrimFlags prevflag = Flags;
2010-08-10 16:26:31 +00:00
if ( ( Flags & flag ) ! = 0 )
2007-08-03 12:00:24 +00:00
{
2009-02-22 20:52:55 +00:00
//m_log.Debug("Removing flag: " + ((PrimFlags)flag).ToString());
2010-08-10 16:26:31 +00:00
Flags & = ~ flag ;
2007-08-03 12:00:24 +00:00
}
2009-02-22 20:52:55 +00:00
//m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
2008-05-01 18:04:42 +00:00
//ScheduleFullUpdate();
2007-08-03 12:00:24 +00:00
}
2010-01-25 21:51:58 +00:00
2008-09-06 07:52:41 +00:00
public void RemoveScriptEvents ( UUID scriptid )
2007-07-30 20:11:40 +00:00
{
2008-06-27 19:21:15 +00:00
lock ( m_scriptEvents )
2008-02-15 21:35:52 +00:00
{
2008-06-27 19:21:15 +00:00
if ( m_scriptEvents . ContainsKey ( scriptid ) )
2008-05-01 16:35:00 +00:00
{
2008-06-27 19:21:15 +00:00
scriptEvents oldparts = scriptEvents . None ;
oldparts = ( scriptEvents ) m_scriptEvents [ scriptid ] ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// remove values from aggregated script events
2008-07-26 21:22:15 +00:00
AggregateScriptEvents & = ~ oldparts ;
2008-06-27 19:21:15 +00:00
m_scriptEvents . Remove ( scriptid ) ;
2008-09-08 22:19:06 +00:00
aggregateScriptEvents ( ) ;
2008-06-27 19:21:15 +00:00
}
2008-02-15 21:35:52 +00:00
}
2007-07-30 20:11:40 +00:00
}
2007-09-19 00:30:55 +00:00
2008-05-01 18:04:42 +00:00
/// <summary>
2008-09-06 07:52:41 +00:00
/// Reset UUIDs for this part. This involves generate this part's own UUID and
/// generating new UUIDs for all the items in the inventory.
2008-05-01 18:04:42 +00:00
/// </summary>
2008-06-27 19:21:15 +00:00
/// <param name="linkNum">Link number for the part</param>
public void ResetIDs ( int linkNum )
2007-10-30 23:38:56 +00:00
{
2008-09-06 07:52:41 +00:00
UUID = UUID . Random ( ) ;
2008-06-27 19:21:15 +00:00
LinkNum = linkNum ;
2008-11-21 18:44:48 +00:00
LocalId = 0 ;
2010-10-05 01:28:17 +00:00
Inventory . ResetInventoryIDs ( ) ;
2008-05-01 16:35:00 +00:00
}
2007-10-30 23:38:56 +00:00
2008-05-01 16:35:00 +00:00
/// <summary>
2011-07-18 03:54:21 +00:00
/// Set the scale of this part.
2008-05-01 16:35:00 +00:00
/// </summary>
2011-07-18 03:54:21 +00:00
/// <remarks>
/// Unlike the scale property, this checks the new size against scene limits and schedules a full property
/// update to viewers.
/// </remarks>
2008-06-27 19:21:15 +00:00
/// <param name="scale"></param>
2008-09-06 07:52:41 +00:00
public void Resize ( Vector3 scale )
2008-05-01 16:35:00 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
2012-09-26 22:17:21 +00:00
if ( ParentGroup . Scene ! = null )
2011-07-16 03:22:57 +00:00
{
2012-09-26 22:17:21 +00:00
scale . X = Math . Max ( ParentGroup . Scene . m_minNonphys , Math . Min ( ParentGroup . Scene . m_maxNonphys , scale . X ) ) ;
scale . Y = Math . Max ( ParentGroup . Scene . m_minNonphys , Math . Min ( ParentGroup . Scene . m_maxNonphys , scale . Y ) ) ;
scale . Z = Math . Max ( ParentGroup . Scene . m_minNonphys , Math . Min ( ParentGroup . Scene . m_maxNonphys , scale . Z ) ) ;
if ( pa ! = null & & pa . IsPhysical )
{
scale . X = Math . Max ( ParentGroup . Scene . m_minPhys , Math . Min ( ParentGroup . Scene . m_maxPhys , scale . X ) ) ;
scale . Y = Math . Max ( ParentGroup . Scene . m_minPhys , Math . Min ( ParentGroup . Scene . m_maxPhys , scale . Y ) ) ;
scale . Z = Math . Max ( ParentGroup . Scene . m_minPhys , Math . Min ( ParentGroup . Scene . m_maxPhys , scale . Z ) ) ;
}
2011-07-18 03:54:21 +00:00
}
2011-07-16 03:22:57 +00:00
2011-07-18 03:54:21 +00:00
// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2011-07-16 03:22:57 +00:00
2011-07-18 03:54:21 +00:00
Scale = scale ;
2011-07-11 02:47:49 +00:00
2008-06-27 16:36:19 +00:00
ParentGroup . HasGroupChanged = true ;
2008-05-01 18:04:42 +00:00
ScheduleFullUpdate ( ) ;
2007-10-30 23:38:56 +00:00
}
2009-12-22 00:26:12 +00:00
public void RotLookAt ( Quaternion target , float strength , float damping )
2010-02-14 21:41:57 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsAttachment )
2010-02-14 21:41:57 +00:00
{
/ *
ScenePresence avatar = m_scene . GetScenePresence ( rootpart . AttachedAvatar ) ;
if ( avatar ! = null )
{
Rotate the Av ?
} * /
}
else
{
APIDDamp = damping ;
APIDStrength = strength ;
APIDTarget = target ;
2012-01-13 22:48:56 +00:00
if ( APIDStrength < = 0 )
{
m_log . WarnFormat ( "[SceneObjectPart] Invalid rotation strength {0}" , APIDStrength ) ;
return ;
}
m_APIDIterations = 1 + ( int ) ( Math . PI * APIDStrength ) ;
2010-02-14 21:41:57 +00:00
}
2012-01-13 22:48:56 +00:00
// Necessary to get the lookat deltas applied
ParentGroup . QueueForUpdateCheck ( ) ;
2010-02-14 21:41:57 +00:00
}
2012-01-13 22:48:56 +00:00
public void StartLookAt ( Quaternion target , float strength , float damping )
2010-02-14 21:41:57 +00:00
{
2012-01-13 22:48:56 +00:00
RotLookAt ( target , strength , damping ) ;
2010-02-14 21:41:57 +00:00
}
2012-01-13 22:48:56 +00:00
public void StopLookAt ( )
2010-02-14 21:41:57 +00:00
{
APIDTarget = Quaternion . Identity ;
2009-12-22 00:26:12 +00:00
}
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Schedules this prim for a full update
/// </summary>
public void ScheduleFullUpdate ( )
2008-03-14 06:20:50 +00:00
{
2010-01-25 21:51:58 +00:00
// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId);
2011-09-01 00:22:28 +00:00
2011-11-11 01:21:37 +00:00
if ( ParentGroup = = null )
2011-09-01 00:22:28 +00:00
return ;
2011-11-11 01:21:37 +00:00
ParentGroup . QueueForUpdateCheck ( ) ;
2007-11-16 08:53:37 +00:00
2008-06-27 19:21:15 +00:00
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 ;
2008-05-01 18:04:42 +00:00
}
else
{
2008-06-27 19:21:15 +00:00
TimeStampFull = ( uint ) timeNow ;
2008-05-01 18:04:42 +00:00
}
2008-03-02 09:31:39 +00:00
2011-11-02 21:59:00 +00:00
UpdateFlag = UpdateRequired . FULL ;
2008-06-27 19:21:15 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
// UUID, Name, TimeStampFull);
2012-02-03 23:18:48 +00:00
if ( ParentGroup . Scene ! = null )
2012-10-06 00:32:07 +00:00
ParentGroup . Scene . EventManager . TriggerSceneObjectPartUpdated ( this , true ) ;
2008-06-27 19:21:15 +00:00
}
/// <summary>
/// Schedule a terse update for this prim. Terse updates only send position,
2012-08-01 15:34:00 +00:00
/// rotation, velocity and rotational velocity information.
2008-06-27 19:21:15 +00:00
/// </summary>
public void ScheduleTerseUpdate ( )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup = = null )
2011-09-01 00:22:28 +00:00
return ;
2011-11-12 01:16:52 +00:00
// This was pulled from SceneViewer. Attachments always receive full updates.
// I could not verify if this is a requirement but this maintains existing behavior
if ( ParentGroup . IsAttachment )
{
ScheduleFullUpdate ( ) ;
2012-02-03 23:18:48 +00:00
return ;
2011-11-12 01:16:52 +00:00
}
2011-11-02 21:59:00 +00:00
if ( UpdateFlag = = UpdateRequired . NONE )
2008-05-01 16:35:00 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . HasGroupChanged = true ;
ParentGroup . QueueForUpdateCheck ( ) ;
2011-09-01 00:22:28 +00:00
2008-06-27 19:21:15 +00:00
TimeStampTerse = ( uint ) Util . UnixTimeSinceEpoch ( ) ;
2011-11-02 21:59:00 +00:00
UpdateFlag = UpdateRequired . TERSE ;
2008-06-27 19:21:15 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
// UUID, Name, TimeStampTerse);
2008-05-01 16:35:00 +00:00
}
2012-02-03 23:18:48 +00:00
if ( ParentGroup . Scene ! = null )
2012-10-06 00:32:07 +00:00
ParentGroup . Scene . EventManager . TriggerSceneObjectPartUpdated ( this , false ) ;
2008-06-27 19:21:15 +00:00
}
public void ScriptSetPhysicsStatus ( bool UsePhysics )
{
2011-11-11 01:21:37 +00:00
ParentGroup . ScriptSetPhysicsStatus ( UsePhysics ) ;
2008-06-27 19:21:15 +00:00
}
2011-07-16 00:36:27 +00:00
/// <summary>
2011-07-16 02:02:28 +00:00
/// Set sculpt and mesh data, and tell the physics engine to process the change.
2011-07-16 00:36:27 +00:00
/// </summary>
/// <param name="texture">The mesh itself.</param>
2012-10-07 00:20:52 +00:00
/ *
2011-07-16 02:02:28 +00:00
public void SculptTextureCallback ( AssetBase texture )
2008-06-27 19:21:15 +00:00
{
if ( m_shape . SculptEntry )
{
2009-05-29 05:11:50 +00:00
// commented out for sculpt map caching test - null could mean a cached sculpt map has been found
2009-05-29 06:50:15 +00:00
//if (texture != null)
2008-05-01 18:04:42 +00:00
{
2009-05-29 06:50:15 +00:00
if ( texture ! = null )
2011-07-11 02:13:59 +00:00
{
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Setting sculpt data for {0} on SculptTextureCallback()", Name);
2009-05-29 04:29:55 +00:00
m_shape . SculptData = texture . Data ;
2011-07-11 02:13:59 +00:00
}
2009-05-29 04:29:55 +00:00
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
2008-05-25 04:15:32 +00:00
{
2011-07-11 02:13:59 +00:00
// Update the physics actor with the new loaded sculpt data and set the taint signal.
2012-04-03 04:50:13 +00:00
pa . Shape = m_shape ;
2009-01-15 02:17:30 +00:00
2012-04-03 04:50:13 +00:00
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( pa ) ;
2008-05-25 04:15:32 +00:00
}
2008-05-01 18:04:42 +00:00
}
}
2008-06-27 19:21:15 +00:00
}
2012-10-07 00:20:52 +00:00
* /
2008-06-27 19:21:15 +00:00
/// <summary>
2010-03-03 23:29:09 +00:00
/// Send a full update to the client for the given part
2008-06-27 19:21:15 +00:00
/// </summary>
/// <param name="remoteClient"></param>
2011-12-16 23:20:12 +00:00
protected internal void SendFullUpdate ( IClientAPI remoteClient )
2008-06-27 19:21:15 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup = = null )
2011-09-01 00:22:28 +00:00
return ;
2010-03-03 23:29:09 +00:00
// m_log.DebugFormat(
// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
if ( IsRoot )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsAttachment )
2010-03-03 23:29:09 +00:00
{
2011-12-16 23:20:12 +00:00
SendFullUpdateToClient ( remoteClient , AttachedPos ) ;
2010-03-03 23:29:09 +00:00
}
else
{
2011-12-16 23:20:12 +00:00
SendFullUpdateToClient ( remoteClient , AbsolutePosition ) ;
2010-03-03 23:29:09 +00:00
}
}
else
{
2011-12-16 23:20:12 +00:00
SendFullUpdateToClient ( remoteClient ) ;
2010-03-03 23:29:09 +00:00
}
2010-03-10 04:15:36 +00:00
}
2008-06-10 08:35:46 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
2010-03-03 23:29:09 +00:00
/// Send a full update for this part to all clients.
2008-06-27 19:21:15 +00:00
/// </summary>
public void SendFullUpdateToAllClients ( )
2008-05-01 16:35:00 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup = = null )
2011-09-01 00:22:28 +00:00
return ;
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . ForEachScenePresence ( delegate ( ScenePresence avatar )
2008-05-01 16:35:00 +00:00
{
2011-12-16 23:20:12 +00:00
SendFullUpdate ( avatar . ControllingClient ) ;
2010-03-17 13:40:00 +00:00
} ) ;
2007-11-16 08:53:37 +00:00
}
2008-06-10 08:35:46 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Sends a full update to the client
/// </summary>
/// <param name="remoteClient"></param>
2011-12-16 23:20:12 +00:00
public void SendFullUpdateToClient ( IClientAPI remoteClient )
2008-05-01 16:35:00 +00:00
{
2011-12-16 23:20:12 +00:00
SendFullUpdateToClient ( remoteClient , OffsetPosition ) ;
2008-06-27 19:21:15 +00:00
}
/// <summary>
/// Sends a full update to the client
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="lPos"></param>
2011-12-16 23:20:12 +00:00
public void SendFullUpdateToClient ( IClientAPI remoteClient , Vector3 lPos )
2008-06-27 19:21:15 +00:00
{
2011-09-01 00:22:28 +00:00
if ( ParentGroup = = null )
return ;
2008-10-03 21:44:33 +00:00
// Suppress full updates during attachment editing
/ /
2011-08-26 23:15:21 +00:00
if ( ParentGroup . IsSelected & & ParentGroup . IsAttachment )
2008-10-03 21:44:33 +00:00
return ;
2008-11-17 16:33:41 +00:00
if ( ParentGroup . IsDeleted )
return ;
2008-10-03 21:44:33 +00:00
2012-06-14 00:12:16 +00:00
if ( ParentGroup . IsAttachment
& & ParentGroup . AttachedAvatar ! = remoteClient . AgentId
& & ParentGroup . HasPrivateAttachmentPoint )
2011-09-24 22:51:43 +00:00
return ;
2011-11-11 01:21:37 +00:00
if ( remoteClient . AgentId = = OwnerID )
2008-05-01 16:35:00 +00:00
{
2010-08-10 16:26:31 +00:00
if ( ( Flags & PrimFlags . CreateSelected ) ! = 0 )
Flags & = ~ PrimFlags . CreateSelected ;
2008-06-27 19:21:15 +00:00
}
2008-08-17 03:09:47 +00:00
//bool isattachment = IsAttachment;
//if (LocalId != ParentGroup.RootPart.LocalId)
//isattachment = ParentGroup.RootPart.IsAttachment;
2008-05-01 18:04:42 +00:00
2011-10-14 00:45:46 +00:00
remoteClient . SendEntityUpdate ( this , PrimUpdateFlags . FullUpdate ) ;
2011-10-11 21:17:05 +00:00
ParentGroup . Scene . StatsReporter . AddObjectUpdates ( 1 ) ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Tell all the prims which have had updates scheduled
/// </summary>
public void SendScheduledUpdates ( )
{
2009-10-28 21:13:17 +00:00
const float ROTATION_TOLERANCE = 0.01f ;
const float VELOCITY_TOLERANCE = 0.001f ;
const float POSITION_TOLERANCE = 0.05f ;
2009-10-28 10:21:53 +00:00
const int TIME_MS_TOLERANCE = 3000 ;
2009-10-27 01:22:32 +00:00
2011-11-02 21:59:00 +00:00
switch ( UpdateFlag )
2008-06-27 19:21:15 +00:00
{
2011-11-02 21:59:00 +00:00
case UpdateRequired . TERSE :
2009-10-27 01:22:32 +00:00
{
2011-12-14 05:37:17 +00:00
ClearUpdateSchedule ( ) ;
2011-11-02 21:59:00 +00:00
// Throw away duplicate or insignificant updates
if ( ! RotationOffset . ApproxEquals ( m_lastRotation , ROTATION_TOLERANCE ) | |
! Acceleration . Equals ( m_lastAcceleration ) | |
! Velocity . ApproxEquals ( m_lastVelocity , VELOCITY_TOLERANCE ) | |
Velocity . ApproxEquals ( Vector3 . Zero , VELOCITY_TOLERANCE ) | |
! AngularVelocity . ApproxEquals ( m_lastAngularVelocity , VELOCITY_TOLERANCE ) | |
! OffsetPosition . ApproxEquals ( m_lastPosition , POSITION_TOLERANCE ) | |
Environment . TickCount - m_lastTerseSent > TIME_MS_TOLERANCE )
{
2011-11-12 01:16:52 +00:00
SendTerseUpdateToAllClients ( ) ;
2011-11-02 21:59:00 +00:00
// Update the "last" values
m_lastPosition = OffsetPosition ;
m_lastRotation = RotationOffset ;
m_lastVelocity = Velocity ;
m_lastAcceleration = Acceleration ;
m_lastAngularVelocity = AngularVelocity ;
m_lastTerseSent = Environment . TickCount ;
}
break ;
2009-10-27 01:22:32 +00:00
}
2011-11-02 21:59:00 +00:00
case UpdateRequired . FULL :
2008-06-27 19:21:15 +00:00
{
2011-12-14 05:37:17 +00:00
ClearUpdateSchedule ( ) ;
2011-11-12 01:16:52 +00:00
SendFullUpdateToAllClients ( ) ;
2011-11-02 21:59:00 +00:00
break ;
2008-06-27 19:21:15 +00:00
}
}
}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
2008-11-17 16:33:41 +00:00
/// Send a terse update to all clients
2008-06-27 19:21:15 +00:00
/// </summary>
public void SendTerseUpdateToAllClients ( )
{
2011-11-12 01:16:52 +00:00
ParentGroup . Scene . ForEachClient ( delegate ( IClientAPI client )
2008-06-27 19:21:15 +00:00
{
2011-11-12 01:16:52 +00:00
SendTerseUpdateToClient ( client ) ;
2010-03-17 13:40:00 +00:00
} ) ;
2007-12-23 13:14:56 +00:00
}
2008-06-27 19:21:15 +00:00
public void SetAxisRotation ( int axis , int rotate )
2008-02-05 05:26:18 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . SetAxisRotation ( axis , rotate ) ;
2011-07-11 02:13:59 +00:00
2010-01-10 19:58:44 +00:00
//Cannot use ScriptBaseClass constants as no referance to it currently.
2012-12-18 22:59:41 +00:00
if ( ( axis & ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_X ) ! = 0 )
2010-01-10 19:58:44 +00:00
STATUS_ROTATE_X = rotate ;
2011-07-11 02:13:59 +00:00
2012-12-18 22:59:41 +00:00
if ( ( axis & ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_Y ) ! = 0 )
2010-01-10 19:58:44 +00:00
STATUS_ROTATE_Y = rotate ;
2011-07-11 02:13:59 +00:00
2012-12-18 22:59:41 +00:00
if ( ( axis & ( int ) SceneObjectGroup . axisSelect . STATUS_ROTATE_Z ) ! = 0 )
2010-01-07 03:19:00 +00:00
STATUS_ROTATE_Z = rotate ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
public void SetBuoyancy ( float fvalue )
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . Buoyancy = fvalue ;
2008-02-05 05:26:18 +00:00
}
2008-06-27 19:21:15 +00:00
public void SetDieAtEdge ( bool p )
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup . IsDeleted )
2008-06-27 19:21:15 +00:00
return ;
2008-02-05 05:26:18 +00:00
2011-11-11 01:21:37 +00:00
ParentGroup . RootPart . DIE_AT_EDGE = p ;
2008-06-27 19:21:15 +00:00
}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
public void SetFloatOnWater ( int floatYN )
2008-05-01 18:04:42 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . FloatOnWater = floatYN = = 1 ;
2008-02-05 05:26:18 +00:00
}
2009-10-26 06:16:12 +00:00
public void SetForce ( Vector3 force )
2008-07-24 07:45:58 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . Force = force ;
2008-07-24 07:45:58 +00:00
}
2008-09-28 22:38:59 +00:00
public void SetVehicleType ( int type )
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . VehicleType = type ;
2008-09-28 22:38:59 +00:00
}
2008-09-28 20:20:32 +00:00
public void SetVehicleFloatParam ( int param , float value )
2008-09-28 18:36:30 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . VehicleFloatParam ( param , value ) ;
2008-09-28 20:20:32 +00:00
}
2009-10-26 06:16:12 +00:00
public void SetVehicleVectorParam ( int param , Vector3 value )
2008-09-28 20:20:32 +00:00
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . VehicleVectorParam ( param , value ) ;
2008-09-28 18:36:30 +00:00
}
2008-09-28 21:53:56 +00:00
public void SetVehicleRotationParam ( int param , Quaternion rotation )
{
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . VehicleRotationParam ( param , rotation ) ;
2008-09-28 21:53:56 +00:00
}
2012-08-17 14:09:52 +00:00
/// <summary>
/// Set the color & alpha of prim faces
/// </summary>
/// <param name="face"></param>
/// <param name="color"></param>
/// <param name="alpha"></param>
2012-08-20 08:31:29 +00:00
public void SetFaceColorAlpha ( int face , Vector3 color , double ? alpha )
2012-08-17 14:09:52 +00:00
{
2012-08-20 08:26:26 +00:00
Vector3 clippedColor = Util . Clip ( color , 0.0f , 1.0f ) ;
2012-08-20 08:31:29 +00:00
float clippedAlpha = alpha . HasValue ?
Util . Clip ( ( float ) alpha . Value , 0.0f , 1.0f ) : 0 ;
2012-08-20 08:26:26 +00:00
2012-08-17 14:09:52 +00:00
// The only way to get a deep copy/ If we don't do this, we can
// never detect color changes further down.
Byte [ ] buf = Shape . Textures . GetBytes ( ) ;
Primitive . TextureEntry tex = new Primitive . TextureEntry ( buf , 0 , buf . Length ) ;
Color4 texcolor ;
if ( face > = 0 & & face < GetNumberOfSides ( ) )
{
texcolor = tex . CreateFace ( ( uint ) face ) . RGBA ;
2012-08-20 08:26:26 +00:00
texcolor . R = clippedColor . X ;
texcolor . G = clippedColor . Y ;
texcolor . B = clippedColor . Z ;
2012-08-20 08:31:29 +00:00
if ( alpha . HasValue )
{
texcolor . A = clippedAlpha ;
}
2012-08-17 14:09:52 +00:00
tex . FaceTextures [ face ] . RGBA = texcolor ;
UpdateTextureEntry ( tex . GetBytes ( ) ) ;
return ;
}
else if ( face = = ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
texcolor = tex . FaceTextures [ i ] . RGBA ;
2012-08-20 08:26:26 +00:00
texcolor . R = clippedColor . X ;
texcolor . G = clippedColor . Y ;
texcolor . B = clippedColor . Z ;
2012-08-20 08:31:29 +00:00
if ( alpha . HasValue )
{
texcolor . A = clippedAlpha ;
}
2012-08-17 14:09:52 +00:00
tex . FaceTextures [ i ] . RGBA = texcolor ;
}
texcolor = tex . DefaultTexture . RGBA ;
2012-08-20 08:26:26 +00:00
texcolor . R = clippedColor . X ;
texcolor . G = clippedColor . Y ;
texcolor . B = clippedColor . Z ;
2012-08-20 08:31:29 +00:00
if ( alpha . HasValue )
{
texcolor . A = clippedAlpha ;
}
2012-08-17 14:09:52 +00:00
tex . DefaultTexture . RGBA = texcolor ;
}
UpdateTextureEntry ( tex . GetBytes ( ) ) ;
return ;
}
}
2010-02-01 21:35:05 +00:00
/// <summary>
/// Get the number of sides that this part has.
/// </summary>
/// <returns></returns>
public int GetNumberOfSides ( )
{
int ret = 0 ;
bool hasCut ;
bool hasHollow ;
bool hasDimple ;
bool hasProfileCut ;
2010-02-01 22:33:15 +00:00
PrimType primType = GetPrimType ( ) ;
2010-02-01 22:08:00 +00:00
HasCutHollowDimpleProfileCut ( primType , Shape , out hasCut , out hasHollow , out hasDimple , out hasProfileCut ) ;
2010-02-01 21:35:05 +00:00
switch ( primType )
{
case PrimType . BOX :
ret = 6 ;
if ( hasCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . CYLINDER :
ret = 3 ;
if ( hasCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . PRISM :
ret = 5 ;
if ( hasCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . SPHERE :
ret = 1 ;
if ( hasCut ) ret + = 2 ;
if ( hasDimple ) ret + = 2 ;
2010-02-01 22:29:21 +00:00
if ( hasHollow ) ret + = 1 ;
2010-02-01 21:35:05 +00:00
break ;
case PrimType . TORUS :
ret = 1 ;
if ( hasCut ) ret + = 2 ;
if ( hasProfileCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . TUBE :
ret = 4 ;
if ( hasCut ) ret + = 2 ;
if ( hasProfileCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . RING :
ret = 3 ;
if ( hasCut ) ret + = 2 ;
if ( hasProfileCut ) ret + = 2 ;
if ( hasHollow ) ret + = 1 ;
break ;
case PrimType . SCULPT :
2011-11-25 14:21:42 +00:00
// Special mesh handling
2011-12-03 15:54:06 +00:00
if ( Shape . SculptType = = ( byte ) SculptType . Mesh )
ret = 8 ; // if it's a mesh then max 8 faces
2011-11-25 14:21:42 +00:00
else
2011-12-03 15:54:06 +00:00
ret = 1 ; // if it's a sculpt then max 1 face
2010-02-01 21:35:05 +00:00
break ;
}
2011-12-03 15:54:06 +00:00
2010-02-01 21:35:05 +00:00
return ret ;
}
/// <summary>
/// Tell us what type this prim is
/// </summary>
/// <param name="primShape"></param>
/// <returns></returns>
2010-02-01 22:33:15 +00:00
public PrimType GetPrimType ( )
2010-02-01 21:35:05 +00:00
{
if ( Shape . SculptEntry )
return PrimType . SCULPT ;
2011-12-03 15:54:06 +00:00
2010-02-01 21:35:05 +00:00
if ( ( Shape . ProfileCurve & 0x07 ) = = ( byte ) ProfileShape . Square )
{
if ( Shape . PathCurve = = ( byte ) Extrusion . Straight )
return PrimType . BOX ;
else if ( Shape . PathCurve = = ( byte ) Extrusion . Curve1 )
return PrimType . TUBE ;
}
else if ( ( Shape . ProfileCurve & 0x07 ) = = ( byte ) ProfileShape . Circle )
{
if ( Shape . PathCurve = = ( byte ) Extrusion . Straight )
return PrimType . CYLINDER ;
// ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
else if ( Shape . PathCurve = = ( byte ) Extrusion . Curve1 )
return PrimType . TORUS ;
}
else if ( ( Shape . ProfileCurve & 0x07 ) = = ( byte ) ProfileShape . HalfCircle )
{
if ( Shape . PathCurve = = ( byte ) Extrusion . Curve1 | | Shape . PathCurve = = ( byte ) Extrusion . Curve2 )
return PrimType . SPHERE ;
}
else if ( ( Shape . ProfileCurve & 0x07 ) = = ( byte ) ProfileShape . EquilateralTriangle )
{
if ( Shape . PathCurve = = ( byte ) Extrusion . Straight )
return PrimType . PRISM ;
else if ( Shape . PathCurve = = ( byte ) Extrusion . Curve1 )
return PrimType . RING ;
}
return PrimType . BOX ;
}
/// <summary>
/// Tell us if this object has cut, hollow, dimple, and other factors affecting the number of faces
/// </summary>
/// <param name="primType"></param>
/// <param name="shape"></param>
/// <param name="hasCut"></param>
/// <param name="hasHollow"></param>
/// <param name="hasDimple"></param>
/// <param name="hasProfileCut"></param>
2010-02-01 22:08:00 +00:00
protected static void HasCutHollowDimpleProfileCut ( PrimType primType , PrimitiveBaseShape shape , out bool hasCut , out bool hasHollow ,
2010-02-01 21:35:05 +00:00
out bool hasDimple , out bool hasProfileCut )
{
if ( primType = = PrimType . BOX
| |
primType = = PrimType . CYLINDER
| |
primType = = PrimType . PRISM )
hasCut = ( shape . ProfileBegin > 0 ) | | ( shape . ProfileEnd > 0 ) ;
else
hasCut = ( shape . PathBegin > 0 ) | | ( shape . PathEnd > 0 ) ;
hasHollow = shape . ProfileHollow > 0 ;
hasDimple = ( shape . ProfileBegin > 0 ) | | ( shape . ProfileEnd > 0 ) ; // taken from llSetPrimitiveParms
hasProfileCut = hasDimple ; // is it the same thing?
}
2010-02-14 21:41:57 +00:00
public void SetVehicleFlags ( int param , bool remove )
{
2012-05-08 23:11:10 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
pa . VehicleFlags ( param , remove ) ;
2010-02-14 21:41:57 +00:00
}
2008-09-06 07:52:41 +00:00
public void SetGroup ( UUID groupID , IClientAPI client )
2008-06-27 19:21:15 +00:00
{
2011-12-17 02:23:24 +00:00
// Scene.AddNewPrims() calls with client == null so can't use this.
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Setting group for {0} to {1} for {2}",
// Name, groupID, OwnerID);
2011-11-11 01:21:37 +00:00
GroupID = groupID ;
2008-11-17 21:44:09 +00:00
if ( client ! = null )
2011-09-15 17:58:58 +00:00
SendPropertiesToClient ( client ) ;
2011-11-02 21:59:00 +00:00
UpdateFlag = UpdateRequired . FULL ;
2008-06-27 19:21:15 +00:00
}
2007-09-19 00:30:55 +00:00
2007-07-30 20:11:40 +00:00
/// <summary>
2011-09-01 00:22:28 +00:00
/// Set the parent group of this prim.
2007-07-30 20:11:40 +00:00
/// </summary>
2008-06-27 19:21:15 +00:00
public void SetParent ( SceneObjectGroup parent )
2007-07-30 20:11:40 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup = parent ;
2008-06-27 19:21:15 +00:00
}
// Use this for attachments! LocalID should be avatar's localid
public void SetParentLocalId ( uint localID )
{
2011-11-11 01:21:37 +00:00
ParentID = localID ;
2008-06-27 19:21:15 +00:00
}
public void SetPhysicsAxisRotation ( )
{
2012-05-08 23:11:10 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
2008-11-15 17:19:35 +00:00
{
2012-05-08 23:11:10 +00:00
pa . LockAngularMotion ( RotationAxis ) ;
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( pa ) ;
2008-11-15 17:19:35 +00:00
}
2008-06-27 19:21:15 +00:00
}
2010-02-02 19:04:06 +00:00
/// <summary>
/// Set the events that this part will pass on to listeners.
/// </summary>
/// <param name="scriptid"></param>
/// <param name="events"></param>
2008-09-06 07:52:41 +00:00
public void SetScriptEvents ( UUID scriptid , int events )
2008-06-27 19:21:15 +00:00
{
2008-06-27 19:57:06 +00:00
// scriptEvents oldparts;
2008-06-27 19:21:15 +00:00
lock ( m_scriptEvents )
2008-05-28 03:44:49 +00:00
{
2008-06-27 19:21:15 +00:00
if ( m_scriptEvents . ContainsKey ( scriptid ) )
{
2008-06-27 19:57:06 +00:00
// oldparts = m_scriptEvents[scriptid];
2008-06-27 19:21:15 +00:00
// remove values from aggregated script events
2008-09-08 22:19:06 +00:00
if ( m_scriptEvents [ scriptid ] = = ( scriptEvents ) events )
return ;
2008-06-27 19:21:15 +00:00
m_scriptEvents [ scriptid ] = ( scriptEvents ) events ;
}
else
{
m_scriptEvents . Add ( scriptid , ( scriptEvents ) events ) ;
}
2008-05-28 03:44:49 +00:00
}
2008-06-27 19:21:15 +00:00
aggregateScriptEvents ( ) ;
}
/// <summary>
/// Set the text displayed for this part.
/// </summary>
/// <param name="text"></param>
public void SetText ( string text )
{
Text = text ;
2007-08-02 16:40:50 +00:00
2011-09-01 00:22:28 +00:00
if ( ParentGroup ! = null )
{
ParentGroup . HasGroupChanged = true ;
ScheduleFullUpdate ( ) ;
}
2008-06-27 19:21:15 +00:00
}
2009-12-22 00:26:12 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
/// Set the text displayed for this part.
/// </summary>
/// <param name="text"></param>
/// <param name="color"></param>
/// <param name="alpha"></param>
public void SetText ( string text , Vector3 color , double alpha )
2007-12-05 06:44:32 +00:00
{
2010-05-24 22:37:47 +00:00
Color = Color . FromArgb ( ( int ) ( alpha * 0xff ) ,
2008-09-06 07:52:41 +00:00
( int ) ( color . X * 0xff ) ,
( int ) ( color . Y * 0xff ) ,
( int ) ( color . Z * 0xff ) ) ;
2008-06-27 19:21:15 +00:00
SetText ( text ) ;
2008-05-01 18:04:42 +00:00
}
2008-02-11 13:26:55 +00:00
2008-06-27 19:21:15 +00:00
public void StopMoveToTarget ( )
2008-05-01 18:04:42 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . stopMoveToTarget ( ) ;
2008-07-25 20:45:06 +00:00
2011-11-11 01:21:37 +00:00
ParentGroup . ScheduleGroupForTerseUpdate ( ) ;
//ParentGroup.ScheduleGroupForFullUpdate();
2008-06-27 19:21:15 +00:00
}
2008-02-16 13:01:42 +00:00
2008-06-27 19:21:15 +00:00
public void StoreUndoState ( )
2011-07-19 02:01:54 +00:00
{
StoreUndoState ( false ) ;
}
public void StoreUndoState ( bool forGroup )
2008-06-27 19:21:15 +00:00
{
2012-09-26 22:31:10 +00:00
if ( ParentGroup = = null | | ParentGroup . Scene = = null )
return ;
2012-09-26 22:25:50 +00:00
if ( Undoing )
2008-05-01 16:35:00 +00:00
{
2012-09-26 22:25:50 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
return ;
}
if ( IgnoreUndoUpdate )
{
// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
return ;
}
lock ( m_undo )
{
if ( m_undo . Count > 0 )
2008-05-01 18:04:42 +00:00
{
2012-09-26 22:25:50 +00:00
UndoState last = m_undo [ m_undo . Count - 1 ] ;
if ( last ! = null )
2008-05-01 18:04:42 +00:00
{
2012-09-26 22:25:50 +00:00
// TODO: May need to fix for group comparison
if ( last . Compare ( this ) )
2008-06-27 19:21:15 +00:00
{
2012-09-26 22:25:50 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
// Name, LocalId, m_undo.Count);
return ;
}
}
}
2012-09-26 20:28:43 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
// Name, LocalId, forGroup, m_undo.Count);
2012-09-26 21:49:44 +00:00
2012-09-26 23:12:34 +00:00
if ( ParentGroup . Scene . MaxUndoCount > 0 )
2012-09-26 22:25:50 +00:00
{
UndoState nUndo = new UndoState ( this , forGroup ) ;
m_undo . Add ( nUndo ) ;
2012-09-26 23:12:34 +00:00
if ( m_undo . Count > ParentGroup . Scene . MaxUndoCount )
2012-09-26 22:25:50 +00:00
m_undo . RemoveAt ( 0 ) ;
if ( m_redo . Count > 0 )
m_redo . Clear ( ) ;
2012-09-26 20:28:43 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
// Name, LocalId, forGroup, m_undo.Count);
2008-06-27 19:21:15 +00:00
}
2008-02-11 13:26:55 +00:00
}
2008-05-01 18:04:42 +00:00
}
2011-07-18 01:01:12 +00:00
/// <summary>
/// Return number of undos on the stack. Here temporarily pending a refactor.
/// </summary>
public int UndoCount
{
get
{
lock ( m_undo )
return m_undo . Count ;
}
}
2011-07-18 00:33:57 +00:00
public void Undo ( )
{
lock ( m_undo )
{
2011-07-19 04:14:58 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
// Name, LocalId, m_undo.Count);
2011-07-18 03:54:21 +00:00
2011-07-18 00:33:57 +00:00
if ( m_undo . Count > 0 )
{
2012-09-26 21:49:44 +00:00
UndoState goback = m_undo [ m_undo . Count - 1 ] ;
m_undo . RemoveAt ( m_undo . Count - 1 ) ;
2011-07-18 00:33:57 +00:00
2012-09-26 21:49:44 +00:00
UndoState nUndo = null ;
2012-09-26 23:12:34 +00:00
if ( ParentGroup . Scene . MaxUndoCount > 0 )
2011-07-18 00:33:57 +00:00
{
2012-09-26 21:49:44 +00:00
nUndo = new UndoState ( this , goback . ForGroup ) ;
}
goback . PlaybackState ( this ) ;
2011-07-19 02:01:54 +00:00
2012-09-26 21:49:44 +00:00
if ( nUndo ! = null )
{
m_redo . Add ( nUndo ) ;
2011-07-18 03:54:21 +00:00
2012-09-26 23:12:34 +00:00
if ( m_redo . Count > ParentGroup . Scene . MaxUndoCount )
2012-09-26 21:49:44 +00:00
m_redo . RemoveAt ( 0 ) ;
2011-07-18 00:33:57 +00:00
}
}
2011-07-18 03:54:21 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}",
// Name, LocalId, m_undo.Count);
2011-07-18 00:33:57 +00:00
}
}
public void Redo ( )
{
2011-07-19 05:13:05 +00:00
lock ( m_undo )
2011-07-18 00:33:57 +00:00
{
2011-07-18 03:54:21 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
// Name, LocalId, m_redo.Count);
2011-07-19 05:05:23 +00:00
if ( m_redo . Count > 0 )
2011-07-19 02:01:54 +00:00
{
2012-09-26 21:49:44 +00:00
UndoState gofwd = m_redo [ m_redo . Count - 1 ] ;
m_redo . RemoveAt ( m_redo . Count - 1 ) ;
2012-09-26 23:12:34 +00:00
if ( ParentGroup . Scene . MaxUndoCount > 0 )
2011-07-19 02:01:54 +00:00
{
2012-09-26 21:49:44 +00:00
UndoState nUndo = new UndoState ( this , gofwd . ForGroup ) ;
m_undo . Add ( nUndo ) ;
2012-09-26 23:12:34 +00:00
if ( m_undo . Count > ParentGroup . Scene . MaxUndoCount )
2012-09-26 21:49:44 +00:00
m_undo . RemoveAt ( 0 ) ;
2011-07-19 02:01:54 +00:00
}
2012-09-26 21:49:44 +00:00
gofwd . PlayfwdState ( this ) ;
2011-07-18 03:54:21 +00:00
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",
// Name, LocalId, m_redo.Count);
2011-07-19 05:05:23 +00:00
}
2011-07-18 00:33:57 +00:00
}
}
public void ClearUndoState ( )
{
2011-07-18 03:54:21 +00:00
// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId);
2011-07-18 00:33:57 +00:00
lock ( m_undo )
{
m_undo . Clear ( ) ;
m_redo . Clear ( ) ;
}
}
2008-06-27 19:21:15 +00:00
public EntityIntersection TestIntersection ( Ray iray , Quaternion parentrot )
2008-05-01 18:04:42 +00:00
{
2009-08-14 08:16:41 +00:00
// In this case we're using a sphere with a radius of the largest dimension of the prim
2008-06-27 19:21:15 +00:00
// TODO: Change to take shape into account
2008-05-01 18:04:42 +00:00
2009-08-14 08:16:41 +00:00
EntityIntersection result = new EntityIntersection ( ) ;
2008-09-06 07:52:41 +00:00
Vector3 vAbsolutePosition = AbsolutePosition ;
Vector3 vScale = Scale ;
2008-06-27 19:21:15 +00:00
Vector3 rOrigin = iray . Origin ;
Vector3 rDirection = iray . Direction ;
//rDirection = rDirection.Normalize();
// Buidling the first part of the Quadratic equation
Vector3 r2ndDirection = rDirection * rDirection ;
2008-09-06 07:52:41 +00:00
float itestPart1 = r2ndDirection . X + r2ndDirection . Y + r2ndDirection . Z ;
2008-06-27 19:21:15 +00:00
// Buidling the second part of the Quadratic equation
Vector3 tmVal2 = rOrigin - vAbsolutePosition ;
Vector3 r2Direction = rDirection * 2.0f ;
Vector3 tmVal3 = r2Direction * tmVal2 ;
2008-09-06 07:52:41 +00:00
float itestPart2 = tmVal3 . X + tmVal3 . Y + tmVal3 . Z ;
2008-06-27 19:21:15 +00:00
// Buidling the third part of the Quadratic equation
Vector3 tmVal4 = rOrigin * rOrigin ;
Vector3 tmVal5 = vAbsolutePosition * vAbsolutePosition ;
Vector3 tmVal6 = vAbsolutePosition * rOrigin ;
2009-08-14 08:16:41 +00:00
// Set Radius to the largest dimension of the prim
2008-06-27 19:21:15 +00:00
float radius = 0f ;
2008-09-06 07:52:41 +00:00
if ( vScale . X > radius )
radius = vScale . X ;
if ( vScale . Y > radius )
radius = vScale . Y ;
if ( vScale . Z > radius )
radius = vScale . Z ;
2008-06-27 19:21:15 +00:00
// 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;
2008-09-06 07:52:41 +00:00
float itestPart3 = tmVal4 . X + tmVal4 . Y + tmVal4 . Z + tmVal5 . X + tmVal5 . Y + tmVal5 . Z -
( 2.0f * ( tmVal6 . X + tmVal6 . Y + tmVal6 . Z + ( radius * radius ) ) ) ;
2008-06-27 19:21:15 +00:00
// Yuk Quadradrics.. Solve first
float rootsqr = ( itestPart2 * itestPart2 ) - ( 4.0f * itestPart1 * itestPart3 ) ;
if ( rootsqr < 0.0f )
2007-09-06 14:15:16 +00:00
{
2008-06-27 19:21:15 +00:00
// No intersection
2009-08-14 08:16:41 +00:00
return result ;
2008-06-27 19:21:15 +00:00
}
float root = ( ( - itestPart2 ) - ( float ) Math . Sqrt ( ( double ) rootsqr ) ) / ( itestPart1 * 2.0f ) ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
if ( root < 0.0f )
{
// perform second quadratic root solution
root = ( ( - itestPart2 ) + ( float ) Math . Sqrt ( ( double ) rootsqr ) ) / ( itestPart1 * 2.0f ) ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// is there any intersection?
if ( root < 0.0f )
2008-05-01 16:35:00 +00:00
{
2008-06-27 19:21:15 +00:00
// nope, no intersection
2009-08-14 08:16:41 +00:00
return result ;
2008-02-10 10:55:57 +00:00
}
}
2007-09-06 14:15:16 +00:00
2008-06-27 19:21:15 +00:00
// We got an intersection. putting together an EntityIntersection object with the
// intersection information
Vector3 ipoint =
2008-09-06 07:52:41 +00:00
new Vector3 ( iray . Origin . X + ( iray . Direction . X * root ) , iray . Origin . Y + ( iray . Direction . Y * root ) ,
iray . Origin . Z + ( iray . Direction . Z * root ) ) ;
2007-08-03 12:00:24 +00:00
2009-08-14 08:16:41 +00:00
result . HitTF = true ;
result . ipoint = ipoint ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// Normal is calculated by the difference and then normalizing the result
Vector3 normalpart = ipoint - vAbsolutePosition ;
2009-08-14 08:16:41 +00:00
result . normal = normalpart / normalpart . Length ( ) ;
2008-06-27 19:21:15 +00:00
2008-09-06 07:52:41 +00:00
// It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't.
2008-06-27 19:21:15 +00:00
// I can write a function to do it.. but I like the fact that this one is Static.
2008-09-06 07:52:41 +00:00
Vector3 distanceConvert1 = new Vector3 ( iray . Origin . X , iray . Origin . Y , iray . Origin . Z ) ;
Vector3 distanceConvert2 = new Vector3 ( ipoint . X , ipoint . Y , ipoint . Z ) ;
2008-06-27 19:21:15 +00:00
float distance = ( float ) Util . GetDistanceTo ( distanceConvert1 , distanceConvert2 ) ;
2009-08-14 08:16:41 +00:00
result . distance = distance ;
2008-06-27 19:21:15 +00:00
2009-08-14 08:16:41 +00:00
return result ;
2008-06-27 19:21:15 +00:00
}
public EntityIntersection TestIntersectionOBB ( Ray iray , Quaternion parentrot , bool frontFacesOnly , bool faceCenters )
2007-08-07 17:25:21 +00:00
{
2008-06-27 19:21:15 +00:00
// 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 ] ;
2008-06-27 19:57:06 +00:00
// float[] distance = new float[6];
2008-06-27 19:21:15 +00:00
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
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
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 ) ;
2007-08-07 17:25:21 +00:00
2008-06-27 19:21:15 +00:00
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 ( ) ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
Vector3 pos = GetWorldPosition ( ) ;
Quaternion rot = GetWorldRotation ( ) ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// Variables prefixed with AX are Axiom.Math copies of the LL variety.
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
Quaternion AXrot = rot ;
2008-06-27 19:21:15 +00:00
AXrot . Normalize ( ) ;
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
Vector3 AXpos = pos ;
2007-09-06 14:15:16 +00:00
2008-06-27 19:21:15 +00:00
// 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
2007-09-06 14:15:16 +00:00
2008-09-06 07:52:41 +00:00
Vector3 tScale = Vector3 . Zero ;
2007-08-03 12:00:24 +00:00
2008-06-27 19:21:15 +00:00
Vector3 AXscale = new Vector3 ( m_shape . Scale . X * 0.5f , m_shape . Scale . Y * 0.5f , m_shape . Scale . Z * 0.5f ) ;
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
//Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale));
//Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1));
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// rScale is the rotated offset to find a vertex based on the scale and the world rotation.
Vector3 rScale = new Vector3 ( ) ;
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
// Get Vertexes for Faces Stick them into ABCD for each Face
// Form: Face<vertex>[face] that corresponds to the below diagram
#region ABCD Face Vertex Map Comment Diagram
// A _________ B
// | |
// | 4 top |
// |_________|
// C D
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
// A _________ B
// | Back |
// | 3 |
// |_________|
// C D
2007-09-19 00:30:55 +00:00
2008-06-27 19:21:15 +00:00
// A _________ B B _________ A
// | Left | | Right |
// | 0 | | 2 |
// |_________| |_________|
// C D D C
2007-12-27 21:41:48 +00:00
2008-06-27 19:21:15 +00:00
// A _________ B
// | Front |
// | 1 |
// |_________|
// C D
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
// C _________ D
// | |
// | 5 bot |
// |_________|
// A B
# endregion
2008-05-16 01:22:11 +00:00
2008-06-27 19:21:15 +00:00
#region Plane Decomposition of Oriented Bounding Box
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( AXscale . X , - AXscale . Y , AXscale . Z ) ;
rScale = tScale * AXrot ;
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;
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
FaceA [ 0 ] = vertexes [ 0 ] ;
FaceB [ 3 ] = vertexes [ 0 ] ;
FaceA [ 4 ] = vertexes [ 0 ] ;
2007-12-27 21:41:48 +00:00
2008-06-27 19:21:15 +00:00
tScale = AXscale ;
2008-09-06 07:52:41 +00:00
rScale = tScale * AXrot ;
vertexes [ 1 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2007-11-16 08:53:37 +00:00
2008-09-06 07:52:41 +00:00
// vertexes[1].X = pos.X + vertexes[1].X;
// vertexes[1].Y = pos.Y + vertexes[1].Y;
//vertexes[1].Z = pos.Z + vertexes[1].Z;
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
FaceB [ 0 ] = vertexes [ 1 ] ;
FaceA [ 1 ] = vertexes [ 1 ] ;
FaceC [ 4 ] = vertexes [ 1 ] ;
2007-08-16 18:40:44 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( AXscale . X , - AXscale . Y , - AXscale . Z ) ;
rScale = tScale * AXrot ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
vertexes [ 2 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
//vertexes[2].X = pos.X + vertexes[2].X;
//vertexes[2].Y = pos.Y + vertexes[2].Y;
//vertexes[2].Z = pos.Z + vertexes[2].Z;
2008-03-25 14:27:39 +00:00
2008-06-27 19:21:15 +00:00
FaceC [ 0 ] = vertexes [ 2 ] ;
FaceD [ 3 ] = vertexes [ 2 ] ;
FaceC [ 5 ] = vertexes [ 2 ] ;
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( AXscale . X , AXscale . Y , - AXscale . Z ) ;
rScale = tScale * AXrot ;
vertexes [ 3 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
//vertexes[3].X = pos.X + vertexes[3].X;
// vertexes[3].Y = pos.Y + vertexes[3].Y;
// vertexes[3].Z = pos.Z + vertexes[3].Z;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
FaceD [ 0 ] = vertexes [ 3 ] ;
FaceC [ 1 ] = vertexes [ 3 ] ;
FaceA [ 5 ] = vertexes [ 3 ] ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( - AXscale . X , AXscale . Y , AXscale . Z ) ;
rScale = tScale * AXrot ;
vertexes [ 4 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-03-04 05:31:54 +00:00
2008-09-06 07:52:41 +00:00
// vertexes[4].X = pos.X + vertexes[4].X;
// vertexes[4].Y = pos.Y + vertexes[4].Y;
// vertexes[4].Z = pos.Z + vertexes[4].Z;
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
FaceB [ 1 ] = vertexes [ 4 ] ;
FaceA [ 2 ] = vertexes [ 4 ] ;
FaceD [ 4 ] = vertexes [ 4 ] ;
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( - AXscale . X , AXscale . Y , - AXscale . Z ) ;
rScale = tScale * AXrot ;
vertexes [ 5 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-05-01 16:35:00 +00:00
2008-09-06 07:52:41 +00:00
// vertexes[5].X = pos.X + vertexes[5].X;
// vertexes[5].Y = pos.Y + vertexes[5].Y;
// vertexes[5].Z = pos.Z + vertexes[5].Z;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
FaceD [ 1 ] = vertexes [ 5 ] ;
FaceC [ 2 ] = vertexes [ 5 ] ;
FaceB [ 5 ] = vertexes [ 5 ] ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( - AXscale . X , - AXscale . Y , AXscale . Z ) ;
rScale = tScale * AXrot ;
vertexes [ 6 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-03-04 05:31:54 +00:00
2008-09-06 07:52:41 +00:00
// vertexes[6].X = pos.X + vertexes[6].X;
// vertexes[6].Y = pos.Y + vertexes[6].Y;
// vertexes[6].Z = pos.Z + vertexes[6].Z;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
FaceB [ 2 ] = vertexes [ 6 ] ;
FaceA [ 3 ] = vertexes [ 6 ] ;
FaceB [ 4 ] = vertexes [ 6 ] ;
2008-05-01 18:04:42 +00:00
2008-09-06 07:52:41 +00:00
tScale = new Vector3 ( - AXscale . X , - AXscale . Y , - AXscale . Z ) ;
rScale = tScale * AXrot ;
vertexes [ 7 ] = ( new Vector3 ( ( pos . X + rScale . X ) , ( pos . Y + rScale . Y ) , ( pos . Z + rScale . Z ) ) ) ;
2008-03-04 05:31:54 +00:00
2008-09-06 07:52:41 +00:00
// vertexes[7].X = pos.X + vertexes[7].X;
// vertexes[7].Y = pos.Y + vertexes[7].Y;
// vertexes[7].Z = pos.Z + vertexes[7].Z;
2008-06-27 19:21:15 +00:00
FaceD [ 2 ] = vertexes [ 7 ] ;
FaceC [ 3 ] = vertexes [ 7 ] ;
FaceD [ 5 ] = vertexes [ 7 ] ;
# endregion
// Get our plane normals
for ( int i = 0 ; i < 6 ; i + + )
2008-05-01 18:04:42 +00:00
{
2008-06-27 19:21:15 +00:00
//m_log.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]);
2008-03-04 05:31:54 +00:00
2008-06-27 19:21:15 +00:00
// Our Plane direction
AmBa = FaceA [ i ] - FaceB [ i ] ;
AmBb = FaceB [ i ] - FaceC [ i ] ;
2008-03-04 05:31:54 +00:00
2008-09-06 07:52:41 +00:00
cross = Vector3 . Cross ( AmBb , AmBa ) ;
2008-03-04 05:31:54 +00:00
2008-06-27 19:21:15 +00:00
// normalize the cross product to get the normal.
2008-09-06 07:52:41 +00:00
normals [ i ] = cross / cross . Length ( ) ;
2008-06-27 19:21:15 +00:00
//m_log.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString());
2008-09-06 07:52:41 +00:00
//distance[i] = (normals[i].X * AmBa.X + normals[i].Y * AmBa.Y + normals[i].Z * AmBa.Z) * -1;
2008-03-04 05:31:54 +00:00
}
2009-08-14 08:16:41 +00:00
EntityIntersection result = new EntityIntersection ( ) ;
2008-03-04 05:31:54 +00:00
2009-08-14 08:16:41 +00:00
result . distance = 1024 ;
2008-06-27 19:21:15 +00:00
float c = 0 ;
float a = 0 ;
float d = 0 ;
Vector3 q = new Vector3 ( ) ;
2008-03-25 14:27:39 +00:00
2008-06-27 19:21:15 +00:00
#region OBB Version 2 Experiment
//float fmin = 999999;
//float fmax = -999999;
//float s = 0;
2008-04-28 01:48:21 +00:00
2008-06-27 19:21:15 +00:00
//for (int i=0;i<6;i++)
//{
//s = iray.Direction.Dot(normals[i]);
//d = normals[i].Dot(FaceB[i]);
2008-04-30 16:52:12 +00:00
2008-06-27 19:21:15 +00:00
//if (s == 0)
//{
//if (iray.Origin.Dot(normals[i]) > d)
//{
2009-08-14 08:16:41 +00:00
//return result;
2008-06-27 19:21:15 +00:00
//}
// else
//{
//continue;
//}
//}
//a = (d - iray.Origin.Dot(normals[i])) / s;
//if (iray.Direction.Dot(normals[i]) < 0)
//{
//if (a > fmax)
//{
//if (a > fmin)
//{
2009-08-14 08:16:41 +00:00
//return result;
2008-06-27 19:21:15 +00:00
//}
//fmax = a;
//}
2008-04-30 16:52:12 +00:00
2008-06-27 19:21:15 +00:00
//}
//else
//{
//if (a < fmin)
//{
//if (a < 0 || a < fmax)
//{
2009-08-14 08:16:41 +00:00
//return result;
2008-06-27 19:21:15 +00:00
//}
//fmin = a;
//}
//}
//}
//if (fmax > 0)
// a= fmax;
//else
// a=fmin;
2008-04-30 16:52:12 +00:00
2008-06-27 19:21:15 +00:00
//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 ] ;
2008-09-06 07:52:41 +00:00
d = Vector3 . Dot ( normals [ i ] , FaceB [ i ] ) ;
2008-06-27 19:21:15 +00:00
//if (faceCenters)
//{
// c = normals[i].Dot(normals[i]);
//}
//else
//{
2008-09-06 07:52:41 +00:00
c = Vector3 . Dot ( iray . Direction , normals [ i ] ) ;
2008-06-27 19:21:15 +00:00
//}
if ( c = = 0 )
continue ;
2008-04-30 16:52:12 +00:00
2008-09-06 07:52:41 +00:00
a = ( d - Vector3 . Dot ( iray . Origin , normals [ i ] ) ) / c ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
if ( a < 0 )
continue ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
// If the normal is pointing outside the object
2008-09-06 07:52:41 +00:00
if ( Vector3 . Dot ( iray . Direction , normals [ i ] ) < 0 | | ! frontFacesOnly )
2008-06-27 19:21:15 +00:00
{
//if (faceCenters)
//{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f;
// q = iray.Origin + a * normals[i];
//}
//else
//{
2008-09-06 07:52:41 +00:00
q = iray . Origin + iray . Direction * a ;
2008-06-27 19:21:15 +00:00
//}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
float distance2 = ( float ) GetDistanceTo ( q , AXpos ) ;
// Is this the closest hit to the object's origin?
//if (faceCenters)
//{
// distance2 = (float)GetDistanceTo(q, iray.Origin);
//}
2008-05-01 18:04:42 +00:00
2009-08-14 08:16:41 +00:00
if ( distance2 < result . distance )
2008-06-27 19:21:15 +00:00
{
2009-08-14 08:16:41 +00:00
result . distance = distance2 ;
result . HitTF = true ;
result . ipoint = q ;
2013-01-24 02:58:51 +00:00
result . face = i ;
2008-06-27 19:21:15 +00:00
//m_log.Info("[FACE]:" + i.ToString());
//m_log.Info("[POINT]: " + q.ToString());
//m_log.Info("[DIST]: " + distance2.ToString());
if ( faceCenters )
{
2009-08-14 08:16:41 +00:00
result . normal = AAfacenormals [ i ] * AXrot ;
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
Vector3 scaleComponent = AAfacenormals [ i ] ;
float ScaleOffset = 0.5f ;
2008-09-06 07:52:41 +00:00
if ( scaleComponent . X ! = 0 ) ScaleOffset = AXscale . X ;
if ( scaleComponent . Y ! = 0 ) ScaleOffset = AXscale . Y ;
if ( scaleComponent . Z ! = 0 ) ScaleOffset = AXscale . Z ;
2008-06-27 19:21:15 +00:00
ScaleOffset = Math . Abs ( ScaleOffset ) ;
2009-08-14 08:16:41 +00:00
Vector3 offset = result . normal * ScaleOffset ;
result . ipoint = AXpos + offset ;
2008-08-18 00:39:10 +00:00
2008-06-27 19:21:15 +00:00
///pos = (intersectionpoint + offset);
}
else
{
2009-08-14 08:16:41 +00:00
result . normal = normals [ i ] ;
2008-06-27 19:21:15 +00:00
}
2009-08-14 08:16:41 +00:00
result . AAfaceNormal = AAfacenormals [ i ] ;
2008-06-27 19:21:15 +00:00
}
}
}
2009-08-14 08:16:41 +00:00
return result ;
2008-04-30 16:52:12 +00:00
}
2008-06-27 19:21:15 +00:00
/// <summary>
/// Serialize this part to xml.
/// </summary>
/// <param name="xmlWriter"></param>
2010-10-17 17:35:38 +00:00
public void ToXml ( XmlTextWriter xmlWriter )
2008-05-01 18:04:42 +00:00
{
2010-10-17 17:35:38 +00:00
SceneObjectSerializer . SOPToXml2 ( xmlWriter , this , new Dictionary < string , object > ( ) ) ;
2008-05-01 18:04:42 +00:00
}
2008-05-01 16:35:00 +00:00
2008-06-27 19:21:15 +00:00
public void TriggerScriptChangedEvent ( Changed val )
2008-05-06 22:41:38 +00:00
{
2011-11-11 01:21:37 +00:00
if ( ParentGroup ! = null & & ParentGroup . Scene ! = null )
ParentGroup . Scene . EventManager . TriggerOnScriptChangedEvent ( LocalId , ( uint ) val ) ;
2008-05-06 22:41:38 +00:00
}
2008-05-01 18:04:42 +00:00
2008-06-27 19:21:15 +00:00
public void TrimPermissions ( )
2008-04-30 16:52:12 +00:00
{
2011-11-11 01:21:37 +00:00
BaseMask & = ( uint ) PermissionMask . All ;
OwnerMask & = ( uint ) PermissionMask . All ;
GroupMask & = ( uint ) PermissionMask . All ;
EveryoneMask & = ( uint ) PermissionMask . All ;
NextOwnerMask & = ( uint ) PermissionMask . All ;
2008-05-01 18:04:42 +00:00
}
2008-04-30 16:52:12 +00:00
2008-06-27 19:21:15 +00:00
public void UpdateExtraParam ( ushort type , bool inUse , byte [ ] data )
{
m_shape . ReadInUpdateExtraParam ( type , inUse , data ) ;
2012-10-07 00:20:52 +00:00
/ *
2008-06-27 19:21:15 +00:00
if ( type = = 0x30 )
2008-05-03 04:33:17 +00:00
{
2008-09-06 07:52:41 +00:00
if ( m_shape . SculptEntry & & m_shape . SculptTexture ! = UUID . Zero )
2008-05-03 04:33:17 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . Scene . AssetService . Get ( m_shape . SculptTexture . ToString ( ) , this , AssetReceived ) ;
2008-05-03 04:33:17 +00:00
}
2008-05-01 18:04:42 +00:00
}
2012-10-07 00:20:52 +00:00
* /
2011-09-01 00:22:28 +00:00
if ( ParentGroup ! = null )
{
ParentGroup . HasGroupChanged = true ;
ScheduleFullUpdate ( ) ;
}
2008-05-06 22:41:38 +00:00
}
2008-06-10 08:35:46 +00:00
2008-09-06 07:52:41 +00:00
public void UpdateGroupPosition ( Vector3 pos )
2008-05-03 04:33:17 +00:00
{
2008-06-27 19:21:15 +00:00
if ( ( pos . X ! = GroupPosition . X ) | |
( pos . Y ! = GroupPosition . Y ) | |
( pos . Z ! = GroupPosition . Z ) )
2008-06-05 13:24:59 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 newPos = new Vector3 ( pos . X , pos . Y , pos . Z ) ;
2008-06-27 19:21:15 +00:00
GroupPosition = newPos ;
ScheduleTerseUpdate ( ) ;
2008-06-05 13:24:59 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-06-05 13:24:59 +00:00
2008-06-27 19:21:15 +00:00
/// <summary>
///
/// </summary>
/// <param name="pos"></param>
2008-09-06 07:52:41 +00:00
public void UpdateOffSet ( Vector3 pos )
2008-06-27 19:21:15 +00:00
{
if ( ( pos . X ! = OffsetPosition . X ) | |
( pos . Y ! = OffsetPosition . Y ) | |
( pos . Z ! = OffsetPosition . Z ) )
{
2008-09-06 07:52:41 +00:00
Vector3 newPos = new Vector3 ( pos . X , pos . Y , pos . Z ) ;
2010-02-14 21:41:57 +00:00
if ( ParentGroup . RootPart . GetStatusSandbox ( ) )
{
if ( Util . GetDistanceTo ( ParentGroup . RootPart . StatusSandboxPos , newPos ) > 10 )
{
ParentGroup . RootPart . ScriptSetPhysicsStatus ( false ) ;
newPos = OffsetPosition ;
ParentGroup . Scene . SimChat ( Utils . StringToBytes ( "Hit Sandbox Limit" ) ,
ChatTypeEnum . DebugChannel , 0x7FFFFFFF , ParentGroup . RootPart . AbsolutePosition , Name , UUID , false ) ;
}
}
2008-06-27 19:21:15 +00:00
OffsetPosition = newPos ;
ScheduleTerseUpdate ( ) ;
2008-06-05 13:24:59 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-06-05 13:24:59 +00:00
2011-11-10 23:20:21 +00:00
/// <summary>
/// Update permissions on the SOP. Should only be called from SOG.UpdatePermissions because the SOG
/// will handle the client notifications once all of its parts are updated.
/// </summary>
/// <param name="AgentID"></param>
/// <param name="field"></param>
/// <param name="localID"></param>
/// <param name="mask"></param>
/// <param name="addRemTF"></param>
2008-09-06 07:52:41 +00:00
public void UpdatePermissions ( UUID AgentID , byte field , uint localID , uint mask , byte addRemTF )
2008-06-27 19:21:15 +00:00
{
bool set = addRemTF = = 1 ;
2011-11-11 01:21:37 +00:00
bool god = ParentGroup . Scene . Permissions . IsGod ( AgentID ) ;
2008-10-06 06:08:45 +00:00
2011-11-11 01:21:37 +00:00
uint baseMask = BaseMask ;
2008-10-06 06:08:45 +00:00
if ( god )
baseMask = 0x7ffffff0 ;
2008-06-27 19:21:15 +00:00
// Are we the owner?
2011-11-11 01:21:37 +00:00
if ( ( AgentID = = OwnerID ) | | god )
2008-06-05 13:24:59 +00:00
{
2008-06-27 19:21:15 +00:00
switch ( field )
2008-06-05 13:24:59 +00:00
{
2008-10-06 23:08:52 +00:00
case 1 :
if ( god )
{
2011-11-11 01:21:37 +00:00
BaseMask = ApplyMask ( BaseMask , set , mask ) ;
2008-11-21 21:16:42 +00:00
Inventory . ApplyGodPermissions ( _baseMask ) ;
2008-10-06 23:08:52 +00:00
}
break ;
2008-06-27 19:21:15 +00:00
case 2 :
2011-11-11 01:21:37 +00:00
OwnerMask = ApplyMask ( OwnerMask , set , mask ) &
2008-10-06 06:08:45 +00:00
baseMask ;
2008-06-27 19:21:15 +00:00
break ;
case 4 :
2011-11-11 01:21:37 +00:00
GroupMask = ApplyMask ( GroupMask , set , mask ) &
2008-10-06 06:08:45 +00:00
baseMask ;
2008-06-27 19:21:15 +00:00
break ;
case 8 :
2011-11-11 01:21:37 +00:00
EveryoneMask = ApplyMask ( EveryoneMask , set , mask ) &
2008-10-06 06:08:45 +00:00
baseMask ;
2008-06-27 19:21:15 +00:00
break ;
case 16 :
2011-11-11 01:21:37 +00:00
NextOwnerMask = ApplyMask ( NextOwnerMask , set , mask ) &
2008-10-06 06:08:45 +00:00
baseMask ;
2010-07-11 12:26:57 +00:00
// Prevent the client from creating no mod, no copy
// objects
2011-11-11 01:21:37 +00:00
if ( ( NextOwnerMask & ( uint ) PermissionMask . Copy ) = = 0 )
NextOwnerMask | = ( uint ) PermissionMask . Transfer ;
2010-07-15 18:03:08 +00:00
2011-11-11 01:21:37 +00:00
NextOwnerMask | = ( uint ) PermissionMask . Move ;
2010-07-15 18:03:08 +00:00
2008-06-27 19:21:15 +00:00
break ;
2008-06-05 13:24:59 +00:00
}
2008-06-27 19:21:15 +00:00
2011-09-15 17:58:58 +00:00
SendFullUpdateToAllClients ( ) ;
2008-06-05 13:24:59 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-06-05 13:24:59 +00:00
2012-08-23 23:15:30 +00:00
public void ClonePermissions ( SceneObjectPart source )
{
bool update = false ;
if ( BaseMask ! = source . BaseMask | |
OwnerMask ! = source . OwnerMask | |
GroupMask ! = source . GroupMask | |
EveryoneMask ! = source . EveryoneMask | |
NextOwnerMask ! = source . NextOwnerMask )
update = true ;
BaseMask = source . BaseMask ;
OwnerMask = source . OwnerMask ;
GroupMask = source . GroupMask ;
EveryoneMask = source . EveryoneMask ;
NextOwnerMask = source . NextOwnerMask ;
if ( update )
SendFullUpdateToAllClients ( ) ;
}
2008-12-26 12:58:02 +00:00
public bool IsHingeJoint ( )
{
// For now, we use the NINJA naming scheme for identifying joints.
// In the future, we can support other joint specification schemes such as a
// custom checkbox in the viewer GUI.
2012-04-20 23:54:48 +00:00
if ( ParentGroup . Scene ! = null & & ParentGroup . Scene . PhysicsScene . SupportsNINJAJoints )
2008-12-26 12:58:02 +00:00
{
string hingeString = "hingejoint" ;
return ( Name . Length > = hingeString . Length & & Name . Substring ( 0 , hingeString . Length ) = = hingeString ) ;
}
else
{
return false ;
}
}
public bool IsBallJoint ( )
{
// For now, we use the NINJA naming scheme for identifying joints.
// In the future, we can support other joint specification schemes such as a
// custom checkbox in the viewer GUI.
2012-04-20 23:54:48 +00:00
if ( ParentGroup . Scene ! = null & & ParentGroup . Scene . PhysicsScene . SupportsNINJAJoints )
2008-12-26 12:58:02 +00:00
{
string ballString = "balljoint" ;
return ( Name . Length > = ballString . Length & & Name . Substring ( 0 , ballString . Length ) = = ballString ) ;
}
else
{
return false ;
}
}
public bool IsJoint ( )
{
// For now, we use the NINJA naming scheme for identifying joints.
// In the future, we can support other joint specification schemes such as a
// custom checkbox in the viewer GUI.
2012-04-20 23:54:48 +00:00
if ( ParentGroup . Scene ! = null & & ParentGroup . Scene . PhysicsScene . SupportsNINJAJoints )
2008-12-26 12:58:02 +00:00
{
return IsHingeJoint ( ) | | IsBallJoint ( ) ;
}
else
{
return false ;
}
}
2011-07-11 01:09:11 +00:00
/// <summary>
/// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
/// </summary>
/// <param name="UsePhysics"></param>
/// <param name="SetTemporary"></param>
/// <param name="SetPhantom"></param>
/// <param name="SetVD"></param>
public void UpdatePrimFlags ( bool UsePhysics , bool SetTemporary , bool SetPhantom , bool SetVD )
2008-06-27 19:21:15 +00:00
{
2010-08-13 19:23:53 +00:00
bool wasUsingPhysics = ( ( Flags & PrimFlags . Physics ) ! = 0 ) ;
bool wasTemporary = ( ( Flags & PrimFlags . TemporaryOnRez ) ! = 0 ) ;
bool wasPhantom = ( ( Flags & PrimFlags . Phantom ) ! = 0 ) ;
2008-12-20 21:36:42 +00:00
bool wasVD = VolumeDetectActive ;
2008-11-08 19:55:33 +00:00
2011-07-11 01:11:16 +00:00
if ( ( UsePhysics = = wasUsingPhysics ) & & ( wasTemporary = = SetTemporary ) & & ( wasPhantom = = SetPhantom ) & & ( SetVD = = wasVD ) )
2008-11-08 19:55:33 +00:00
return ;
2008-06-27 19:21:15 +00:00
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
2008-12-20 21:36:42 +00:00
// Special cases for VD. VD can only be called from a script
// and can't be combined with changes to other states. So we can rely
// that...
// ... if VD is changed, all others are not.
// ... if one of the others is changed, VD is not.
2011-07-11 01:09:11 +00:00
if ( SetVD ) // VD is active, special logic applies
2008-12-20 21:36:42 +00:00
{
// State machine logic for VolumeDetect
// More logic below
2011-07-11 01:09:11 +00:00
bool phanReset = ( SetPhantom ! = wasPhantom ) & & ! SetPhantom ;
2008-12-20 21:36:42 +00:00
if ( phanReset ) // Phantom changes from on to off switch VD off too
{
2011-07-11 01:09:11 +00:00
SetVD = false ; // Switch it of for the course of this routine
2008-12-20 21:36:42 +00:00
VolumeDetectActive = false ; // and also permanently
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
pa . SetVolumeDetect ( 0 ) ; // Let physics know about it too
2008-12-20 21:36:42 +00:00
}
else
{
// If volumedetect is active we don't want phantom to be applied.
// If this is a new call to VD out of the state "phantom"
// this will also cause the prim to be visible to physics
2011-07-11 01:09:11 +00:00
SetPhantom = false ;
2008-12-20 21:36:42 +00:00
}
}
2008-12-26 12:58:02 +00:00
if ( UsePhysics & & IsJoint ( ) )
{
2011-07-11 01:09:11 +00:00
SetPhantom = true ;
2008-12-26 12:58:02 +00:00
}
2008-11-07 22:57:32 +00:00
if ( UsePhysics )
2008-06-05 13:24:59 +00:00
{
2008-09-06 07:52:41 +00:00
AddFlag ( PrimFlags . Physics ) ;
2008-06-27 19:21:15 +00:00
if ( ! wasUsingPhysics )
2008-06-05 13:24:59 +00:00
{
2008-11-07 22:57:32 +00:00
DoPhysicsPropertyUpdate ( UsePhysics , false ) ;
2008-06-08 22:53:52 +00:00
}
2008-06-05 13:24:59 +00:00
}
2008-06-27 19:21:15 +00:00
else
2008-06-05 13:24:59 +00:00
{
2008-09-06 07:52:41 +00:00
RemFlag ( PrimFlags . Physics ) ;
2008-06-27 19:21:15 +00:00
if ( wasUsingPhysics )
2008-06-05 13:24:59 +00:00
{
2008-11-07 22:57:32 +00:00
DoPhysicsPropertyUpdate ( UsePhysics , false ) ;
2008-06-27 19:21:15 +00:00
}
}
2008-06-05 13:24:59 +00:00
2011-08-26 23:15:21 +00:00
if ( SetPhantom
| | ParentGroup . IsAttachment
| | ( Shape . PathCurve = = ( byte ) Extrusion . Flexible ) ) // note: this may have been changed above in the case of joints
2008-06-27 19:21:15 +00:00
{
2008-09-06 07:52:41 +00:00
AddFlag ( PrimFlags . Phantom ) ;
2011-10-15 01:02:39 +00:00
2009-09-30 16:51:02 +00:00
if ( PhysActor ! = null )
2012-04-22 18:51:51 +00:00
{
2011-10-15 01:02:39 +00:00
RemoveFromPhysics ( ) ;
2012-04-22 18:51:51 +00:00
pa = null ;
}
2008-06-05 13:24:59 +00:00
}
2008-12-20 21:36:42 +00:00
else // Not phantom
2008-06-05 13:24:59 +00:00
{
2008-09-06 07:52:41 +00:00
RemFlag ( PrimFlags . Phantom ) ;
2008-12-20 21:36:42 +00:00
2011-08-05 23:22:14 +00:00
if ( ParentGroup . Scene = = null )
return ;
2012-04-03 08:28:17 +00:00
if ( ParentGroup . Scene . CollidablePrims & & pa = = null )
2008-06-05 13:24:59 +00:00
{
2012-04-03 08:28:17 +00:00
pa = AddToPhysics ( UsePhysics ) ;
2008-06-27 19:21:15 +00:00
2012-04-03 08:28:17 +00:00
if ( pa ! = null )
2011-10-15 01:07:05 +00:00
{
2012-04-03 08:28:17 +00:00
pa . SetMaterial ( Material ) ;
DoPhysicsPropertyUpdate ( UsePhysics , true ) ;
if (
( ( AggregateScriptEvents & scriptEvents . collision ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . collision_end ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . collision_start ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . land_collision_start ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . land_collision ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . land_collision_end ) ! = 0 ) | |
2012-05-15 00:02:38 +00:00
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision_end ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision_start ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision_start ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision_end ) ! = 0 ) | |
2012-04-03 08:28:17 +00:00
( CollisionSound ! = UUID . Zero )
)
{
pa . OnCollisionUpdate + = PhysicsCollision ;
pa . SubscribeEvents ( 1000 ) ;
2008-06-08 22:53:52 +00:00
}
}
2008-06-27 19:21:15 +00:00
}
2008-12-20 21:36:42 +00:00
else // it already has a physical representation
2008-06-27 19:21:15 +00:00
{
2008-12-20 21:36:42 +00:00
DoPhysicsPropertyUpdate ( UsePhysics , false ) ; // Update physical status. If it's phantom this will remove the prim
2008-06-08 22:53:52 +00:00
}
2008-06-05 13:24:59 +00:00
}
2011-07-11 01:09:11 +00:00
if ( SetVD )
2008-12-20 21:36:42 +00:00
{
// If the above logic worked (this is urgent candidate to unit tests!)
// we now have a physicsactor.
// Defensive programming calls for a check here.
// Better would be throwing an exception that could be catched by a unit test as the internal
// logic should make sure, this Physactor is always here.
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
2008-12-20 21:36:42 +00:00
{
2012-04-03 04:50:13 +00:00
pa . SetVolumeDetect ( 1 ) ;
2008-12-20 21:36:42 +00:00
AddFlag ( PrimFlags . Phantom ) ; // We set this flag also if VD is active
2012-04-22 18:51:51 +00:00
VolumeDetectActive = true ;
2008-12-20 21:36:42 +00:00
}
}
2012-12-14 22:15:40 +00:00
else if ( SetVD ! = wasVD )
2011-07-11 02:13:59 +00:00
{
// Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
2009-09-30 16:51:02 +00:00
// (mumbles, well, at least if you have infinte CPU powers :-))
2009-09-30 17:04:06 +00:00
if ( pa ! = null )
2012-04-22 18:51:51 +00:00
pa . SetVolumeDetect ( 0 ) ;
2011-07-11 02:13:59 +00:00
2012-12-14 22:15:40 +00:00
RemFlag ( PrimFlags . Phantom ) ;
2012-04-22 18:51:51 +00:00
VolumeDetectActive = false ;
2008-12-20 21:36:42 +00:00
}
2011-07-11 01:09:11 +00:00
if ( SetTemporary )
2008-06-27 19:21:15 +00:00
{
2008-09-06 07:52:41 +00:00
AddFlag ( PrimFlags . TemporaryOnRez ) ;
2008-06-27 19:21:15 +00:00
}
else
{
2008-09-06 07:52:41 +00:00
RemFlag ( PrimFlags . TemporaryOnRez ) ;
2008-06-27 19:21:15 +00:00
}
2012-04-03 04:50:13 +00:00
2009-02-22 20:52:55 +00:00
// m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
2008-12-20 21:36:42 +00:00
2011-09-01 00:22:28 +00:00
if ( ParentGroup ! = null )
{
ParentGroup . HasGroupChanged = true ;
ScheduleFullUpdate ( ) ;
}
2011-08-05 22:42:05 +00:00
// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
2008-06-27 19:21:15 +00:00
}
2008-06-05 13:24:59 +00:00
2011-10-15 01:02:39 +00:00
/// <summary>
2012-04-03 08:28:17 +00:00
/// Adds this part to the physics scene.
/// </summary>
/// <remarks>This method also sets the PhysActor property.</remarks>
/// <param name="rigidBody">Add this prim with a rigid body.</param>
/// <returns>
/// The physics actor. null if there was a failure.
/// </returns>
private PhysicsActor AddToPhysics ( bool rigidBody )
{
PhysicsActor pa ;
try
{
pa = ParentGroup . Scene . PhysicsScene . AddPrimShape (
string . Format ( "{0}/{1}" , Name , UUID ) ,
Shape ,
AbsolutePosition ,
Scale ,
RotationOffset ,
rigidBody ,
m_localId ) ;
}
2013-01-10 01:40:22 +00:00
catch ( Exception e )
2012-04-03 08:28:17 +00:00
{
2013-01-10 01:40:22 +00:00
m_log . ErrorFormat ( "[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}" , m_uuid , e ) ;
2012-04-03 08:28:17 +00:00
pa = null ;
}
// FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
// properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
// being set.
PhysActor = pa ;
// Basic Physics can also return null as well as an exception catch.
if ( pa ! = null )
{
pa . SOPName = this . Name ; // save object into the PhysActor so ODE internals know the joint/body info
pa . SetMaterial ( Material ) ;
DoPhysicsPropertyUpdate ( rigidBody , true ) ;
}
return pa ;
}
/// <summary>
/// This removes the part from the physics scene.
2011-10-15 01:02:39 +00:00
/// </summary>
/// <remarks>
/// This isn't the same as turning off physical, since even without being physical the prim has a physics
/// representation for collision detection. Rather, this would be used in situations such as making a prim
/// phantom.
/// </remarks>
public void RemoveFromPhysics ( )
{
ParentGroup . Scene . PhysicsScene . RemovePrim ( PhysActor ) ;
PhysActor = null ;
}
2011-10-28 22:15:51 +00:00
/// <summary>
/// This updates the part's rotation and sends out an update to clients if necessary.
/// </summary>
/// <param name="rot"></param>
2008-09-06 07:52:41 +00:00
public void UpdateRotation ( Quaternion rot )
2008-05-04 22:55:52 +00:00
{
2011-10-28 22:15:51 +00:00
if ( rot ! = RotationOffset )
2008-06-27 19:21:15 +00:00
{
2008-09-06 07:52:41 +00:00
RotationOffset = rot ;
2011-09-01 00:22:28 +00:00
if ( ParentGroup ! = null )
{
ParentGroup . HasGroupChanged = true ;
ScheduleTerseUpdate ( ) ;
}
2008-06-27 19:21:15 +00:00
}
2008-05-04 22:55:52 +00:00
}
2008-06-27 19:21:15 +00:00
/// <summary>
/// Update the shape of this part.
/// </summary>
/// <param name="shapeBlock"></param>
public void UpdateShape ( ObjectShapePacket . ObjectDataBlock shapeBlock )
2008-05-04 22:55:52 +00:00
{
2008-06-27 19:21:15 +00:00
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 ;
2011-07-11 02:35:29 +00:00
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
if ( pa ! = null )
2008-06-27 19:21:15 +00:00
{
2012-04-03 04:50:13 +00:00
pa . Shape = m_shape ;
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( pa ) ;
2008-06-27 19:21:15 +00:00
}
2008-05-04 22:55:52 +00:00
2008-10-18 05:51:36 +00:00
// This is what makes vehicle trailers work
// A script in a child prim re-issues
// llSetPrimitiveParams(PRIM_TYPE) every few seconds. That
// prevents autoreturn. This is not well known. It also works
// in SL.
/ /
if ( ParentGroup . RootPart ! = this )
2009-10-25 07:40:21 +00:00
ParentGroup . RootPart . Rezzed = DateTime . UtcNow ;
2008-10-18 05:51:36 +00:00
2008-06-27 19:21:15 +00:00
ParentGroup . HasGroupChanged = true ;
2010-11-22 12:57:48 +00:00
TriggerScriptChangedEvent ( Changed . SHAPE ) ;
2008-06-27 19:21:15 +00:00
ScheduleFullUpdate ( ) ;
2008-05-04 22:55:52 +00:00
}
2008-05-16 23:11:00 +00:00
2012-08-01 14:18:02 +00:00
public void UpdateSlice ( float begin , float end )
{
if ( end < begin )
{
float temp = begin ;
begin = end ;
end = temp ;
}
end = Math . Min ( 1f , Math . Max ( 0f , end ) ) ;
begin = Math . Min ( Math . Min ( 1f , Math . Max ( 0f , begin ) ) , end - 0.02f ) ;
if ( begin < 0.02f & & end < 0.02f )
{
begin = 0f ;
end = 0.02f ;
}
ushort uBegin = ( ushort ) ( 50000.0 * begin ) ;
ushort uEnd = ( ushort ) ( 50000.0 * ( 1f - end ) ) ;
bool updatePossiblyNeeded = false ;
2012-08-02 08:28:32 +00:00
PrimType primType = GetPrimType ( ) ;
if ( primType = = PrimType . SPHERE | | primType = = PrimType . TORUS | | primType = = PrimType . TUBE | | primType = = PrimType . RING )
2012-08-01 14:18:02 +00:00
{
if ( m_shape . ProfileBegin ! = uBegin | | m_shape . ProfileEnd ! = uEnd )
{
m_shape . ProfileBegin = uBegin ;
m_shape . ProfileEnd = uEnd ;
updatePossiblyNeeded = true ;
}
}
else if ( m_shape . PathBegin ! = uBegin | | m_shape . PathEnd ! = uEnd )
{
m_shape . PathBegin = uBegin ;
m_shape . PathEnd = uEnd ;
updatePossiblyNeeded = true ;
}
if ( updatePossiblyNeeded & & ParentGroup ! = null )
{
ParentGroup . HasGroupChanged = true ;
}
if ( updatePossiblyNeeded & & PhysActor ! = null )
{
PhysActor . Shape = m_shape ;
ParentGroup . Scene . PhysicsScene . AddPhysicsActorTaint ( PhysActor ) ;
}
if ( updatePossiblyNeeded )
{
ScheduleFullUpdate ( ) ;
}
}
2011-07-11 02:35:29 +00:00
/// <summary>
/// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
/// engine can use it.
/// </summary>
/// <remarks>
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
/// </remarks>
2012-10-07 00:20:52 +00:00
/ *
2011-07-11 02:35:29 +00:00
public void CheckSculptAndLoad ( )
{
2011-07-31 02:41:35 +00:00
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
2011-07-11 02:35:29 +00:00
if ( ParentGroup . IsDeleted )
return ;
if ( ( ParentGroup . RootPart . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Phantom ) ! = 0 )
return ;
if ( Shape . SculptEntry & & Shape . SculptTexture ! = UUID . Zero )
{
// check if a previously decoded sculpt map has been cached
2011-07-16 02:02:28 +00:00
// We don't read the file here - the meshmerizer will do that later.
// TODO: Could we simplify the meshmerizer code by reading and setting the data here?
2011-07-11 02:35:29 +00:00
if ( File . Exists ( System . IO . Path . Combine ( "j2kDecodeCache" , "smap_" + Shape . SculptTexture . ToString ( ) ) ) )
{
2011-07-16 02:02:28 +00:00
SculptTextureCallback ( null ) ;
2011-07-11 02:35:29 +00:00
}
else
{
ParentGroup . Scene . AssetService . Get ( Shape . SculptTexture . ToString ( ) , this , AssetReceived ) ;
}
}
}
2012-10-07 00:20:52 +00:00
* /
2008-06-27 19:21:15 +00:00
/// <summary>
/// Update the texture entry for this part.
/// </summary>
2012-01-28 02:45:13 +00:00
/// <param name="serializedTextureEntry"></param>
public void UpdateTextureEntry ( byte [ ] serializedTextureEntry )
{
UpdateTextureEntry ( new Primitive . TextureEntry ( serializedTextureEntry , 0 , serializedTextureEntry . Length ) ) ;
}
/// <summary>
/// Update the texture entry for this part.
/// </summary>
/// <param name="newTex"></param>
public void UpdateTextureEntry ( Primitive . TextureEntry newTex )
2008-05-18 03:21:22 +00:00
{
2011-12-05 19:01:14 +00:00
Primitive . TextureEntry oldTex = Shape . Textures ;
Changed changeFlags = 0 ;
2008-06-27 19:21:15 +00:00
2011-12-05 19:01:14 +00:00
for ( int i = 0 ; i < GetNumberOfSides ( ) ; i + + )
{
Primitive . TextureEntryFace newFace = newTex . DefaultTexture ;
Primitive . TextureEntryFace oldFace = oldTex . DefaultTexture ;
if ( oldTex . FaceTextures [ i ] ! = null )
oldFace = oldTex . FaceTextures [ i ] ;
if ( newTex . FaceTextures [ i ] ! = null )
newFace = newTex . FaceTextures [ i ] ;
Color4 oldRGBA = oldFace . RGBA ;
Color4 newRGBA = newFace . RGBA ;
if ( oldRGBA . R ! = newRGBA . R | |
oldRGBA . G ! = newRGBA . G | |
oldRGBA . B ! = newRGBA . B | |
oldRGBA . A ! = newRGBA . A )
changeFlags | = Changed . COLOR ;
if ( oldFace . TextureID ! = newFace . TextureID )
changeFlags | = Changed . TEXTURE ;
// Max change, skip the rest of testing
if ( changeFlags = = ( Changed . TEXTURE | Changed . COLOR ) )
break ;
}
2012-01-28 02:45:13 +00:00
m_shape . TextureEntry = newTex . GetBytes ( ) ;
2011-12-05 19:01:14 +00:00
if ( changeFlags ! = 0 )
TriggerScriptChangedEvent ( changeFlags ) ;
UpdateFlag = UpdateRequired . FULL ;
2008-06-27 19:21:15 +00:00
ParentGroup . HasGroupChanged = true ;
2011-12-05 19:01:14 +00:00
2009-04-25 19:54:51 +00:00
//This is madness..
//ParentGroup.ScheduleGroupForFullUpdate();
//This is sparta
ScheduleFullUpdate ( ) ;
2008-05-18 03:21:22 +00:00
}
2008-06-27 19:21:15 +00:00
public void aggregateScriptEvents ( )
2008-05-25 20:50:45 +00:00
{
2012-05-15 02:16:12 +00:00
if ( ParentGroup = = null | | ParentGroup . RootPart = = null )
2012-05-15 01:27:21 +00:00
return ;
2008-09-08 22:19:06 +00:00
AggregateScriptEvents = 0 ;
2008-06-27 19:21:15 +00:00
// Aggregate script events
lock ( m_scriptEvents )
2008-05-25 20:50:45 +00:00
{
2008-06-27 19:21:15 +00:00
foreach ( scriptEvents s in m_scriptEvents . Values )
2008-05-25 20:50:45 +00:00
{
2008-07-26 21:22:15 +00:00
AggregateScriptEvents | = s ;
2008-06-27 19:21:15 +00:00
}
}
2008-05-25 20:50:45 +00:00
2008-06-27 19:21:15 +00:00
uint objectflagupdate = 0 ;
2008-05-25 20:50:45 +00:00
2008-06-27 19:21:15 +00:00
if (
2008-07-26 21:22:15 +00:00
( ( AggregateScriptEvents & scriptEvents . touch ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . touch_end ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . touch_start ) ! = 0 )
2008-06-27 19:21:15 +00:00
)
{
2008-09-06 07:52:41 +00:00
objectflagupdate | = ( uint ) PrimFlags . Touch ;
2008-06-27 19:21:15 +00:00
}
2008-07-26 21:22:15 +00:00
if ( ( AggregateScriptEvents & scriptEvents . money ) ! = 0 )
2008-06-27 19:21:15 +00:00
{
2008-09-06 07:52:41 +00:00
objectflagupdate | = ( uint ) PrimFlags . Money ;
2008-06-27 19:21:15 +00:00
}
if ( AllowedDrop )
{
2008-09-06 07:52:41 +00:00
objectflagupdate | = ( uint ) PrimFlags . AllowInventoryDrop ;
2008-06-27 19:21:15 +00:00
}
2012-04-03 04:50:13 +00:00
PhysicsActor pa = PhysActor ;
2008-06-27 19:21:15 +00:00
if (
2008-07-26 21:22:15 +00:00
( ( AggregateScriptEvents & scriptEvents . collision ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . collision_end ) ! = 0 ) | |
2008-11-19 18:30:16 +00:00
( ( AggregateScriptEvents & scriptEvents . collision_start ) ! = 0 ) | |
2010-01-10 20:28:53 +00:00
( ( AggregateScriptEvents & scriptEvents . land_collision_start ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . land_collision ) ! = 0 ) | |
( ( AggregateScriptEvents & scriptEvents . land_collision_end ) ! = 0 ) | |
2012-05-15 00:02:38 +00:00
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision_end ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . collision_start ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision_start ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision ) ! = 0 ) | |
( ( ParentGroup . RootPart . AggregateScriptEvents & scriptEvents . land_collision_end ) ! = 0 ) | |
2008-11-21 17:35:34 +00:00
( CollisionSound ! = UUID . Zero )
2008-06-27 19:21:15 +00:00
)
{
// subscribe to physics updates.
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
2008-06-27 19:21:15 +00:00
{
2012-04-03 04:50:13 +00:00
pa . OnCollisionUpdate + = PhysicsCollision ;
pa . SubscribeEvents ( 1000 ) ;
2008-06-27 19:21:15 +00:00
}
}
else
{
2012-04-03 04:50:13 +00:00
if ( pa ! = null )
2008-06-27 19:21:15 +00:00
{
2012-04-03 04:50:13 +00:00
pa . UnSubscribeEvents ( ) ;
pa . OnCollisionUpdate - = PhysicsCollision ;
2008-05-25 20:50:45 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-11-19 18:30:16 +00:00
2009-08-07 19:43:23 +00:00
//if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
//{
2011-11-11 01:21:37 +00:00
// ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
2009-08-07 19:43:23 +00:00
//}
//else
//{
2011-11-11 01:21:37 +00:00
// ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
2009-08-07 19:43:23 +00:00
//}
2008-06-27 19:21:15 +00:00
2011-08-05 22:42:05 +00:00
LocalFlags = ( PrimFlags ) objectflagupdate ;
2008-06-27 19:21:15 +00:00
2011-11-11 01:21:37 +00:00
if ( ParentGroup ! = null & & ParentGroup . RootPart = = this )
2010-01-25 21:51:58 +00:00
{
2011-11-11 01:21:37 +00:00
ParentGroup . aggregateScriptEvents ( ) ;
2010-01-25 21:51:58 +00:00
}
2008-06-27 19:21:15 +00:00
else
2010-01-25 21:51:58 +00:00
{
// m_log.DebugFormat(
2010-02-15 10:15:03 +00:00
// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
2008-06-27 19:21:15 +00:00
ScheduleFullUpdate ( ) ;
2010-01-25 21:51:58 +00:00
}
2008-06-27 19:21:15 +00:00
}
2008-09-13 22:07:07 +00:00
public void SetCameraAtOffset ( Vector3 v )
{
2008-08-01 02:33:28 +00:00
m_cameraAtOffset = v ;
}
2008-08-18 00:39:10 +00:00
2008-09-13 22:07:07 +00:00
public void SetCameraEyeOffset ( Vector3 v )
{
2008-08-01 02:33:28 +00:00
m_cameraEyeOffset = v ;
}
2008-08-18 00:39:10 +00:00
2008-09-13 22:07:07 +00:00
public void SetForceMouselook ( bool force )
{
2008-08-01 02:33:28 +00:00
m_forceMouselook = force ;
}
2008-08-18 00:39:10 +00:00
2008-09-13 22:07:07 +00:00
public Vector3 GetCameraAtOffset ( )
{
2008-08-01 02:33:28 +00:00
return m_cameraAtOffset ;
}
2008-08-18 00:39:10 +00:00
2008-09-13 22:07:07 +00:00
public Vector3 GetCameraEyeOffset ( )
{
2008-08-01 02:33:28 +00:00
return m_cameraEyeOffset ;
}
2008-08-18 00:39:10 +00:00
2008-09-13 22:07:07 +00:00
public bool GetForceMouselook ( )
{
2008-08-01 02:33:28 +00:00
return m_forceMouselook ;
}
2008-09-12 00:37:59 +00:00
public override string ToString ( )
{
return String . Format ( "{0} {1} (parent {2}))" , Name , UUID , ParentGroup ) ;
2009-09-30 16:00:09 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 19:21:15 +00:00
#endregion Public Methods
2008-11-06 23:40:58 +00:00
2008-10-18 05:51:36 +00:00
public void SendTerseUpdateToClient ( IClientAPI remoteClient )
{
2011-09-01 00:22:28 +00:00
if ( ParentGroup . IsDeleted )
2008-10-18 05:51:36 +00:00
return ;
2012-06-20 21:46:01 +00:00
if ( ParentGroup . IsAttachment
& & ( ParentGroup . RootPart ! = this
| | ParentGroup . AttachedAvatar ! = remoteClient . AgentId & & ParentGroup . HasPrivateAttachmentPoint ) )
2010-08-26 15:27:41 +00:00
return ;
2009-10-19 03:24:20 +00:00
2009-09-09 20:20:19 +00:00
// Causes this thread to dig into the Client Thread Data.
// Remember your locking here!
2011-10-14 00:45:46 +00:00
remoteClient . SendEntityUpdate (
2011-10-11 21:17:05 +00:00
this ,
PrimUpdateFlags . Position | PrimUpdateFlags . Rotation | PrimUpdateFlags . Velocity
| PrimUpdateFlags . Acceleration | PrimUpdateFlags . AngularVelocity ) ;
ParentGroup . Scene . StatsReporter . AddObjectUpdates ( 1 ) ;
2008-10-18 05:51:36 +00:00
}
2008-11-21 21:16:42 +00:00
public void AddScriptLPS ( int count )
{
2011-11-11 01:21:37 +00:00
ParentGroup . AddScriptLPS ( count ) ;
2008-11-21 21:16:42 +00:00
}
public void ApplyNextOwnerPermissions ( )
{
2011-11-11 01:21:37 +00:00
BaseMask & = NextOwnerMask ;
OwnerMask & = NextOwnerMask ;
EveryoneMask & = NextOwnerMask ;
2008-11-19 18:30:16 +00:00
2008-11-21 21:16:42 +00:00
Inventory . ApplyNextOwnerPermissions ( ) ;
2009-09-30 16:00:09 +00:00
}
2011-07-11 02:35:29 +00:00
2010-02-14 21:41:57 +00:00
public void UpdateLookAt ( )
{
try
{
if ( APIDTarget ! = Quaternion . Identity )
{
2012-01-13 22:48:56 +00:00
if ( m_APIDIterations < = 1 )
2010-02-14 21:41:57 +00:00
{
2012-01-13 22:48:56 +00:00
UpdateRotation ( APIDTarget ) ;
2010-02-14 21:41:57 +00:00
APIDTarget = Quaternion . Identity ;
return ;
}
2012-01-13 22:48:56 +00:00
Quaternion rot = Quaternion . Slerp ( RotationOffset , APIDTarget , 1.0f / ( float ) m_APIDIterations ) ;
2012-10-10 00:37:59 +00:00
rot . Normalize ( ) ;
2010-02-14 21:41:57 +00:00
UpdateRotation ( rot ) ;
2012-01-13 22:48:56 +00:00
m_APIDIterations - - ;
// This ensures that we'll check this object on the next iteration
ParentGroup . QueueForUpdateCheck ( ) ;
2010-02-14 21:41:57 +00:00
}
}
catch ( Exception ex )
{
m_log . Error ( "[Physics] " + ex ) ;
}
}
2010-03-06 06:56:55 +00:00
public Color4 GetTextColor ( )
{
2010-05-12 22:59:48 +00:00
Color color = Color ;
return new Color4 ( color . R , color . G , color . B , ( byte ) ( 0xFF - color . A ) ) ;
2010-03-06 06:56:55 +00:00
}
2012-07-09 20:24:32 +00:00
/// <summary>
/// Record an avatar sitting on this part.
/// </summary>
/// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks>
/// <returns>
/// true if the avatar was not already recorded, false otherwise.
/// </returns>
/// <param name='avatarId'></param>
protected internal bool AddSittingAvatar ( UUID avatarId )
{
2013-01-04 20:34:39 +00:00
lock ( ParentGroup . m_sittingAvatars )
{
if ( IsSitTargetSet & & SitTargetAvatar = = UUID . Zero )
SitTargetAvatar = avatarId ;
2012-07-10 22:50:04 +00:00
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars = = null )
m_sittingAvatars = new HashSet < UUID > ( ) ;
2012-07-09 20:24:32 +00:00
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars . Add ( avatarId ) )
{
ParentGroup . m_sittingAvatars . Add ( avatarId ) ;
2012-07-09 20:24:32 +00:00
2013-01-04 20:34:39 +00:00
return true ;
}
return false ;
2012-07-09 20:24:32 +00:00
}
}
/// <summary>
/// Remove an avatar recorded as sitting on this part.
/// </summary>
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
/// <returns>
/// true if the avatar was present and removed, false if it was not present.
/// </returns>
/// <param name='avatarId'></param>
protected internal bool RemoveSittingAvatar ( UUID avatarId )
{
2013-01-04 20:34:39 +00:00
lock ( ParentGroup . m_sittingAvatars )
{
if ( SitTargetAvatar = = avatarId )
SitTargetAvatar = UUID . Zero ;
2012-07-09 20:24:32 +00:00
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars = = null )
return false ;
2012-07-09 20:24:32 +00:00
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars . Remove ( avatarId ) )
2012-07-09 20:24:32 +00:00
{
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars . Count = = 0 )
2012-07-09 20:24:32 +00:00
m_sittingAvatars = null ;
2013-01-04 20:34:39 +00:00
ParentGroup . m_sittingAvatars . Remove ( avatarId ) ;
2012-07-09 20:24:32 +00:00
return true ;
}
2013-01-04 20:34:39 +00:00
return false ;
}
2012-07-09 20:24:32 +00:00
}
/// <summary>
/// Get a copy of the list of sitting avatars.
/// </summary>
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
2012-07-10 22:03:52 +00:00
/// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
2012-07-09 20:24:32 +00:00
public HashSet < UUID > GetSittingAvatars ( )
{
2013-01-04 20:34:39 +00:00
lock ( ParentGroup . m_sittingAvatars )
2012-07-10 22:03:52 +00:00
{
2013-01-04 20:34:39 +00:00
if ( m_sittingAvatars = = null )
return null ;
else
return new HashSet < UUID > ( m_sittingAvatars ) ;
2012-07-10 22:03:52 +00:00
}
2012-07-09 20:24:32 +00:00
}
/// <summary>
/// Gets the number of sitting avatars.
/// </summary>
/// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
/// <returns></returns>
public int GetSittingAvatarsCount ( )
{
2013-01-04 20:34:39 +00:00
lock ( ParentGroup . m_sittingAvatars )
{
if ( m_sittingAvatars = = null )
return 0 ;
else
return m_sittingAvatars . Count ;
}
2012-07-09 20:24:32 +00:00
}
2009-09-30 16:00:09 +00:00
}
2010-08-16 19:38:20 +00:00
}