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 .
* * Neither the name of the OpenSim Project nor the
* 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 ;
2007-09-19 00:30:55 +00:00
using System.IO ;
2009-02-09 22:27:27 +00:00
using System.Threading ;
2007-08-13 13:36:42 +00:00
using System.Xml ;
2008-05-14 05:43:21 +00:00
using System.Xml.Serialization ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
using OpenMetaverse.Packets ;
2007-10-29 21:46:25 +00:00
using OpenSim.Framework ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Interfaces ;
2007-09-19 00:30:55 +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
2007-07-30 20:11:40 +00:00
{
2008-04-20 04:19:44 +00:00
[Flags]
2008-04-21 14:11:36 +00:00
public enum scriptEvents
2008-04-20 04:19:44 +00:00
{
None = 0 ,
attach = 1 ,
2008-08-04 21:30:12 +00:00
collision = 16 ,
2008-04-20 04:19:44 +00:00
collision_end = 32 ,
collision_start = 64 ,
control = 128 ,
dataserver = 256 ,
email = 512 ,
http_response = 1024 ,
land_collision = 2048 ,
land_collision_end = 4096 ,
land_collision_start = 8192 ,
2008-04-25 01:00:55 +00:00
at_target = 16384 ,
2008-04-20 04:19:44 +00:00
listen = 32768 ,
money = 65536 ,
moving_end = 131072 ,
moving_start = 262144 ,
not_at_rot_target = 524288 ,
not_at_target = 1048576 ,
remote_data = 8388608 ,
run_time_permissions = 268435456 ,
state_entry = 1073741824 ,
state_exit = 2 ,
timer = 4 ,
touch = 8 ,
touch_end = 536870912 ,
touch_start = 2097152 ,
object_rez = 4194304
}
2008-05-01 18:04:42 +00:00
struct scriptPosTarget
2008-04-25 01:00:55 +00:00
{
2008-09-06 07:52:41 +00:00
public Vector3 targetPos ;
2008-04-25 01:00:55 +00:00
public float tolerance ;
}
2007-08-27 15:34:21 +00:00
public delegate void PrimCountTaintedDelegate ( ) ;
2007-07-30 20:11:40 +00:00
2008-05-26 02:17:03 +00:00
/// <summary>
/// A scene object group is conceptually an object in the scene. The object is constituted of SceneObjectParts
/// (often known as prims), one of which is considered the root part.
/// </summary>
2009-02-09 22:27:27 +00:00
public partial class SceneObjectGroup : EntityBase , ISceneObject
2007-07-30 20:11:40 +00:00
{
2008-06-27 23:03:39 +00:00
// private PrimCountTaintedDelegate handlerPrimCountTainted = null;
2007-07-30 20:11:40 +00:00
2008-01-18 18:43:16 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// Signal whether the non-inventory attributes of any prims in the group have changed
2008-01-18 18:57:28 +00:00
/// since the group's last persistent backup
2008-01-18 18:43:16 +00:00
/// </summary>
2008-11-15 17:52:00 +00:00
private bool m_hasGroupChanged = false ;
private long timeFirstChanged ;
private long timeLastChanged ;
public bool HasGroupChanged
{
set
{
if ( value )
{
timeLastChanged = DateTime . Now . Ticks ;
if ( ! m_hasGroupChanged )
timeFirstChanged = DateTime . Now . Ticks ;
}
m_hasGroupChanged = value ;
}
get { return m_hasGroupChanged ; }
}
private bool isTimeToPersist ( )
{
if ( IsSelected | | IsDeleted | | IsAttachment )
return false ;
if ( ! m_hasGroupChanged )
return false ;
if ( m_scene . ShuttingDown )
return true ;
long currentTime = DateTime . Now . Ticks ;
if ( currentTime - timeLastChanged > m_scene . m_dontPersistBefore | | currentTime - timeFirstChanged > m_scene . m_persistAfter )
return true ;
return false ;
}
2008-11-01 21:50:07 +00:00
/// <value>
/// Is this scene object acting as an attachment?
///
/// We return false if the group has already been deleted.
///
/// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I
/// presume either all or no parts in a linkset can be part of an attachment (in which
/// case the value would get proprogated down into all the descendent parts).
/// </value>
public bool IsAttachment
{
get
{
if ( ! IsDeleted )
return m_rootPart . IsAttachment ;
return false ;
}
}
2008-08-18 00:39:10 +00:00
2008-05-25 20:50:45 +00:00
public float scriptScore = 0f ;
2008-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
private Vector3 lastPhysGroupPos ;
private Quaternion lastPhysGroupRot ;
2007-11-03 19:33:00 +00:00
2008-10-18 05:51:36 +00:00
private bool m_isBackedUp = false ;
2008-04-21 14:11:36 +00:00
/// <summary>
/// The constituent parts of this group
/// </summary>
2008-09-06 07:52:41 +00:00
protected Dictionary < UUID , SceneObjectPart > m_parts = new Dictionary < UUID , SceneObjectPart > ( ) ;
2008-04-21 14:11:36 +00:00
protected ulong m_regionHandle ;
protected SceneObjectPart m_rootPart ;
2008-09-06 07:52:41 +00:00
// private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
2008-04-21 14:11:36 +00:00
2008-05-01 18:04:42 +00:00
private Dictionary < uint , scriptPosTarget > m_targets = new Dictionary < uint , scriptPosTarget > ( ) ;
private bool m_scriptListens_atTarget = false ;
private bool m_scriptListens_notAtTarget = false ;
2007-08-13 13:36:42 +00:00
#region Properties
2008-08-18 00:39:10 +00:00
2008-06-21 18:11:45 +00:00
/// <summary>
/// The name of an object grouping is always the same as its root part
/// </summary>
public override string Name
{
2008-10-18 05:51:36 +00:00
get {
if ( RootPart = = null )
return "" ;
return RootPart . Name ;
}
2008-06-21 18:11:45 +00:00
set { RootPart . Name = value ; }
2008-08-18 00:39:10 +00:00
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
/// Added because the Parcel code seems to use it
/// but not sure a object should have this
/// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
/// think really there should be a list (or whatever) in each scenepresence
2008-05-16 01:22:11 +00:00
/// saying what prim(s) that user has selected.
2008-04-21 14:11:36 +00:00
/// </summary>
2008-05-01 18:04:42 +00:00
protected bool m_isSelected = false ;
2008-04-21 14:11:36 +00:00
2007-07-30 20:11:40 +00:00
/// <summary>
2008-06-21 23:45:22 +00:00
/// Number of prims in this group
2007-07-30 20:11:40 +00:00
/// </summary>
2007-08-01 16:50:20 +00:00
public int PrimCount
2007-07-30 20:11:40 +00:00
{
2007-12-17 02:30:03 +00:00
get { return m_parts . Count ; }
2007-07-30 20:11:40 +00:00
}
2008-09-06 07:52:41 +00:00
public Quaternion GroupRotation
2007-08-15 16:57:47 +00:00
{
get { return m_rootPart . RotationOffset ; }
}
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
public UUID GroupID
2007-11-14 11:56:57 +00:00
{
get { return m_rootPart . GroupID ; }
set { m_rootPart . GroupID = value ; }
}
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
public Dictionary < UUID , SceneObjectPart > Children
2007-08-09 17:54:22 +00:00
{
2007-09-19 00:30:55 +00:00
get { return m_parts ; }
2007-08-09 17:54:22 +00:00
set { m_parts = value ; }
}
2008-11-10 20:04:55 +00:00
/// <value>
/// The root part of this scene object
/// </value>
2007-08-10 13:59:19 +00:00
public SceneObjectPart RootPart
{
2007-09-19 00:30:55 +00:00
get { return m_rootPart ; }
2007-08-10 13:59:19 +00:00
}
public ulong RegionHandle
{
get { return m_regionHandle ; }
set
{
m_regionHandle = value ;
2007-09-19 00:30:55 +00:00
lock ( m_parts )
2007-08-10 13:59:19 +00:00
{
2007-09-19 00:30:55 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-10 13:59:19 +00:00
{
part . RegionHandle = m_regionHandle ;
}
}
}
}
2008-09-12 00:37:59 +00:00
/// <summary>
/// The absolute position of this scene object in the scene
/// </summary>
2008-09-06 07:52:41 +00:00
public override Vector3 AbsolutePosition
2007-08-07 18:31:20 +00:00
{
2008-03-14 15:28:34 +00:00
get
{
2008-04-21 14:11:36 +00:00
if ( m_rootPart = = null )
2008-03-14 15:28:34 +00:00
{
2008-04-07 17:28:02 +00:00
throw new NullReferenceException (
string . Format ( "[SCENE OBJECT GROUP]: Object {0} has no root part." , m_uuid ) ) ;
2008-03-14 15:28:34 +00:00
}
return m_rootPart . GroupPosition ;
}
2007-08-07 18:31:20 +00:00
set
{
2008-09-06 07:52:41 +00:00
Vector3 val = value ;
2008-09-12 00:37:59 +00:00
2008-11-01 22:04:35 +00:00
if ( ( val . X > 257f | | val . X < - 1f | | val . Y > 257f | | val . Y < - 1f ) & & ! IsAttachment )
2008-09-12 00:37:59 +00:00
{
2008-11-07 05:48:44 +00:00
m_scene . CrossPrimGroupIntoNewRegion ( val , this , true ) ;
2007-08-24 12:34:00 +00:00
}
2008-04-21 14:11:36 +00:00
2007-09-19 00:30:55 +00:00
lock ( m_parts )
2007-08-07 18:31:20 +00:00
{
2007-09-19 00:30:55 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-07 18:31:20 +00:00
{
2007-08-24 12:34:00 +00:00
part . GroupPosition = val ;
2007-08-07 18:31:20 +00:00
}
}
2008-05-16 01:22:11 +00:00
2008-01-14 18:29:04 +00:00
//if (m_rootPart.PhysActor != null)
//{
2008-04-21 14:11:36 +00:00
//m_rootPart.PhysActor.Position =
//new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
//m_rootPart.GroupPosition.Z);
//m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2008-01-14 18:29:04 +00:00
//}
2007-08-13 14:39:12 +00:00
}
2007-08-07 18:31:20 +00:00
}
2008-05-16 01:22:11 +00:00
2007-08-07 18:31:20 +00:00
public override uint LocalId
{
2008-04-21 14:11:36 +00:00
get
{
2008-03-23 07:10:04 +00:00
if ( m_rootPart = = null )
{
2008-04-07 17:28:02 +00:00
m_log . Error ( "[SCENE OBJECT GROUP]: Unable to find the rootpart for a LocalId Request!" ) ;
2008-03-23 07:10:04 +00:00
return 0 ;
}
2008-04-21 14:11:36 +00:00
return m_rootPart . LocalId ;
}
2008-03-05 18:57:13 +00:00
set { m_rootPart . LocalId = value ; }
2007-08-07 18:31:20 +00:00
}
2008-09-06 07:52:41 +00:00
public override UUID UUID
2007-08-07 18:31:20 +00:00
{
2008-10-11 16:58:05 +00:00
get {
if ( m_rootPart = = null )
{
m_log . Error ( "Got a null rootpart while requesting UUID. Called from: " , new Exception ( ) ) ;
return UUID . Zero ;
}
else return m_rootPart . UUID ;
}
2007-08-07 18:31:20 +00:00
set { m_rootPart . UUID = value ; }
}
2008-09-06 07:52:41 +00:00
public UUID OwnerID
2007-08-09 17:54:22 +00:00
{
2008-04-21 14:11:36 +00:00
get
{
2008-03-23 07:10:04 +00:00
if ( m_rootPart = = null )
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2008-03-23 07:10:04 +00:00
2008-04-21 14:11:36 +00:00
return m_rootPart . OwnerID ;
2008-03-23 07:10:04 +00:00
}
2007-11-14 11:56:57 +00:00
set { m_rootPart . OwnerID = value ; }
2007-08-09 17:54:22 +00:00
}
2007-12-04 16:41:20 +00:00
public Color Color
2007-11-11 22:23:34 +00:00
{
get { return m_rootPart . Color ; }
set { m_rootPart . Color = value ; }
}
2007-08-16 16:31:32 +00:00
public string Text
{
2008-05-29 16:21:41 +00:00
get {
string returnstr = m_rootPart . Text ;
if ( returnstr . Length > 255 )
{
returnstr = returnstr . Substring ( 0 , 255 ) ;
}
return returnstr ;
}
2007-08-16 16:31:32 +00:00
set { m_rootPart . Text = value ; }
}
2008-05-25 23:27:38 +00:00
2007-09-13 05:25:26 +00:00
protected virtual bool InSceneBackup
{
2007-09-19 00:30:55 +00:00
get { return true ; }
2008-05-25 23:27:38 +00:00
}
2007-09-13 05:25:26 +00:00
2007-08-09 17:54:22 +00:00
public bool IsSelected
{
2007-08-13 14:39:12 +00:00
get { return m_isSelected ; }
2008-04-21 14:11:36 +00:00
set
{
2008-01-29 15:10:18 +00:00
m_isSelected = value ;
// Tell physics engine that group is selected
2008-11-07 05:48:44 +00:00
if ( m_rootPart ! = null & & m_rootPart . PhysActor ! = null )
2008-01-29 15:10:18 +00:00
{
m_rootPart . PhysActor . Selected = value ;
2008-02-23 11:42:55 +00:00
// Pass it on to the children.
foreach ( SceneObjectPart child in Children . Values )
{
if ( child . PhysActor ! = null )
{
child . PhysActor . Selected = value ;
}
}
2008-01-29 15:10:18 +00:00
}
}
2007-08-09 17:54:22 +00:00
}
2007-08-20 16:07:37 +00:00
// The UUID for the Region this Object is in.
2008-09-06 07:52:41 +00:00
public UUID RegionUUID
2007-08-20 16:07:37 +00:00
{
get
{
if ( m_scene ! = null )
2007-09-19 00:30:55 +00:00
{
2007-10-18 15:10:43 +00:00
return m_scene . RegionInfo . RegionID ;
2007-09-19 00:30:55 +00:00
}
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2007-08-20 16:07:37 +00:00
}
}
2007-09-19 00:30:55 +00:00
2007-08-13 13:36:42 +00:00
# endregion
#region Constructors
2007-09-19 00:30:55 +00:00
2007-08-03 14:47:38 +00:00
/// <summary>
2008-06-12 16:54:04 +00:00
/// Constructor
2007-08-03 14:47:38 +00:00
/// </summary>
2007-08-09 17:54:22 +00:00
public SceneObjectGroup ( )
2007-08-03 14:47:38 +00:00
{
}
2007-12-04 16:41:20 +00:00
2007-11-13 19:57:11 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
/// The original SceneObjectPart will be used rather than a copy, preserving
2007-11-13 19:57:11 +00:00
/// its existing localID and UUID.
2008-05-16 01:22:11 +00:00
/// </summary>
2008-11-07 19:49:22 +00:00
public SceneObjectGroup ( SceneObjectPart part )
2007-12-04 16:41:20 +00:00
{
2008-11-10 19:47:13 +00:00
SetRootPart ( part ) ;
2007-11-13 19:57:11 +00:00
}
2009-01-02 17:22:24 +00:00
2008-12-17 16:11:03 +00:00
public SceneObjectGroup ( string xmlData , bool isOriginalXmlFormat )
2009-01-02 17:22:24 +00:00
: this ( UUID . Zero , xmlData , isOriginalXmlFormat )
2008-12-17 16:11:03 +00:00
{
}
2007-08-03 14:47:38 +00:00
2007-08-13 13:36:42 +00:00
/// <summary>
2008-06-12 17:49:08 +00:00
/// Create an object using serialized data in OpenSim's original xml format.
2007-08-13 13:36:42 +00:00
/// </summary>
2008-12-17 16:11:03 +00:00
/// <param name="fromUserInventoryItemID">
/// If applicable, the user inventory item id from which this object was rezzed. If not applicable then this
/// should be UUID.Zero
/// </param>
2008-11-07 18:46:11 +00:00
/// <param name="xmlData"></param>
/// <param name="isOriginalXmlFormat">
/// This parameter only exists to separate the two different xml constructors. In the future, versions should
/// be specified within the xml itself.
/// </param>
2008-12-17 16:11:03 +00:00
public SceneObjectGroup ( UUID fromUserInventoryItemID , string xmlData , bool isOriginalXmlFormat )
2007-08-13 13:36:42 +00:00
{
2008-11-07 18:46:11 +00:00
if ( ! isOriginalXmlFormat )
throw new Exception ( "This constructor must specify the xml is in OpenSim's original format" ) ;
2009-01-02 17:22:24 +00:00
2009-01-23 17:17:46 +00:00
//m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
2009-01-02 17:22:24 +00:00
int time = System . Environment . TickCount ;
2008-09-06 19:21:41 +00:00
// libomv.types changes UUID to Guid
xmlData = xmlData . Replace ( "<UUID>" , "<Guid>" ) ;
xmlData = xmlData . Replace ( "</UUID>" , "</Guid>" ) ;
2008-04-21 14:11:36 +00:00
2008-09-06 19:21:41 +00:00
// Handle Nested <UUID><UUID> property
xmlData = xmlData . Replace ( "<Guid><Guid>" , "<UUID><Guid>" ) ;
xmlData = xmlData . Replace ( "</Guid></Guid>" , "</Guid></UUID>" ) ;
2007-08-13 13:36:42 +00:00
StringReader sr = new StringReader ( xmlData ) ;
XmlTextReader reader = new XmlTextReader ( sr ) ;
2008-09-09 03:48:09 +00:00
2008-04-07 16:30:29 +00:00
try
2007-08-16 16:31:32 +00:00
{
2008-04-07 16:30:29 +00:00
reader . Read ( ) ;
reader . ReadStartElement ( "SceneObjectGroup" ) ;
reader . ReadStartElement ( "RootPart" ) ;
2008-12-17 16:11:03 +00:00
SetRootPart ( SceneObjectPart . FromXml ( fromUserInventoryItemID , reader ) ) ;
2008-04-21 14:11:36 +00:00
2008-04-07 16:30:29 +00:00
reader . ReadEndElement ( ) ;
2008-04-21 14:11:36 +00:00
2008-04-07 16:30:29 +00:00
while ( reader . Read ( ) )
2007-08-16 16:31:32 +00:00
{
2008-04-07 16:30:29 +00:00
switch ( reader . NodeType )
{
case XmlNodeType . Element :
if ( reader . Name = = "Part" )
{
reader . Read ( ) ;
SceneObjectPart part = SceneObjectPart . FromXml ( reader ) ;
2008-11-10 20:54:34 +00:00
// We reset the link number in order to make sure that the persisted linkset order is
int linkNum = part . LinkNum ;
2008-04-07 16:30:29 +00:00
AddPart ( part ) ;
2008-09-09 03:48:09 +00:00
part . LinkNum = linkNum ;
2008-04-21 14:11:36 +00:00
2008-04-07 16:30:29 +00:00
part . TrimPermissions ( ) ;
2008-04-28 01:48:21 +00:00
part . StoreUndoState ( ) ;
2008-04-07 16:30:29 +00:00
}
break ;
2008-11-07 18:46:11 +00:00
2008-04-07 16:30:29 +00:00
case XmlNodeType . EndElement :
break ;
}
2007-08-16 16:31:32 +00:00
}
}
2008-11-10 20:54:34 +00:00
catch ( XmlException e )
2008-04-07 16:30:29 +00:00
{
2008-11-10 20:54:34 +00:00
m_log . ErrorFormat ( "[SCENE]: Deserialization of xml failed with {0}. xml was {1}" , e , xmlData ) ;
2008-04-07 16:30:29 +00:00
}
2008-04-21 14:11:36 +00:00
2007-08-13 13:36:42 +00:00
reader . Close ( ) ;
sr . Close ( ) ;
2009-02-18 20:04:14 +00:00
//m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
2007-08-13 13:36:42 +00:00
}
2007-10-10 08:30:36 +00:00
/// <summary>
2008-06-12 17:49:08 +00:00
/// Create an object using serialized data in OpenSim's xml2 format.
2007-10-10 08:30:36 +00:00
/// </summary>
public SceneObjectGroup ( string xmlData )
2008-11-16 04:40:36 +00:00
{
SetFromXml ( xmlData ) ;
}
protected void SetFromXml ( string xmlData )
2007-10-10 08:30:36 +00:00
{
2009-01-23 17:17:46 +00:00
//m_log.DebugFormat("[SOG]: Starting deserialization of SOG");
//int time = System.Environment.TickCount;
2009-01-02 17:22:24 +00:00
2008-09-06 19:40:04 +00:00
// libomv.types changes UUID to Guid
xmlData = xmlData . Replace ( "<UUID>" , "<Guid>" ) ;
xmlData = xmlData . Replace ( "</UUID>" , "</Guid>" ) ;
// Handle Nested <UUID><UUID> property
xmlData = xmlData . Replace ( "<Guid><Guid>" , "<UUID><Guid>" ) ;
xmlData = xmlData . Replace ( "</Guid></Guid>" , "</Guid></UUID>" ) ;
2007-10-10 08:30:36 +00:00
StringReader sr = new StringReader ( xmlData ) ;
XmlTextReader reader = new XmlTextReader ( sr ) ;
reader . Read ( ) ;
2007-10-30 09:05:31 +00:00
2007-10-10 08:30:36 +00:00
reader . ReadStartElement ( "SceneObjectGroup" ) ;
2008-11-16 04:40:36 +00:00
SetRootPart ( CreatePartFromXml ( reader ) ) ;
2007-10-10 08:30:36 +00:00
2007-10-18 19:17:07 +00:00
reader . Read ( ) ;
bool more = true ;
while ( more )
2007-10-10 08:30:36 +00:00
{
switch ( reader . NodeType )
{
case XmlNodeType . Element :
2007-10-16 11:16:25 +00:00
if ( reader . Name = = "SceneObjectPart" )
2007-10-10 08:30:36 +00:00
{
2008-11-16 04:40:36 +00:00
SceneObjectPart part = CreatePartFromXml ( reader ) ;
2008-11-10 21:06:26 +00:00
AddPart ( part ) ;
part . StoreUndoState ( ) ;
2007-10-10 08:30:36 +00:00
}
2007-11-21 12:00:28 +00:00
else
{
2009-02-22 20:52:55 +00:00
m_log . Warn ( "found unexpected element: " + reader . Name ) ;
2007-11-21 12:00:28 +00:00
reader . Read ( ) ;
}
2007-10-10 08:30:36 +00:00
break ;
case XmlNodeType . EndElement :
2007-10-30 09:05:31 +00:00
reader . Read ( ) ;
2007-10-10 08:30:36 +00:00
break ;
}
2007-10-30 09:05:31 +00:00
more = ! reader . EOF ;
2007-10-10 08:30:36 +00:00
}
2008-08-18 00:39:10 +00:00
2007-10-10 08:30:36 +00:00
reader . Close ( ) ;
sr . Close ( ) ;
2009-01-02 17:22:24 +00:00
2009-01-23 17:17:46 +00:00
//m_log.DebugFormat("[SOG]: Finished deserialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
2007-10-10 08:30:36 +00:00
}
2008-08-18 00:39:10 +00:00
2008-11-16 04:40:36 +00:00
protected virtual SceneObjectPart CreatePartFromXml ( XmlTextReader reader )
{
SceneObjectPart part = SceneObjectPart . FromXml ( reader ) ;
return part ;
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-11-06 22:21:25 +00:00
/// Constructor. This object is added to the scene later via AttachToScene()
2008-04-21 14:11:36 +00:00
/// </summary>
2008-11-07 21:07:14 +00:00
public SceneObjectGroup ( UUID ownerID , Vector3 pos , Quaternion rot , PrimitiveBaseShape shape )
2008-04-21 14:11:36 +00:00
{
2008-11-10 19:47:13 +00:00
Vector3 rootOffset = new Vector3 ( 0 , 0 , 0 ) ;
SetRootPart ( new SceneObjectPart ( ownerID , shape , pos , rot , rootOffset ) ) ;
2008-04-21 14:11:36 +00:00
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-11-06 22:21:25 +00:00
/// Constructor.
2008-04-21 14:11:36 +00:00
/// </summary>
2008-11-07 21:07:14 +00:00
public SceneObjectGroup ( UUID ownerID , Vector3 pos , PrimitiveBaseShape shape )
: this ( ownerID , pos , Quaternion . Identity , shape )
2008-04-21 14:11:36 +00:00
{
}
2008-09-06 07:52:41 +00:00
public void SetFromAssetID ( UUID AssetId )
2008-04-27 14:37:51 +00:00
{
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
2008-07-26 21:22:15 +00:00
part . FromAssetID = AssetId ;
2008-04-27 14:37:51 +00:00
}
}
}
2008-09-06 07:52:41 +00:00
public UUID GetFromAssetID ( )
2008-04-27 14:37:51 +00:00
{
if ( m_rootPart ! = null )
{
2008-07-26 21:22:15 +00:00
return m_rootPart . FromAssetID ;
2008-04-27 14:37:51 +00:00
}
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2008-04-27 14:37:51 +00:00
}
2008-04-01 17:06:33 +00:00
/// <summary>
/// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes.
/// </summary>
2008-06-12 17:49:08 +00:00
public void AttachToBackup ( )
2007-09-13 05:25:26 +00:00
{
if ( InSceneBackup )
{
2008-07-25 17:48:58 +00:00
//m_log.DebugFormat(
// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
2008-05-25 23:27:38 +00:00
2008-10-18 05:51:36 +00:00
if ( ! m_isBackedUp )
m_scene . EventManager . OnBackup + = ProcessBackup ;
2009-01-29 18:39:33 +00:00
2008-10-18 05:51:36 +00:00
m_isBackedUp = true ;
2007-09-13 05:25:26 +00:00
}
}
2008-11-06 22:21:25 +00:00
/// <summary>
2008-11-07 19:30:20 +00:00
/// Attach this object to a scene. It will also now appear to agents.
2008-11-06 22:21:25 +00:00
/// </summary>
/// <param name="scene"></param>
public void AttachToScene ( Scene scene )
{
2008-11-07 18:46:11 +00:00
m_scene = scene ;
RegionHandle = m_scene . RegionInfo . RegionHandle ;
2008-11-20 00:13:15 +00:00
2008-11-29 01:33:10 +00:00
if ( m_rootPart . Shape . PCode ! = 9 | | m_rootPart . Shape . State = = 0 )
m_rootPart . ParentID = 0 ;
2008-11-21 18:44:48 +00:00
if ( m_rootPart . LocalId = = 0 )
m_rootPart . LocalId = m_scene . AllocateLocalId ( ) ;
2008-11-20 00:13:15 +00:00
2008-11-07 18:52:28 +00:00
// No need to lock here since the object isn't yet in a scene
2008-11-07 18:46:11 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
{
if ( Object . ReferenceEquals ( part , m_rootPart ) )
continue ;
2008-11-20 00:13:15 +00:00
if ( part . LocalId = = 0 )
2008-11-21 18:44:48 +00:00
part . LocalId = m_scene . AllocateLocalId ( ) ;
2008-11-07 18:46:11 +00:00
part . ParentID = m_rootPart . LocalId ;
2008-11-07 18:52:28 +00:00
//m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
2008-11-07 18:46:11 +00:00
}
2008-11-06 22:21:25 +00:00
ApplyPhysics ( m_scene . m_physicalPrim ) ;
ScheduleGroupForFullUpdate ( ) ;
}
2008-05-25 23:27:38 +00:00
2008-09-06 07:52:41 +00:00
public Vector3 GroupScale ( )
2008-05-01 06:31:12 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 minScale = new Vector3 ( Constants . RegionSize , Constants . RegionSize , Constants . RegionSize ) ;
Vector3 maxScale = new Vector3 ( 0f , 0f , 0f ) ;
Vector3 finalScale = new Vector3 ( 0.5f , 0.5f , 0.5f ) ;
2008-05-01 06:31:12 +00:00
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
2008-09-06 07:52:41 +00:00
Vector3 partscale = part . Scale ;
Vector3 partoffset = part . OffsetPosition ;
2007-09-13 05:25:26 +00:00
2008-05-01 06:31:12 +00:00
minScale . X = ( partscale . X + partoffset . X < minScale . X ) ? partscale . X + partoffset . X : minScale . X ;
minScale . Y = ( partscale . Y + partoffset . Y < minScale . Y ) ? partscale . X + partoffset . Y : minScale . Y ;
minScale . Z = ( partscale . Z + partoffset . Z < minScale . Z ) ? partscale . X + partoffset . Z : minScale . Z ;
maxScale . X = ( partscale . X + partoffset . X > maxScale . X ) ? partscale . X + partoffset . X : maxScale . X ;
maxScale . Y = ( partscale . Y + partoffset . Y > maxScale . Y ) ? partscale . Y + partoffset . Y : maxScale . Y ;
maxScale . Z = ( partscale . Z + partoffset . Z > maxScale . Z ) ? partscale . Z + partoffset . Z : maxScale . Z ;
}
}
finalScale . X = ( minScale . X > maxScale . X ) ? minScale . X : maxScale . X ;
finalScale . Y = ( minScale . Y > maxScale . Y ) ? minScale . Y : maxScale . Y ;
finalScale . Z = ( minScale . Z > maxScale . Z ) ? minScale . Z : maxScale . Z ;
return finalScale ;
2008-05-01 16:35:00 +00:00
2008-05-01 18:04:42 +00:00
}
2008-05-01 15:17:49 +00:00
public EntityIntersection TestIntersection ( Ray hRay , bool frontFacesOnly , bool faceCenters )
2007-11-23 05:56:35 +00:00
{
2007-11-30 16:29:23 +00:00
// We got a request from the inner_scene to raytrace along the Ray hRay
// We're going to check all of the prim in this group for intersection with the ray
// If we get a result, we're going to find the closest result to the origin of the ray
// and send back the intersection information back to the innerscene.
2007-11-23 05:56:35 +00:00
EntityIntersection returnresult = new EntityIntersection ( ) ;
2007-11-30 16:29:23 +00:00
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-11-23 05:56:35 +00:00
{
2008-03-18 20:42:01 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
{
// Temporary commented to stop compiler warning
//Vector3 partPosition =
// new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
2008-09-06 07:52:41 +00:00
Quaternion parentrotation = GroupRotation ;
2007-12-04 16:41:20 +00:00
2008-03-18 20:42:01 +00:00
// Telling the prim to raytrace.
2008-03-23 06:24:59 +00:00
//EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
2008-05-01 18:04:42 +00:00
EntityIntersection inter = part . TestIntersectionOBB ( hRay , parentrotation , frontFacesOnly , faceCenters ) ;
2007-12-04 16:41:20 +00:00
2008-05-16 01:22:11 +00:00
// This may need to be updated to the maximum draw distance possible..
2008-03-18 20:42:01 +00:00
// We might (and probably will) be checking for prim creation from other sims
// when the camera crosses the border.
2008-04-21 14:11:36 +00:00
float idist = Constants . RegionSize ;
2007-11-23 05:56:35 +00:00
2008-03-18 20:42:01 +00:00
if ( inter . HitTF )
2007-12-04 16:41:20 +00:00
{
2008-03-18 20:42:01 +00:00
// We need to find the closest prim to return to the testcaller along the ray
if ( inter . distance < idist )
{
returnresult . HitTF = true ;
returnresult . ipoint = inter . ipoint ;
returnresult . obj = part ;
returnresult . normal = inter . normal ;
returnresult . distance = inter . distance ;
}
2007-11-23 05:56:35 +00:00
}
}
}
return returnresult ;
}
2007-12-04 16:41:20 +00:00
2007-08-13 13:36:42 +00:00
# endregion
2007-07-30 20:11:40 +00:00
2008-04-21 14:11:36 +00:00
2007-08-13 13:36:42 +00:00
public string ToXmlString ( )
{
2007-10-12 19:31:37 +00:00
using ( StringWriter sw = new StringWriter ( ) )
{
using ( XmlTextWriter writer = new XmlTextWriter ( sw ) )
{
ToXml ( writer ) ;
}
return sw . ToString ( ) ;
}
}
public void ToXml ( XmlTextWriter writer )
{
2009-02-10 19:00:10 +00:00
//m_log.DebugFormat("[SOG]: Starting serialization of {0}", Name);
2009-02-11 20:36:17 +00:00
//int time = System.Environment.TickCount;
2009-01-02 17:22:24 +00:00
2007-08-13 13:36:42 +00:00
writer . WriteStartElement ( String . Empty , "SceneObjectGroup" , String . Empty ) ;
writer . WriteStartElement ( String . Empty , "RootPart" , String . Empty ) ;
m_rootPart . ToXml ( writer ) ;
writer . WriteEndElement ( ) ;
2007-08-16 16:31:32 +00:00
writer . WriteStartElement ( String . Empty , "OtherParts" , String . Empty ) ;
2008-04-21 14:11:36 +00:00
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-08-16 16:31:32 +00:00
{
2008-03-18 20:42:01 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-16 16:31:32 +00:00
{
2008-03-18 20:42:01 +00:00
if ( part . UUID ! = m_rootPart . UUID )
{
writer . WriteStartElement ( String . Empty , "Part" , String . Empty ) ;
part . ToXml ( writer ) ;
writer . WriteEndElement ( ) ;
}
2007-08-16 16:31:32 +00:00
}
}
2008-04-21 14:11:36 +00:00
2007-08-16 16:31:32 +00:00
writer . WriteEndElement ( ) ;
2007-08-13 13:36:42 +00:00
writer . WriteEndElement ( ) ;
2009-01-02 17:22:24 +00:00
2009-02-10 19:00:10 +00:00
//m_log.DebugFormat("[SOG]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
2007-08-13 13:36:42 +00:00
}
2007-08-03 16:17:05 +00:00
2007-10-22 11:06:54 +00:00
public string ToXmlString2 ( )
{
using ( StringWriter sw = new StringWriter ( ) )
{
using ( XmlTextWriter writer = new XmlTextWriter ( sw ) )
{
ToXml2 ( writer ) ;
}
return sw . ToString ( ) ;
}
}
public void ToXml2 ( XmlTextWriter writer )
{
2009-02-18 20:04:14 +00:00
//m_log.DebugFormat("[SOG]: Starting serialization of SOG {0} to XML2", Name);
2009-01-02 17:22:24 +00:00
int time = System . Environment . TickCount ;
2007-10-22 11:06:54 +00:00
writer . WriteStartElement ( String . Empty , "SceneObjectGroup" , String . Empty ) ;
m_rootPart . ToXml ( writer ) ;
writer . WriteStartElement ( String . Empty , "OtherParts" , String . Empty ) ;
2008-04-21 14:11:36 +00:00
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-10-22 11:06:54 +00:00
{
2008-03-18 20:42:01 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-10-22 11:06:54 +00:00
{
2008-03-18 20:42:01 +00:00
if ( part . UUID ! = m_rootPart . UUID )
{
part . ToXml ( writer ) ;
}
2007-10-22 11:06:54 +00:00
}
}
2008-04-21 14:11:36 +00:00
2007-10-22 11:06:54 +00:00
writer . WriteEndElement ( ) ;
writer . WriteEndElement ( ) ;
2009-02-18 20:04:14 +00:00
//m_log.DebugFormat("[SOG]: Finished serialization of SOG {0} to XML2, {1}ms", Name, System.Environment.TickCount - time);
2007-10-22 11:06:54 +00:00
}
2008-06-27 16:36:19 +00:00
/// <summary>
/// Attach this scene object to the given avatar.
/// </summary>
/// <param name="agentID"></param>
/// <param name="attachmentpoint"></param>
/// <param name="AttachOffset"></param>
2008-11-07 05:48:44 +00:00
public void AttachToAgent ( UUID agentID , uint attachmentpoint , Vector3 AttachOffset , bool silent )
2008-04-24 11:32:41 +00:00
{
ScenePresence avatar = m_scene . GetScenePresence ( agentID ) ;
if ( avatar ! = null )
{
2008-09-21 16:07:41 +00:00
// don't attach attachments to child agents
if ( avatar . IsChildAgent ) return ;
2008-10-03 13:45:54 +00:00
DetachFromBackup ( ) ;
2008-04-26 17:36:30 +00:00
2008-10-03 16:18:38 +00:00
// Remove from database and parcel prim count
/ /
m_scene . DeleteFromStorage ( UUID ) ;
m_scene . EventManager . TriggerParcelPrimCountTainted ( ) ;
m_rootPart . AttachedAvatar = agentID ;
2008-05-16 01:22:11 +00:00
2008-04-24 11:32:41 +00:00
if ( m_rootPart . PhysActor ! = null )
{
m_scene . PhysicsScene . RemovePrim ( m_rootPart . PhysActor ) ;
m_rootPart . PhysActor = null ;
}
2008-04-27 20:10:28 +00:00
AbsolutePosition = AttachOffset ;
2008-07-26 21:22:15 +00:00
m_rootPart . AttachedPos = AttachOffset ;
m_rootPart . IsAttachment = true ;
2008-04-26 17:36:30 +00:00
m_rootPart . SetParentLocalId ( avatar . LocalId ) ;
2008-10-03 21:44:33 +00:00
SetAttachmentPoint ( Convert . ToByte ( attachmentpoint ) ) ;
2008-04-26 17:36:30 +00:00
avatar . AddAttachment ( this ) ;
2008-11-07 05:48:44 +00:00
2008-11-08 14:28:43 +00:00
if ( ! silent )
2008-10-04 05:38:16 +00:00
{
2008-11-07 05:48:44 +00:00
// Killing it here will cause the client to deselect it
// It then reappears on the avatar, deselected
// through the full update below
/ /
if ( IsSelected )
{
m_scene . SendKillObject ( m_rootPart . LocalId ) ;
}
2008-10-03 21:44:33 +00:00
2008-11-07 05:48:44 +00:00
IsSelected = false ; // fudge....
ScheduleGroupForFullUpdate ( ) ;
}
2008-04-24 11:32:41 +00:00
}
}
2008-11-07 05:48:44 +00:00
2008-04-26 17:36:30 +00:00
public byte GetAttachmentPoint ( )
{
if ( m_rootPart ! = null )
{
return m_rootPart . Shape . State ;
}
2008-05-01 18:04:42 +00:00
return ( byte ) 0 ;
2008-04-26 17:36:30 +00:00
}
2008-04-24 11:32:41 +00:00
2008-04-29 13:12:36 +00:00
public void ClearPartAttachmentData ( )
{
2008-10-03 21:44:33 +00:00
SetAttachmentPoint ( ( Byte ) 0 ) ;
2008-04-29 13:12:36 +00:00
}
2008-04-24 11:32:41 +00:00
public void DetachToGround ( )
{
2008-07-26 21:22:15 +00:00
ScenePresence avatar = m_scene . GetScenePresence ( m_rootPart . AttachedAvatar ) ;
2008-11-14 15:30:15 +00:00
if ( avatar = = null )
return ;
avatar . RemoveAttachment ( this ) ;
2008-09-06 07:52:41 +00:00
Vector3 detachedpos = new Vector3 ( 127f , 127f , 127f ) ;
2008-10-04 01:09:22 +00:00
if ( avatar = = null )
return ;
detachedpos = avatar . AbsolutePosition ;
2008-04-24 11:32:41 +00:00
AbsolutePosition = detachedpos ;
2008-09-06 07:52:41 +00:00
m_rootPart . AttachedAvatar = UUID . Zero ;
2008-04-24 11:32:41 +00:00
m_rootPart . SetParentLocalId ( 0 ) ;
2008-10-03 21:44:33 +00:00
SetAttachmentPoint ( ( byte ) 0 ) ;
2008-12-22 09:29:59 +00:00
m_rootPart . ApplyPhysics ( m_rootPart . GetEffectiveObjectFlags ( ) , m_rootPart . VolumeDetectActive , m_scene . m_physicalPrim ) ;
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-10-18 05:51:36 +00:00
RootPart . Rezzed = DateTime . Now ;
2008-11-10 16:11:22 +00:00
RootPart . RemFlag ( PrimFlags . TemporaryOnRez ) ;
2008-04-26 17:36:30 +00:00
AttachToBackup ( ) ;
2008-10-04 01:09:22 +00:00
m_scene . EventManager . TriggerParcelPrimCountTainted ( ) ;
2008-04-24 11:32:41 +00:00
m_rootPart . ScheduleFullUpdate ( ) ;
2008-04-28 01:48:21 +00:00
m_rootPart . ClearUndoState ( ) ;
2008-04-24 11:32:41 +00:00
}
2008-08-18 00:39:10 +00:00
2008-04-27 20:10:28 +00:00
public void DetachToInventoryPrep ( )
{
2008-07-26 21:22:15 +00:00
ScenePresence avatar = m_scene . GetScenePresence ( m_rootPart . AttachedAvatar ) ;
2008-09-06 07:52:41 +00:00
//Vector3 detachedpos = new Vector3(127f, 127f, 127f);
2008-04-27 20:10:28 +00:00
if ( avatar ! = null )
{
//detachedpos = avatar.AbsolutePosition;
avatar . RemoveAttachment ( this ) ;
}
2008-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
m_rootPart . AttachedAvatar = UUID . Zero ;
2008-04-27 20:10:28 +00:00
m_rootPart . SetParentLocalId ( 0 ) ;
//m_rootPart.SetAttachmentPoint((byte)0);
2008-07-26 21:22:15 +00:00
m_rootPart . IsAttachment = false ;
AbsolutePosition = m_rootPart . AttachedPos ;
2008-04-30 16:52:12 +00:00
//m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
2008-04-27 20:10:28 +00:00
//AttachToBackup();
//m_rootPart.ScheduleFullUpdate();
2008-05-16 01:22:11 +00:00
2008-04-27 20:10:28 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="part"></param>
private void SetPartAsNonRoot ( SceneObjectPart part )
{
part . ParentID = m_rootPart . LocalId ;
2008-04-28 01:48:21 +00:00
part . ClearUndoState ( ) ;
2008-04-21 14:11:36 +00:00
}
2007-12-27 21:41:48 +00:00
2008-04-21 14:11:36 +00:00
public override void UpdateMovement ( )
{
lock ( m_parts )
2007-08-03 14:47:38 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-03 14:47:38 +00:00
{
2008-04-21 14:11:36 +00:00
part . UpdateMovement ( ) ;
2007-08-03 14:47:38 +00:00
}
}
2008-04-21 14:11:36 +00:00
}
2007-08-13 18:25:12 +00:00
2008-04-21 14:11:36 +00:00
public float GetTimeDilation ( )
{
return m_scene . TimeDilation ;
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// Added as a way for the storage provider to reset the scene,
2008-04-21 14:11:36 +00:00
/// most likely a better way to do this sort of thing but for now...
/// </summary>
/// <param name="scene"></param>
public void SetScene ( Scene scene )
{
m_scene = scene ;
2007-08-03 14:47:38 +00:00
}
2008-11-10 19:47:13 +00:00
/// <summary>
/// Set a part to act as the root part for this scene object
/// </summary>
/// <param name="part"></param>
2008-11-10 20:04:55 +00:00
public void SetRootPart ( SceneObjectPart part )
2008-11-10 19:47:13 +00:00
{
part . SetParent ( this ) ;
m_rootPart = part ;
2008-11-29 01:33:10 +00:00
if ( ! IsAttachment )
part . ParentID = 0 ;
part . LinkNum = 0 ;
2008-11-10 20:54:34 +00:00
// No locking required since the SOG should not be in the scene yet - one can't change root parts after
// the scene object has been attached to the scene
2008-11-10 19:47:13 +00:00
m_parts . Add ( m_rootPart . UUID , m_rootPart ) ;
}
2007-08-03 14:47:38 +00:00
2007-08-04 18:15:48 +00:00
/// <summary>
2008-11-10 19:47:13 +00:00
/// Add a new part to this scene object. The part must already be correctly configured.
2007-08-04 18:15:48 +00:00
/// </summary>
/// <param name="part"></param>
2008-04-21 14:11:36 +00:00
public void AddPart ( SceneObjectPart part )
2007-08-03 14:47:38 +00:00
{
2008-03-18 20:42:01 +00:00
lock ( m_parts )
{
2008-04-21 14:11:36 +00:00
part . SetParent ( this ) ;
2008-11-10 20:10:23 +00:00
m_parts . Add ( part . UUID , part ) ;
2008-07-19 04:05:34 +00:00
part . LinkNum = m_parts . Count ;
2008-07-23 13:24:25 +00:00
if ( part . LinkNum = = 2 & & RootPart ! = null )
2008-07-19 04:05:34 +00:00
RootPart . LinkNum = 1 ;
2008-03-14 06:20:50 +00:00
}
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-07-12 21:43:35 +00:00
/// Make sure that every non root part has the proper parent root part local id
2008-04-21 14:11:36 +00:00
/// </summary>
2008-11-07 19:17:24 +00:00
private void UpdateParentIDs ( )
2008-03-14 06:20:50 +00:00
{
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
2008-04-21 14:11:36 +00:00
if ( part . UUID ! = m_rootPart . UUID )
2008-03-14 06:20:50 +00:00
{
2008-04-21 14:11:36 +00:00
part . ParentID = m_rootPart . LocalId ;
2008-03-14 06:20:50 +00:00
}
}
}
}
2008-04-21 14:11:36 +00:00
public void RegenerateFullIDs ( )
2008-01-17 14:59:05 +00:00
{
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2008-01-17 14:59:05 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2008-02-12 00:01:55 +00:00
{
2008-09-06 07:52:41 +00:00
part . UUID = UUID . Random ( ) ;
2008-05-16 01:22:11 +00:00
2008-02-12 00:01:55 +00:00
}
2008-01-17 14:59:05 +00:00
}
}
2008-04-28 01:48:21 +00:00
// helper provided for parts.
public int GetSceneMaxUndo ( )
{
if ( m_scene ! = null )
return m_scene . MaxUndoCount ;
return 5 ;
}
2008-08-18 00:39:10 +00:00
// justincc: I don't believe this hack is needed any longer, especially since the physics
2008-07-25 17:48:58 +00:00
// parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
// this method was preventing proper reload of scene objects.
2009-02-08 18:05:12 +00:00
2008-08-18 00:39:10 +00:00
// dahlia: I had to uncomment it, without it meshing was failing on some prims and objects
2008-07-26 01:58:13 +00:00
// at region startup
2009-02-08 18:05:12 +00:00
// teravus: After this was removed from the linking algorithm, Linked prims no longer collided
2009-02-09 20:06:06 +00:00
// properly when non-physical if they havn't been moved. This breaks ALL builds.
2009-02-08 18:05:12 +00:00
// see: http://opensimulator.org/mantis/view.php?id=3108
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
// unmoved prims! As soon as you move a Prim/group, it will collide properly because Absolute
// Position has been set!
2008-07-26 01:58:13 +00:00
public void ResetChildPrimPhysicsPositions ( )
{
2008-07-26 19:51:17 +00:00
AbsolutePosition = AbsolutePosition ; // could someone in the know please explain how this works?
2009-02-08 18:05:12 +00:00
// teravus: AbsolutePosition is NOT a normal property!
// the code in the getter of AbsolutePosition is significantly different then the code in the setter!
2008-07-26 01:58:13 +00:00
}
2008-03-25 03:36:31 +00:00
2008-09-06 07:52:41 +00:00
public UUID GetPartsFullID ( uint localID )
2007-12-04 16:41:20 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-12-05 06:44:32 +00:00
{
2008-04-21 14:11:36 +00:00
return part . UUID ;
2007-12-05 06:44:32 +00:00
}
2008-09-26 17:25:22 +00:00
return UUID . Zero ;
2007-11-14 11:56:57 +00:00
}
2007-08-03 14:47:38 +00:00
2008-09-06 07:52:41 +00:00
public void ObjectGrabHandler ( uint localId , Vector3 offsetPos , IClientAPI remoteClient )
2007-08-03 14:47:38 +00:00
{
2008-04-21 14:11:36 +00:00
if ( m_rootPart . LocalId = = localId )
2008-03-18 20:42:01 +00:00
{
2008-04-21 14:11:36 +00:00
OnGrabGroup ( offsetPos , remoteClient ) ;
2008-03-18 20:42:01 +00:00
}
2008-04-21 14:11:36 +00:00
else
2007-12-01 21:52:10 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localId ) ;
OnGrabPart ( part , offsetPos , remoteClient ) ;
2008-05-16 01:22:11 +00:00
2007-12-01 21:52:10 +00:00
}
}
2007-12-27 21:41:48 +00:00
2008-09-06 07:52:41 +00:00
public virtual void OnGrabPart ( SceneObjectPart part , Vector3 offsetPos , IClientAPI remoteClient )
2007-11-15 07:32:24 +00:00
{
2008-04-28 01:48:21 +00:00
part . StoreUndoState ( ) ;
2008-04-21 14:11:36 +00:00
part . OnGrab ( offsetPos , remoteClient ) ;
2007-11-15 07:32:24 +00:00
}
2007-12-27 21:41:48 +00:00
2008-09-06 07:52:41 +00:00
public virtual void OnGrabGroup ( Vector3 offsetPos , IClientAPI remoteClient )
2007-11-14 11:56:57 +00:00
{
2008-04-21 14:11:36 +00:00
m_scene . EventManager . TriggerGroupGrab ( UUID , offsetPos , remoteClient . AgentId ) ;
2007-11-14 11:56:57 +00:00
}
2007-09-19 00:30:55 +00:00
2007-08-03 14:47:38 +00:00
/// <summary>
2008-06-21 19:56:19 +00:00
/// Delete this group from its scene and tell all the scene presences about that deletion.
2009-02-02 14:57:01 +00:00
/// </summary>
/// <param name="silent">Broadcast deletions to all clients.</param>
2008-11-07 05:48:44 +00:00
public void DeleteGroup ( bool silent )
2007-08-03 14:47:38 +00:00
{
2008-08-18 00:39:10 +00:00
// We need to keep track of this state in case this group is still queued for backup.
2008-06-21 19:56:19 +00:00
m_isDeleted = true ;
2008-08-18 00:39:10 +00:00
2008-10-03 13:45:54 +00:00
DetachFromBackup ( ) ;
2008-04-21 14:11:36 +00:00
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-11-03 19:33:00 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-11-03 19:33:00 +00:00
{
2008-11-21 21:16:42 +00:00
// part.Inventory.RemoveScriptInstances();
2008-08-18 00:39:10 +00:00
2008-05-14 21:09:41 +00:00
List < ScenePresence > avatars = Scene . GetScenePresences ( ) ;
2008-04-21 14:11:36 +00:00
for ( int i = 0 ; i < avatars . Count ; i + + )
2008-03-18 20:42:01 +00:00
{
2008-04-21 14:11:36 +00:00
if ( avatars [ i ] . ParentID = = LocalId )
{
avatars [ i ] . StandUp ( ) ;
}
2008-11-07 05:48:44 +00:00
if ( ! silent )
{
if ( m_rootPart ! = null & & part = = m_rootPart )
avatars [ i ] . ControllingClient . SendKillObject ( m_regionHandle , part . LocalId ) ;
}
2008-03-18 20:42:01 +00:00
}
2007-11-03 19:33:00 +00:00
}
2007-08-03 14:47:38 +00:00
}
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
public void AddScriptLPS ( int count )
2007-09-06 14:15:16 +00:00
{
2008-05-25 20:50:45 +00:00
if ( scriptScore + count > = float . MaxValue - count )
scriptScore = 0 ;
scriptScore + = ( float ) count ;
2009-02-20 17:18:07 +00:00
SceneGraph d = m_scene . SceneGraph ;
2008-04-21 14:11:36 +00:00
d . AddToScriptLPS ( count ) ;
2007-09-06 14:15:16 +00:00
}
2008-04-21 14:11:36 +00:00
public void AddActiveScriptCount ( int count )
2007-08-03 14:47:38 +00:00
{
2009-02-20 17:18:07 +00:00
SceneGraph d = m_scene . SceneGraph ;
2008-04-21 14:11:36 +00:00
d . AddActiveScripts ( count ) ;
2007-08-03 14:47:38 +00:00
}
2008-04-21 14:11:36 +00:00
public void aggregateScriptEvents ( )
2007-07-30 20:11:40 +00:00
{
2008-05-06 22:41:38 +00:00
uint objectflagupdate = ( uint ) RootPart . GetEffectiveObjectFlags ( ) ;
2007-07-30 20:11:40 +00:00
2008-05-06 22:41:38 +00:00
scriptEvents aggregateScriptEvents = 0 ;
2007-09-19 00:30:55 +00:00
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-12-17 02:30:03 +00:00
{
2008-03-18 20:42:01 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-12-17 02:30:03 +00:00
{
2008-05-06 22:41:38 +00:00
if ( part = = null )
continue ;
if ( part ! = RootPart )
part . ObjectFlags = objectflagupdate ;
2008-07-26 21:22:15 +00:00
aggregateScriptEvents | = part . AggregateScriptEvents ;
2007-12-17 02:30:03 +00:00
}
}
2008-04-25 01:00:55 +00:00
2008-04-30 16:52:12 +00:00
if ( ( aggregateScriptEvents & scriptEvents . at_target ) ! = 0 )
2008-04-25 01:00:55 +00:00
{
m_scriptListens_atTarget = true ;
}
else
{
m_scriptListens_atTarget = false ;
}
2008-04-30 16:52:12 +00:00
if ( ( aggregateScriptEvents & scriptEvents . not_at_target ) ! = 0 )
2008-04-25 01:00:55 +00:00
{
m_scriptListens_notAtTarget = true ;
}
else
{
m_scriptListens_notAtTarget = false ;
}
if ( m_scriptListens_atTarget | | m_scriptListens_notAtTarget )
{
}
else
{
lock ( m_targets )
m_targets . Clear ( ) ;
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
ScheduleGroupForFullUpdate ( ) ;
2007-12-17 02:30:03 +00:00
}
2008-04-21 14:11:36 +00:00
public override void SetText ( string text , Vector3 color , double alpha )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
Color = Color . FromArgb ( 0xff - ( int ) ( alpha * 0xff ) ,
2008-09-06 07:52:41 +00:00
( int ) ( color . X * 0xff ) ,
( int ) ( color . Y * 0xff ) ,
( int ) ( color . Z * 0xff ) ) ;
2008-04-21 14:11:36 +00:00
Text = text ;
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
m_rootPart . ScheduleFullUpdate ( ) ;
2007-07-30 20:11:40 +00:00
}
2008-06-17 17:23:00 +00:00
/// <summary>
/// Apply physics to this group
/// </summary>
/// <param name="m_physicalPrim"></param>
2008-04-21 14:11:36 +00:00
public void ApplyPhysics ( bool m_physicalPrim )
2007-07-30 20:11:40 +00:00
{
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
if ( m_parts . Count > 1 )
2007-07-30 20:11:40 +00:00
{
2008-12-22 09:29:59 +00:00
m_rootPart . ApplyPhysics ( m_rootPart . GetEffectiveObjectFlags ( ) , m_rootPart . VolumeDetectActive , m_physicalPrim ) ;
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2008-03-18 20:42:01 +00:00
{
2008-04-21 14:11:36 +00:00
if ( part . LocalId ! = m_rootPart . LocalId )
{
2008-12-22 09:29:59 +00:00
part . ApplyPhysics ( m_rootPart . GetEffectiveObjectFlags ( ) , part . VolumeDetectActive , m_physicalPrim ) ;
2008-09-12 00:45:24 +00:00
}
}
// Hack to get the physics scene geometries in the right spot
ResetChildPrimPhysicsPositions ( ) ;
2007-07-30 20:11:40 +00:00
}
2008-04-21 14:11:36 +00:00
else
{
2008-12-22 09:29:59 +00:00
m_rootPart . ApplyPhysics ( m_rootPart . GetEffectiveObjectFlags ( ) , m_rootPart . VolumeDetectActive , m_physicalPrim ) ;
2008-04-21 14:11:36 +00:00
}
2007-07-30 20:11:40 +00:00
}
}
2008-09-06 07:52:41 +00:00
public void SetOwnerId ( UUID userId )
2007-08-02 16:40:50 +00:00
{
2008-04-21 14:11:36 +00:00
ForEachPart ( delegate ( SceneObjectPart part ) { part . OwnerID = userId ; } ) ;
2007-08-02 16:40:50 +00:00
}
2008-04-21 14:11:36 +00:00
public void ForEachPart ( Action < SceneObjectPart > whatToDo )
2007-08-02 16:40:50 +00:00
{
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-08-02 16:40:50 +00:00
{
2008-03-18 20:42:01 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-02 16:40:50 +00:00
{
2008-04-21 14:11:36 +00:00
whatToDo ( part ) ;
2007-08-02 16:40:50 +00:00
}
}
}
2008-04-21 14:11:36 +00:00
#region Events
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-09-16 17:30:30 +00:00
/// Processes backup.
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="datastore"></param>
2009-02-04 16:00:39 +00:00
public void ProcessBackup ( IRegionDataStore datastore , bool forcedBackup )
2008-08-18 00:39:10 +00:00
{
2008-11-16 00:47:21 +00:00
if ( ! m_isBackedUp )
return ;
2008-09-16 17:30:30 +00:00
// Since this is the top of the section of call stack for backing up a particular scene object, don't let
// any exception propogate upwards.
2008-10-18 15:43:02 +00:00
2008-11-17 15:40:27 +00:00
if ( IsDeleted | | UUID = = UUID . Zero )
2008-10-18 15:43:02 +00:00
return ;
2008-09-16 17:30:30 +00:00
try
2008-03-18 20:42:01 +00:00
{
2008-11-15 17:52:00 +00:00
if ( ! m_scene . ShuttingDown ) // if shutting down then there will be nothing to handle the return so leave till next restart
2008-10-18 05:51:36 +00:00
{
2008-11-15 17:52:00 +00:00
ILandObject parcel = m_scene . LandChannel . GetLandObject (
m_rootPart . GroupPosition . X , m_rootPart . GroupPosition . Y ) ;
if ( parcel ! = null & & parcel . landData ! = null & &
parcel . landData . OtherCleanTime ! = 0 )
2008-10-18 05:51:36 +00:00
{
2008-11-15 17:52:00 +00:00
if ( parcel . landData . OwnerID ! = OwnerID & &
( parcel . landData . GroupID ! = GroupID | |
parcel . landData . GroupID = = UUID . Zero ) )
2008-10-18 05:51:36 +00:00
{
2008-11-15 17:52:00 +00:00
if ( ( DateTime . Now - RootPart . Rezzed ) . TotalMinutes >
parcel . landData . OtherCleanTime )
{
2008-11-23 06:57:38 +00:00
DetachFromBackup ( ) ;
2008-11-28 17:18:10 +00:00
m_log . InfoFormat ( "[SCENE]: Returning object {0} due to parcel auto return" , RootPart . UUID . ToString ( ) ) ;
2008-11-21 07:33:13 +00:00
m_scene . AddReturn ( OwnerID , Name , AbsolutePosition , "parcel auto return" ) ;
2008-11-15 17:52:00 +00:00
m_scene . DeRezObject ( null , RootPart . LocalId ,
2008-11-28 17:18:10 +00:00
RootPart . GroupID , DeRezAction . Return , UUID . Zero ) ;
2008-10-18 05:51:36 +00:00
2008-11-15 17:52:00 +00:00
return ;
}
2008-10-18 05:51:36 +00:00
}
}
}
2008-09-16 17:30:30 +00:00
if ( HasGroupChanged )
2008-05-25 19:21:21 +00:00
{
2008-09-16 17:30:30 +00:00
// don't backup while it's selected or you're asking for changes mid stream.
2009-02-04 16:00:39 +00:00
if ( ( isTimeToPersist ( ) ) | | ( forcedBackup ) )
2008-09-16 17:30:30 +00:00
{
2008-09-16 17:35:35 +00:00
m_log . DebugFormat (
2008-09-16 17:30:30 +00:00
"[SCENE]: Storing {0}, {1} in {2}" ,
Name , UUID , m_scene . RegionInfo . RegionName ) ;
2008-05-25 23:27:38 +00:00
2008-09-16 17:30:30 +00:00
SceneObjectGroup backup_group = Copy ( OwnerID , GroupID , false ) ;
backup_group . RootPart . Velocity = RootPart . Velocity ;
backup_group . RootPart . Acceleration = RootPart . Acceleration ;
backup_group . RootPart . AngularVelocity = RootPart . AngularVelocity ;
backup_group . RootPart . ParticleSystem = RootPart . ParticleSystem ;
2008-11-15 17:52:00 +00:00
HasGroupChanged = false ;
2008-05-25 23:27:38 +00:00
2008-09-16 17:30:30 +00:00
datastore . StoreObject ( backup_group , m_scene . RegionInfo . RegionID ) ;
2008-05-25 01:09:14 +00:00
2009-01-29 18:39:33 +00:00
backup_group . ForEachPart ( delegate ( SceneObjectPart part )
{
part . Inventory . ProcessInventoryBackup ( datastore ) ;
} ) ;
2008-05-25 23:27:38 +00:00
2008-09-16 17:30:30 +00:00
backup_group = null ;
}
// else
// {
// m_log.DebugFormat(
// "[SCENE]: Did not update persistence of object {0} {1}, selected = {2}",
// Name, UUID, IsSelected);
// }
2008-05-25 19:21:21 +00:00
}
2008-09-16 17:30:30 +00:00
}
catch ( Exception e )
{
m_log . ErrorFormat (
2008-11-01 22:20:54 +00:00
"[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}\n\t{4}" ,
Name , UUID , m_scene . RegionInfo . RegionName , e , e . StackTrace ) ;
2008-03-18 20:42:01 +00:00
}
2008-04-21 14:11:36 +00:00
}
2007-11-20 04:38:08 +00:00
2008-04-21 14:11:36 +00:00
# endregion
2007-08-24 11:04:07 +00:00
2008-04-21 14:11:36 +00:00
#region Client Updating
2008-11-07 05:48:44 +00:00
public void SendFullUpdateToClient ( IClientAPI remoteClient )
2008-04-21 14:11:36 +00:00
{
2008-11-21 22:14:57 +00:00
SendPartFullUpdate ( remoteClient , RootPart , m_scene . Permissions . GenerateClientFlags ( remoteClient . AgentId , RootPart . UUID ) ) ;
2008-11-07 05:48:44 +00:00
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-08-20 15:49:06 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-20 15:49:06 +00:00
{
2008-11-07 05:48:44 +00:00
if ( part ! = RootPart )
2008-11-21 22:14:57 +00:00
SendPartFullUpdate ( remoteClient , part , m_scene . Permissions . GenerateClientFlags ( remoteClient . AgentId , part . UUID ) ) ;
2007-08-20 15:49:06 +00:00
}
}
2008-04-21 14:11:36 +00:00
}
2007-08-13 13:36:42 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
/// Send a full update to the client for the given part
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="part"></param>
internal void SendPartFullUpdate ( IClientAPI remoteClient , SceneObjectPart part , uint clientFlags )
{
2008-10-06 04:20:27 +00:00
if ( m_rootPart ! = null & & m_rootPart . UUID = = part . UUID )
2008-04-21 14:11:36 +00:00
{
2008-11-01 22:04:35 +00:00
if ( IsAttachment )
2008-04-25 21:41:55 +00:00
{
2008-07-26 21:22:15 +00:00
part . SendFullUpdateToClient ( remoteClient , m_rootPart . AttachedPos , clientFlags ) ;
2008-04-25 21:41:55 +00:00
}
else
{
part . SendFullUpdateToClient ( remoteClient , AbsolutePosition , clientFlags ) ;
}
2008-04-21 14:11:36 +00:00
}
else
{
part . SendFullUpdateToClient ( remoteClient , clientFlags ) ;
}
}
2007-09-13 05:25:26 +00:00
2008-04-21 14:11:36 +00:00
# endregion
2008-03-12 18:59:50 +00:00
2008-04-21 14:11:36 +00:00
#region Copying
2007-12-04 16:41:20 +00:00
2007-11-13 19:57:11 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// Duplicates this object, including operations such as physics set up and attaching to the backup event.
2007-11-13 19:57:11 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public SceneObjectGroup Copy ( UUID cAgentID , UUID cGroupID , bool userExposed )
2008-04-21 14:11:36 +00:00
{
2009-02-03 17:50:25 +00:00
SceneObjectGroup dupe = ( SceneObjectGroup ) MemberwiseClone ( ) ;
2008-10-20 22:14:24 +00:00
dupe . m_isBackedUp = false ;
2008-09-06 07:52:41 +00:00
dupe . m_parts = new Dictionary < UUID , SceneObjectPart > ( ) ;
dupe . AbsolutePosition = new Vector3 ( AbsolutePosition . X , AbsolutePosition . Y , AbsolutePosition . Z ) ;
2007-12-04 16:41:20 +00:00
2008-05-21 21:22:56 +00:00
dupe . CopyRootPart ( m_rootPart , OwnerID , GroupID , userExposed ) ;
2008-11-26 07:34:38 +00:00
dupe . m_rootPart . LinkNum = m_rootPart . LinkNum ;
2008-05-21 21:22:56 +00:00
if ( userExposed )
dupe . m_rootPart . TrimPermissions ( ) ;
2008-01-15 04:27:02 +00:00
2008-04-21 14:11:36 +00:00
/// may need to create a new Physics actor.
2008-05-21 21:22:56 +00:00
if ( dupe . RootPart . PhysActor ! = null & & userExposed )
2008-04-21 14:11:36 +00:00
{
PrimitiveBaseShape pbs = dupe . RootPart . Shape ;
2007-12-04 16:41:20 +00:00
2008-04-21 14:11:36 +00:00
dupe . RootPart . PhysActor = m_scene . PhysicsScene . AddPrimShape (
dupe . RootPart . Name ,
pbs ,
2008-09-06 07:52:41 +00:00
new PhysicsVector ( dupe . RootPart . AbsolutePosition . X , dupe . RootPart . AbsolutePosition . Y , dupe . RootPart . AbsolutePosition . Z ) ,
2008-04-21 14:11:36 +00:00
new PhysicsVector ( dupe . RootPart . Scale . X , dupe . RootPart . Scale . Y , dupe . RootPart . Scale . Z ) ,
2008-09-06 07:52:41 +00:00
dupe . RootPart . RotationOffset ,
2008-04-21 14:11:36 +00:00
dupe . RootPart . PhysActor . IsPhysical ) ;
2007-12-04 16:41:20 +00:00
2008-04-21 14:11:36 +00:00
dupe . RootPart . PhysActor . LocalID = dupe . RootPart . LocalId ;
dupe . RootPart . DoPhysicsPropertyUpdate ( dupe . RootPart . PhysActor . IsPhysical , true ) ;
}
2008-08-18 00:39:10 +00:00
2008-05-16 01:22:11 +00:00
// Now we've made a copy that replaces this one, we need to
2008-04-21 14:11:36 +00:00
// switch the owner to the person who did the copying
// Second Life copies an object and duplicates the first one in it's place
// So, we have to make a copy of this one, set it in it's place then set the owner on this one
2008-05-21 21:22:56 +00:00
if ( userExposed )
{
SetRootPartOwner ( m_rootPart , cAgentID , cGroupID ) ;
m_rootPart . ScheduleFullUpdate ( ) ;
2008-05-25 23:27:38 +00:00
}
2009-02-03 18:06:24 +00:00
List < SceneObjectPart > partList ;
2007-12-04 16:41:20 +00:00
2009-02-03 18:06:24 +00:00
lock ( m_parts )
{
partList = new List < SceneObjectPart > ( m_parts . Values ) ;
}
2008-11-26 07:34:38 +00:00
partList . Sort ( delegate ( SceneObjectPart p1 , SceneObjectPart p2 )
{
return p1 . LinkNum . CompareTo ( p2 . LinkNum ) ;
}
) ;
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in partList )
2007-11-13 19:57:11 +00:00
{
2008-04-21 14:11:36 +00:00
if ( part . UUID ! = m_rootPart . UUID )
{
2009-02-03 17:50:25 +00:00
SceneObjectPart newPart = dupe . CopyPart ( part , OwnerID , GroupID , userExposed ) ;
2008-11-26 07:34:38 +00:00
newPart . LinkNum = part . LinkNum ;
2008-05-25 23:27:38 +00:00
2008-05-21 21:22:56 +00:00
if ( userExposed )
{
2008-11-26 07:34:38 +00:00
SetPartOwner ( newPart , cAgentID , cGroupID ) ;
newPart . ScheduleFullUpdate ( ) ;
2008-05-21 21:22:56 +00:00
}
2008-04-21 14:11:36 +00:00
}
2007-12-04 16:41:20 +00:00
}
2007-08-13 13:36:42 +00:00
2008-05-21 21:22:56 +00:00
if ( userExposed )
{
dupe . UpdateParentIDs ( ) ;
2008-06-27 16:36:19 +00:00
dupe . HasGroupChanged = true ;
2008-05-21 21:22:56 +00:00
dupe . AttachToBackup ( ) ;
2008-08-18 00:39:10 +00:00
2008-05-21 21:22:56 +00:00
ScheduleGroupForFullUpdate ( ) ;
}
2008-04-21 14:11:36 +00:00
return dupe ;
2007-09-13 05:25:26 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="part"></param>
/// <param name="cAgentID"></param>
/// <param name="cGroupID"></param>
2008-09-06 07:52:41 +00:00
public void CopyRootPart ( SceneObjectPart part , UUID cAgentID , UUID cGroupID , bool userExposed )
2007-08-20 15:49:06 +00:00
{
2008-11-10 19:47:13 +00:00
SetRootPart ( part . Copy ( m_scene . AllocateLocalId ( ) , OwnerID , GroupID , m_parts . Count , userExposed ) ) ;
2008-04-21 14:11:36 +00:00
}
2007-08-21 16:25:57 +00:00
2008-04-21 14:11:36 +00:00
public void ScriptSetPhysicsStatus ( bool UsePhysics )
{
2008-11-07 22:57:32 +00:00
bool IsTemporary = ( ( RootPart . Flags & PrimFlags . TemporaryOnRez ) ! = 0 ) ;
bool IsPhantom = ( ( RootPart . Flags & PrimFlags . Phantom ) ! = 0 ) ;
2008-12-20 21:36:42 +00:00
bool IsVolumeDetect = RootPart . VolumeDetectActive ;
UpdatePrimFlags ( RootPart . LocalId , UsePhysics , IsTemporary , IsPhantom , IsVolumeDetect ) ;
2008-11-07 22:57:32 +00:00
}
2007-08-21 16:25:57 +00:00
2008-11-07 22:57:32 +00:00
public void ScriptSetTemporaryStatus ( bool TemporaryStatus )
{
bool UsePhysics = ( ( RootPart . Flags & PrimFlags . Physics ) ! = 0 ) ;
bool IsPhantom = ( ( RootPart . Flags & PrimFlags . Phantom ) ! = 0 ) ;
2008-12-20 21:36:42 +00:00
bool IsVolumeDetect = RootPart . VolumeDetectActive ;
UpdatePrimFlags ( RootPart . LocalId , UsePhysics , TemporaryStatus , IsPhantom , IsVolumeDetect ) ;
2007-08-20 15:49:06 +00:00
}
2008-04-21 14:11:36 +00:00
public void ScriptSetPhantomStatus ( bool PhantomStatus )
2007-07-30 20:11:40 +00:00
{
2008-11-07 22:57:32 +00:00
bool UsePhysics = ( ( RootPart . Flags & PrimFlags . Physics ) ! = 0 ) ;
bool IsTemporary = ( ( RootPart . Flags & PrimFlags . TemporaryOnRez ) ! = 0 ) ;
2008-12-20 21:36:42 +00:00
bool IsVolumeDetect = RootPart . VolumeDetectActive ;
UpdatePrimFlags ( RootPart . LocalId , UsePhysics , IsTemporary , PhantomStatus , IsVolumeDetect ) ;
}
public void ScriptSetVolumeDetect ( bool VDStatus )
{
bool UsePhysics = ( ( RootPart . Flags & PrimFlags . Physics ) ! = 0 ) ;
bool IsTemporary = ( ( RootPart . Flags & PrimFlags . TemporaryOnRez ) ! = 0 ) ;
bool IsPhantom = ( ( RootPart . Flags & PrimFlags . Phantom ) ! = 0 ) ;
UpdatePrimFlags ( RootPart . LocalId , UsePhysics , IsTemporary , IsPhantom , VDStatus ) ;
/ *
ScriptSetPhantomStatus ( false ) ; // What ever it was before, now it's not phantom anymore
if ( PhysActor ! = null ) // Should always be the case now
{
PhysActor . SetVolumeDetect ( param ) ;
}
if ( param ! = 0 )
AddFlag ( PrimFlags . Phantom ) ;
ScheduleFullUpdate ( ) ;
* /
2007-07-30 20:11:40 +00:00
}
2008-04-21 14:11:36 +00:00
public void applyImpulse ( PhysicsVector impulse )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
// We check if rootpart is null here because scripts don't delete if you delete the host.
// This means that unfortunately, we can pass a null physics actor to Simulate!
// Make sure we don't do that!
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
{
if ( rootpart . PhysActor ! = null )
{
2008-11-01 22:04:35 +00:00
if ( IsAttachment )
2008-05-06 00:23:19 +00:00
{
2008-07-26 21:22:15 +00:00
ScenePresence avatar = m_scene . GetScenePresence ( rootpart . AttachedAvatar ) ;
2008-05-06 00:23:19 +00:00
if ( avatar ! = null )
{
avatar . PushForce ( impulse ) ;
}
}
else
{
rootpart . PhysActor . AddForce ( impulse , true ) ;
m_scene . PhysicsScene . AddPhysicsActorTaint ( rootpart . PhysActor ) ;
}
2008-04-21 14:11:36 +00:00
}
}
2007-07-30 20:11:40 +00:00
}
2008-12-14 14:30:28 +00:00
public void applyAngularImpulse ( PhysicsVector impulse )
{
// We check if rootpart is null here because scripts don't delete if you delete the host.
// This means that unfortunately, we can pass a null physics actor to Simulate!
// Make sure we don't do that!
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
{
if ( rootpart . PhysActor ! = null )
{
if ( ! IsAttachment )
{
rootpart . PhysActor . AddAngularForce ( impulse , true ) ;
m_scene . PhysicsScene . AddPhysicsActorTaint ( rootpart . PhysActor ) ;
}
}
}
}
public void setAngularImpulse ( PhysicsVector impulse )
{
// We check if rootpart is null here because scripts don't delete if you delete the host.
// This means that unfortunately, we can pass a null physics actor to Simulate!
// Make sure we don't do that!
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
{
if ( rootpart . PhysActor ! = null )
{
if ( ! IsAttachment )
{
rootpart . PhysActor . Torque = impulse ;
m_scene . PhysicsScene . AddPhysicsActorTaint ( rootpart . PhysActor ) ;
}
}
}
}
public Vector3 GetTorque ( )
{
// We check if rootpart is null here because scripts don't delete if you delete the host.
// This means that unfortunately, we can pass a null physics actor to Simulate!
// Make sure we don't do that!
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
{
if ( rootpart . PhysActor ! = null )
{
if ( ! IsAttachment )
{
PhysicsVector torque = rootpart . PhysActor . Torque ;
return new Vector3 ( torque . X , torque . Y , torque . Z ) ;
}
}
}
return Vector3 . Zero ;
}
2008-09-06 07:52:41 +00:00
public void moveToTarget ( Vector3 target , float tau )
2007-08-09 17:54:22 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
2007-08-13 14:39:12 +00:00
{
2008-04-23 15:32:19 +00:00
if ( rootpart . PhysActor ! = null )
{
rootpart . PhysActor . PIDTarget = new PhysicsVector ( target . X , target . Y , target . Z ) ;
rootpart . PhysActor . PIDTau = tau ;
rootpart . PhysActor . PIDActive = true ;
}
2007-08-13 14:39:12 +00:00
}
2007-08-09 17:54:22 +00:00
}
2008-04-21 14:11:36 +00:00
public void stopMoveToTarget ( )
2007-08-09 17:54:22 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart rootpart = m_rootPart ;
if ( rootpart ! = null )
2007-08-09 17:54:22 +00:00
{
2008-10-22 14:06:07 +00:00
if ( rootpart . PhysActor ! = null )
{
rootpart . PhysActor . PIDActive = false ;
}
2007-08-09 17:54:22 +00:00
}
}
2008-11-10 20:54:34 +00:00
/// <summary>
/// Set the owner of the root part.
/// </summary>
/// <param name="part"></param>
/// <param name="cAgentID"></param>
/// <param name="cGroupID"></param>
2008-09-06 07:52:41 +00:00
public void SetRootPartOwner ( SceneObjectPart part , UUID cAgentID , UUID cGroupID )
2007-08-13 14:39:12 +00:00
{
2008-04-21 14:11:36 +00:00
part . LastOwnerID = part . OwnerID ;
part . OwnerID = cAgentID ;
part . GroupID = cGroupID ;
if ( part . OwnerID ! = cAgentID )
2007-08-13 14:39:12 +00:00
{
2008-04-21 14:11:36 +00:00
// Apply Next Owner Permissions if we're not bypassing permissions
2008-11-21 22:14:57 +00:00
if ( ! m_scene . Permissions . BypassPermissions ( ) )
2008-05-15 19:28:10 +00:00
ApplyNextOwnerPermissions ( ) ;
2008-04-21 14:11:36 +00:00
}
part . ScheduleFullUpdate ( ) ;
2007-08-13 14:39:12 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-07-13 00:18:29 +00:00
/// Make a copy of the given part.
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="part"></param>
/// <param name="cAgentID"></param>
/// <param name="cGroupID"></param>
2008-11-26 07:34:38 +00:00
public SceneObjectPart CopyPart ( SceneObjectPart part , UUID cAgentID , UUID cGroupID , bool userExposed )
2007-08-13 14:39:12 +00:00
{
2008-11-07 22:49:36 +00:00
SceneObjectPart newPart = part . Copy ( m_scene . AllocateLocalId ( ) , OwnerID , GroupID , m_parts . Count , userExposed ) ;
2008-04-21 14:11:36 +00:00
newPart . SetParent ( this ) ;
2007-08-13 14:39:12 +00:00
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-08-16 16:31:32 +00:00
{
2008-04-21 14:11:36 +00:00
m_parts . Add ( newPart . UUID , newPart ) ;
2007-08-16 16:31:32 +00:00
}
2008-05-16 01:22:11 +00:00
2008-04-21 14:11:36 +00:00
SetPartAsNonRoot ( newPart ) ;
2008-05-16 01:22:11 +00:00
2008-11-26 07:34:38 +00:00
return newPart ;
2007-08-16 16:31:32 +00:00
}
2007-08-03 11:44:30 +00:00
/// <summary>
2008-09-06 07:52:41 +00:00
/// Reset the UUIDs for all the prims that make up this group.
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// This is called by methods which want to add a new group to an existing scene, in order
/// to ensure that there are no clashes with groups already present.
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
public void ResetIDs ( )
2007-10-30 23:38:56 +00:00
{
2008-04-21 14:11:36 +00:00
// As this is only ever called for prims which are not currently part of the scene (and hence
// not accessible by clients), there should be no need to lock
List < SceneObjectPart > partsList = new List < SceneObjectPart > ( m_parts . Values ) ;
m_parts . Clear ( ) ;
foreach ( SceneObjectPart part in partsList )
2007-10-30 23:38:56 +00:00
{
2008-09-09 03:48:09 +00:00
part . ResetIDs ( part . LinkNum ) ; // Don't change link nums
2008-04-21 14:11:36 +00:00
m_parts . Add ( part . UUID , part ) ;
2007-10-30 23:38:56 +00:00
}
}
2007-11-01 19:19:05 +00:00
2007-08-03 11:44:30 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="part"></param>
2008-09-06 07:52:41 +00:00
public void ServiceObjectPropertiesFamilyRequest ( IClientAPI remoteClient , UUID AgentID , uint RequestFlags )
2007-08-03 11:44:30 +00:00
{
2008-05-10 20:25:40 +00:00
remoteClient . SendObjectPropertiesFamilyData ( RequestFlags , RootPart . UUID , RootPart . ObjectOwner , RootPart . GroupID , RootPart . BaseMask ,
RootPart . OwnerMask , RootPart . GroupMask , RootPart . EveryoneMask , RootPart . NextOwnerMask ,
RootPart . OwnershipCost , RootPart . ObjectSaleType , RootPart . SalePrice , RootPart . Category ,
RootPart . CreatorID , RootPart . Name , RootPart . Description ) ;
2007-08-03 11:44:30 +00:00
}
2007-09-19 00:30:55 +00:00
2008-09-06 07:52:41 +00:00
public void SetPartOwner ( SceneObjectPart part , UUID cAgentID , UUID cGroupID )
2007-12-05 06:44:32 +00:00
{
2008-04-21 14:11:36 +00:00
part . OwnerID = cAgentID ;
part . GroupID = cGroupID ;
2007-12-05 06:44:32 +00:00
}
2007-08-13 13:36:42 +00:00
# endregion
2007-08-03 11:44:30 +00:00
2008-04-21 14:11:36 +00:00
#region Scheduling
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
public override void Update ( )
2007-07-30 20:11:40 +00:00
{
2008-09-06 01:10:47 +00:00
// Check that the group was not deleted before the scheduled update
// FIXME: This is merely a temporary measure to reduce the incidence of failure when
// an object has been deleted from a scene before update was processed.
// A more fundamental overhaul of the update mechanism is required to eliminate all
// the race conditions.
if ( m_isDeleted )
return ;
2008-05-16 01:22:11 +00:00
2008-09-18 15:24:16 +00:00
// This is what happens when an orphanced link set child prim's
// group was queued when it was linked
/ /
if ( m_rootPart = = null )
return ;
2009-02-10 22:54:05 +00:00
if ( ( RootPart . Flags & PrimFlags . TemporaryOnRez ) ! = 0 )
return ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-11-10 05:21:51 +00:00
bool UsePhysics = ( ( RootPart . Flags & PrimFlags . Physics ) ! = 0 ) ;
2008-11-01 22:04:35 +00:00
//if (IsAttachment)
2008-04-26 17:36:30 +00:00
//{
2008-05-01 18:04:42 +00:00
//foreach (SceneObjectPart part in m_parts.Values)
//{
//part.SendScheduledUpdates();
//}
//return;
2008-04-26 17:36:30 +00:00
//}
2008-05-16 01:22:11 +00:00
2009-02-23 06:55:42 +00:00
if ( Util . DistanceLessThan ( lastPhysGroupPos , AbsolutePosition , 0.02 ) & & UsePhysics )
2008-04-21 14:11:36 +00:00
{
2008-04-26 17:36:30 +00:00
m_rootPart . UpdateFlag = 1 ;
2008-04-21 14:11:36 +00:00
lastPhysGroupPos = AbsolutePosition ;
}
2009-02-23 06:55:42 +00:00
//foreach (SceneObjectPart part in m_parts.Values)
2008-05-01 18:04:42 +00:00
//{
//if (part.UpdateFlag == 0) part.UpdateFlag = 1;
//}
2008-04-26 17:36:30 +00:00
2008-09-06 00:44:50 +00:00
checkAtTargets ( ) ;
2007-09-19 00:30:55 +00:00
2008-11-10 05:21:51 +00:00
if ( ( ( Math . Abs ( lastPhysGroupRot . W - GroupRotation . W ) > 0.1 )
2008-04-21 14:11:36 +00:00
| | ( Math . Abs ( lastPhysGroupRot . X - GroupRotation . X ) > 0.1 )
| | ( Math . Abs ( lastPhysGroupRot . Y - GroupRotation . Y ) > 0.1 )
| | ( Math . Abs ( lastPhysGroupRot . Z - GroupRotation . Z ) > 0.1 ) )
2008-11-10 05:21:51 +00:00
& & UsePhysics )
2008-04-21 14:11:36 +00:00
{
2008-04-26 17:36:30 +00:00
m_rootPart . UpdateFlag = 1 ;
2007-07-30 20:11:40 +00:00
2008-04-21 14:11:36 +00:00
lastPhysGroupRot = GroupRotation ;
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-08-23 11:38:50 +00:00
{
2008-04-21 14:11:36 +00:00
part . SendScheduledUpdates ( ) ;
2007-08-23 11:38:50 +00:00
}
2007-08-09 17:54:22 +00:00
}
}
2008-04-21 14:11:36 +00:00
public void ScheduleFullUpdateToAvatar ( ScenePresence presence )
2008-04-19 21:01:26 +00:00
{
2008-11-07 05:48:44 +00:00
RootPart . AddFullUpdateToAvatar ( presence ) ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2008-04-19 21:01:26 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2008-04-19 21:01:26 +00:00
{
2008-11-07 05:48:44 +00:00
if ( part ! = RootPart )
part . AddFullUpdateToAvatar ( presence ) ;
2008-04-19 21:01:26 +00:00
}
}
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
public void ScheduleTerseUpdateToAvatar ( ScenePresence presence )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-11-30 12:10:12 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
{
part . AddTerseUpdateToAvatar ( presence ) ;
}
2007-11-30 12:10:12 +00:00
}
2007-07-30 20:11:40 +00:00
}
2007-08-03 11:44:30 +00:00
/// <summary>
2008-06-27 14:15:14 +00:00
/// Schedule a full update for this scene object
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
public void ScheduleGroupForFullUpdate ( )
2007-07-30 20:11:40 +00:00
{
2008-04-25 01:00:55 +00:00
checkAtTargets ( ) ;
2008-11-07 05:48:44 +00:00
RootPart . ScheduleFullUpdate ( ) ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-07-30 20:11:40 +00:00
{
2008-11-07 05:48:44 +00:00
if ( part ! = RootPart )
part . ScheduleFullUpdate ( ) ;
2007-07-30 20:11:40 +00:00
}
}
}
2007-08-03 11:44:30 +00:00
/// <summary>
2008-06-27 14:15:14 +00:00
/// Schedule a terse update for this scene object
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
public void ScheduleGroupForTerseUpdate ( )
2008-09-09 01:26:48 +00:00
{
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
part . ScheduleTerseUpdate ( ) ;
2007-07-30 20:11:40 +00:00
}
}
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-06-27 14:15:14 +00:00
/// Immediately send a full update for this scene object.
2008-04-21 14:11:36 +00:00
/// </summary>
public void SendGroupFullUpdate ( )
2008-02-11 01:43:54 +00:00
{
2008-11-17 16:33:41 +00:00
if ( IsDeleted )
return ;
2008-11-07 05:48:44 +00:00
RootPart . SendFullUpdateToAllClients ( ) ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
2008-11-07 05:48:44 +00:00
if ( part ! = RootPart )
part . SendFullUpdateToAllClients ( ) ;
2008-04-21 14:11:36 +00:00
}
}
}
2009-01-30 23:23:02 +00:00
/// <summary>
/// Immediately send an update for this scene object's root prim only.
/// This is for updates regarding the object as a whole, and none of its parts in particular.
/// Note: this may not be cused by opensim (it probably should) but it's used by
/// external modules.
/// </summary>
public void SendGroupRootUpdate ( )
{
if ( IsDeleted )
return ;
RootPart . SendFullUpdateToAllClients ( ) ;
}
2008-04-21 14:11:36 +00:00
public void QueueForUpdateCheck ( )
{
2008-11-18 17:21:33 +00:00
if ( m_scene = = null ) // Need to check here as it's null during object creation
return ;
2009-02-20 17:18:07 +00:00
m_scene . SceneGraph . AddToUpdateList ( this ) ;
2008-04-21 14:11:36 +00:00
}
/// <summary>
2008-06-27 14:15:14 +00:00
/// Immediately send a terse update for this scene object.
2008-04-21 14:11:36 +00:00
/// </summary>
public void SendGroupTerseUpdate ( )
{
2008-11-17 16:33:41 +00:00
if ( IsDeleted )
return ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
part . SendTerseUpdateToAllClients ( ) ;
}
}
2008-02-11 01:43:54 +00:00
}
2007-07-30 20:11:40 +00:00
# endregion
2008-04-21 14:11:36 +00:00
#region SceneGroupPart Methods
2007-09-19 00:30:55 +00:00
2007-08-03 11:44:30 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// Get the child part by LinkNum
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="linknum"></param>
/// <returns>null if no child part with that linknum or child part</returns>
public SceneObjectPart GetLinkNumPart ( int linknum )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-08-23 11:38:50 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
{
if ( part . LinkNum = = linknum )
{
return part ;
}
}
2007-08-23 11:38:50 +00:00
}
2008-04-21 14:11:36 +00:00
return null ;
2007-07-30 20:11:40 +00:00
}
/// <summary>
2008-04-21 14:11:36 +00:00
/// Get a child part with a given UUID
2007-07-30 20:11:40 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="primID"></param>
/// <returns>null if a child part with the primID was not found</returns>
2008-09-06 07:52:41 +00:00
public SceneObjectPart GetChildPart ( UUID primID )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart childPart = null ;
if ( m_parts . ContainsKey ( primID ) )
2007-08-23 11:38:50 +00:00
{
2008-04-21 14:11:36 +00:00
childPart = m_parts [ primID ] ;
2007-08-23 11:38:50 +00:00
}
2008-04-21 14:11:36 +00:00
return childPart ;
2007-07-30 20:11:40 +00:00
}
2007-08-03 11:44:30 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// Get a child part with a given local ID
2007-08-03 11:44:30 +00:00
/// </summary>
/// <param name="localID"></param>
2008-04-21 14:11:36 +00:00
/// <returns>null if a child part with the local ID was not found</returns>
public SceneObjectPart GetChildPart ( uint localID )
2007-07-30 20:11:40 +00:00
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Entered looking for {0}", localID);
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-07-30 20:11:40 +00:00
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Found {0}", part.LocalId);
2008-04-21 14:11:36 +00:00
if ( part . LocalId = = localID )
{
return part ;
}
2007-07-30 20:11:40 +00:00
}
}
2008-04-21 14:11:36 +00:00
return null ;
2007-07-30 20:11:40 +00:00
}
2007-08-03 11:44:30 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// Does this group contain the child prim
/// should be able to remove these methods once we have a entity index in scene
2007-08-03 11:44:30 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="primID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public bool HasChildPrim ( UUID primID )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
if ( m_parts . ContainsKey ( primID ) )
2007-08-23 11:38:50 +00:00
{
2008-04-21 14:11:36 +00:00
return true ;
2007-08-23 11:38:50 +00:00
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
return false ;
}
2007-07-30 20:11:40 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
/// Does this group contain the child prim
/// should be able to remove these methods once we have a entity index in scene
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
public bool HasChildPrim ( uint localID )
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2008-03-18 20:42:01 +00:00
lock ( m_parts )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2007-07-30 20:11:40 +00:00
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Found {0}", part.LocalId);
2008-04-21 14:11:36 +00:00
if ( part . LocalId = = localID )
2008-03-18 20:42:01 +00:00
{
2008-04-21 14:11:36 +00:00
return true ;
2008-03-18 20:42:01 +00:00
}
2007-07-30 20:11:40 +00:00
}
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
return false ;
2007-07-30 20:11:40 +00:00
}
2007-09-19 00:30:55 +00:00
2007-07-30 20:11:40 +00:00
# endregion
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
#region Packet Handlers
2007-07-30 20:11:40 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// Link the prims in a given group to this group
2007-07-30 20:11:40 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="objectGroup">The group of prims which should be linked to this group</param>
public void LinkToGroup ( SceneObjectGroup objectGroup )
2007-07-30 20:11:40 +00:00
{
2008-04-21 14:11:36 +00:00
if ( objectGroup . RootPart . UpdateFlag > 0 )
{
2008-05-16 01:22:11 +00:00
// I've never actually seen this happen, though I think it's theoretically possible
2008-04-21 14:11:36 +00:00
m_log . WarnFormat (
"[SCENE OBJECT GROUP]: Aborted linking {0}, {1} to {2}, {3} as it has yet to finish delinking" ,
objectGroup . RootPart . Name , objectGroup . RootPart . UUID , RootPart . Name , RootPart . UUID ) ;
return ;
}
// m_log.DebugFormat(
2008-05-16 01:22:11 +00:00
// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
2008-04-21 14:11:36 +00:00
// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
SceneObjectPart linkPart = objectGroup . m_rootPart ;
2008-09-06 07:52:41 +00:00
Vector3 oldGroupPosition = linkPart . GroupPosition ;
Quaternion oldRootRotation = linkPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
linkPart . OffsetPosition = linkPart . GroupPosition - AbsolutePosition ;
linkPart . GroupPosition = AbsolutePosition ;
2008-09-06 07:52:41 +00:00
Vector3 axPos = linkPart . OffsetPosition ;
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
Quaternion parentRot = m_rootPart . RotationOffset ;
axPos * = Quaternion . Inverse ( parentRot ) ;
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
linkPart . OffsetPosition = axPos ;
Quaternion oldRot = linkPart . RotationOffset ;
2008-09-07 13:24:23 +00:00
Quaternion newRot = Quaternion . Inverse ( parentRot ) * oldRot ;
2008-09-06 07:52:41 +00:00
linkPart . RotationOffset = newRot ;
2008-04-21 14:11:36 +00:00
linkPart . ParentID = m_rootPart . LocalId ;
2008-07-23 13:24:25 +00:00
if ( m_rootPart . LinkNum = = 0 )
2008-07-19 04:05:34 +00:00
m_rootPart . LinkNum = 1 ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
{
m_parts . Add ( linkPart . UUID , linkPart ) ;
2008-10-29 03:22:54 +00:00
// Insert in terms of link numbers, the new links
// before the current ones (with the exception of
// the root prim. Shuffle the old ones up
foreach ( KeyValuePair < UUID , SceneObjectPart > kvp in m_parts )
{
if ( kvp . Value . LinkNum ! = 1 )
{
// Don't update root prim link number
kvp . Value . LinkNum + = objectGroup . PrimCount ;
}
}
linkPart . LinkNum = 2 ;
linkPart . SetParent ( this ) ;
linkPart . AddFlag ( PrimFlags . CreateSelected ) ;
//if (linkPart.PhysActor != null)
//{
// m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
//linkPart.PhysActor = null;
//}
//TODO: rest of parts
int linkNum = 3 ;
foreach ( SceneObjectPart part in objectGroup . Children . Values )
{
if ( part . UUID ! = objectGroup . m_rootPart . UUID )
{
LinkNonRootPart ( part , oldGroupPosition , oldRootRotation , linkNum + + ) ;
}
part . ClearUndoState ( ) ;
}
}
2008-04-21 14:11:36 +00:00
2008-06-07 00:24:43 +00:00
m_scene . UnlinkSceneObject ( objectGroup . UUID , true ) ;
2009-02-03 19:36:57 +00:00
objectGroup . m_isDeleted = true ;
lock ( objectGroup . m_parts )
{
objectGroup . m_parts . Clear ( ) ;
}
2009-02-03 18:48:04 +00:00
// Can't do this yet since backup still makes use of the root part without any synchronization
2008-11-17 15:40:27 +00:00
// objectGroup.m_rootPart = null;
2008-04-21 14:11:36 +00:00
2009-02-09 20:06:06 +00:00
AttachToBackup ( ) ;
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
// unmoved prims!
2009-02-08 18:05:12 +00:00
ResetChildPrimPhysicsPositions ( ) ;
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForFullUpdate ( ) ;
2007-07-30 20:11:40 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
/// Delink the given prim from this group. The delinked prim is established as
2008-04-21 14:11:36 +00:00
/// an independent SceneObjectGroup.
2007-07-30 20:11:40 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="partID"></param>
public void DelinkFromGroup ( uint partID )
2008-07-19 04:05:34 +00:00
{
DelinkFromGroup ( partID , true ) ;
}
2008-11-07 21:07:14 +00:00
/// <summary>
/// Delink the given prim from this group. The delinked prim is established as
/// an independent SceneObjectGroup.
/// </summary>
/// <param name="partID"></param>
/// <param name="sendEvents"></param>
2008-07-19 04:05:34 +00:00
public void DelinkFromGroup ( uint partID , bool sendEvents )
2008-04-21 14:11:36 +00:00
{
SceneObjectPart linkPart = GetChildPart ( partID ) ;
2008-05-16 01:22:11 +00:00
2008-04-21 14:11:36 +00:00
if ( null ! = linkPart )
{
2008-04-29 13:53:24 +00:00
linkPart . ClearUndoState ( ) ;
2008-04-21 14:11:36 +00:00
// m_log.DebugFormat(
2008-05-16 01:22:11 +00:00
// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2008-04-21 14:11:36 +00:00
// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2008-09-06 07:52:41 +00:00
Quaternion worldRot = linkPart . GetWorldRotation ( ) ;
2008-04-21 14:11:36 +00:00
// Remove the part from this object
lock ( m_parts )
{
m_parts . Remove ( linkPart . UUID ) ;
}
2008-07-23 13:24:25 +00:00
if ( m_parts . Count = = 1 & & RootPart ! = null ) //Single prim is left
2008-07-19 04:05:34 +00:00
RootPart . LinkNum = 0 ;
else
{
foreach ( SceneObjectPart p in m_parts . Values )
2008-07-23 13:24:25 +00:00
{
if ( p . LinkNum > linkPart . LinkNum )
2008-07-19 04:05:34 +00:00
p . LinkNum - - ;
2008-07-23 13:24:25 +00:00
}
2008-07-19 04:05:34 +00:00
}
2008-04-21 14:11:36 +00:00
linkPart . ParentID = 0 ;
2008-07-19 04:05:34 +00:00
linkPart . LinkNum = 0 ;
2008-04-21 14:11:36 +00:00
if ( linkPart . PhysActor ! = null )
{
m_scene . PhysicsScene . RemovePrim ( linkPart . PhysActor ) ;
}
2008-05-16 01:22:11 +00:00
// We need to reset the child part's position
// ready for life as a separate object after being a part of another object
2008-09-06 07:52:41 +00:00
Quaternion parentRot = m_rootPart . RotationOffset ;
Vector3 axPos = linkPart . OffsetPosition ;
axPos * = parentRot ;
linkPart . OffsetPosition = new Vector3 ( axPos . X , axPos . Y , axPos . Z ) ;
2008-04-21 14:11:36 +00:00
linkPart . GroupPosition = AbsolutePosition + linkPart . OffsetPosition ;
2008-09-06 07:52:41 +00:00
linkPart . OffsetPosition = new Vector3 ( 0 , 0 , 0 ) ;
2008-04-21 14:11:36 +00:00
linkPart . RotationOffset = worldRot ;
2008-11-07 19:49:22 +00:00
SceneObjectGroup objectGroup = new SceneObjectGroup ( linkPart ) ;
2008-04-21 14:11:36 +00:00
2008-06-27 14:25:36 +00:00
m_scene . AddNewSceneObject ( objectGroup , true ) ;
2008-04-21 14:11:36 +00:00
2008-07-23 13:24:25 +00:00
if ( sendEvents )
2008-07-19 04:05:34 +00:00
linkPart . TriggerScriptChangedEvent ( Changed . LINK ) ;
2008-10-18 05:51:36 +00:00
linkPart . Rezzed = RootPart . Rezzed ;
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForFullUpdate ( ) ;
}
else
{
m_log . InfoFormat ( "[SCENE OBJECT GROUP]: " +
"DelinkFromGroup(): Child prim {0} not found in object {1}, {2}" ,
partID , LocalId , UUID ) ;
}
}
2008-06-12 17:49:08 +00:00
/// <summary>
/// Stop this object from being persisted over server restarts.
/// </summary>
/// <param name="objectGroup"></param>
2008-10-03 13:45:54 +00:00
public void DetachFromBackup ( )
2007-07-30 20:11:40 +00:00
{
2008-10-18 05:51:36 +00:00
if ( m_isBackedUp )
m_scene . EventManager . OnBackup - = ProcessBackup ;
2008-11-07 21:07:14 +00:00
2008-10-18 05:51:36 +00:00
m_isBackedUp = false ;
2008-04-21 14:11:36 +00:00
}
2008-10-28 11:26:23 +00:00
private void LinkNonRootPart ( SceneObjectPart part , Vector3 oldGroupPosition , Quaternion oldGroupRotation , int linkNum )
2008-04-21 14:11:36 +00:00
{
2008-12-21 14:50:58 +00:00
Quaternion parentRot = oldGroupRotation ;
Quaternion oldRot = part . RotationOffset ;
Quaternion worldRot = parentRot * oldRot ;
parentRot = oldGroupRotation ;
Vector3 axPos = part . OffsetPosition ;
axPos * = parentRot ;
part . OffsetPosition = axPos ;
part . GroupPosition = oldGroupPosition + part . OffsetPosition ;
part . OffsetPosition = Vector3 . Zero ;
part . RotationOffset = worldRot ;
2008-04-21 14:11:36 +00:00
part . SetParent ( this ) ;
2008-03-05 18:57:13 +00:00
part . ParentID = m_rootPart . LocalId ;
2008-04-21 14:11:36 +00:00
2008-10-29 03:22:54 +00:00
// Caller locks m_parts for us
m_parts . Add ( part . UUID , part ) ;
2008-04-21 14:11:36 +00:00
2008-10-28 11:26:23 +00:00
part . LinkNum = linkNum ;
2008-07-19 04:05:34 +00:00
2008-12-21 14:50:58 +00:00
part . OffsetPosition = part . GroupPosition - AbsolutePosition ;
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
Quaternion rootRotation = m_rootPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
2008-09-06 07:52:41 +00:00
Vector3 pos = part . OffsetPosition ;
pos * = Quaternion . Inverse ( rootRotation ) ;
part . OffsetPosition = pos ;
2008-04-21 14:11:36 +00:00
2008-12-21 14:50:58 +00:00
parentRot = m_rootPart . RotationOffset ;
oldRot = part . RotationOffset ;
Quaternion newRot = Quaternion . Inverse ( parentRot ) * oldRot ;
part . RotationOffset = newRot ;
2007-07-30 20:11:40 +00:00
}
2007-08-03 12:00:24 +00:00
/// <summary>
2008-04-21 14:11:36 +00:00
/// If object is physical, apply force to move it around
/// If object is not physical, just put it at the resulting location
2007-08-03 12:00:24 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="offset">Always seems to be 0,0,0, so ignoring</param>
/// <param name="pos">New position. We do the math here to turn it into a force</param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
public void GrabMovement ( Vector3 offset , Vector3 pos , IClientAPI remoteClient )
2007-08-03 12:00:24 +00:00
{
2008-04-21 14:11:36 +00:00
if ( m_scene . EventManager . TriggerGroupMove ( UUID , pos ) )
{
if ( m_rootPart . PhysActor ! = null )
{
if ( m_rootPart . PhysActor . IsPhysical )
{
2008-09-06 07:52:41 +00:00
Vector3 llmoveforce = pos - AbsolutePosition ;
2008-04-21 14:11:36 +00:00
PhysicsVector grabforce = new PhysicsVector ( llmoveforce . X , llmoveforce . Y , llmoveforce . Z ) ;
grabforce = ( grabforce / 10 ) * m_rootPart . PhysActor . Mass ;
2008-05-06 00:23:19 +00:00
m_rootPart . PhysActor . AddForce ( grabforce , true ) ;
2008-04-21 14:11:36 +00:00
m_scene . PhysicsScene . AddPhysicsActorTaint ( m_rootPart . PhysActor ) ;
}
else
{
//NonPhysicalGrabMovement(pos);
}
}
else
{
//NonPhysicalGrabMovement(pos);
}
}
2007-08-03 12:00:24 +00:00
}
2007-08-07 17:25:21 +00:00
2008-09-06 07:52:41 +00:00
public void NonPhysicalGrabMovement ( Vector3 pos )
2008-04-21 14:11:36 +00:00
{
AbsolutePosition = pos ;
m_rootPart . SendTerseUpdateToAllClients ( ) ;
}
2007-09-19 00:30:55 +00:00
2007-08-13 13:36:42 +00:00
/// <summary>
2008-04-26 20:31:01 +00:00
/// Return metadata about a prim (name, description, sale price, etc.)
2007-08-13 13:36:42 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="client"></param>
public void GetProperties ( IClientAPI client )
2007-08-13 13:36:42 +00:00
{
2008-05-17 00:06:35 +00:00
m_rootPart . GetProperties ( client ) ;
2007-08-13 13:36:42 +00:00
}
/// <summary>
2008-04-21 14:11:36 +00:00
/// Set the name of a prim
2007-08-13 13:36:42 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="name"></param>
/// <param name="localID"></param>
public void SetPartName ( string name , uint localID )
2007-08-13 13:36:42 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-29 15:32:48 +00:00
{
2008-04-21 14:11:36 +00:00
part . Name = name ;
2007-08-29 15:32:48 +00:00
}
2007-08-13 13:36:42 +00:00
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
public void SetPartDescription ( string des , uint localID )
2007-08-10 13:59:19 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-10 13:59:19 +00:00
{
2008-04-21 14:11:36 +00:00
part . Description = des ;
2007-08-10 13:59:19 +00:00
}
}
2007-12-04 16:41:20 +00:00
2008-04-21 14:11:36 +00:00
public void SetPartText ( string text , uint localID )
2007-08-07 17:25:21 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-07 17:25:21 +00:00
{
2008-04-21 14:11:36 +00:00
part . SetText ( text ) ;
2007-08-07 17:25:21 +00:00
}
}
2007-08-07 18:31:20 +00:00
2008-09-06 07:52:41 +00:00
public void SetPartText ( string text , UUID partID )
2007-08-07 18:31:20 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( partID ) ;
if ( part ! = null )
2007-08-07 18:31:20 +00:00
{
2008-04-21 14:11:36 +00:00
part . SetText ( text ) ;
2007-08-07 18:31:20 +00:00
}
}
2007-09-19 00:30:55 +00:00
2008-04-21 14:11:36 +00:00
public string GetPartName ( uint localID )
2007-08-15 16:57:47 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-15 16:57:47 +00:00
{
2008-04-21 14:11:36 +00:00
return part . Name ;
2007-08-15 16:57:47 +00:00
}
2008-04-21 14:11:36 +00:00
return String . Empty ;
2007-08-13 13:36:42 +00:00
}
2008-04-21 14:11:36 +00:00
public string GetPartDescription ( uint localID )
2007-08-13 13:36:42 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2008-03-18 20:42:01 +00:00
{
2008-04-21 14:11:36 +00:00
return part . Description ;
2008-03-04 18:49:44 +00:00
}
2008-04-21 14:11:36 +00:00
return String . Empty ;
2007-08-13 13:36:42 +00:00
}
/// <summary>
2008-07-12 19:05:12 +00:00
/// Update prim flags for this group.
2007-08-13 13:36:42 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="localID"></param>
/// <param name="type"></param>
/// <param name="inUse"></param>
/// <param name="data"></param>
2008-12-20 21:36:42 +00:00
public void UpdatePrimFlags ( uint localID , bool UsePhysics , bool IsTemporary , bool IsPhantom , bool IsVolumeDetect )
2007-08-13 13:36:42 +00:00
{
2008-07-12 19:05:12 +00:00
SceneObjectPart selectionPart = GetChildPart ( localID ) ;
2008-08-18 00:39:10 +00:00
2008-11-07 22:57:32 +00:00
if ( IsTemporary )
2008-10-03 16:18:38 +00:00
{
2008-10-03 15:32:44 +00:00
DetachFromBackup ( ) ;
2008-10-03 16:18:38 +00:00
// Remove from database and parcel prim count
/ /
m_scene . DeleteFromStorage ( UUID ) ;
m_scene . EventManager . TriggerParcelPrimCountTainted ( ) ;
}
2008-10-03 15:32:44 +00:00
2008-07-12 19:05:12 +00:00
if ( selectionPart ! = null )
2007-08-13 13:36:42 +00:00
{
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2007-08-13 13:36:42 +00:00
{
2008-07-12 19:05:12 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2008-07-10 03:13:29 +00:00
{
2008-07-12 18:54:21 +00:00
if ( part . Scale . X > 10.0 | | part . Scale . Y > 10.0 | | part . Scale . Z > 10.0 )
2008-07-10 03:13:29 +00:00
{
2008-11-07 22:57:32 +00:00
UsePhysics = false ; // Reset physics
2008-07-10 03:13:29 +00:00
break ;
}
}
2008-07-12 19:05:12 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
2008-04-21 14:11:36 +00:00
{
2008-12-20 21:36:42 +00:00
part . UpdatePrimFlags ( UsePhysics , IsTemporary , IsPhantom , IsVolumeDetect ) ;
2008-03-18 20:42:01 +00:00
}
2007-08-13 13:36:42 +00:00
}
}
}
2007-08-13 20:24:37 +00:00
2008-04-21 14:11:36 +00:00
public void UpdateExtraParam ( uint localID , ushort type , bool inUse , byte [ ] data )
2007-08-21 16:25:57 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-21 16:25:57 +00:00
{
2008-04-21 14:11:36 +00:00
part . UpdateExtraParam ( type , inUse , data ) ;
2007-08-21 16:25:57 +00:00
}
}
2008-05-26 01:50:40 +00:00
/// <summary>
/// Get the parts of this scene object
/// </summary>
2008-05-26 02:17:03 +00:00
/// <returns></returns>
2008-04-21 14:11:36 +00:00
public SceneObjectPart [ ] GetParts ( )
2008-01-15 04:14:27 +00:00
{
2008-04-21 14:11:36 +00:00
int numParts = Children . Count ;
SceneObjectPart [ ] partArray = new SceneObjectPart [ numParts ] ;
Children . Values . CopyTo ( partArray , 0 ) ;
return partArray ;
2008-01-15 04:14:27 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-26 02:17:03 +00:00
/// Update the texture entry for this part
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="textureEntry"></param>
public void UpdateTextureEntry ( uint localID , byte [ ] textureEntry )
2007-08-13 20:24:37 +00:00
{
2007-09-19 00:30:55 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
2007-08-13 20:24:37 +00:00
if ( part ! = null )
{
2008-04-21 14:11:36 +00:00
part . UpdateTextureEntry ( textureEntry ) ;
2007-08-13 20:24:37 +00:00
}
}
2007-08-16 16:31:32 +00:00
2008-10-06 02:29:38 +00:00
public void UpdatePermissions ( UUID AgentID , byte field , uint localID ,
uint mask , byte addRemTF )
2007-08-15 21:24:25 +00:00
{
2008-10-06 02:29:38 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
part . UpdatePermissions ( AgentID , field , localID , mask ,
addRemTF ) ;
2008-04-21 14:11:36 +00:00
HasGroupChanged = true ;
2007-08-15 21:24:25 +00:00
}
2008-04-21 14:11:36 +00:00
# endregion
2007-08-15 21:24:25 +00:00
2008-04-21 14:11:36 +00:00
#region Shape
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="shapeBlock"></param>
public void UpdateShape ( ObjectShapePacket . ObjectDataBlock shapeBlock , uint localID )
2007-08-15 21:24:25 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
{
part . UpdateShape ( shapeBlock ) ;
if ( part . PhysActor ! = null )
m_scene . PhysicsScene . AddPhysicsActorTaint ( part . PhysActor ) ;
}
2007-08-15 21:24:25 +00:00
}
2007-08-16 16:31:32 +00:00
2008-04-21 14:11:36 +00:00
# endregion
#region Resize
2008-03-13 00:22:38 +00:00
/// <summary>
2008-06-27 14:15:14 +00:00
/// Resize the given part
2008-03-13 00:22:38 +00:00
/// </summary>
2008-04-21 14:11:36 +00:00
/// <param name="scale"></param>
/// <param name="localID"></param>
2008-09-06 07:52:41 +00:00
public void Resize ( Vector3 scale , uint localID )
2008-04-21 14:11:36 +00:00
{
2008-07-23 13:24:25 +00:00
if ( scale . X > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . X = m_scene . m_maxNonphys ;
2008-07-23 13:24:25 +00:00
if ( scale . Y > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . Y = m_scene . m_maxNonphys ;
2008-07-23 13:24:25 +00:00
if ( scale . Z > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . Z = m_scene . m_maxNonphys ;
2008-07-10 03:13:29 +00:00
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
2007-08-16 16:31:32 +00:00
{
2008-04-21 14:11:36 +00:00
part . Resize ( scale ) ;
if ( part . PhysActor ! = null )
2007-08-16 16:31:32 +00:00
{
2008-07-23 13:24:25 +00:00
if ( part . PhysActor . IsPhysical )
2008-07-10 03:13:29 +00:00
{
2008-07-23 13:24:25 +00:00
if ( scale . X > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . X = m_scene . m_maxPhys ;
2008-07-23 13:24:25 +00:00
if ( scale . Y > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . Y = m_scene . m_maxPhys ;
2008-07-23 13:24:25 +00:00
if ( scale . Z > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . Z = m_scene . m_maxPhys ;
2008-07-10 03:13:29 +00:00
}
2008-04-21 14:11:36 +00:00
part . PhysActor . Size =
new PhysicsVector ( scale . X , scale . Y , scale . Z ) ;
m_scene . PhysicsScene . AddPhysicsActorTaint ( part . PhysActor ) ;
}
//if (part.UUID != m_rootPart.UUID)
2008-08-18 00:39:10 +00:00
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForFullUpdate ( ) ;
//if (part.UUID == m_rootPart.UUID)
//{
//if (m_rootPart.PhysActor != null)
//{
//m_rootPart.PhysActor.Size =
//new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
//m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
//}
//}
}
}
2008-09-06 07:52:41 +00:00
public void GroupResize ( Vector3 scale , uint localID )
2008-04-21 14:11:36 +00:00
{
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
{
2008-07-23 13:24:25 +00:00
if ( scale . X > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . X = m_scene . m_maxNonphys ;
2008-07-23 13:24:25 +00:00
if ( scale . Y > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . Y = m_scene . m_maxNonphys ;
2008-07-23 13:24:25 +00:00
if ( scale . Z > m_scene . m_maxNonphys )
2008-07-20 15:19:26 +00:00
scale . Z = m_scene . m_maxNonphys ;
2008-07-23 13:24:25 +00:00
if ( part . PhysActor ! = null & & part . PhysActor . IsPhysical )
2008-07-10 03:13:29 +00:00
{
2008-07-23 13:24:25 +00:00
if ( scale . X > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . X = m_scene . m_maxPhys ;
2008-07-23 13:24:25 +00:00
if ( scale . Y > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . Y = m_scene . m_maxPhys ;
2008-07-23 13:24:25 +00:00
if ( scale . Z > m_scene . m_maxPhys )
2008-07-20 15:19:26 +00:00
scale . Z = m_scene . m_maxPhys ;
2008-07-10 03:13:29 +00:00
}
2008-04-21 14:11:36 +00:00
float x = ( scale . X / part . Scale . X ) ;
float y = ( scale . Y / part . Scale . Y ) ;
float z = ( scale . Z / part . Scale . Z ) ;
2008-07-10 03:13:29 +00:00
lock ( m_parts )
{
2008-07-23 13:24:25 +00:00
if ( x > 1.0f | | y > 1.0f | | z > 1.0f )
2008-07-10 03:13:29 +00:00
{
foreach ( SceneObjectPart obPart in m_parts . Values )
{
if ( obPart . UUID ! = m_rootPart . UUID )
{
2008-09-06 07:52:41 +00:00
Vector3 oldSize = new Vector3 ( obPart . Scale ) ;
2008-07-10 03:13:29 +00:00
float f = 1.0f ;
float a = 1.0f ;
2008-07-23 13:24:25 +00:00
if ( part . PhysActor ! = null & & part . PhysActor . IsPhysical )
2008-07-10 03:13:29 +00:00
{
2008-07-23 13:24:25 +00:00
if ( oldSize . X * x > m_scene . m_maxPhys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxPhys / oldSize . X ;
2008-07-10 03:13:29 +00:00
a = f / x ;
x * = a ;
y * = a ;
z * = a ;
}
2008-07-23 13:24:25 +00:00
if ( oldSize . Y * y > m_scene . m_maxPhys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxPhys / oldSize . Y ;
2008-07-10 03:13:29 +00:00
a = f / y ;
x * = a ;
y * = a ;
z * = a ;
}
2008-07-23 13:24:25 +00:00
if ( oldSize . Z * z > m_scene . m_maxPhys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxPhys / oldSize . Z ;
2008-07-10 03:13:29 +00:00
a = f / z ;
x * = a ;
y * = a ;
z * = a ;
}
}
else
{
2008-07-23 13:24:25 +00:00
if ( oldSize . X * x > m_scene . m_maxNonphys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxNonphys / oldSize . X ;
2008-07-10 03:13:29 +00:00
a = f / x ;
x * = a ;
y * = a ;
z * = a ;
}
2008-07-23 13:24:25 +00:00
if ( oldSize . Y * y > m_scene . m_maxNonphys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxNonphys / oldSize . Y ;
2008-07-10 03:13:29 +00:00
a = f / y ;
x * = a ;
y * = a ;
z * = a ;
}
2008-07-23 13:24:25 +00:00
if ( oldSize . Z * z > m_scene . m_maxNonphys )
2008-07-10 03:13:29 +00:00
{
2008-07-20 15:19:26 +00:00
f = m_scene . m_maxNonphys / oldSize . Z ;
2008-07-10 03:13:29 +00:00
a = f / z ;
x * = a ;
y * = a ;
z * = a ;
}
}
}
}
}
}
2008-09-06 07:52:41 +00:00
Vector3 prevScale = part . Scale ;
2008-07-10 03:13:29 +00:00
prevScale . X * = x ;
prevScale . Y * = y ;
prevScale . Z * = z ;
part . Resize ( prevScale ) ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
{
foreach ( SceneObjectPart obPart in m_parts . Values )
2007-11-20 21:25:27 +00:00
{
2008-04-21 14:11:36 +00:00
if ( obPart . UUID ! = m_rootPart . UUID )
2008-03-18 20:42:01 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 currentpos = new Vector3 ( obPart . OffsetPosition ) ;
2008-04-21 14:11:36 +00:00
currentpos . X * = x ;
currentpos . Y * = y ;
currentpos . Z * = z ;
2008-09-06 07:52:41 +00:00
Vector3 newSize = new Vector3 ( obPart . Scale ) ;
2008-04-21 14:11:36 +00:00
newSize . X * = x ;
newSize . Y * = y ;
newSize . Z * = z ;
obPart . Resize ( newSize ) ;
obPart . UpdateOffSet ( currentpos ) ;
2008-03-18 20:42:01 +00:00
}
}
2007-08-16 16:31:32 +00:00
}
2007-08-16 18:40:44 +00:00
2008-04-21 14:11:36 +00:00
if ( part . PhysActor ! = null )
2008-03-18 20:11:35 +00:00
{
2008-04-21 14:11:36 +00:00
part . PhysActor . Size =
2008-07-10 03:13:29 +00:00
new PhysicsVector ( prevScale . X , prevScale . Y , prevScale . Z ) ;
2008-04-21 14:11:36 +00:00
m_scene . PhysicsScene . AddPhysicsActorTaint ( part . PhysActor ) ;
2008-03-18 20:11:35 +00:00
}
2008-04-21 14:11:36 +00:00
2008-06-27 15:04:35 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForTerseUpdate ( ) ;
2008-03-18 20:11:35 +00:00
}
2007-08-21 16:25:57 +00:00
}
2008-04-21 14:11:36 +00:00
# endregion
2008-02-06 08:03:22 +00:00
2008-04-21 14:11:36 +00:00
#region Position
2008-02-06 08:03:22 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-06-27 14:39:21 +00:00
/// Move this scene object
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="pos"></param>
2008-09-06 07:52:41 +00:00
public void UpdateGroupPosition ( Vector3 pos )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
if ( m_scene . EventManager . TriggerGroupMove ( UUID , pos ) )
2008-04-20 04:19:44 +00:00
{
2008-11-01 22:04:35 +00:00
if ( IsAttachment )
2008-04-25 21:41:55 +00:00
{
2008-07-26 21:22:15 +00:00
m_rootPart . AttachedPos = pos ;
2008-04-25 21:41:55 +00:00
}
2008-04-21 14:11:36 +00:00
AbsolutePosition = pos ;
2008-08-18 00:39:10 +00:00
2008-06-27 14:39:21 +00:00
HasGroupChanged = true ;
2008-04-20 04:19:44 +00:00
}
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
//we need to do a terse update even if the move wasn't allowed
// so that the position is reset in the client (the object snaps back)
ScheduleGroupForTerseUpdate ( ) ;
2008-04-20 04:19:44 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-06-27 14:39:21 +00:00
/// Update the position of a single part of this scene object
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="pos"></param>
/// <param name="localID"></param>
2008-09-06 07:52:41 +00:00
public void UpdateSinglePosition ( Vector3 pos , uint localID )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
2008-08-18 00:39:10 +00:00
2008-04-21 14:11:36 +00:00
if ( part ! = null )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
if ( part . UUID = = m_rootPart . UUID )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
UpdateRootPosition ( pos ) ;
2008-04-20 04:19:44 +00:00
}
else
{
2008-04-21 14:11:36 +00:00
part . UpdateOffSet ( pos ) ;
2008-04-20 04:19:44 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 14:39:21 +00:00
HasGroupChanged = true ;
2008-04-20 04:19:44 +00:00
}
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="pos"></param>
2008-09-06 07:52:41 +00:00
private void UpdateRootPosition ( Vector3 pos )
2008-04-20 04:19:44 +00:00
{
2008-09-06 07:52:41 +00:00
Vector3 newPos = new Vector3 ( pos . X , pos . Y , pos . Z ) ;
Vector3 oldPos =
new Vector3 ( AbsolutePosition . X + m_rootPart . OffsetPosition . X ,
2008-04-21 14:11:36 +00:00
AbsolutePosition . Y + m_rootPart . OffsetPosition . Y ,
AbsolutePosition . Z + m_rootPart . OffsetPosition . Z ) ;
2008-09-06 07:52:41 +00:00
Vector3 diff = oldPos - newPos ;
2008-04-21 14:11:36 +00:00
Vector3 axDiff = new Vector3 ( diff . X , diff . Y , diff . Z ) ;
2008-09-06 07:52:41 +00:00
Quaternion partRotation = m_rootPart . RotationOffset ;
axDiff * = Quaternion . Inverse ( partRotation ) ;
diff = axDiff ;
2008-04-21 14:11:36 +00:00
lock ( m_parts )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart obPart in m_parts . Values )
2008-04-20 04:19:44 +00:00
{
2008-04-21 14:11:36 +00:00
if ( obPart . UUID ! = m_rootPart . UUID )
{
obPart . OffsetPosition = obPart . OffsetPosition + diff ;
}
2008-04-20 04:19:44 +00:00
}
}
2008-04-21 14:11:36 +00:00
AbsolutePosition = newPos ;
2008-08-18 00:39:10 +00:00
2008-06-27 15:04:35 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForTerseUpdate ( ) ;
}
2008-04-20 04:19:44 +00:00
2008-09-06 07:52:41 +00:00
public void OffsetForNewRegion ( Vector3 offset )
2008-04-21 14:11:36 +00:00
{
m_rootPart . GroupPosition = offset ;
}
2008-04-20 04:19:44 +00:00
2008-04-21 14:11:36 +00:00
# endregion
#region Rotation
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="rot"></param>
2008-09-06 07:52:41 +00:00
public void UpdateGroupRotation ( Quaternion rot )
2008-04-21 14:11:36 +00:00
{
m_rootPart . UpdateRotation ( rot ) ;
if ( m_rootPart . PhysActor ! = null )
2008-04-20 04:19:44 +00:00
{
2008-09-06 07:52:41 +00:00
m_rootPart . PhysActor . Orientation = m_rootPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
m_scene . PhysicsScene . AddPhysicsActorTaint ( m_rootPart . PhysActor ) ;
2008-04-20 04:19:44 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 15:04:35 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForTerseUpdate ( ) ;
2008-04-20 04:19:44 +00:00
}
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="pos"></param>
/// <param name="rot"></param>
2008-09-06 07:52:41 +00:00
public void UpdateGroupRotation ( Vector3 pos , Quaternion rot )
2007-08-16 18:40:44 +00:00
{
2008-04-21 14:11:36 +00:00
m_rootPart . UpdateRotation ( rot ) ;
if ( m_rootPart . PhysActor ! = null )
{
2008-09-06 07:52:41 +00:00
m_rootPart . PhysActor . Orientation = m_rootPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
m_scene . PhysicsScene . AddPhysicsActorTaint ( m_rootPart . PhysActor ) ;
}
AbsolutePosition = pos ;
2008-08-18 00:39:10 +00:00
2008-06-27 15:04:35 +00:00
HasGroupChanged = true ;
2008-04-21 14:11:36 +00:00
ScheduleGroupForTerseUpdate ( ) ;
2007-08-16 18:40:44 +00:00
}
2007-12-04 11:11:13 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="rot"></param>
/// <param name="localID"></param>
2008-09-06 07:52:41 +00:00
public void UpdateSingleRotation ( Quaternion rot , uint localID )
2007-12-04 11:11:13 +00:00
{
2008-04-21 14:11:36 +00:00
SceneObjectPart part = GetChildPart ( localID ) ;
if ( part ! = null )
{
if ( part . UUID = = m_rootPart . UUID )
2008-01-14 18:29:04 +00:00
{
2008-04-21 14:11:36 +00:00
UpdateRootRotation ( rot ) ;
2008-01-14 18:29:04 +00:00
}
2008-03-18 20:42:01 +00:00
else
{
2008-04-21 14:11:36 +00:00
part . UpdateRotation ( rot ) ;
}
2008-01-14 18:29:04 +00:00
}
2007-12-04 11:11:13 +00:00
}
2008-01-17 09:32:02 +00:00
2008-04-21 14:11:36 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2008-04-21 14:11:36 +00:00
/// </summary>
/// <param name="rot"></param>
2008-09-06 07:52:41 +00:00
private void UpdateRootRotation ( Quaternion rot )
2008-01-17 09:32:02 +00:00
{
2008-09-06 07:52:41 +00:00
Quaternion axRot = rot ;
Quaternion oldParentRot = m_rootPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
m_rootPart . UpdateRotation ( rot ) ;
if ( m_rootPart . PhysActor ! = null )
{
2008-09-06 07:52:41 +00:00
m_rootPart . PhysActor . Orientation = m_rootPart . RotationOffset ;
2008-04-21 14:11:36 +00:00
m_scene . PhysicsScene . AddPhysicsActorTaint ( m_rootPart . PhysActor ) ;
}
2008-01-17 09:32:02 +00:00
2008-01-21 15:06:49 +00:00
lock ( m_parts )
2008-01-17 09:32:02 +00:00
{
2008-04-21 14:11:36 +00:00
foreach ( SceneObjectPart prim in m_parts . Values )
2008-01-21 15:06:49 +00:00
{
2008-04-21 14:11:36 +00:00
if ( prim . UUID ! = m_rootPart . UUID )
{
2008-09-06 07:52:41 +00:00
Vector3 axPos = prim . OffsetPosition ;
axPos * = oldParentRot ;
axPos * = Quaternion . Inverse ( axRot ) ;
prim . OffsetPosition = axPos ;
Quaternion primsRot = prim . RotationOffset ;
2008-12-22 00:03:18 +00:00
Quaternion newRot = primsRot * oldParentRot ;
2008-09-06 07:52:41 +00:00
newRot * = Quaternion . Inverse ( axRot ) ;
prim . RotationOffset = newRot ;
2008-04-21 14:11:36 +00:00
prim . ScheduleTerseUpdate ( ) ;
}
2008-01-21 15:06:49 +00:00
}
2008-01-17 09:32:02 +00:00
}
2008-04-21 14:11:36 +00:00
m_rootPart . ScheduleTerseUpdate ( ) ;
2008-01-17 09:32:02 +00:00
}
2008-03-25 03:36:31 +00:00
2008-04-21 14:11:36 +00:00
# endregion
2008-05-01 18:04:42 +00:00
internal void SetAxisRotation ( int axis , int rotate10 )
{
bool setX = false ;
bool setY = false ;
bool setZ = false ;
int xaxis = 2 ;
int yaxis = 4 ;
int zaxis = 8 ;
if ( m_rootPart ! = null )
{
setX = ( ( axis & xaxis ) ! = 0 ) ? true : false ;
setY = ( ( axis & yaxis ) ! = 0 ) ? true : false ;
setZ = ( ( axis & zaxis ) ! = 0 ) ? true : false ;
float setval = ( rotate10 > 0 ) ? 1f : 0f ;
if ( setX )
2008-07-26 21:22:15 +00:00
m_rootPart . RotationAxis . X = setval ;
2008-05-01 18:04:42 +00:00
if ( setY )
2008-07-26 21:22:15 +00:00
m_rootPart . RotationAxis . Y = setval ;
2008-05-01 18:04:42 +00:00
if ( setZ )
2008-07-26 21:22:15 +00:00
m_rootPart . RotationAxis . Z = setval ;
2008-05-01 18:04:42 +00:00
if ( setX | | setY | | setZ )
{
m_rootPart . SetPhysicsAxisRotation ( ) ;
}
}
}
2008-09-06 07:52:41 +00:00
public int registerTargetWaypoint ( Vector3 target , float tolerance )
2008-05-01 18:04:42 +00:00
{
scriptPosTarget waypoint = new scriptPosTarget ( ) ;
waypoint . targetPos = target ;
waypoint . tolerance = tolerance ;
2008-11-07 22:49:36 +00:00
uint handle = m_scene . AllocateLocalId ( ) ;
2008-05-01 18:04:42 +00:00
lock ( m_targets )
{
m_targets . Add ( handle , waypoint ) ;
}
return ( int ) handle ;
}
2008-11-07 21:50:03 +00:00
2008-05-01 18:04:42 +00:00
public void unregisterTargetWaypoint ( int handle )
{
lock ( m_targets )
{
if ( m_targets . ContainsKey ( ( uint ) handle ) )
m_targets . Remove ( ( uint ) handle ) ;
}
}
private void checkAtTargets ( )
{
if ( m_scriptListens_atTarget | | m_scriptListens_notAtTarget )
{
if ( m_targets . Count > 0 )
{
bool at_target = false ;
2008-09-06 07:52:41 +00:00
//Vector3 targetPos;
2008-05-01 18:04:42 +00:00
//uint targetHandle;
Dictionary < uint , scriptPosTarget > atTargets = new Dictionary < uint , scriptPosTarget > ( ) ;
lock ( m_targets )
{
foreach ( uint idx in m_targets . Keys )
{
scriptPosTarget target = m_targets [ idx ] ;
if ( Util . GetDistanceTo ( target . targetPos , m_rootPart . GroupPosition ) < = target . tolerance )
{
// trigger at_target
if ( m_scriptListens_atTarget )
{
// Reusing att.tolerance to hold the index of the target in the targets dictionary
// to avoid deadlocking the sim.
at_target = true ;
scriptPosTarget att = new scriptPosTarget ( ) ;
att . targetPos = target . targetPos ;
att . tolerance = ( float ) idx ;
atTargets . Add ( idx , att ) ;
}
}
}
}
if ( atTargets . Count > 0 )
{
uint [ ] localids = new uint [ 0 ] ;
lock ( m_parts )
{
localids = new uint [ m_parts . Count ] ;
int cntr = 0 ;
foreach ( SceneObjectPart part in m_parts . Values )
{
localids [ cntr ] = part . LocalId ;
cntr + + ;
}
}
for ( int ctr = 0 ; ctr < localids . Length ; ctr + + )
{
foreach ( uint target in atTargets . Keys )
{
scriptPosTarget att = atTargets [ target ] ;
// Reusing att.tolerance to hold the index of the target in the targets dictionary
// to avoid deadlocking the sim.
m_scene . TriggerAtTargetEvent ( localids [ ctr ] , ( uint ) att . tolerance , att . targetPos , m_rootPart . GroupPosition ) ;
2008-05-16 01:22:11 +00:00
2008-05-01 18:04:42 +00:00
}
}
return ;
}
if ( m_scriptListens_notAtTarget & & ! at_target )
{
//trigger not_at_target
uint [ ] localids = new uint [ 0 ] ;
lock ( m_parts )
{
localids = new uint [ m_parts . Count ] ;
int cntr = 0 ;
foreach ( SceneObjectPart part in m_parts . Values )
{
localids [ cntr ] = part . LocalId ;
cntr + + ;
}
}
for ( int ctr = 0 ; ctr < localids . Length ; ctr + + )
{
m_scene . TriggerNotAtTargetEvent ( localids [ ctr ] ) ;
}
}
}
}
}
2008-11-17 15:40:27 +00:00
2008-05-05 00:03:30 +00:00
public float GetMass ( )
{
float retmass = 0f ;
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
retmass + = part . GetMass ( ) ;
}
}
return retmass ;
}
2008-11-17 15:40:27 +00:00
2008-05-09 07:50:00 +00:00
public void CheckSculptAndLoad ( )
{
lock ( m_parts )
{
2008-11-17 15:40:27 +00:00
if ( ! IsDeleted )
2008-05-09 07:50:00 +00:00
{
2008-09-06 07:52:41 +00:00
if ( ( RootPart . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Phantom ) = = 0 )
2008-05-09 07:50:00 +00:00
{
2008-05-25 04:15:32 +00:00
foreach ( SceneObjectPart part in m_parts . Values )
{
2008-09-06 07:52:41 +00:00
if ( part . Shape . SculptEntry & & part . Shape . SculptTexture ! = UUID . Zero )
2008-05-25 04:15:32 +00:00
{
2009-02-16 19:15:16 +00:00
m_scene . CommsManager . AssetCache . GetAsset (
part . Shape . SculptTexture , part . SculptTextureCallback , true ) ;
2008-05-25 04:15:32 +00:00
}
}
2008-05-09 07:50:00 +00:00
}
}
}
}
2008-08-18 00:39:10 +00:00
2008-06-27 14:15:14 +00:00
/// <summary>
/// Set the user group to which this scene object belongs.
/// </summary>
/// <param name="GroupID"></param>
/// <param name="client"></param>
2008-09-06 07:52:41 +00:00
public void SetGroup ( UUID GroupID , IClientAPI client )
2008-05-18 03:21:22 +00:00
{
lock ( m_parts )
{
foreach ( SceneObjectPart part in m_parts . Values )
{
part . SetGroup ( GroupID , client ) ;
2008-11-21 21:16:42 +00:00
part . Inventory . ChangeInventoryGroup ( GroupID ) ;
2008-05-18 03:21:22 +00:00
}
2008-08-18 00:39:10 +00:00
2008-06-27 16:36:19 +00:00
HasGroupChanged = true ;
2008-05-18 03:21:22 +00:00
}
2008-08-18 00:39:10 +00:00
2008-05-18 03:21:22 +00:00
ScheduleGroupForFullUpdate ( ) ;
}
2008-07-19 04:05:34 +00:00
public void TriggerScriptChangedEvent ( Changed val )
{
foreach ( SceneObjectPart part in Children . Values )
{
part . TriggerScriptChangedEvent ( val ) ;
}
}
2008-09-12 00:37:59 +00:00
public override string ToString ( )
{
return String . Format ( "{0} {1} ({2})" , Name , UUID , AbsolutePosition ) ;
}
2008-10-03 21:44:33 +00:00
public void SetAttachmentPoint ( byte point )
{
2008-10-05 14:15:39 +00:00
lock ( m_parts )
2008-10-03 21:44:33 +00:00
{
foreach ( SceneObjectPart part in m_parts . Values )
part . SetAttachmentPoint ( point ) ;
}
}
2009-02-09 22:27:27 +00:00
#region ISceneObject
public virtual ISceneObject CloneForNewScene ( )
{
SceneObjectGroup sog = Copy ( this . OwnerID , this . GroupID , false ) ;
2009-02-10 22:54:05 +00:00
sog . m_isDeleted = false ;
2009-02-09 22:27:27 +00:00
return sog ;
}
public virtual string ExtraToXmlString ( )
{
return "<ExtraFromAssetID>" + GetFromAssetID ( ) . ToString ( ) + "</ExtraFromAssetID>" ;
}
public virtual void ExtraFromXmlString ( string xmlstr )
{
string id = xmlstr . Substring ( xmlstr . IndexOf ( "<ExtraFromAssetID>" ) ) ;
id = xmlstr . Replace ( "<ExtraFromAssetID>" , "" ) ;
id = id . Replace ( "</ExtraFromAssetID>" , "" ) ;
UUID uuid = UUID . Zero ;
UUID . TryParse ( id , out uuid ) ;
SetFromAssetID ( uuid ) ;
}
#endregion
2007-07-30 20:11:40 +00:00
}
2008-05-01 18:04:42 +00:00
}