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 ( ) ;
2009-01-06 15:14:15 +00:00
public delegate void ObjectDuplicateDelegate ( EntityBase original , EntityBase clone ) ;
public delegate void ObjectCreateDelegate ( EntityBase obj ) ;
public delegate void ObjectDeleteDelegate ( EntityBase obj ) ;
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
2009-01-06 15:14:15 +00:00
public event ObjectDuplicateDelegate OnObjectDuplicate ;
public event ObjectCreateDelegate OnObjectCreate ;
public event ObjectDeleteDelegate OnObjectRemove ;
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-01-07 02:33:22 +00:00
// SceneObjects is not currently populated or used.
2008-09-06 07:52:41 +00:00
//public Dictionary<UUID, SceneObjectGroup> SceneObjects;
2008-11-24 14:45:05 +00:00
protected internal EntityManager Entities = new EntityManager ( ) ;
// protected internal Dictionary<UUID, EntityBase> Entities = new Dictionary<UUID, EntityBase>();
2008-09-06 07:52:41 +00:00
protected internal Dictionary < UUID , ScenePresence > RestorePresences = new Dictionary < UUID , ScenePresence > ( ) ;
2008-05-01 18:04:42 +00:00
2008-05-26 01:06:50 +00:00
protected internal BasicQuadTreeNode QuadTree ;
2008-05-01 18:04:42 +00:00
2008-05-01 16:35:00 +00:00
protected RegionInfo m_regInfo ;
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 object m_syncRoot = new object ( ) ;
2008-05-01 18:04:42 +00:00
2008-05-26 01:06:50 +00:00
protected internal PhysicsScene _PhyScene ;
2007-12-27 21:41:48 +00:00
2009-04-12 15:18:04 +00:00
protected internal Dictionary < uint , SceneObjectGroup > SceneObjectGroupsByLocalID = new Dictionary < uint , SceneObjectGroup > ( ) ;
protected internal Dictionary < UUID , SceneObjectGroup > SceneObjectGroupsByFullID = new Dictionary < UUID , SceneObjectGroup > ( ) ;
private readonly Object m_dictionary_lock = new Object ( ) ;
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
2008-11-12 20:16:46 +00:00
protected internal SceneGraph ( Scene parent , RegionInfo regInfo )
2007-11-04 14:34:45 +00:00
{
m_parentScene = parent ;
m_regInfo = regInfo ;
2008-05-01 18:04:42 +00:00
QuadTree = new BasicQuadTreeNode ( null , "/0/" , 0 , 0 , ( short ) Constants . RegionSize , ( short ) Constants . RegionSize ) ;
2007-11-04 14:34:45 +00:00
QuadTree . Subdivide ( ) ;
QuadTree . Subdivide ( ) ;
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-07-21 13:40:08 +00:00
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
2009-04-12 15:18:04 +00:00
lock ( m_dictionary_lock )
{
SceneObjectGroupsByFullID . Clear ( ) ;
SceneObjectGroupsByLocalID . 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
}
}
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
}
2008-05-26 01:06:50 +00:00
protected internal float UpdatePhysics ( double elapsed )
2007-11-04 22:22:53 +00:00
{
lock ( m_syncRoot )
{
2008-12-26 12:58:02 +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().
2008-05-01 18:04:42 +00:00
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
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>
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 (
SceneObjectGroup sceneObject , bool attachToBackup , bool alreadyPersisted )
2007-11-04 14:34:45 +00:00
{
2008-07-13 00:18:29 +00:00
if ( ! alreadyPersisted )
{
sceneObject . ForceInventoryPersistence ( ) ;
sceneObject . HasGroupChanged = true ;
}
2008-08-18 00:39:10 +00:00
2010-03-03 22:14:06 +00:00
return AddSceneObject ( sceneObject , attachToBackup , true ) ;
2007-11-04 14:34:45 +00:00
}
2008-08-18 00:39:10 +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
{
2008-06-27 14:46:44 +00:00
// Ensure that we persist this new scene object
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
}
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>
/// <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
{
2008-10-13 20:45:13 +00:00
if ( sceneObject = = null | | sceneObject . RootPart = = null | | sceneObject . RootPart . UUID = = UUID . Zero )
2008-10-11 16:23:15 +00:00
return false ;
2010-03-03 22:14:06 +00:00
2010-05-21 20:57:56 +00:00
lock ( sceneObject )
{
if ( Entities . ContainsKey ( sceneObject . UUID ) )
2008-11-12 01:40:38 +00:00
{
2010-05-21 20:57:56 +00:00
// m_log.WarnFormat(
// "[SCENE GRAPH]: Scene object {0} {1} was already in region {2} on add request",
// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
return false ;
2008-11-12 01:40:38 +00:00
}
2010-05-21 20:57:56 +00:00
2010-05-21 20:22:53 +00:00
// m_log.DebugFormat(
// "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
2010-05-21 20:57:56 +00:00
// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
if ( m_parentScene . m_clampPrimSize )
{
foreach ( SceneObjectPart part in sceneObject . Children . Values )
2009-04-12 15:18:04 +00:00
{
2010-05-21 20:57:56 +00:00
Vector3 scale = part . Shape . Scale ;
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 ;
part . Shape . Scale = scale ;
}
}
sceneObject . AttachToScene ( m_parentScene ) ;
if ( sendClientUpdates )
sceneObject . ScheduleGroupForFullUpdate ( ) ;
Entities . Add ( sceneObject ) ;
m_numPrim + = sceneObject . Children . Count ;
if ( attachToBackup )
sceneObject . AttachToBackup ( ) ;
if ( OnObjectCreate ! = null )
OnObjectCreate ( sceneObject ) ;
lock ( m_dictionary_lock )
{
SceneObjectGroupsByFullID [ sceneObject . UUID ] = sceneObject ;
SceneObjectGroupsByLocalID [ sceneObject . LocalId ] = sceneObject ;
foreach ( SceneObjectPart part in sceneObject . Children . Values )
{
SceneObjectGroupsByFullID [ part . UUID ] = sceneObject ;
SceneObjectGroupsByLocalID [ part . LocalId ] = sceneObject ;
2009-04-12 15:18:04 +00:00
}
2010-03-03 22:14:06 +00:00
}
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
{
2008-11-24 15:09:25 +00:00
if ( Entities . ContainsKey ( uuid ) )
2008-05-24 23:11:07 +00:00
{
2008-11-24 15:09:25 +00:00
if ( ! resultOfObjectLinked )
2008-05-24 23:11:07 +00:00
{
2008-11-24 15:09:25 +00:00
m_numPrim - = ( ( SceneObjectGroup ) Entities [ uuid ] ) . Children . Count ;
2009-01-03 03:30:03 +00:00
if ( ( ( ( SceneObjectGroup ) Entities [ uuid ] ) . RootPart . Flags & PrimFlags . Physics ) = = PrimFlags . Physics )
{
RemovePhysicalPrim ( ( ( SceneObjectGroup ) Entities [ uuid ] ) . Children . Count ) ;
}
2008-05-24 23:11:07 +00:00
}
2009-01-03 03:30:03 +00:00
2009-01-06 15:14:15 +00:00
if ( OnObjectRemove ! = null )
OnObjectRemove ( Entities [ uuid ] ) ;
2009-01-03 03:30:03 +00:00
2009-04-12 15:18:04 +00:00
lock ( m_dictionary_lock )
{
SceneObjectGroupsByFullID . Remove ( uuid ) ;
SceneObjectGroupsByLocalID . Remove ( ( ( SceneObjectGroup ) Entities [ uuid ] ) . LocalId ) ;
}
2008-11-24 15:09:25 +00:00
Entities . Remove ( uuid ) ;
2009-01-03 03:30:03 +00:00
//SceneObjectGroup part;
//((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
2008-11-24 15:09:25 +00:00
return true ;
2008-05-24 23:11:07 +00:00
}
2008-05-28 03:44:49 +00:00
2008-05-24 23:11:07 +00:00
return false ;
}
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 ;
2009-10-29 06:10:16 +00:00
List < SceneObjectGroup > updates ;
2009-04-12 15:18:04 +00:00
// Some updates add more updates to the updateList.
// Get the current list of updates and clear the list before iterating
2008-02-20 00:08:04 +00:00
lock ( m_updateList )
{
2009-10-29 06:10:16 +00:00
updates = new List < SceneObjectGroup > ( m_updateList . Values ) ;
2009-04-12 15:18:04 +00:00
m_updateList . Clear ( ) ;
}
2009-10-29 06:10:16 +00:00
2009-10-14 02:13:06 +00:00
// Go through all updates
2009-10-29 06:10:16 +00:00
for ( int i = 0 ; i < updates . Count ; i + + )
2009-04-12 15:18:04 +00:00
{
2009-10-29 06:10:16 +00:00
SceneObjectGroup sog = updates [ i ] ;
2009-04-12 15:18:04 +00:00
// Don't abort the whole update if one entity happens to give us an exception.
try
2008-02-20 00:08:04 +00:00
{
2009-10-29 06:10:16 +00:00
sog . Update ( ) ;
2009-04-12 15:18:04 +00:00
}
catch ( Exception e )
{
m_log . ErrorFormat (
2009-10-29 06:10:16 +00:00
"[INNER SCENE]: Failed to update {0}, {1} - {2}" , sog . Name , sog . UUID , e ) ;
2008-02-20 00:08:04 +00:00
}
}
2009-12-06 00:25:04 +00:00
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
2009-03-20 13:57:22 +00:00
public void DropObject ( uint objectLocalID , IClientAPI remoteClient )
2008-10-04 01:09:22 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup group = GetGroupByPrim ( objectLocalID ) ;
if ( group ! = null )
2010-04-16 22:15:13 +00:00
m_parentScene . AttachmentsModule . DetachSingleAttachmentToGround ( group . UUID , remoteClient ) ;
2008-10-04 01:09:22 +00:00
}
2008-05-26 01:06:50 +00:00
protected internal void DetachObject ( uint objectLocalID , IClientAPI remoteClient )
2008-04-24 11:32:41 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup group = GetGroupByPrim ( objectLocalID ) ;
2009-04-14 11:38:33 +00:00
if ( group ! = null )
2008-04-24 11:32:41 +00:00
{
2009-04-12 15:18:04 +00:00
//group.DetachToGround();
2010-03-06 00:07:47 +00:00
m_parentScene . AttachmentsModule . ShowDetachInUserInventory ( group . GetFromItemID ( ) , remoteClient ) ;
2008-04-24 11:32:41 +00:00
}
}
2008-04-28 01:48:21 +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
}
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 ) ;
if ( part ! = null )
part . Redo ( ) ;
}
}
2008-05-28 03:44:49 +00:00
2008-05-26 01:06:50 +00:00
protected internal void HandleObjectGroupUpdate (
2008-09-06 07:52:41 +00:00
IClientAPI remoteClient , UUID GroupID , uint objectLocalID , UUID Garbage )
2008-05-18 03:21:22 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup group = GetGroupByPrim ( objectLocalID ) ;
2009-04-14 11:38:33 +00:00
if ( group ! = null )
2008-05-18 03:21:22 +00:00
{
2009-04-12 15:18:04 +00:00
if ( group . OwnerID = = remoteClient . AgentId )
group . SetGroup ( GroupID , remoteClient ) ;
2008-05-18 03:21:22 +00:00
}
}
2008-05-28 03:44:49 +00:00
2008-11-28 20:11:17 +00:00
protected internal ScenePresence CreateAndAddChildScenePresence ( IClientAPI client , AvatarAppearance appearance )
2007-11-04 14:34:45 +00:00
{
ScenePresence newAvatar = null ;
2007-12-07 17:23:11 +00:00
newAvatar = new ScenePresence ( client , m_parentScene , m_regInfo , appearance ) ;
2008-11-28 20:11:17 +00:00
newAvatar . IsChildAgent = true ;
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
{
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 (
"[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene Entities list" ,
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 ) ;
// Remember the old presene reference from the dictionary
ScenePresence oldref = newmap [ agentID ] ;
// Remove the presence reference from the dictionary
if ( newmap . Remove ( agentID ) )
2009-10-23 08:02:36 +00:00
{
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
{
2008-08-18 00:39:10 +00:00
m_log . WarnFormat ( "[SCENE] 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
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
}
/// <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
{
2009-04-09 10:07:40 +00:00
if ( Entities . ContainsKey ( localID ) )
return Entities [ localID ] as SceneObjectGroup ;
2008-11-10 18:10:00 +00:00
//m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
2009-04-12 15:18:04 +00:00
SceneObjectGroup sog ;
lock ( SceneObjectGroupsByLocalID )
{
if ( SceneObjectGroupsByLocalID . TryGetValue ( localID , out sog ) )
{
return sog ;
}
}
2007-12-17 16:41:28 +00:00
List < 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 )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . HasChildPrim ( localID ) )
2009-04-12 15:18:04 +00:00
{
sog = ( SceneObjectGroup ) ent ;
lock ( SceneObjectGroupsByLocalID )
{
SceneObjectGroupsByLocalID [ localID ] = sog ;
}
return sog ;
}
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>
2008-09-06 07:52:41 +00:00
private SceneObjectGroup GetGroupByPrim ( UUID fullID )
2007-11-04 14:34:45 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup sog ;
lock ( SceneObjectGroupsByFullID )
{
if ( SceneObjectGroupsByFullID . TryGetValue ( fullID , out sog ) )
{
return sog ;
}
}
2007-12-17 16:41:28 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
2007-11-04 14:34:45 +00:00
{
if ( ent is SceneObjectGroup )
{
2008-05-01 18:04:42 +00:00
if ( ( ( SceneObjectGroup ) ent ) . HasChildPrim ( fullID ) )
2009-04-12 15:18:04 +00:00
{
sog = ( SceneObjectGroup ) ent ;
lock ( SceneObjectGroupsByFullID )
{
SceneObjectGroupsByFullID [ fullID ] = sog ;
}
return sog ;
}
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 ( ) ;
2008-06-25 12:21:51 +00:00
List < EntityBase > EntityList = GetEntities ( ) ;
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
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 ;
2009-04-12 15:18:04 +00:00
return group . GetChildPart ( 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>
/// Get a named prim contained in this 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 SceneObjectPart GetSceneObjectPart ( string name )
{
List < EntityBase > EntityList = GetEntities ( ) ;
2008-12-26 12:58:02 +00:00
// FIXME: use a dictionary here
2008-10-01 06:39:36 +00:00
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
2008-10-05 14:15:39 +00:00
foreach ( SceneObjectPart p in ( ( SceneObjectGroup ) ent ) . GetParts ( ) )
{
2009-08-14 08:16:41 +00:00
if ( p . Name = = name )
2008-10-05 14:15:39 +00:00
{
return p ;
}
}
2008-10-01 06:39:36 +00:00
}
}
return null ;
}
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 ;
2009-04-12 15:18:04 +00:00
return group . GetChildPart ( 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>
2008-05-26 01:06:50 +00:00
protected internal List < 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
}
2009-02-06 16:55:34 +00:00
public Dictionary < uint , float > GetTopScripts ( )
2008-05-25 20:50:45 +00:00
{
Dictionary < uint , float > topScripts = new Dictionary < uint , float > ( ) ;
List < EntityBase > EntityList = GetEntities ( ) ;
int limit = 0 ;
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
SceneObjectGroup grp = ( SceneObjectGroup ) ent ;
2008-09-06 07:52:41 +00:00
if ( ( grp . RootPart . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Scripted ) ! = 0 )
2008-05-25 20:50:45 +00:00
{
if ( grp . scriptScore > = 0.01 )
{
topScripts . Add ( grp . LocalId , grp . scriptScore ) ;
limit + + ;
if ( limit > = 100 )
{
break ;
}
}
grp . scriptScore = 0 ;
}
}
}
return topScripts ;
}
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>
/// Performs action on all scene object groups.
/// </summary>
/// <param name="action"></param>
2009-09-29 14:54:56 +00:00
protected internal void ForEachSOG ( Action < SceneObjectGroup > action )
{
List < SceneObjectGroup > objlist = new List < SceneObjectGroup > ( SceneObjectGroupsByFullID . Values ) ;
foreach ( SceneObjectGroup obj in objlist )
{
try
{
action ( obj ) ;
}
catch ( Exception e )
{
// Catch it and move on. This includes situations where splist has inconsistent info
m_log . WarnFormat ( "[SCENE]: Problem processing action in ForEachSOG: " , e . Message ) ;
}
}
}
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 )
{
m_log . Info ( "[BUG] in " + m_parentScene . RegionInfo . RegionName + ": " + e . ToString ( ) ) ;
m_log . Info ( "[BUG] Stack Trace: " + e . StackTrace ) ;
}
} ) ;
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 )
{
m_log . Info ( "[BUG] in " + m_parentScene . RegionInfo . RegionName + ": " + e . ToString ( ) ) ;
m_log . Info ( "[BUG] Stack Trace: " + e . StackTrace ) ;
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>
2008-05-16 01:22:11 +00:00
///
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
{
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
{
group . Resize ( scale , localID ) ;
}
}
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
{
group . GroupResize ( scale , localID ) ;
}
}
}
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 ) )
{
group . UpdateSingleRotation ( rot , pos , localID ) ;
}
}
}
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 UpdatePrimRotation ( 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>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimRotation ( 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>
2008-06-27 14:39:21 +00:00
/// Update the position of the given part
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="pos"></param>
/// <param name="remoteClient"></param>
2008-09-06 07:52:41 +00:00
protected internal void UpdatePrimPosition ( 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-05-16 01:22:11 +00:00
2008-09-06 07:52:41 +00:00
// Vector3 oldPos = group.AbsolutePosition;
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
{
2009-03-10 06:14:29 +00:00
// If this is an attachment, then we need to save the modified
// object back into the avatar's inventory. First we save the
// attachment point information, then we update the relative
// positioning (which caused this method to get driven in the
// first place. Then we have to mark the object as NOT an
// attachment. This is necessary in order to correctly save
// and retrieve GroupPosition information for the attachment.
// Then we save the asset back into the appropriate inventory
// entry. Finally, we restore the object's attachment status.
byte attachmentPoint = group . GetAttachmentPoint ( ) ;
2008-04-24 11:32:41 +00:00
group . UpdateGroupPosition ( pos ) ;
2009-03-10 06:14:29 +00:00
group . RootPart . IsAttachment = false ;
group . AbsolutePosition = group . RootPart . AttachedPos ;
2009-08-15 16:36:45 +00:00
m_parentScene . UpdateKnownItem ( remoteClient , group , group . GetFromItemID ( ) , group . OwnerID ) ;
2009-03-10 06:14:29 +00:00
group . SetAttachmentPoint ( attachmentPoint ) ;
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
{
2008-11-22 15:58:52 +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>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <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 ) ;
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>
2008-05-16 01:22:11 +00:00
///
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="localID"></param>
/// <param name="packet"></param>
/// <param name="remoteClient"></param>
2008-12-20 21:36:42 +00:00
/// This routine seems to get called when a user changes object settings in the viewer.
/// If some one can confirm that, please change the comment according.
2008-11-07 22:57:32 +00:00
protected internal void UpdatePrimFlags ( uint localID , bool UsePhysics , bool IsTemporary , bool IsPhantom , 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
{
2008-12-20 21:36:42 +00:00
group . UpdatePrimFlags ( localID , UsePhysics , IsTemporary , IsPhantom , false ) ; // VolumeDetect can't be set via UI and will always be off when a change is made there
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>
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 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
}
2008-09-12 20:42:04 +00:00
protected internal void PrimClickAction ( IClientAPI remoteClient , uint primLocalID , string clickAction )
{
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 ) ;
part . ClickAction = Convert . ToByte ( clickAction ) ;
group . HasGroupChanged = true ;
}
}
}
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 ) ;
part . Material = Convert . ToByte ( material ) ;
group . HasGroupChanged = true ;
}
}
}
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
{
2008-11-21 22:14:57 +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
{
2008-11-21 22:14:57 +00:00
if ( m_parentScene . Permissions . CanEditObject ( group . GetPartsFullID ( primLocalID ) , 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
{
2009-12-06 01:20:39 +00:00
Monitor . Enter ( m_updateLock ) ;
try
2007-11-04 14:34:45 +00:00
{
2010-04-30 10:46:50 +00:00
SceneObjectGroup parentGroup = root . ParentGroup ;
2009-12-06 00:25:04 +00:00
List < SceneObjectGroup > childGroups = new List < SceneObjectGroup > ( ) ;
if ( parentGroup ! = null )
2007-11-04 14:34:45 +00:00
{
2009-12-06 00:25:04 +00:00
// We do this in reverse to get the link order of the prims correct
2010-04-30 10:46:50 +00:00
for ( int i = children . Count - 1 ; i > = 0 ; i - - )
2007-11-04 14:34:45 +00:00
{
2010-04-30 10:46:50 +00:00
SceneObjectGroup child = children [ i ] . ParentGroup ;
2009-12-06 00:25:04 +00:00
if ( child ! = null )
{
// 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 ) ;
}
2007-11-04 14:34:45 +00:00
}
}
2009-12-06 00:25:04 +00:00
else
{
return ; // parent is null so not in this region
}
2007-11-04 14:34:45 +00:00
2009-12-06 00:25:04 +00:00
foreach ( SceneObjectGroup child in childGroups )
{
parentGroup . LinkToGroup ( child ) ;
2008-12-07 04:03:09 +00:00
2009-12-06 00:25:04 +00:00
// this is here so physics gets updated!
// Don't remove! Bad juju! Stay away! or fix physics!
child . AbsolutePosition = child . AbsolutePosition ;
}
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)
parentGroup . RootPart . AddFlag ( PrimFlags . CreateSelected ) ;
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 )
{
2009-12-06 02:00:32 +00:00
if ( part . ParentGroup . Children . Count ! = 1 ) // Skip single
{
if ( part . LinkNum < 2 ) // Root
rootParts . Add ( part ) ;
else
childParts . Add ( part ) ;
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 ) ;
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 ;
List < SceneObjectPart > newSet = new List < SceneObjectPart > ( group . Children . Values ) ;
int numChildren = group . Children . 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
List < uint > linkIDs = new List < uint > ( ) ;
foreach ( SceneObjectPart newChild in newSet )
newChild . UpdateFlag = 0 ;
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 ;
List < EntityBase > EntityList = GetEntities ( ) ;
foreach ( EntityBase ent in EntityList )
{
if ( ent is SceneObjectGroup )
{
2008-09-06 07:52:41 +00:00
foreach ( KeyValuePair < UUID , SceneObjectPart > subent in ( ( SceneObjectGroup ) ent ) . Children )
2008-04-16 03:55:21 +00:00
{
if ( subent . Value . LocalId = = localID )
{
objid = subent . Key ;
obj = subent . Value ;
}
}
}
}
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
}
2007-11-04 14:34:45 +00:00
/// <summary>
2008-06-10 00:18:00 +00:00
/// Duplicate the given object, Fire and Forget, No rotation, no return wrapper
2007-11-04 14:34:45 +00:00
/// </summary>
/// <param name="originalPrim"></param>
/// <param name="offset"></param>
/// <param name="flags"></param>
2008-09-06 07:52:41 +00:00
protected internal void DuplicateObject ( uint originalPrim , Vector3 offset , uint flags , UUID AgentID , UUID GroupID )
2007-11-04 14:34:45 +00:00
{
2008-05-24 21:57:00 +00:00
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
2008-05-16 01:22:11 +00:00
2008-06-27 19:57:06 +00:00
// SceneObjectGroup dupe = DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Zero);
2008-09-06 07:52:41 +00:00
DuplicateObject ( originalPrim , offset , flags , AgentID , GroupID , Quaternion . Identity ) ;
2008-06-10 00:18:00 +00:00
}
2009-02-03 17:50:25 +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>
2009-04-12 15:18:04 +00:00
protected internal SceneObjectGroup DuplicateObject ( uint originalPrimID , Vector3 offset , uint flags , UUID AgentID , UUID GroupID , Quaternion rot )
2008-06-10 00:18:00 +00:00
{
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, 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
{
2009-04-12 15:18:04 +00:00
if ( m_parentScene . Permissions . CanDuplicateObject ( original . Children . Count , original . UUID , AgentID , original . AbsolutePosition ) )
2007-11-18 11:11:44 +00:00
{
2009-04-12 15:18:04 +00:00
SceneObjectGroup copy = original . Copy ( AgentID , GroupID , true ) ;
2007-11-18 11:11:44 +00:00
copy . AbsolutePosition = copy . AbsolutePosition + offset ;
2008-02-16 13:01:42 +00:00
2008-11-24 15:09:25 +00:00
Entities . Add ( copy ) ;
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
2008-06-06 23:20:02 +00:00
m_numPrim + = copy . Children . Count ;
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
}
2008-11-09 19:30:40 +00:00
copy . CreateScriptInstances ( 0 , false , m_parentScene . DefaultScriptEngine , 0 ) ;
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
if ( OnObjectDuplicate ! = null )
2009-04-12 15:18:04 +00:00
OnObjectDuplicate ( original , copy ) ;
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
}