2007-12-27 21:41:48 +00:00
/ *
2008-03-18 05:16:43 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2007-12-11 01:26:06 +00:00
using System ;
2009-12-06 00:25:04 +00:00
using System.Threading ;
2007-11-04 14:34:45 +00:00
using System.Collections.Generic ;
2008-04-21 07:09:17 +00:00
using System.Reflection ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
using OpenMetaverse.Packets ;
2008-04-21 07:09:17 +00:00
using log4net ;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Scenes.Types ;
2007-11-04 14:34:45 +00:00
using OpenSim.Region.Physics.Manager ;
2010-01-30 17:23:07 +00:00
using OpenSim.Region.Framework.Interfaces ;
2007-11-04 14:34:45 +00:00
2009-02-06 16:55:34 +00:00
namespace OpenSim.Region.Framework.Scenes
2007-11-04 14:34:45 +00:00
{
2007-11-28 06:18:07 +00:00
public delegate void PhysicsCrash ( ) ;
2008-11-12 20:16:46 +00:00
/// <summary>
/// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
/// should be migrated out over time.
/// </summary>
public class SceneGraph
2007-11-04 14:34:45 +00:00
{
2008-04-21 07:09:17 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-02-05 19:44:27 +00:00
2007-11-28 06:18:07 +00:00
#region Events
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal event PhysicsCrash UnRecoverableError ;
2008-05-01 18:04:42 +00:00
private PhysicsCrash handlerPhysicsCrash = null ;
2007-12-27 21:41:48 +00:00
2007-11-28 06:18:07 +00:00
# endregion
2007-11-04 22:22:53 +00:00
#region Fields
2007-12-27 21:41:48 +00:00
2010-05-04 23:49:46 +00:00
protected object m_presenceLock = new object ( ) ;
protected Dictionary < UUID , ScenePresence > m_scenePresenceMap = new Dictionary < UUID , ScenePresence > ( ) ;
protected List < ScenePresence > m_scenePresenceArray = new List < ScenePresence > ( ) ;
2009-10-23 08:02:36 +00:00
2008-11-24 14:45:05 +00:00
protected internal EntityManager Entities = new EntityManager ( ) ;
2008-05-01 18:04:42 +00:00
protected Scene m_parentScene ;
2009-10-14 02:13:06 +00:00
protected Dictionary < UUID , SceneObjectGroup > m_updateList = new Dictionary < UUID , SceneObjectGroup > ( ) ;
2008-05-01 18:04:42 +00:00
protected int m_numRootAgents = 0 ;
protected int m_numPrim = 0 ;
protected int m_numChildAgents = 0 ;
protected int m_physicalPrim = 0 ;
2007-11-04 22:22:53 +00:00
2008-05-01 18:04:42 +00:00
protected int m_activeScripts = 0 ;
protected int m_scriptLPS = 0 ;
2008-02-06 08:03:22 +00:00
2008-05-26 01:06:50 +00:00
protected internal PhysicsScene _PhyScene ;
2011-03-26 00:53:19 +00:00
/// <summary>
/// Index the SceneObjectGroup for each part by the root part's UUID.
/// </summary>
protected internal Dictionary < UUID , SceneObjectGroup > SceneObjectGroupsByFullID = new Dictionary < UUID , SceneObjectGroup > ( ) ;
/// <summary>
/// Index the SceneObjectGroup for each part by that part's UUID.
/// </summary>
2011-03-26 00:42:48 +00:00
protected internal Dictionary < UUID , SceneObjectGroup > SceneObjectGroupsByFullPartID = new Dictionary < UUID , SceneObjectGroup > ( ) ;
2011-03-26 00:53:19 +00:00
/// <summary>
/// Index the SceneObjectGroup for each part by that part's local ID.
/// </summary>
protected internal Dictionary < uint , SceneObjectGroup > SceneObjectGroupsByLocalPartID = new Dictionary < uint , SceneObjectGroup > ( ) ;
2009-04-12 15:18:04 +00:00
2012-04-17 22:54:51 +00:00
/// <summary>
/// Lock to prevent object group update, linking and delinking operations from running concurrently.
/// </summary>
2009-12-06 00:25:04 +00:00
private Object m_updateLock = new Object ( ) ;
2007-11-04 22:22:53 +00:00
# endregion
2007-11-04 14:34:45 +00:00
2011-09-12 21:51:56 +00:00
protected internal SceneGraph ( Scene parent )
2007-11-04 14:34:45 +00:00
{
m_parentScene = parent ;
2007-11-28 06:18:07 +00:00
}
2007-12-06 18:17:44 +00:00
2007-11-29 15:27:57 +00:00
public PhysicsScene PhysicsScene
2007-11-28 06:18:07 +00:00
{
2007-12-27 21:41:48 +00:00
get { return _PhyScene ; }
2007-11-28 06:18:07 +00:00
set
{
// If we're not doing the initial set
2008-05-16 01:22:11 +00:00
// Then we've got to remove the previous
2007-11-28 06:18:07 +00:00
// event handler
2008-08-18 00:39:10 +00:00
if ( _PhyScene ! = null )
2007-12-27 21:41:48 +00:00
_PhyScene . OnPhysicsCrash - = physicsBasedCrash ;
2007-11-28 06:18:07 +00:00
_PhyScene = value ;
2007-12-27 21:41:48 +00:00
2008-07-21 13:40:08 +00:00
if ( _PhyScene ! = null )
_PhyScene . OnPhysicsCrash + = physicsBasedCrash ;
2007-11-28 06:18:07 +00:00
}
2007-11-04 14:34:45 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal void Close ( )
2007-11-04 14:34:45 +00:00
{
2010-05-04 23:49:46 +00:00
lock ( m_presenceLock )
2008-05-07 22:59:30 +00:00
{
2010-05-04 23:49:46 +00:00
Dictionary < UUID , ScenePresence > newmap = new Dictionary < UUID , ScenePresence > ( ) ;
List < ScenePresence > newlist = new List < ScenePresence > ( ) ;
m_scenePresenceMap = newmap ;
m_scenePresenceArray = newlist ;
2008-05-07 22:59:30 +00:00
}
2009-10-23 08:02:36 +00:00
2011-03-26 00:53:19 +00:00
lock ( SceneObjectGroupsByFullID )
SceneObjectGroupsByFullID . Clear ( ) ;
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
SceneObjectGroupsByFullPartID . Clear ( ) ;
lock ( SceneObjectGroupsByLocalPartID )
SceneObjectGroupsByLocalPartID . Clear ( ) ;
2008-05-16 01:22:11 +00:00
2008-11-24 15:09:25 +00:00
Entities . Clear ( ) ;
2007-11-04 14:34:45 +00:00
}
2007-11-04 22:22:53 +00:00
#region Update Methods
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void UpdatePreparePhysics ( )
2007-11-04 22:22:53 +00:00
{
// If we are using a threaded physics engine
// grab the latest scene from the engine before
// trying to process it.
// PhysX does this (runs in the background).
2007-11-28 06:18:07 +00:00
if ( _PhyScene . IsThreaded )
2007-11-04 22:22:53 +00:00
{
2007-11-28 06:18:07 +00:00
_PhyScene . GetResults ( ) ;
2007-11-04 22:22:53 +00:00
}
}
2011-10-05 23:45:25 +00:00
/// <summary>
/// Update the position of all the scene presences.
/// </summary>
/// <remarks>
/// Called only from the main scene loop.
/// </remarks>
2008-05-26 01:06:50 +00:00
protected internal void UpdatePresences ( )
2008-02-20 00:08:04 +00:00
{
2010-03-17 13:40:00 +00:00
ForEachScenePresence ( delegate ( ScenePresence presence )
{
presence . Update ( ) ;
} ) ;
2008-02-20 00:08:04 +00:00
}
2011-10-05 21:08:56 +00:00
/// <summary>
/// Perform a physics frame update.
/// </summary>
/// <param name="elapsed"></param>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal float UpdatePhysics ( double elapsed )
2007-11-04 22:22:53 +00:00
{
2011-10-29 01:42:53 +00:00
// Here is where the Scene calls the PhysicsScene. This is a one-way
// interaction; the PhysicsScene cannot access the calling Scene directly.
// But with joints, we want a PhysicsActor to be able to influence a
// non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
// with a joint should be able to move the SceneObjectPart which is the visual
// representation of that joint (for editing and serialization purposes).
// However the PhysicsActor normally cannot directly influence anything outside
// of the PhysicsScene, and the non-physical SceneObjectPart which represents
// the joint in the Scene does not exist in the PhysicsScene.
/ /
// To solve this, we have an event in the PhysicsScene that is fired when a joint
// has changed position (because one of its associated PhysicsActors has changed
// position).
/ /
// Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
return _PhyScene . Simulate ( ( float ) elapsed ) ;
2007-11-04 22:22:53 +00:00
}
2009-09-02 02:33:31 +00:00
protected internal void UpdateScenePresenceMovement ( )
2007-11-04 22:22:53 +00:00
{
2010-03-17 13:40:00 +00:00
ForEachScenePresence ( delegate ( ScenePresence presence )
{
presence . UpdateMovement ( ) ;
} ) ;
2007-11-04 22:22:53 +00:00
}
2007-12-27 21:41:48 +00:00
2010-06-08 23:30:51 +00:00
public void GetCoarseLocations ( out List < Vector3 > coarseLocations , out List < UUID > avatarUUIDs , uint maxLocations )
{
coarseLocations = new List < Vector3 > ( ) ;
avatarUUIDs = new List < UUID > ( ) ;
List < ScenePresence > presences = GetScenePresences ( ) ;
for ( int i = 0 ; i < Math . Min ( presences . Count , maxLocations ) ; + + i )
{
ScenePresence sp = presences [ i ] ;
2011-02-24 22:33:54 +00:00
2010-06-08 23:30:51 +00:00
// If this presence is a child agent, we don't want its coarse locations
if ( sp . IsChildAgent )
2011-02-24 22:33:54 +00:00
continue ;
2010-06-08 23:30:51 +00:00
2012-03-09 02:50:57 +00:00
coarseLocations . Add ( sp . AbsolutePosition ) ;
2012-03-09 02:38:11 +00:00
avatarUUIDs . Add ( sp . UUID ) ;
2010-06-08 23:30:51 +00:00
}
}
2007-11-04 22:22:53 +00:00
# endregion
#region Entity Methods
2007-12-27 21:41:48 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
/// Add an object into the scene that has come from storage
/// </summary>
/// <param name="sceneObject"></param>
2008-06-27 14:15:14 +00:00
/// <param name="attachToBackup">
/// If true, changes to the object will be reflected in its persisted data
/// If false, the persisted data will not be changed even if the object in the scene is changed
/// </param>
2008-07-13 00:18:29 +00:00
/// <param name="alreadyPersisted">
/// If true, we won't persist this object until it changes
/// If false, we'll persist this object immediately
/// </param>
2010-06-08 14:07:57 +00:00
/// <param name="sendClientUpdates">
/// If true, we send updates to the client to tell it about this object
/// If false, we leave it up to the caller to do this
/// </param>
2008-07-12 22:14:38 +00:00
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
2008-08-18 00:39:10 +00:00
/// </returns>
2008-07-13 00:18:29 +00:00
protected internal bool AddRestoredSceneObject (
2010-06-08 14:07:57 +00:00
SceneObjectGroup sceneObject , bool attachToBackup , bool alreadyPersisted , bool sendClientUpdates )
2007-11-04 14:34:45 +00:00
{
2010-11-16 21:01:56 +00:00
if ( attachToBackup & & ( ! alreadyPersisted ) )
2008-07-13 00:18:29 +00:00
{
sceneObject . ForceInventoryPersistence ( ) ;
sceneObject . HasGroupChanged = true ;
}
2008-08-18 00:39:10 +00:00
2010-06-08 14:07:57 +00:00
return AddSceneObject ( sceneObject , attachToBackup , sendClientUpdates ) ;
2007-11-04 14:34:45 +00:00
}
2010-06-08 14:07:57 +00:00
2008-06-27 14:25:36 +00:00
/// <summary>
/// Add a newly created object to the scene. This will both update the scene, and send information about the
/// new object to all clients interested in the scene.
/// </summary>
/// <param name="sceneObject"></param>
/// <param name="attachToBackup">
/// If true, the object is made persistent into the scene.
/// If false, the object will not persist over server restarts
/// </param>
2008-07-12 22:14:38 +00:00
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
2008-08-18 00:39:10 +00:00
/// </returns>
2010-03-03 22:14:06 +00:00
protected internal bool AddNewSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup , bool sendClientUpdates )
2008-08-18 00:39:10 +00:00
{
2010-11-16 21:01:56 +00:00
// Ensure that we persist this new scene object if it's not an
// attachment
if ( attachToBackup )
sceneObject . HasGroupChanged = true ;
2008-08-18 00:39:10 +00:00
2010-03-03 22:14:06 +00:00
return AddSceneObject ( sceneObject , attachToBackup , sendClientUpdates ) ;
2008-06-27 14:25:36 +00:00
}
2010-08-24 22:25:19 +00:00
/// <summary>
/// Add a newly created object to the scene.
/// </summary>
///
/// This method does not send updates to the client - callers need to handle this themselves.
2012-01-19 10:53:21 +00:00
/// Caller should also trigger EventManager.TriggerObjectAddedToScene
2010-08-24 22:25:19 +00:00
/// <param name="sceneObject"></param>
/// <param name="attachToBackup"></param>
2011-05-20 23:02:53 +00:00
/// <param name="pos">Position of the object. If null then the position stored in the object is used.</param>
/// <param name="rot">Rotation of the object. If null then the rotation stored in the object is used.</param>
2010-08-24 22:25:19 +00:00
/// <param name="vel">Velocity of the object. This parameter only has an effect if the object is physical</param>
2010-09-12 17:43:49 +00:00
/// <returns></returns>
2010-08-24 22:25:19 +00:00
public bool AddNewSceneObject (
2011-05-20 23:02:53 +00:00
SceneObjectGroup sceneObject , bool attachToBackup , Vector3 ? pos , Quaternion ? rot , Vector3 vel )
2010-08-24 22:25:19 +00:00
{
AddNewSceneObject ( sceneObject , true , false ) ;
2011-05-20 23:02:53 +00:00
if ( pos ! = null )
sceneObject . AbsolutePosition = ( Vector3 ) pos ;
2010-08-24 22:25:19 +00:00
if ( sceneObject . RootPart . Shape . PCode = = ( byte ) PCode . Prim )
{
sceneObject . ClearPartAttachmentData ( ) ;
}
2011-05-20 23:02:53 +00:00
if ( rot ! = null )
sceneObject . UpdateGroupRotationR ( ( Quaternion ) rot ) ;
2012-04-03 04:50:13 +00:00
PhysicsActor pa = sceneObject . RootPart . PhysActor ;
if ( pa ! = null & & pa . IsPhysical & & vel ! = Vector3 . Zero )
2010-08-24 22:25:19 +00:00
{
sceneObject . RootPart . ApplyImpulse ( ( vel * sceneObject . GetMass ( ) ) , false ) ;
sceneObject . Velocity = vel ;
}
return true ;
2010-09-12 17:43:49 +00:00
}
2007-11-04 14:34:45 +00:00
2008-05-24 22:10:14 +00:00
/// <summary>
2008-06-17 20:36:21 +00:00
/// Add an object to the scene. This will both update the scene, and send information about the
/// new object to all clients interested in the scene.
2008-05-24 22:10:14 +00:00
/// </summary>
2011-05-20 22:22:27 +00:00
/// <remarks>
/// The object's stored position, rotation and velocity are used.
/// </remarks>
2008-05-24 22:10:14 +00:00
/// <param name="sceneObject"></param>
2008-06-12 17:49:08 +00:00
/// <param name="attachToBackup">
2008-06-13 00:21:53 +00:00
/// If true, the object is made persistent into the scene.
2008-06-12 17:49:08 +00:00
/// If false, the object will not persist over server restarts
/// </param>
2010-03-03 22:14:06 +00:00
/// <param name="sendClientUpdates">
/// If true, updates for the new scene object are sent to all viewers in range.
/// If false, it is left to the caller to schedule the update
/// </param>
/// <returns>
/// true if the object was added, false if an object with the same uuid was already in the scene
2008-05-24 23:11:07 +00:00
/// </returns>
2010-03-03 22:14:06 +00:00
protected bool AddSceneObject ( SceneObjectGroup sceneObject , bool attachToBackup , bool sendClientUpdates )
2007-11-04 14:34:45 +00:00
{
2012-01-31 20:30:30 +00:00
if ( sceneObject . UUID = = UUID . Zero )
{
m_log . ErrorFormat (
"[SCENEGRAPH]: Tried to add scene object {0} to {1} with illegal UUID of {2}" ,
sceneObject . Name , m_parentScene . RegionInfo . RegionName , UUID . Zero ) ;
2012-02-15 01:45:25 +00:00
2008-10-11 16:23:15 +00:00
return false ;
2012-01-31 20:30:30 +00:00
}
2010-03-03 22:14:06 +00:00
2010-09-10 19:04:12 +00:00
if ( Entities . ContainsKey ( sceneObject . UUID ) )
2012-01-31 19:56:37 +00:00
{
// m_log.DebugFormat(
// "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()",
// m_parentScene.RegionInfo.RegionName, sceneObject.UUID);
2012-02-15 01:45:25 +00:00
2010-09-10 19:04:12 +00:00
return false ;
2012-01-31 19:56:37 +00:00
}
2012-02-15 01:45:25 +00:00
2011-03-26 02:24:32 +00:00
// m_log.DebugFormat(
2012-02-15 01:45:25 +00:00
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
2011-03-26 02:24:32 +00:00
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
2010-09-10 19:04:12 +00:00
2011-09-13 16:56:02 +00:00
SceneObjectPart [ ] parts = sceneObject . Parts ;
2010-09-10 19:41:36 +00:00
// Clamp child prim sizes and add child prims to the m_numPrim count
if ( m_parentScene . m_clampPrimSize )
2010-09-10 19:04:12 +00:00
{
2011-09-13 16:56:02 +00:00
foreach ( SceneObjectPart part in parts )
2010-05-21 20:57:56 +00:00
{
2010-09-10 19:41:36 +00:00
Vector3 scale = part . Shape . Scale ;
2010-09-10 19:04:12 +00:00
2010-09-10 19:41:36 +00:00
if ( scale . X > m_parentScene . m_maxNonphys )
scale . X = m_parentScene . m_maxNonphys ;
if ( scale . Y > m_parentScene . m_maxNonphys )
scale . Y = m_parentScene . m_maxNonphys ;
if ( scale . Z > m_parentScene . m_maxNonphys )
scale . Z = m_parentScene . m_maxNonphys ;
2010-09-10 19:04:12 +00:00
2010-09-10 19:41:36 +00:00
part . Shape . Scale = scale ;
2010-08-27 23:40:33 +00:00
}
2010-09-10 19:04:12 +00:00
}
2011-09-13 16:56:02 +00:00
m_numPrim + = parts . Length ;
2010-08-27 23:40:33 +00:00
2010-09-10 19:04:12 +00:00
sceneObject . AttachToScene ( m_parentScene ) ;
2010-08-27 23:40:33 +00:00
2010-09-10 19:04:12 +00:00
if ( sendClientUpdates )
sceneObject . ScheduleGroupForFullUpdate ( ) ;
Entities . Add ( sceneObject ) ;
if ( attachToBackup )
sceneObject . AttachToBackup ( ) ;
2011-03-26 00:53:19 +00:00
lock ( SceneObjectGroupsByFullID )
SceneObjectGroupsByFullID [ sceneObject . UUID ] = sceneObject ;
2012-02-15 01:45:25 +00:00
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
2010-09-10 19:04:12 +00:00
{
2011-09-13 16:56:02 +00:00
foreach ( SceneObjectPart part in parts )
2011-03-26 00:42:48 +00:00
SceneObjectGroupsByFullPartID [ part . UUID ] = sceneObject ;
2010-09-10 19:04:12 +00:00
}
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByLocalPartID )
2010-09-10 19:04:12 +00:00
{
2011-09-12 21:44:14 +00:00
// m_log.DebugFormat(
// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
2011-09-13 16:56:02 +00:00
foreach ( SceneObjectPart part in parts )
2011-03-26 00:42:48 +00:00
SceneObjectGroupsByLocalPartID [ part . LocalId ] = sceneObject ;
2007-11-04 14:34:45 +00:00
}
2008-11-24 15:09:25 +00:00
2010-05-21 20:57:56 +00:00
return true ;
2007-11-04 14:34:45 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-24 23:11:07 +00:00
/// <summary>
/// Delete an object from the scene
/// </summary>
/// <returns>true if the object was deleted, false if there was no object to delete</returns>
2009-02-06 16:55:34 +00:00
public bool DeleteSceneObject ( UUID uuid , bool resultOfObjectLinked )
2008-05-24 23:11:07 +00:00
{
2011-09-13 19:25:32 +00:00
// m_log.DebugFormat(
// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
// uuid, resultOfObjectLinked);
2010-09-10 19:04:12 +00:00
EntityBase entity ;
2010-10-27 19:47:27 +00:00
if ( ! Entities . TryGetValue ( uuid , out entity ) | | ( ! ( entity is SceneObjectGroup ) ) )
2010-09-10 19:04:12 +00:00
return false ;
2010-08-25 21:11:00 +00:00
2010-09-10 19:04:12 +00:00
SceneObjectGroup grp = ( SceneObjectGroup ) entity ;
2009-01-03 03:30:03 +00:00
2010-10-27 19:47:27 +00:00
if ( entity = = null )
return false ;
2010-09-10 19:04:12 +00:00
if ( ! resultOfObjectLinked )
{
m_numPrim - = grp . PrimCount ;
2009-01-03 03:30:03 +00:00
2010-09-10 19:04:12 +00:00
if ( ( grp . RootPart . Flags & PrimFlags . Physics ) = = PrimFlags . Physics )
RemovePhysicalPrim ( grp . PrimCount ) ;
}
2011-03-26 00:53:19 +00:00
lock ( SceneObjectGroupsByFullID )
SceneObjectGroupsByFullID . Remove ( grp . UUID ) ;
2010-08-25 21:11:00 +00:00
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
2010-09-10 19:04:12 +00:00
{
2010-09-17 00:30:46 +00:00
SceneObjectPart [ ] parts = grp . Parts ;
for ( int i = 0 ; i < parts . Length ; i + + )
2011-03-26 00:42:48 +00:00
SceneObjectGroupsByFullPartID . Remove ( parts [ i ] . UUID ) ;
2010-09-10 19:04:12 +00:00
}
2008-11-24 15:09:25 +00:00
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByLocalPartID )
2010-09-10 19:04:12 +00:00
{
2010-09-17 00:30:46 +00:00
SceneObjectPart [ ] parts = grp . Parts ;
for ( int i = 0 ; i < parts . Length ; i + + )
2011-03-26 00:42:48 +00:00
SceneObjectGroupsByLocalPartID . Remove ( parts [ i ] . LocalId ) ;
2008-05-24 23:11:07 +00:00
}
2008-05-28 03:44:49 +00:00
2010-09-10 19:04:12 +00:00
return Entities . Remove ( uuid ) ;
2008-05-24 23:11:07 +00:00
}
2007-12-27 21:41:48 +00:00
2008-03-13 00:22:38 +00:00
/// <summary>
2009-10-14 02:13:06 +00:00
/// Add an object to the list of prims to process on the next update
2008-03-13 00:22:38 +00:00
/// </summary>
/// <param name="obj">
2009-10-14 02:13:06 +00:00
/// A <see cref="SceneObjectGroup"/>
2008-03-13 00:22:38 +00:00
/// </param>
2009-10-14 02:13:06 +00:00
protected internal void AddToUpdateList ( SceneObjectGroup obj )
2008-02-20 00:08:04 +00:00
{
lock ( m_updateList )
2009-04-12 15:18:04 +00:00
m_updateList [ obj . UUID ] = obj ;
2008-02-20 00:08:04 +00:00
}
2008-03-12 18:11:08 +00:00
/// <summary>
/// Process all pending updates
/// </summary>
2009-10-14 02:13:06 +00:00
protected internal void UpdateObjectGroups ( )
2008-02-20 00:08:04 +00:00
{
2009-12-06 00:25:04 +00:00
if ( ! Monitor . TryEnter ( m_updateLock ) )
return ;
2010-09-10 19:04:12 +00:00
try
2009-04-12 15:18:04 +00:00
{
2010-09-10 19:04:12 +00:00
List < SceneObjectGroup > updates ;
2009-10-29 06:10:16 +00:00
2010-09-10 19:04:12 +00:00
// Some updates add more updates to the updateList.
// Get the current list of updates and clear the list before iterating
lock ( m_updateList )
2008-02-20 00:08:04 +00:00
{
2010-09-10 19:04:12 +00:00
updates = new List < SceneObjectGroup > ( m_updateList . Values ) ;
m_updateList . Clear ( ) ;
2009-04-12 15:18:04 +00:00
}
2010-09-10 19:04:12 +00:00
// Go through all updates
for ( int i = 0 ; i < updates . Count ; i + + )
2009-04-12 15:18:04 +00:00
{
2010-09-10 19:04:12 +00:00
SceneObjectGroup sog = updates [ i ] ;
// Don't abort the whole update if one entity happens to give us an exception.
try
{
sog . Update ( ) ;
}
catch ( Exception e )
{
m_log . ErrorFormat (
"[INNER SCENE]: Failed to update {0}, {1} - {2}" , sog . Name , sog . UUID , e ) ;
}
2008-02-20 00:08:04 +00:00
}
}
2010-09-10 19:04:12 +00:00
finally
{
Monitor . Exit ( m_updateLock ) ;
}
2008-02-20 00:08:04 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal void AddPhysicalPrim ( int number )
2007-12-14 00:49:40 +00:00
{
m_physicalPrim + + ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void RemovePhysicalPrim ( int number )
2007-12-14 00:49:40 +00:00
{
m_physicalPrim - - ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 01:06:50 +00:00
protected internal void AddToScriptLPS ( int number )
2008-02-06 08:03:22 +00:00
{
m_scriptLPS + = number ;
}
2008-05-26 01:06:50 +00:00
protected internal void AddActiveScripts ( int number )
2008-02-06 08:03:22 +00:00
{
m_activeScripts + = number ;
}
2008-05-28 03:44:49 +00:00
2008-09-06 07:52:41 +00:00
protected internal void HandleUndo ( IClientAPI remoteClient , UUID primId )
2008-04-28 01:48:21 +00:00
{
2008-09-06 07:52:41 +00:00
if ( primId ! = UUID . Zero )
2008-04-28 01:48:21 +00:00
{
2008-05-01 18:04:42 +00:00
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primId ) ;
2008-04-28 01:48:21 +00:00
if ( part ! = null )
part . Undo ( ) ;
2008-05-28 03:44:49 +00:00
}
2008-04-28 01:48:21 +00:00
}
2011-07-18 03:54:21 +00:00
2010-02-14 21:41:57 +00:00
protected internal void HandleRedo ( IClientAPI remoteClient , UUID primId )
{
if ( primId ! = UUID . Zero )
{
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primId ) ;
2011-07-16 04:23:21 +00:00
2010-02-14 21:41:57 +00:00
if ( part ! = null )
part . Redo ( ) ;
}
}
2008-05-28 03:44:49 +00:00
2011-08-17 23:53:05 +00:00
protected internal ScenePresence CreateAndAddChildScenePresence (
IClientAPI client , AvatarAppearance appearance , PresenceType type )
2007-11-04 14:34:45 +00:00
{
ScenePresence newAvatar = null ;
2011-01-26 21:33:34 +00:00
// ScenePresence always defaults to child agent
2011-09-12 21:51:56 +00:00
newAvatar = new ScenePresence ( client , m_parentScene , appearance , type ) ;
2007-11-04 14:34:45 +00:00
2008-05-26 00:47:36 +00:00
AddScenePresence ( newAvatar ) ;
2008-05-28 03:44:49 +00:00
2007-11-04 14:34:45 +00:00
return newAvatar ;
}
2007-12-27 21:41:48 +00:00
2008-05-26 00:38:04 +00:00
/// <summary>
/// Add a presence to the scene
/// </summary>
/// <param name="presence"></param>
2008-05-26 00:47:36 +00:00
protected internal void AddScenePresence ( ScenePresence presence )
2008-03-04 05:31:54 +00:00
{
2011-01-26 21:33:34 +00:00
// Always a child when added to the scene
2008-03-04 05:31:54 +00:00
bool child = presence . IsChildAgent ;
2008-08-18 00:39:10 +00:00
2008-03-04 05:31:54 +00:00
if ( child )
{
m_numChildAgents + + ;
}
else
{
m_numRootAgents + + ;
2009-02-15 05:00:58 +00:00
presence . AddToPhysicalScene ( false ) ;
2008-03-04 05:31:54 +00:00
}
2008-11-24 15:09:25 +00:00
Entities [ presence . UUID ] = presence ;
2008-03-14 15:28:34 +00:00
2010-05-04 23:49:46 +00:00
lock ( m_presenceLock )
2008-03-04 05:31:54 +00:00
{
2010-05-04 23:49:46 +00:00
Dictionary < UUID , ScenePresence > newmap = new Dictionary < UUID , ScenePresence > ( m_scenePresenceMap ) ;
List < ScenePresence > newlist = new List < ScenePresence > ( m_scenePresenceArray ) ;
if ( ! newmap . ContainsKey ( presence . UUID ) )
2009-10-23 08:02:36 +00:00
{
2010-05-04 23:49:46 +00:00
newmap . Add ( presence . UUID , presence ) ;
newlist . Add ( presence ) ;
2009-10-23 08:02:36 +00:00
}
else
{
2010-05-04 23:49:46 +00:00
// Remember the old presene reference from the dictionary
ScenePresence oldref = newmap [ presence . UUID ] ;
// Replace the presence reference in the dictionary with the new value
newmap [ presence . UUID ] = presence ;
// Find the index in the list where the old ref was stored and update the reference
newlist [ newlist . IndexOf ( oldref ) ] = presence ;
2009-10-23 08:02:36 +00:00
}
2010-05-04 23:49:46 +00:00
// Swap out the dictionary and list with new references
m_scenePresenceMap = newmap ;
m_scenePresenceArray = newlist ;
2008-03-04 05:31:54 +00:00
}
2008-03-14 15:28:34 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-26 00:38:04 +00:00
/// <summary>
/// Remove a presence from the scene
/// </summary>
2008-09-06 07:52:41 +00:00
protected internal void RemoveScenePresence ( UUID agentID )
2008-05-26 00:38:04 +00:00
{
2008-11-24 15:09:25 +00:00
if ( ! Entities . Remove ( agentID ) )
2008-05-26 00:38:04 +00:00
{
2008-11-24 15:09:25 +00:00
m_log . WarnFormat (
2011-09-13 21:13:58 +00:00
"[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list" ,
2008-11-24 15:09:25 +00:00
agentID ) ;
2008-05-26 00:38:04 +00:00
}
2008-05-28 03:44:49 +00:00
2010-05-04 23:49:46 +00:00
lock ( m_presenceLock )
2008-05-28 03:44:49 +00:00
{
2010-05-04 23:49:46 +00:00
Dictionary < UUID , ScenePresence > newmap = new Dictionary < UUID , ScenePresence > ( m_scenePresenceMap ) ;
List < ScenePresence > newlist = new List < ScenePresence > ( m_scenePresenceArray ) ;
2010-06-25 17:55:20 +00:00
2010-05-04 23:49:46 +00:00
// Remove the presence reference from the dictionary
2010-06-25 17:55:20 +00:00
if ( newmap . ContainsKey ( agentID ) )
2009-10-23 08:02:36 +00:00
{
2010-06-25 17:55:20 +00:00
ScenePresence oldref = newmap [ agentID ] ;
newmap . Remove ( agentID ) ;
2010-05-04 23:49:46 +00:00
// Find the index in the list where the old ref was stored and remove the reference
newlist . RemoveAt ( newlist . IndexOf ( oldref ) ) ;
// Swap out the dictionary and list with new references
m_scenePresenceMap = newmap ;
m_scenePresenceArray = newlist ;
2009-10-23 08:02:36 +00:00
}
else
2008-05-26 00:38:04 +00:00
{
2011-09-13 21:13:58 +00:00
m_log . WarnFormat ( "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list" , agentID ) ;
2008-05-26 00:38:04 +00:00
}
2008-05-28 03:44:49 +00:00
}
2008-05-26 00:38:04 +00:00
}
2008-03-04 05:31:54 +00:00
2008-05-26 01:06:50 +00:00
protected internal void SwapRootChildAgent ( bool direction_RC_CR_T_F )
2007-12-12 06:58:55 +00:00
{
if ( direction_RC_CR_T_F )
{
m_numRootAgents - - ;
m_numChildAgents + + ;
}
else
{
m_numChildAgents - - ;
m_numRootAgents + + ;
}
}
2007-12-27 21:41:48 +00:00
2009-03-30 18:20:41 +00:00
public void removeUserCount ( bool TypeRCTF )
2007-12-12 06:58:55 +00:00
{
if ( TypeRCTF )
{
m_numRootAgents - - ;
}
2007-12-27 21:41:48 +00:00
else
2007-12-12 06:58:55 +00:00
{
m_numChildAgents - - ;
}
}
2007-12-27 21:41:48 +00:00
2009-01-06 00:07:24 +00:00
public void RecalculateStats ( )
{
int rootcount = 0 ;
int childcount = 0 ;
2010-03-17 13:40:00 +00:00
ForEachScenePresence ( delegate ( ScenePresence presence )
2009-01-06 00:07:24 +00:00
{
2010-03-17 13:40:00 +00:00
if ( presence . IsChildAgent )
2009-10-23 08:02:36 +00:00
+ + childcount ;
2009-01-06 00:07:24 +00:00
else
2009-10-23 08:02:36 +00:00
+ + rootcount ;
2010-03-17 13:40:00 +00:00
} ) ;
2009-10-23 08:02:36 +00:00
2009-01-06 00:07:24 +00:00
m_numRootAgents = rootcount ;
m_numChildAgents = childcount ;
}
2008-06-06 23:20:02 +00:00
public int GetChildAgentCount ( )
2007-12-12 06:58:55 +00:00
{
2008-02-07 08:28:48 +00:00
// some network situations come in where child agents get closed twice.
if ( m_numChildAgents < 0 )
2008-02-16 13:01:42 +00:00
{
m_numChildAgents = 0 ;
2008-02-07 08:28:48 +00:00
}
2007-12-12 06:58:55 +00:00
return m_numChildAgents ;
}
2008-06-06 23:20:02 +00:00
public int GetRootAgentCount ( )
2007-12-12 06:58:55 +00:00
{
return m_numRootAgents ;
}
2007-12-12 14:07:26 +00:00
2008-06-06 23:20:02 +00:00
public int GetTotalObjectsCount ( )
2007-12-12 14:07:26 +00:00
{
return m_numPrim ;
}
2008-06-06 23:20:02 +00:00
public int GetActiveObjectsCount ( )
2007-12-14 00:49:40 +00:00
{
return m_physicalPrim ;
}
2008-06-06 23:20:02 +00:00
public int GetActiveScriptsCount ( )
2008-02-06 08:03:22 +00:00
{
return m_activeScripts ;
}
2008-06-06 23:20:02 +00:00
public int GetScriptLPS ( )
2008-02-06 08:03:22 +00:00
{
int returnval = m_scriptLPS ;
m_scriptLPS = 0 ;
return returnval ;
}
2008-05-28 03:44:49 +00:00
2007-11-04 22:22:53 +00:00
# endregion
#region Get Methods
2012-03-16 00:34:30 +00:00
2008-04-14 18:43:23 +00:00
/// <summary>
/// Get the controlling client for the given avatar, if there is one.
2008-05-16 01:22:11 +00:00
///
/// FIXME: The only user of the method right now is Caps.cs, in order to resolve a client API since it can't
2008-04-14 18:43:23 +00:00
/// use the ScenePresence. This could be better solved in a number of ways - we could establish an
2008-05-16 01:22:11 +00:00
/// OpenSim.Framework.IScenePresence, or move the caps code into a region package (which might be the more
2008-04-14 18:43:23 +00:00
/// suitable solution).
/// </summary>
/// <param name="agentId"></param>
2009-02-06 16:55:34 +00:00
/// <returns>null if either the avatar wasn't in the scene, or
/// they do not have a controlling client</returns>
/// <remarks>this used to be protected internal, but that
/// prevents CapabilitiesModule from accessing it</remarks>
public IClientAPI GetControllingClient ( UUID agentId )
2008-04-14 18:43:23 +00:00
{
ScenePresence presence = GetScenePresence ( agentId ) ;
2008-05-16 01:22:11 +00:00
2008-04-14 18:43:23 +00:00
if ( presence ! = null )
{
return presence . ControllingClient ;
}
2008-05-16 01:22:11 +00:00
2008-04-14 18:43:23 +00:00
return null ;
}
2007-11-04 14:34:45 +00:00
2010-03-17 13:40:00 +00:00
/// <summary>
2010-05-04 23:49:46 +00:00
/// Get a reference to the scene presence list. Changes to the list will be done in a copy
2010-03-19 12:51:16 +00:00
/// There is no guarantee that presences will remain in the scene after the list is returned.
/// This list should remain private to SceneGraph. Callers wishing to iterate should instead
/// pass a delegate to ForEachScenePresence.
2010-03-17 13:40:00 +00:00
/// </summary>
/// <returns></returns>
2010-03-19 12:51:16 +00:00
private List < ScenePresence > GetScenePresences ( )
2010-03-17 13:40:00 +00:00
{
2010-05-04 23:49:46 +00:00
return m_scenePresenceArray ;
2010-03-17 13:40:00 +00:00
}
2011-04-21 22:03:38 +00:00
public int GetNumberOfScenePresences ( )
{
return m_scenePresenceArray . Count ;
}
2010-03-17 13:40:00 +00:00
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request a scene presence by UUID. Fast, indexed lookup.
2010-03-17 13:40:00 +00:00
/// </summary>
2010-03-19 12:51:16 +00:00
/// <param name="agentID"></param>
/// <returns>null if the presence was not found</returns>
protected internal ScenePresence GetScenePresence ( UUID agentID )
2010-03-17 13:40:00 +00:00
{
2010-05-04 23:49:46 +00:00
Dictionary < UUID , ScenePresence > presences = m_scenePresenceMap ;
ScenePresence presence ;
presences . TryGetValue ( agentID , out presence ) ;
return presence ;
2010-03-17 13:40:00 +00:00
}
2007-11-04 14:34:45 +00:00
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request the scene presence by name.
2007-11-04 14:34:45 +00:00
/// </summary>
2010-03-19 12:51:16 +00:00
/// <param name="firstName"></param>
/// <param name="lastName"></param>
/// <returns>null if the presence was not found</returns>
protected internal ScenePresence GetScenePresence ( string firstName , string lastName )
2007-11-04 14:34:45 +00:00
{
2010-05-04 23:49:46 +00:00
List < ScenePresence > presences = GetScenePresences ( ) ;
foreach ( ScenePresence presence in presences )
2010-03-17 13:40:00 +00:00
{
2010-03-19 12:51:16 +00:00
if ( presence . Firstname = = firstName & & presence . Lastname = = lastName )
return presence ;
}
return null ;
2010-03-17 13:40:00 +00:00
}
2007-11-04 14:34:45 +00:00
2010-03-17 13:40:00 +00:00
/// <summary>
2010-03-19 12:51:16 +00:00
/// Request the scene presence by localID.
2010-03-17 13:40:00 +00:00
/// </summary>
2010-03-19 12:51:16 +00:00
/// <param name="localID"></param>
/// <returns>null if the presence was not found</returns>
protected internal ScenePresence GetScenePresence ( uint localID )
2010-03-17 13:40:00 +00:00
{
2010-05-04 23:49:46 +00:00
List < ScenePresence > presences = GetScenePresences ( ) ;
foreach ( ScenePresence presence in presences )
2010-03-19 12:51:16 +00:00
if ( presence . LocalId = = localID )
return presence ;
return null ;
2007-11-04 14:34:45 +00:00
}
2010-03-19 12:58:34 +00:00
protected internal bool TryGetScenePresence ( UUID agentID , out ScenePresence avatar )
2010-03-17 13:40:00 +00:00
{
2010-05-04 23:49:46 +00:00
Dictionary < UUID , ScenePresence > presences = m_scenePresenceMap ;
presences . TryGetValue ( agentID , out avatar ) ;
2010-03-19 12:51:16 +00:00
return ( avatar ! = null ) ;
2007-11-04 14:34:45 +00:00
}
2010-03-19 12:51:16 +00:00
protected internal bool TryGetAvatarByName ( string name , out ScenePresence avatar )
2010-03-17 13:40:00 +00:00
{
2010-03-19 12:51:16 +00:00
avatar = null ;
foreach ( ScenePresence presence in GetScenePresences ( ) )
2010-03-17 13:40:00 +00:00
{
2010-03-19 12:51:16 +00:00
if ( String . Compare ( name , presence . ControllingClient . Name , true ) = = 0 )
{
avatar = presence ;
break ;
}
}
return ( avatar ! = null ) ;
2010-03-17 13:40:00 +00:00
}
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a scene object group that contains the prim with the given local id
/// </summary>
/// <param name="localID"></param>
/// <returns>null if no scene object group containing that prim is found</returns>
2009-10-18 01:01:22 +00:00
public SceneObjectGroup GetGroupByPrim ( uint localID )
2007-11-04 14:34:45 +00:00
{
2010-09-10 19:04:12 +00:00
EntityBase entity ;
if ( Entities . TryGetValue ( localID , out entity ) )
return entity as SceneObjectGroup ;
2009-04-09 10:07:40 +00:00
2011-09-13 19:25:32 +00:00
// m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID);
2009-04-12 15:18:04 +00:00
SceneObjectGroup sog ;
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByLocalPartID )
SceneObjectGroupsByLocalPartID . TryGetValue ( localID , out sog ) ;
2010-09-10 19:41:36 +00:00
if ( sog ! = null )
2009-04-12 15:18:04 +00:00
{
2012-03-31 00:45:37 +00:00
if ( sog . ContainsPart ( localID ) )
2011-09-13 19:25:32 +00:00
{
// m_log.DebugFormat(
// "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.",
// sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
2010-09-10 19:41:36 +00:00
return sog ;
2011-09-13 19:25:32 +00:00
}
else
{
lock ( SceneObjectGroupsByLocalPartID )
{
m_log . WarnFormat (
"[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}." ,
sog . Name , sog . UUID , sog . LocalId , localID , m_parentScene . RegionInfo . RegionName ) ;
SceneObjectGroupsByLocalPartID . Remove ( localID ) ;
}
}
2009-04-12 15:18:04 +00:00
}
2010-09-10 19:04:12 +00:00
EntityBase [ ] entityList = GetEntities ( ) ;
foreach ( EntityBase ent in entityList )
2007-11-04 14:34:45 +00:00
{
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Looking at entity {0}", ent.UUID);
2007-11-04 14:34:45 +00:00
if ( ent is SceneObjectGroup )
{
2010-09-10 19:04:12 +00:00
sog = ( SceneObjectGroup ) ent ;
2012-03-31 00:45:37 +00:00
if ( sog . ContainsPart ( localID ) )
2009-04-12 15:18:04 +00:00
{
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByLocalPartID )
SceneObjectGroupsByLocalPartID [ localID ] = sog ;
2009-04-12 15:18:04 +00:00
return sog ;
}
2007-11-04 14:34:45 +00:00
}
}
2010-09-10 19:04:12 +00:00
2007-11-04 14:34:45 +00:00
return null ;
}
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a scene object group that contains the prim with the given uuid
/// </summary>
/// <param name="fullID"></param>
2008-08-18 00:39:10 +00:00
/// <returns>null if no scene object group containing that prim is found</returns>
2012-01-19 10:53:21 +00:00
public SceneObjectGroup GetGroupByPrim ( UUID fullID )
2007-11-04 14:34:45 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup sog ;
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
SceneObjectGroupsByFullPartID . TryGetValue ( fullID , out sog ) ;
2010-09-10 19:41:36 +00:00
if ( sog ! = null )
2009-04-12 15:18:04 +00:00
{
2010-09-17 00:30:46 +00:00
if ( sog . ContainsPart ( fullID ) )
return sog ;
2010-09-10 19:41:36 +00:00
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
SceneObjectGroupsByFullPartID . Remove ( fullID ) ;
2009-04-12 15:18:04 +00:00
}
2010-09-10 19:04:12 +00:00
EntityBase [ ] entityList = GetEntities ( ) ;
foreach ( EntityBase ent in entityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2010-09-10 19:04:12 +00:00
sog = ( SceneObjectGroup ) ent ;
2012-03-31 00:45:37 +00:00
if ( sog . ContainsPart ( fullID ) )
2009-04-12 15:18:04 +00:00
{
2011-03-26 00:42:48 +00:00
lock ( SceneObjectGroupsByFullPartID )
SceneObjectGroupsByFullPartID [ fullID ] = sog ;
2009-04-12 15:18:04 +00:00
return sog ;
}
2007-11-04 14:34:45 +00:00
}
}
2010-09-10 19:04:12 +00:00
2007-11-04 14:34:45 +00:00
return null ;
}
2008-05-26 01:06:50 +00:00
protected internal EntityIntersection GetClosestIntersectingPrim ( Ray hray , bool frontFacesOnly , bool faceCenters )
2007-11-23 05:56:35 +00:00
{
// Primitive Ray Tracing
float closestDistance = 280f ;
2009-08-14 08:16:41 +00:00
EntityIntersection result = new EntityIntersection ( ) ;
2010-09-10 19:04:12 +00:00
EntityBase [ ] EntityList = GetEntities ( ) ;
2008-06-25 12:21:51 +00:00
foreach ( EntityBase ent in EntityList )
2007-11-23 05:56:35 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
SceneObjectGroup reportingG = ( SceneObjectGroup ) ent ;
2009-08-14 08:16:41 +00:00
EntityIntersection inter = reportingG . TestIntersection ( hray , frontFacesOnly , faceCenters ) ;
if ( inter . HitTF & & inter . distance < closestDistance )
2007-11-23 05:56:35 +00:00
{
2009-08-14 08:16:41 +00:00
closestDistance = inter . distance ;
result = inter ;
2007-11-23 05:56:35 +00:00
}
}
}
2009-08-14 08:16:41 +00:00
return result ;
2008-02-16 13:01:42 +00:00
}
2007-11-23 05:56:35 +00:00
2011-05-20 22:34:34 +00:00
/// <summary>
/// Get a group in the scene
/// </summary>
/// <param name="fullID">UUID of the group</param>
/// <returns>null if no such group was found</returns>
protected internal SceneObjectGroup GetSceneObjectGroup ( UUID fullID )
{
lock ( SceneObjectGroupsByFullID )
{
if ( SceneObjectGroupsByFullID . ContainsKey ( fullID ) )
return SceneObjectGroupsByFullID [ fullID ] ;
}
return null ;
}
2011-05-20 22:41:14 +00:00
/// <summary>
/// Get a group by name from the scene (will return the first
/// found, if there are more than one prim with the same name)
/// </summary>
/// <param name="name"></param>
/// <returns>null if the part was not found</returns>
protected internal SceneObjectGroup GetSceneObjectGroup ( string name )
{
SceneObjectGroup so = null ;
Entities . Find (
delegate ( EntityBase entity )
{
if ( entity is SceneObjectGroup )
{
if ( entity . Name = = name )
{
so = ( SceneObjectGroup ) entity ;
return true ;
}
}
return false ;
}
) ;
return so ;
}
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a part contained in this scene.
/// </summary>
/// <param name="localID"></param>
/// <returns>null if the part was not found</returns>
2008-05-26 01:06:50 +00:00
protected internal SceneObjectPart GetSceneObjectPart ( uint localID )
2007-11-07 02:42:18 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
2009-04-12 15:18:04 +00:00
if ( group = = null )
2007-11-07 02:42:18 +00:00
return null ;
2012-03-31 00:52:06 +00:00
return group . GetPart ( localID ) ;
2007-11-07 02:42:18 +00:00
}
2008-10-05 14:15:39 +00:00
2008-10-01 06:39:36 +00:00
/// <summary>
2011-05-20 22:41:14 +00:00
/// Get a prim by name from the scene (will return the first
2008-10-01 06:39:36 +00:00
/// found, if there are more than one prim with the same name)
/// </summary>
/// <param name="name"></param>
/// <returns>null if the part was not found</returns>
protected internal SceneObjectPart GetSceneObjectPart ( string name )
{
2010-09-10 19:04:12 +00:00
SceneObjectPart sop = null ;
2008-10-01 06:39:36 +00:00
2010-09-10 19:04:12 +00:00
Entities . Find (
delegate ( EntityBase entity )
2008-10-01 06:39:36 +00:00
{
2010-09-10 19:04:12 +00:00
if ( entity is SceneObjectGroup )
2008-10-05 14:15:39 +00:00
{
2010-09-17 00:30:46 +00:00
foreach ( SceneObjectPart p in ( ( SceneObjectGroup ) entity ) . Parts )
2008-10-05 14:15:39 +00:00
{
2011-04-13 20:17:43 +00:00
// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name);
2010-09-10 19:04:12 +00:00
if ( p . Name = = name )
{
sop = p ;
return true ;
}
2008-10-05 14:15:39 +00:00
}
}
2010-09-10 19:04:12 +00:00
return false ;
2008-10-01 06:39:36 +00:00
}
2010-09-10 19:04:12 +00:00
) ;
return sop ;
2008-10-01 06:39:36 +00:00
}
2007-11-07 02:42:18 +00:00
2008-07-12 21:43:35 +00:00
/// <summary>
/// Get a part contained in this scene.
/// </summary>
/// <param name="fullID"></param>
2008-08-18 00:39:10 +00:00
/// <returns>null if the part was not found</returns>
2008-09-06 07:52:41 +00:00
protected internal SceneObjectPart GetSceneObjectPart ( UUID fullID )
2007-11-07 02:42:18 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( fullID ) ;
2009-04-12 15:18:04 +00:00
if ( group = = null )
2007-11-07 02:42:18 +00:00
return null ;
2012-03-31 00:52:06 +00:00
return group . GetPart ( fullID ) ;
2007-11-07 02:42:18 +00:00
}
2008-05-24 21:57:00 +00:00
/// <summary>
2008-06-03 08:34:38 +00:00
/// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
/// it
2008-05-24 21:57:00 +00:00
/// </summary>
/// <returns></returns>
2010-09-10 19:04:12 +00:00
protected internal EntityBase [ ] GetEntities ( )
2007-12-17 16:41:28 +00:00
{
2008-11-24 14:45:05 +00:00
return Entities . GetEntities ( ) ;
2007-12-17 16:41:28 +00:00
}
2007-11-04 22:22:53 +00:00
# endregion
#region Other Methods
2008-05-26 01:06:50 +00:00
protected internal void physicsBasedCrash ( )
2007-11-28 06:18:07 +00:00
{
2008-03-02 22:28:48 +00:00
handlerPhysicsCrash = UnRecoverableError ;
if ( handlerPhysicsCrash ! = null )
2007-11-28 06:18:07 +00:00
{
2008-03-02 22:28:48 +00:00
handlerPhysicsCrash ( ) ;
2007-11-28 06:18:07 +00:00
}
}
2008-09-06 07:52:41 +00:00
protected internal UUID ConvertLocalIDToFullID ( uint localID )
2007-11-04 22:22:53 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
return group . GetPartsFullID ( localID ) ;
else
2008-09-06 07:52:41 +00:00
return UUID . Zero ;
2007-11-04 22:22:53 +00:00
}
2010-03-19 12:51:16 +00:00
/// <summary>
2011-03-26 00:53:19 +00:00
/// Performs action once on all scene object groups.
2010-03-19 12:51:16 +00:00
/// </summary>
/// <param name="action"></param>
2009-09-29 14:54:56 +00:00
protected internal void ForEachSOG ( Action < SceneObjectGroup > action )
{
2012-01-30 19:21:58 +00:00
List < SceneObjectGroup > objlist ;
lock ( SceneObjectGroupsByFullID )
objlist = new List < SceneObjectGroup > ( SceneObjectGroupsByFullID . Values ) ;
2009-09-29 14:54:56 +00:00
foreach ( SceneObjectGroup obj in objlist )
{
try
{
action ( obj ) ;
}
catch ( Exception e )
{
2012-01-30 19:21:58 +00:00
// Catch it and move on. This includes situations where objlist has inconsistent info
2011-03-22 23:47:36 +00:00
m_log . WarnFormat (
"[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}" , e . Message , e . StackTrace ) ;
2009-09-29 14:54:56 +00:00
}
}
}
2011-10-27 07:42:21 +00:00
/// <summary>
/// Performs action on all ROOT (not child) scene presences.
/// This is just a shortcut function since frequently actions only appy to root SPs
/// </summary>
/// <param name="action"></param>
2011-11-04 00:06:08 +00:00
public void ForEachAvatar ( Action < ScenePresence > action )
2011-10-27 07:42:21 +00:00
{
ForEachScenePresence ( delegate ( ScenePresence sp )
{
if ( ! sp . IsChildAgent )
action ( sp ) ;
} ) ;
}
2010-03-17 13:40:00 +00:00
/// <summary>
2010-03-19 12:51:16 +00:00
/// Performs action on all scene presences. This can ultimately run the actions in parallel but
/// any delegates passed in will need to implement their own locking on data they reference and
/// modify outside of the scope of the delegate.
2010-03-17 13:40:00 +00:00
/// </summary>
/// <param name="action"></param>
public void ForEachScenePresence ( Action < ScenePresence > action )
{
2010-03-19 12:51:16 +00:00
// Once all callers have their delegates configured for parallelism, we can unleash this
/ *
Action < ScenePresence > protectedAction = new Action < ScenePresence > ( delegate ( ScenePresence sp )
{
try
{
action ( sp ) ;
}
catch ( Exception e )
{
2011-03-22 23:47:36 +00:00
m_log . Info ( "[SCENEGRAPH]: Error in " + m_parentScene . RegionInfo . RegionName + ": " + e . ToString ( ) ) ;
m_log . Info ( "[SCENEGRAPH]: Stack Trace: " + e . StackTrace ) ;
2010-03-19 12:51:16 +00:00
}
} ) ;
Parallel . ForEach < ScenePresence > ( GetScenePresences ( ) , protectedAction ) ;
* /
2010-05-04 23:49:46 +00:00
// For now, perform actions serially
List < ScenePresence > presences = GetScenePresences ( ) ;
foreach ( ScenePresence sp in presences )
2010-03-17 13:40:00 +00:00
{
2010-03-19 12:51:16 +00:00
try
2010-03-17 13:40:00 +00:00
{
2010-03-19 12:51:16 +00:00
action ( sp ) ;
}
catch ( Exception e )
{
2011-03-22 23:47:36 +00:00
m_log . Error ( "[SCENEGRAPH]: Error in " + m_parentScene . RegionInfo . RegionName + ": " + e . ToString ( ) ) ;
2010-03-17 13:40:00 +00:00
}
}
}
2009-09-29 14:54:56 +00:00
2007-11-04 22:22:53 +00:00
# endregion
2007-11-04 14:34:45 +00:00
#region Client Event handlers
2007-12-27 21:41:48 +00:00
2007-11-04 14:34:45 +00:00
/// <summary>
2011-07-16 02:52:30 +00:00
/// Update the scale of an individual prim.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="scale"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimScale ( uint localID , Vector3 scale , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2011-07-16 03:22:57 +00:00
SceneObjectPart part = GetSceneObjectPart ( localID ) ;
if ( part ! = null )
2007-12-07 07:42:03 +00:00
{
2011-07-16 03:22:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( part . ParentGroup . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2011-07-16 03:22:57 +00:00
part . Resize ( scale ) ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2008-05-28 03:44:49 +00:00
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimGroupScale ( uint localID , Vector3 scale , IClientAPI remoteClient )
2008-04-19 21:01:26 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-04-19 21:01:26 +00:00
{
2011-07-16 01:53:36 +00:00
group . GroupResize ( scale ) ;
2008-04-19 21:01:26 +00:00
}
}
}
2007-11-04 14:34:45 +00:00
2007-11-15 07:32:24 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// This handles the nifty little tool tip that you get when you drag your mouse over an object
2007-11-15 07:32:24 +00:00
/// Send to the Object Group to process. We don't know enough to service the request
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="AgentID"></param>
/// <param name="RequestFlags"></param>
/// <param name="ObjectID"></param>
2008-05-26 01:06:50 +00:00
protected internal void RequestObjectPropertiesFamily (
2008-09-06 07:52:41 +00:00
IClientAPI remoteClient , UUID AgentID , uint RequestFlags , UUID ObjectID )
2007-11-15 07:32:24 +00:00
{
SceneObjectGroup group = GetGroupByPrim ( ObjectID ) ;
if ( group ! = null )
2008-02-12 11:21:23 +00:00
{
2007-11-15 07:32:24 +00:00
group . ServiceObjectPropertiesFamilyRequest ( remoteClient , AgentID , RequestFlags ) ;
2008-02-12 11:21:23 +00:00
}
2007-11-15 07:32:24 +00:00
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimSingleRotation ( uint localID , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateSingleRotation ( rot , localID ) ;
}
}
2007-11-04 14:34:45 +00:00
}
2009-07-17 14:58:54 +00:00
/// <summary>
///
/// </summary>
/// <param name="localID"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
protected internal void UpdatePrimSingleRotationPosition ( uint localID , Quaternion rot , Vector3 pos , IClientAPI remoteClient )
{
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
{
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
{
2011-07-19 02:27:16 +00:00
group . UpdateSingleRotation ( rot , pos , localID ) ;
2009-07-17 14:58:54 +00:00
}
}
}
2007-11-04 14:34:45 +00:00
/// <summary>
2011-07-19 02:44:49 +00:00
/// Update the rotation of a whole group.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2011-07-19 02:44:49 +00:00
protected internal void UpdatePrimGroupRotation ( uint localID , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2009-09-30 16:51:02 +00:00
group . UpdateGroupRotationR ( rot ) ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="rot"></param>
/// <param name="remoteClient"></param>
2011-07-19 02:44:49 +00:00
protected internal void UpdatePrimGroupRotation ( uint localID , Vector3 pos , Quaternion rot , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2009-09-30 16:51:02 +00:00
group . UpdateGroupRotationPR ( pos , rot ) ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2008-06-27 14:39:21 +00:00
/// <summary>
/// Update the position of the given part
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimSinglePosition ( uint localID , Vector3 pos , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) | | group . IsAttachment )
2007-12-07 07:42:03 +00:00
{
group . UpdateSinglePosition ( pos , localID ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2011-07-19 04:20:04 +00:00
/// Update the position of the given group.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2011-07-19 04:20:04 +00:00
public void UpdatePrimGroupPosition ( uint localID , Vector3 pos , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
2010-08-26 20:50:19 +00:00
2007-11-07 02:42:18 +00:00
if ( group ! = null )
2010-09-12 17:43:49 +00:00
{
2008-11-22 16:09:58 +00:00
if ( group . IsAttachment | | ( group . RootPart . Shape . PCode = = 9 & & group . RootPart . Shape . State ! = 0 ) )
2008-04-23 13:22:06 +00:00
{
2010-12-14 00:11:41 +00:00
if ( m_parentScene . AttachmentsModule ! = null )
m_parentScene . AttachmentsModule . UpdateAttachmentPosition ( group , pos ) ;
2008-04-23 13:22:06 +00:00
}
2008-05-16 01:22:11 +00:00
else
2007-12-07 07:42:03 +00:00
{
2010-08-26 20:50:19 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId )
& & m_parentScene . Permissions . CanObjectEntry ( group . UUID , false , pos ) )
2008-04-24 11:32:41 +00:00
{
group . UpdateGroupPosition ( pos ) ;
}
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2010-08-26 20:50:19 +00:00
/// Update the texture entry of the given prim.
2007-11-04 14:34:45 +00:00
/// </summary>
2012-01-30 19:21:58 +00:00
/// <remarks>
2010-08-26 20:50:19 +00:00
/// A texture entry is an object that contains details of all the textures of the prim's face. In this case,
/// the texture is given in its byte serialized form.
2012-01-30 19:21:58 +00:00
/// </remarks>
2007-11-04 14:34:45 +00:00
/// <param name="localID"></param>
/// <param name="texture"></param>
/// <param name="remoteClient"></param>
2008-05-26 01:06:50 +00:00
protected internal void UpdatePrimTexture ( uint localID , byte [ ] texture , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
2010-08-26 20:50:19 +00:00
2007-11-07 02:42:18 +00:00
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
group . UpdateTextureEntry ( localID , texture ) ;
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2011-07-11 01:29:19 +00:00
/// Update the flags on a scene object. This covers properties such as phantom, physics and temporary.
2007-11-04 14:34:45 +00:00
/// </summary>
2011-07-11 01:29:19 +00:00
/// <remarks>
/// This is currently handling the incoming call from the client stack (e.g. LLClientView).
/// </remarks>
2007-11-04 14:34:45 +00:00
/// <param name="localID"></param>
2011-07-11 01:29:19 +00:00
/// <param name="UsePhysics"></param>
/// <param name="SetTemporary"></param>
/// <param name="SetPhantom"></param>
2007-11-04 14:34:45 +00:00
/// <param name="remoteClient"></param>
2011-07-11 01:29:19 +00:00
protected internal void UpdatePrimFlags (
uint localID , bool UsePhysics , bool SetTemporary , bool SetPhantom , IClientAPI remoteClient )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( localID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2011-07-11 01:29:19 +00:00
// VolumeDetect can't be set via UI and will always be off when a change is made there
group . UpdatePrimFlags ( localID , UsePhysics , SetTemporary , SetPhantom , false ) ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2008-06-27 14:39:21 +00:00
/// <summary>
/// Move the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="offset"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-10-10 16:01:59 +00:00
protected internal void MoveObject ( UUID objectID , Vector3 offset , Vector3 pos , IClientAPI remoteClient , List < SurfaceTouchEventArgs > surfaceArgs )
2007-11-04 14:34:45 +00:00
{
2007-12-07 07:42:03 +00:00
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
2007-11-04 14:34:45 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
2007-12-07 07:42:03 +00:00
{
2007-11-07 02:42:18 +00:00
group . GrabMovement ( offset , pos , remoteClient ) ;
2007-12-07 07:42:03 +00:00
}
2008-02-12 15:47:37 +00:00
// This is outside the above permissions condition
// so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world.
2008-02-10 21:27:32 +00:00
group . SendGroupTerseUpdate ( ) ;
2007-11-04 14:34:45 +00:00
}
}
2009-04-10 06:39:52 +00:00
/// <summary>
/// Start spinning the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="rotation"></param>
/// <param name="remoteClient"></param>
protected internal void SpinStart ( UUID objectID , IClientAPI remoteClient )
{
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
{
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
{
group . SpinStart ( remoteClient ) ;
}
}
}
/// <summary>
/// Spin the given object
/// </summary>
/// <param name="objectID"></param>
/// <param name="rotation"></param>
/// <param name="remoteClient"></param>
protected internal void SpinObject ( UUID objectID , Quaternion rotation , IClientAPI remoteClient )
{
SceneObjectGroup group = GetGroupByPrim ( objectID ) ;
if ( group ! = null )
{
if ( m_parentScene . Permissions . CanMoveObject ( group . UUID , remoteClient . AgentId ) ) // && PermissionsMngr.)
{
group . SpinMovement ( rotation , remoteClient ) ;
}
// This is outside the above permissions condition
// so that if the object is locked the client moving the object
// get's it's position on the simulator even if it was the same as before
// This keeps the moving user's client in sync with the rest of the world.
group . SendGroupTerseUpdate ( ) ;
}
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="description"></param>
2008-05-26 01:06:50 +00:00
protected internal void PrimName ( IClientAPI remoteClient , uint primLocalID , string name )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2007-12-28 23:19:03 +00:00
group . SetPartName ( Util . CleanString ( name ) , primLocalID ) ;
2008-08-15 16:51:26 +00:00
group . HasGroupChanged = true ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2011-06-10 01:27:45 +00:00
/// Handle a prim description set request from a viewer.
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="description"></param>
2008-05-26 01:06:50 +00:00
protected internal void PrimDescription ( IClientAPI remoteClient , uint primLocalID , string description )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
2007-12-07 07:42:03 +00:00
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2007-12-07 07:42:03 +00:00
{
2007-12-28 23:19:03 +00:00
group . SetPartDescription ( Util . CleanString ( description ) , primLocalID ) ;
2008-08-15 16:51:26 +00:00
group . HasGroupChanged = true ;
2007-12-07 07:42:03 +00:00
}
}
2007-11-04 14:34:45 +00:00
}
2011-06-10 01:27:45 +00:00
/// <summary>
/// Set a click action for the prim.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="primLocalID"></param>
/// <param name="clickAction"></param>
2008-09-12 20:42:04 +00:00
protected internal void PrimClickAction ( IClientAPI remoteClient , uint primLocalID , string clickAction )
{
2011-06-10 01:27:45 +00:00
// m_log.DebugFormat(
// "[SCENEGRAPH]: User {0} set click action for {1} to {2}", remoteClient.Name, primLocalID, clickAction);
2008-09-12 20:42:04 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-09-12 20:42:04 +00:00
{
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primLocalID ) ;
2011-08-27 03:16:46 +00:00
if ( part ! = null )
{
part . ClickAction = Convert . ToByte ( clickAction ) ;
group . HasGroupChanged = true ;
}
2008-09-12 20:42:04 +00:00
}
}
}
2008-10-03 12:00:13 +00:00
protected internal void PrimMaterial ( IClientAPI remoteClient , uint primLocalID , string material )
{
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
if ( group ! = null )
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , remoteClient . AgentId ) )
2008-10-03 12:00:13 +00:00
{
SceneObjectPart part = m_parentScene . GetSceneObjectPart ( primLocalID ) ;
2011-08-27 03:16:46 +00:00
if ( part ! = null )
{
part . Material = Convert . ToByte ( material ) ;
group . HasGroupChanged = true ;
}
2008-10-03 12:00:13 +00:00
}
}
}
2008-09-12 20:42:04 +00:00
2008-09-06 07:52:41 +00:00
protected internal void UpdateExtraParam ( UUID agentID , uint primLocalID , ushort type , bool inUse , byte [ ] data )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
2007-12-27 21:41:48 +00:00
2007-12-07 07:42:03 +00:00
if ( group ! = null )
2007-11-29 15:24:31 +00:00
{
2012-02-18 01:15:43 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , agentID ) )
2007-12-07 07:42:03 +00:00
{
2007-11-29 15:24:31 +00:00
group . UpdateExtraParam ( primLocalID , type , inUse , data ) ;
2007-12-07 07:42:03 +00:00
}
2007-11-29 15:24:31 +00:00
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="primLocalID"></param>
/// <param name="shapeBlock"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimShape ( UUID agentID , uint primLocalID , UpdateShapeArgs shapeBlock )
2007-11-04 14:34:45 +00:00
{
2007-11-07 02:42:18 +00:00
SceneObjectGroup group = GetGroupByPrim ( primLocalID ) ;
2007-12-07 07:42:03 +00:00
if ( group ! = null )
2007-11-29 15:24:31 +00:00
{
2012-02-18 01:15:43 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . UUID , agentID ) )
2007-12-07 07:42:03 +00:00
{
2008-05-07 20:31:48 +00:00
ObjectShapePacket . ObjectDataBlock shapeData = new ObjectShapePacket . ObjectDataBlock ( ) ;
shapeData . ObjectLocalID = shapeBlock . ObjectLocalID ;
shapeData . PathBegin = shapeBlock . PathBegin ;
shapeData . PathCurve = shapeBlock . PathCurve ;
shapeData . PathEnd = shapeBlock . PathEnd ;
shapeData . PathRadiusOffset = shapeBlock . PathRadiusOffset ;
shapeData . PathRevolutions = shapeBlock . PathRevolutions ;
shapeData . PathScaleX = shapeBlock . PathScaleX ;
shapeData . PathScaleY = shapeBlock . PathScaleY ;
shapeData . PathShearX = shapeBlock . PathShearX ;
shapeData . PathShearY = shapeBlock . PathShearY ;
shapeData . PathSkew = shapeBlock . PathSkew ;
shapeData . PathTaperX = shapeBlock . PathTaperX ;
shapeData . PathTaperY = shapeBlock . PathTaperY ;
shapeData . PathTwist = shapeBlock . PathTwist ;
shapeData . PathTwistBegin = shapeBlock . PathTwistBegin ;
shapeData . ProfileBegin = shapeBlock . ProfileBegin ;
shapeData . ProfileCurve = shapeBlock . ProfileCurve ;
shapeData . ProfileEnd = shapeBlock . ProfileEnd ;
shapeData . ProfileHollow = shapeBlock . ProfileHollow ;
group . UpdateShape ( shapeData , primLocalID ) ;
2007-12-07 07:42:03 +00:00
}
2007-11-29 15:24:31 +00:00
}
2007-11-04 14:34:45 +00:00
}
/// <summary>
2008-04-03 13:33:46 +00:00
/// Initial method invoked when we receive a link objects request from the client.
2007-11-04 14:34:45 +00:00
/// </summary>
2008-04-03 13:33:46 +00:00
/// <param name="client"></param>
2007-11-04 14:34:45 +00:00
/// <param name="parentPrim"></param>
/// <param name="childPrims"></param>
2010-04-30 10:46:50 +00:00
protected internal void LinkObjects ( SceneObjectPart root , List < SceneObjectPart > children )
2007-11-04 14:34:45 +00:00
{
2011-11-11 00:28:12 +00:00
SceneObjectGroup parentGroup = root . ParentGroup ;
if ( parentGroup = = null ) return ;
// Cowardly refuse to link to a group owned root
if ( parentGroup . OwnerID = = parentGroup . GroupID )
return ;
2009-12-06 01:20:39 +00:00
Monitor . Enter ( m_updateLock ) ;
try
2007-11-04 14:34:45 +00:00
{
2009-12-06 00:25:04 +00:00
List < SceneObjectGroup > childGroups = new List < SceneObjectGroup > ( ) ;
2010-04-30 10:46:50 +00:00
2011-09-01 00:22:28 +00:00
// We do this in reverse to get the link order of the prims correct
2011-11-05 00:09:37 +00:00
for ( int i = 0 ; i < children . Count ; i + + )
2009-12-06 00:25:04 +00:00
{
2011-09-01 00:22:28 +00:00
SceneObjectGroup child = children [ i ] . ParentGroup ;
2012-02-08 21:58:59 +00:00
// Don't try and add a group to itself - this will only cause severe problems later on.
if ( child = = parentGroup )
continue ;
2011-09-01 00:22:28 +00:00
// Make sure no child prim is set for sale
// So that, on delink, no prims are unwittingly
// left for sale and sold off
child . RootPart . ObjectSaleType = 0 ;
child . RootPart . SalePrice = 10 ;
childGroups . Add ( child ) ;
2009-12-06 00:25:04 +00:00
}
2007-11-04 14:34:45 +00:00
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectGroup child in childGroups )
{
2011-11-11 00:28:12 +00:00
if ( parentGroup . OwnerID = = child . OwnerID )
{
parentGroup . LinkToGroup ( child ) ;
2008-12-07 04:03:09 +00:00
2011-11-11 00:28:12 +00:00
// this is here so physics gets updated!
// Don't remove! Bad juju! Stay away! or fix physics!
child . AbsolutePosition = child . AbsolutePosition ;
}
2009-12-06 00:25:04 +00:00
}
2008-05-16 01:22:11 +00:00
2009-12-06 00:25:04 +00:00
// We need to explicitly resend the newly link prim's object properties since no other actions
// occur on link to invoke this elsewhere (such as object selection)
2012-02-08 21:58:59 +00:00
if ( childGroups . Count > 0 )
{
parentGroup . RootPart . CreateSelected = true ;
parentGroup . TriggerScriptChangedEvent ( Changed . LINK ) ;
parentGroup . HasGroupChanged = true ;
parentGroup . ScheduleGroupForFullUpdate ( ) ;
}
2008-07-19 04:05:34 +00:00
}
2009-12-06 01:20:39 +00:00
finally
{
Monitor . Exit ( m_updateLock ) ;
}
2007-11-04 14:34:45 +00:00
}
2007-11-18 11:11:44 +00:00
2007-11-13 19:57:11 +00:00
/// <summary>
/// Delink a linkset
/// </summary>
2008-05-16 01:22:11 +00:00
/// <param name="prims"></param>
2010-04-30 10:46:50 +00:00
protected internal void DelinkObjects ( List < SceneObjectPart > prims )
2007-11-13 19:57:11 +00:00
{
2009-12-06 01:20:39 +00:00
Monitor . Enter ( m_updateLock ) ;
try
2007-11-18 11:11:44 +00:00
{
2009-12-06 00:25:04 +00:00
List < SceneObjectPart > childParts = new List < SceneObjectPart > ( ) ;
List < SceneObjectPart > rootParts = new List < SceneObjectPart > ( ) ;
List < SceneObjectGroup > affectedGroups = new List < SceneObjectGroup > ( ) ;
// Look them all up in one go, since that is comparatively expensive
/ /
2010-04-30 10:46:50 +00:00
foreach ( SceneObjectPart part in prims )
2007-11-13 19:57:11 +00:00
{
2009-12-06 00:25:04 +00:00
if ( part ! = null )
{
2010-08-25 23:08:53 +00:00
if ( part . ParentGroup . PrimCount ! = 1 ) // Skip single
2009-12-06 02:00:32 +00:00
{
if ( part . LinkNum < 2 ) // Root
2011-11-11 00:28:12 +00:00
{
2009-12-06 02:00:32 +00:00
rootParts . Add ( part ) ;
2011-11-11 00:28:12 +00:00
}
2009-12-06 02:00:32 +00:00
else
2011-11-11 00:28:12 +00:00
{
part . LastOwnerID = part . ParentGroup . RootPart . LastOwnerID ;
2009-12-06 02:00:32 +00:00
childParts . Add ( part ) ;
2011-11-11 00:28:12 +00:00
}
2009-12-06 02:00:32 +00:00
SceneObjectGroup group = part . ParentGroup ;
if ( ! affectedGroups . Contains ( group ) )
affectedGroups . Add ( group ) ;
}
2009-12-06 00:25:04 +00:00
}
2009-04-29 15:54:16 +00:00
}
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectPart child in childParts )
2009-04-29 15:54:16 +00:00
{
2009-12-06 00:25:04 +00:00
// Unlink all child parts from their groups
/ /
2010-04-30 10:46:50 +00:00
child . ParentGroup . DelinkFromGroup ( child , true ) ;
2010-09-07 10:48:28 +00:00
// These are not in affected groups and will not be
// handled further. Do the honors here.
child . ParentGroup . HasGroupChanged = true ;
child . ParentGroup . ScheduleGroupForFullUpdate ( ) ;
2007-11-18 11:11:44 +00:00
}
2007-11-13 19:57:11 +00:00
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectPart root in rootParts )
2008-07-19 04:05:34 +00:00
{
2009-12-06 00:25:04 +00:00
// In most cases, this will run only one time, and the prim
// will be a solo prim
// However, editing linked parts and unlinking may be different
2008-07-19 04:05:34 +00:00
/ /
2009-12-06 00:25:04 +00:00
SceneObjectGroup group = root . ParentGroup ;
2010-08-25 23:08:53 +00:00
2010-09-17 00:30:46 +00:00
List < SceneObjectPart > newSet = new List < SceneObjectPart > ( group . Parts ) ;
int numChildren = newSet . Count ;
2008-07-19 04:05:34 +00:00
2009-12-06 00:25:04 +00:00
// If there are prims left in a link set, but the root is
// slated for unlink, we need to do this
2008-07-19 04:05:34 +00:00
/ /
2009-12-06 00:25:04 +00:00
if ( numChildren ! = 1 )
2008-07-19 04:05:34 +00:00
{
2009-12-06 00:25:04 +00:00
// Unlink the remaining set
2009-04-29 15:54:16 +00:00
/ /
2009-12-06 00:25:04 +00:00
bool sendEventsToRemainder = true ;
if ( numChildren > 1 )
sendEventsToRemainder = false ;
2009-04-29 15:54:16 +00:00
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectPart p in newSet )
2009-04-29 15:54:16 +00:00
{
2009-12-06 00:25:04 +00:00
if ( p ! = group . RootPart )
group . DelinkFromGroup ( p , sendEventsToRemainder ) ;
}
2008-07-19 04:05:34 +00:00
2009-12-06 00:25:04 +00:00
// If there is more than one prim remaining, we
// need to re-link
2009-04-29 15:54:16 +00:00
/ /
2009-12-06 00:25:04 +00:00
if ( numChildren > 2 )
{
// Remove old root
/ /
if ( newSet . Contains ( root ) )
newSet . Remove ( root ) ;
// Preserve link ordering
/ /
newSet . Sort ( delegate ( SceneObjectPart a , SceneObjectPart b )
{
return a . LinkNum . CompareTo ( b . LinkNum ) ;
} ) ;
2008-07-19 04:05:34 +00:00
2009-12-06 00:25:04 +00:00
// Determine new root
/ /
SceneObjectPart newRoot = newSet [ 0 ] ;
newSet . RemoveAt ( 0 ) ;
2008-07-19 04:05:34 +00:00
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectPart newChild in newSet )
2011-11-02 21:59:00 +00:00
newChild . ClearUpdateSchedule ( ) ;
2008-07-19 04:05:34 +00:00
2010-04-30 10:46:50 +00:00
LinkObjects ( newRoot , newSet ) ;
2009-12-06 00:25:04 +00:00
if ( ! affectedGroups . Contains ( newRoot . ParentGroup ) )
affectedGroups . Add ( newRoot . ParentGroup ) ;
}
2008-07-19 04:05:34 +00:00
}
2007-11-18 11:11:44 +00:00
}
2008-07-19 04:05:34 +00:00
2009-12-06 00:25:04 +00:00
// Finally, trigger events in the roots
/ /
foreach ( SceneObjectGroup g in affectedGroups )
{
g . TriggerScriptChangedEvent ( Changed . LINK ) ;
g . HasGroupChanged = true ; // Persist
g . ScheduleGroupForFullUpdate ( ) ;
}
2007-11-13 19:57:11 +00:00
}
2009-12-06 01:20:39 +00:00
finally
{
Monitor . Exit ( m_updateLock ) ;
}
2007-11-13 19:57:11 +00:00
}
2007-11-04 14:34:45 +00:00
2008-05-26 01:06:50 +00:00
protected internal void MakeObjectSearchable ( IClientAPI remoteClient , bool IncludeInSearch , uint localID )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
UUID user = remoteClient . AgentId ;
2008-09-26 17:25:22 +00:00
UUID objid = UUID . Zero ;
2008-04-16 03:55:21 +00:00
SceneObjectPart obj = null ;
2010-09-10 19:04:12 +00:00
EntityBase [ ] entityList = GetEntities ( ) ;
foreach ( EntityBase ent in entityList )
2008-04-16 03:55:21 +00:00
{
if ( ent is SceneObjectGroup )
{
2010-08-25 23:08:53 +00:00
SceneObjectGroup sog = ent as SceneObjectGroup ;
2010-09-17 00:30:46 +00:00
foreach ( SceneObjectPart part in sog . Parts )
2008-04-16 03:55:21 +00:00
{
2010-09-17 00:30:46 +00:00
if ( part . LocalId = = localID )
2008-04-16 03:55:21 +00:00
{
2010-09-17 00:30:46 +00:00
objid = part . UUID ;
obj = part ;
2008-04-16 03:55:21 +00:00
}
}
}
}
2008-05-16 01:22:11 +00:00
2008-04-16 03:55:21 +00:00
//Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
//aka ObjectFlags.JointWheel = IncludeInSearch
//Permissions model: Object can be REMOVED from search IFF:
// * User owns object
//use CanEditObject
//Object can be ADDED to search IFF:
// * User owns object
// * Asset/DRM permission bit "modify" is enabled
//use CanEditObjectPosition
2008-09-08 10:28:59 +00:00
// libomv will complain about PrimFlags.JointWheel being
// deprecated, so we
#pragma warning disable 0612
2008-11-21 22:14:57 +00:00
if ( IncludeInSearch & & m_parentScene . Permissions . CanEditObject ( objid , user ) )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
obj . ParentGroup . RootPart . AddFlag ( PrimFlags . JointWheel ) ;
2008-10-04 03:04:00 +00:00
obj . ParentGroup . HasGroupChanged = true ;
2008-04-16 03:55:21 +00:00
}
2008-11-21 22:14:57 +00:00
else if ( ! IncludeInSearch & & m_parentScene . Permissions . CanMoveObject ( objid , user ) )
2008-04-16 03:55:21 +00:00
{
2008-09-06 07:52:41 +00:00
obj . ParentGroup . RootPart . RemFlag ( PrimFlags . JointWheel ) ;
2008-10-04 03:04:00 +00:00
obj . ParentGroup . HasGroupChanged = true ;
2008-04-16 03:55:21 +00:00
}
2008-09-08 10:28:59 +00:00
#pragma warning restore 0612
2008-04-16 03:55:21 +00:00
}
2008-06-10 00:18:00 +00:00
/// <summary>
/// Duplicate the given object.
/// </summary>
/// <param name="originalPrim"></param>
/// <param name="offset"></param>
/// <param name="flags"></param>
2010-08-06 23:45:04 +00:00
/// <param name="AgentID"></param>
/// <param name="GroupID"></param>
/// <param name="rot"></param>
2010-08-07 00:06:47 +00:00
public SceneObjectGroup DuplicateObject ( uint originalPrimID , Vector3 offset , uint flags , UUID AgentID , UUID GroupID , Quaternion rot )
2008-06-10 00:18:00 +00:00
{
2011-03-26 02:24:32 +00:00
// m_log.DebugFormat(
// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
// originalPrimID, offset, AgentID);
2009-04-12 15:18:04 +00:00
SceneObjectGroup original = GetGroupByPrim ( originalPrimID ) ;
if ( original ! = null )
2007-11-04 14:34:45 +00:00
{
2010-08-25 23:08:53 +00:00
if ( m_parentScene . Permissions . CanDuplicateObject (
original . PrimCount , original . UUID , AgentID , original . AbsolutePosition ) )
2007-11-18 11:11:44 +00:00
{
2010-06-27 23:48:24 +00:00
SceneObjectGroup copy = original . Copy ( true ) ;
2007-11-18 11:11:44 +00:00
copy . AbsolutePosition = copy . AbsolutePosition + offset ;
2008-02-16 13:01:42 +00:00
2010-06-27 23:29:30 +00:00
if ( original . OwnerID ! = AgentID )
2010-06-27 19:04:30 +00:00
{
copy . SetOwnerId ( AgentID ) ;
copy . SetRootPartOwner ( copy . RootPart , AgentID , GroupID ) ;
2010-09-17 00:30:46 +00:00
SceneObjectPart [ ] partList = copy . Parts ;
2010-06-27 19:04:30 +00:00
if ( m_parentScene . Permissions . PropagatePermissions ( ) )
{
foreach ( SceneObjectPart child in partList )
{
child . Inventory . ChangeInventoryOwner ( AgentID ) ;
child . TriggerScriptChangedEvent ( Changed . OWNER ) ;
child . ApplyNextOwnerPermissions ( ) ;
}
}
copy . RootPart . ObjectSaleType = 0 ;
copy . RootPart . SalePrice = 10 ;
}
2011-03-26 02:24:32 +00:00
// FIXME: This section needs to be refactored so that it just calls AddSceneObject()
2008-11-24 15:09:25 +00:00
Entities . Add ( copy ) ;
2011-03-26 02:24:32 +00:00
lock ( SceneObjectGroupsByFullID )
SceneObjectGroupsByFullID [ copy . UUID ] = copy ;
SceneObjectPart [ ] children = copy . Parts ;
lock ( SceneObjectGroupsByFullPartID )
{
SceneObjectGroupsByFullPartID [ copy . UUID ] = copy ;
foreach ( SceneObjectPart part in children )
SceneObjectGroupsByFullPartID [ part . UUID ] = copy ;
}
lock ( SceneObjectGroupsByLocalPartID )
{
SceneObjectGroupsByLocalPartID [ copy . LocalId ] = copy ;
foreach ( SceneObjectPart part in children )
2011-04-06 19:52:36 +00:00
SceneObjectGroupsByLocalPartID [ part . LocalId ] = copy ;
2011-03-26 02:24:32 +00:00
}
// PROBABLE END OF FIXME
2008-02-16 13:01:42 +00:00
2008-05-25 23:27:38 +00:00
// Since we copy from a source group that is in selected
// state, but the copy is shown deselected in the viewer,
// We need to clear the selection flag here, else that
// prim never gets persisted at all. The client doesn't
// think it's selected, so it will never send a deselect...
copy . IsSelected = false ;
2008-05-25 19:21:21 +00:00
2010-09-17 00:30:46 +00:00
m_numPrim + = copy . Parts . Length ;
2008-02-16 13:01:42 +00:00
2008-09-06 07:52:41 +00:00
if ( rot ! = Quaternion . Identity )
2008-06-10 00:18:00 +00:00
{
2009-09-30 16:51:02 +00:00
copy . UpdateGroupRotationR ( rot ) ;
2008-06-10 00:18:00 +00:00
}
2010-08-31 20:24:11 +00:00
copy . CreateScriptInstances ( 0 , false , m_parentScene . DefaultScriptEngine , 1 ) ;
2008-06-27 16:36:19 +00:00
copy . HasGroupChanged = true ;
2007-11-18 11:11:44 +00:00
copy . ScheduleGroupForFullUpdate ( ) ;
2010-04-19 05:29:26 +00:00
copy . ResumeScripts ( ) ;
2008-12-21 14:50:58 +00:00
// required for physics to update it's position
copy . AbsolutePosition = copy . AbsolutePosition ;
2009-01-06 15:14:15 +00:00
2008-06-10 00:18:00 +00:00
return copy ;
2007-11-18 11:11:44 +00:00
}
2007-11-04 14:34:45 +00:00
}
else
{
2008-02-10 01:57:59 +00:00
m_log . WarnFormat ( "[SCENE]: Attempted to duplicate nonexistant prim id {0}" , GroupID ) ;
2007-11-04 14:34:45 +00:00
}
2009-02-03 17:50:25 +00:00
2008-06-10 00:18:00 +00:00
return null ;
2007-11-18 11:11:44 +00:00
}
2008-11-12 20:16:46 +00:00
2007-12-06 18:17:44 +00:00
/// <summary>
/// Calculates the distance between two Vector3s
/// </summary>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns></returns>
2008-05-26 01:06:50 +00:00
protected internal float Vector3Distance ( Vector3 v1 , Vector3 v2 )
2007-11-22 01:32:13 +00:00
{
2008-05-16 01:22:11 +00:00
// We don't really need the double floating point precision...
2007-11-22 01:32:13 +00:00
// so casting it to a single
2007-11-04 14:34:45 +00:00
2007-12-27 21:41:48 +00:00
return
( float )
2008-09-06 07:52:41 +00:00
Math . Sqrt ( ( v1 . X - v2 . X ) * ( v1 . X - v2 . X ) + ( v1 . Y - v2 . Y ) * ( v1 . Y - v2 . Y ) + ( v1 . Z - v2 . Z ) * ( v1 . Z - v2 . Z ) ) ;
2007-11-22 01:32:13 +00:00
}
2007-12-27 21:41:48 +00:00
2007-11-04 14:34:45 +00:00
# endregion
2009-01-06 00:07:24 +00:00
2007-11-04 14:34:45 +00:00
}
2008-05-01 18:04:42 +00:00
}