* Rewrote the methods that build ObjectUpdate and ImprovedTerseObjectUpdate packets to fill in the data more accurately and avoid allocating memory that is immediately thrown away
* Changed the Send*Data structs in IClientAPI to use public readonly members instead of private members and getters * Made Parallel.ProcessorCount public * Started switching over packet building methods in LLClientView to use Util.StringToBytes[256/1024]() instead of Utils.StringToBytes() * More cleanup of the ScenePresences vs. ClientManager nightmare * ScenePresence.HandleAgentUpdate() will now time out and drop incoming AgentUpdate packets after three seconds. This fixes a deadlock on m_AgentUpdates that was blocking up the LLUDP serverprioritization
							parent
							
								
									1dbbf6edb6
								
							
						
					
					
						commit
						233e16b99c
					
				|  | @ -999,16 +999,16 @@ namespace OpenSim.Client.MXP.ClientStack | |||
|         public void SendAvatarData(SendAvatarData data) | ||||
|         { | ||||
|             //ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID); | ||||
|             UUID ownerID = data.avatarID; | ||||
|             MXPSendAvatarData(data.firstName + " " + data.lastName, ownerID, UUID.Zero, data.avatarID, data.avatarLocalID, data.Pos, data.rotation); | ||||
|             UUID ownerID = data.AvatarID; | ||||
|             MXPSendAvatarData(data.FirstName + " " + data.LastName, ownerID, UUID.Zero, data.AvatarID, data.AvatarLocalID, data.Position, data.Rotation); | ||||
|         } | ||||
| 
 | ||||
|         public void SendAvatarTerseUpdate(SendAvatarTerseData data) | ||||
|         { | ||||
|             MovementEventMessage me = new MovementEventMessage(); | ||||
|             me.ObjectIndex = data.localID; | ||||
|             me.Location = ToOmVector(data.position); | ||||
|             me.Orientation = ToOmQuaternion(data.rotation); | ||||
|             me.ObjectIndex = data.LocalID; | ||||
|             me.Location = ToOmVector(data.Position); | ||||
|             me.Orientation = ToOmQuaternion(data.Rotation); | ||||
| 
 | ||||
|             Session.Send(me); | ||||
|         } | ||||
|  | @ -1030,15 +1030,17 @@ namespace OpenSim.Client.MXP.ClientStack | |||
| 
 | ||||
|         public void SendPrimitiveToClient(SendPrimitiveData data) | ||||
|         { | ||||
|             MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel, data.rotation, data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction, data.material, data.textureanim); | ||||
|             MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel, | ||||
|                 data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction, | ||||
|                 data.material, data.textureanim); | ||||
|         } | ||||
| 
 | ||||
|         public void SendPrimTerseUpdate(SendPrimitiveTerseData data) | ||||
|         { | ||||
|             MovementEventMessage me = new MovementEventMessage(); | ||||
|             me.ObjectIndex = data.localID; | ||||
|             me.Location = ToOmVector(data.position); | ||||
|             me.Orientation = ToOmQuaternion(data.rotation); | ||||
|             me.ObjectIndex = data.LocalID; | ||||
|             me.Location = ToOmVector(data.Position); | ||||
|             me.Orientation = ToOmQuaternion(data.Rotation); | ||||
|             Session.Send(me); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -523,124 +523,100 @@ namespace OpenSim.Framework | |||
| 
 | ||||
|     public struct SendAvatarData | ||||
|     { | ||||
|         private ulong m_regionHandle; | ||||
|         private string m_firstName; | ||||
|         private string m_lastName; | ||||
|         private string m_grouptitle; | ||||
|         private UUID m_avatarID; | ||||
|         private uint m_avatarLocalID; | ||||
|         private Vector3 m_Pos; | ||||
|         private byte[] m_textureEntry; | ||||
|         private uint m_parentID; | ||||
|         private Quaternion m_rotation; | ||||
|         public readonly ulong RegionHandle; | ||||
|         public readonly string FirstName; | ||||
|         public readonly string LastName; | ||||
|         public readonly string GroupTitle; | ||||
|         public readonly UUID AvatarID; | ||||
|         public readonly uint AvatarLocalID; | ||||
|         public readonly Vector3 Position; | ||||
|         public readonly byte[] TextureEntry; | ||||
|         public readonly uint ParentID; | ||||
|         public readonly Quaternion Rotation; | ||||
| 
 | ||||
|         public SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, | ||||
|                             uint avatarLocalID, | ||||
|                             Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) | ||||
|         public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID, | ||||
|             uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation) | ||||
|         { | ||||
|             this.m_regionHandle = regionHandle; | ||||
|             this.m_firstName = firstName; | ||||
|             this.m_lastName = lastName; | ||||
|             this.m_grouptitle = grouptitle; | ||||
|             this.m_avatarID = avatarID; | ||||
|             this.m_avatarLocalID = avatarLocalID; | ||||
|             this.m_Pos = Pos; | ||||
|             this.m_textureEntry = textureEntry; | ||||
|             this.m_parentID = parentID; | ||||
|             this.m_rotation = rotation; | ||||
|             RegionHandle = regionHandle; | ||||
|             FirstName = firstName; | ||||
|             LastName = lastName; | ||||
|             GroupTitle = groupTitle; | ||||
|             AvatarID = avatarID; | ||||
|             AvatarLocalID = avatarLocalID; | ||||
|             Position = position; | ||||
|             TextureEntry = textureEntry; | ||||
|             ParentID = parentID; | ||||
|             Rotation = rotation; | ||||
|         } | ||||
| 
 | ||||
|         public ulong regionHandle { get { return this.m_regionHandle; } } | ||||
|         public string firstName { get { return this.m_firstName; } } | ||||
|         public string lastName { get { return this.m_lastName; } } | ||||
|         public string grouptitle { get { return this.m_grouptitle; } } | ||||
|         public UUID avatarID { get { return this.m_avatarID; } } | ||||
|         public uint avatarLocalID { get { return this.m_avatarLocalID; } } | ||||
|         public Vector3 Pos { get { return this.m_Pos; } } | ||||
|         public byte[] textureEntry { get { return this.m_textureEntry; } } | ||||
|         public uint parentID { get { return this.m_parentID; } } | ||||
|         public Quaternion rotation { get { return this.m_rotation; } } | ||||
|     } | ||||
| 
 | ||||
|     public struct SendAvatarTerseData | ||||
|     { | ||||
|         private ulong m_regionHandle; | ||||
|         private ushort m_timeDilation; | ||||
|         private uint m_localID; | ||||
|         private Vector3 m_position; | ||||
|         private Vector3 m_velocity; | ||||
|         private Quaternion m_rotation; | ||||
|         private UUID m_agentid; | ||||
|         private double m_priority; | ||||
|         public readonly ulong RegionHandle; | ||||
|         public readonly ushort TimeDilation; | ||||
|         public readonly uint LocalID; | ||||
|         public readonly Vector3 Position; | ||||
|         public readonly Vector3 Velocity; | ||||
|         public readonly Vector3 Acceleration; | ||||
|         public readonly Quaternion Rotation; | ||||
|         public readonly Vector4 CollisionPlane; | ||||
|         public readonly UUID AgentID; | ||||
|         public readonly byte[] TextureEntry; | ||||
|         public readonly double Priority; | ||||
| 
 | ||||
|         public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, | ||||
|                                    Vector3 velocity, Quaternion rotation, UUID agentid, double priority) | ||||
|         public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, | ||||
|             Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority) | ||||
|         { | ||||
|             this.m_regionHandle = regionHandle; | ||||
|             this.m_timeDilation = timeDilation; | ||||
|             this.m_localID = localID; | ||||
|             this.m_position = position; | ||||
|             this.m_velocity = velocity; | ||||
|             this.m_rotation = rotation; | ||||
|             this.m_agentid = agentid; | ||||
|             this.m_priority = priority; | ||||
|             RegionHandle = regionHandle; | ||||
|             TimeDilation = timeDilation; | ||||
|             LocalID = localID; | ||||
|             Position = position; | ||||
|             Velocity = velocity; | ||||
|             Acceleration = acceleration; | ||||
|             Rotation = rotation; | ||||
|             CollisionPlane = collisionPlane; | ||||
|             AgentID = agentid; | ||||
|             TextureEntry = textureEntry; | ||||
|             Priority = priority; | ||||
|         } | ||||
| 
 | ||||
|         public ulong regionHandle { get { return this.m_regionHandle; } } | ||||
|         public ushort timeDilation { get { return this.m_timeDilation; } } | ||||
|         public uint localID { get { return this.m_localID; } } | ||||
|         public Vector3 position { get { return this.m_position; } } | ||||
|         public Vector3 velocity { get { return this.m_velocity; } } | ||||
|         public Quaternion rotation { get { return this.m_rotation; } } | ||||
|         public UUID agentid { get { return this.m_agentid; } } | ||||
|         public double priority { get { return this.m_priority; } } | ||||
|     } | ||||
| 
 | ||||
|     public struct SendPrimitiveTerseData | ||||
|     { | ||||
|         private ulong m_regionHandle; | ||||
|         private ushort m_timeDilation; | ||||
|         private uint m_localID; | ||||
|         private Vector3 m_position; | ||||
|         private Quaternion m_rotation; | ||||
|         private Vector3 m_velocity; | ||||
|         private Vector3 m_rotationalvelocity; | ||||
|         private byte m_state; | ||||
|         private UUID m_AssetId; | ||||
|         private UUID m_owner; | ||||
|         private int m_attachPoint; | ||||
|         private double m_priority; | ||||
|         public readonly ulong RegionHandle; | ||||
|         public readonly ushort TimeDilation; | ||||
|         public readonly uint LocalID; | ||||
|         public readonly Vector3 Position; | ||||
|         public readonly Quaternion Rotation; | ||||
|         public readonly Vector3 Velocity; | ||||
|         public readonly Vector3 Acceleration; | ||||
|         public readonly Vector3 AngularVelocity; | ||||
|         public readonly byte State; | ||||
|         public readonly UUID AssetID; | ||||
|         public readonly UUID OwnerID; | ||||
|         public readonly int AttachPoint; | ||||
|         public readonly byte[] TextureEntry; | ||||
|         public readonly double Priority; | ||||
| 
 | ||||
|         public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, | ||||
|                                  Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, | ||||
|                                  UUID AssetId, UUID owner, int attachPoint, double priority) | ||||
|             Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity, byte state, | ||||
|             UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority) | ||||
|         { | ||||
|             this.m_regionHandle = regionHandle; | ||||
|             this.m_timeDilation = timeDilation; | ||||
|             this.m_localID = localID; | ||||
|             this.m_position = position; | ||||
|             this.m_rotation = rotation; | ||||
|             this.m_velocity = velocity; | ||||
|             this.m_rotationalvelocity = rotationalvelocity; | ||||
|             this.m_state = state; | ||||
|             this.m_AssetId = AssetId; | ||||
|             this.m_owner = owner; | ||||
|             this.m_attachPoint = attachPoint; | ||||
|             this.m_priority = priority; | ||||
|             RegionHandle = regionHandle; | ||||
|             TimeDilation = timeDilation; | ||||
|             LocalID = localID; | ||||
|             Position = position; | ||||
|             Rotation = rotation; | ||||
|             Velocity = velocity; | ||||
|             Acceleration = acceleration; | ||||
|             AngularVelocity = rotationalvelocity; | ||||
|             State = state; | ||||
|             AssetID = assetID; | ||||
|             OwnerID = ownerID; | ||||
|             AttachPoint = attachPoint; | ||||
|             TextureEntry = textureEntry; | ||||
|             Priority = priority; | ||||
|         } | ||||
| 
 | ||||
|         public ulong regionHandle { get { return this.m_regionHandle; } } | ||||
|         public ushort timeDilation { get { return this.m_timeDilation; } } | ||||
|         public uint localID { get { return this.m_localID; } } | ||||
|         public Vector3 position { get { return this.m_position; } } | ||||
|         public Quaternion rotation { get { return this.m_rotation; } } | ||||
|         public Vector3 velocity { get { return this.m_velocity; } } | ||||
|         public Vector3 rotationalvelocity { get { return this.m_rotationalvelocity; } } | ||||
|         public byte state { get { return this.m_state; } } | ||||
|         public UUID AssetId { get { return this.m_AssetId; } } | ||||
|         public UUID owner { get { return this.m_owner; } } | ||||
|         public int attachPoint { get { return this.m_attachPoint; } } | ||||
|         public double priority { get { return this.m_priority; } } | ||||
|     } | ||||
| 
 | ||||
|     public struct SendPrimitiveData | ||||
|  | @ -654,7 +630,7 @@ namespace OpenSim.Framework | |||
|         private Vector3 m_acc; | ||||
|         private Quaternion m_rotation; | ||||
|         private Vector3 m_rvel; | ||||
|         private uint m_flags; | ||||
|         private PrimFlags m_flags; | ||||
|         private UUID m_objectID; | ||||
|         private UUID m_ownerID; | ||||
|         private string m_text; | ||||
|  | @ -699,7 +675,7 @@ namespace OpenSim.Framework | |||
|             this.m_acc = acc; | ||||
|             this.m_rotation = rotation; | ||||
|             this.m_rvel = rvel; | ||||
|             this.m_flags = flags; | ||||
|             this.m_flags = (PrimFlags)flags; | ||||
|             this.m_objectID = objectID; | ||||
|             this.m_ownerID = ownerID; | ||||
|             this.m_text = text; | ||||
|  | @ -728,7 +704,7 @@ namespace OpenSim.Framework | |||
|         public Vector3 acc { get { return this.m_acc; } } | ||||
|         public Quaternion rotation { get { return this.m_rotation; } } | ||||
|         public Vector3 rvel { get { return this.m_rvel; } } | ||||
|         public uint flags { get { return this.m_flags; } } | ||||
|         public PrimFlags flags { get { return this.m_flags; } } | ||||
|         public UUID objectID { get { return this.m_objectID; } } | ||||
|         public UUID ownerID { get { return this.m_ownerID; } } | ||||
|         public string text { get { return this.m_text; } } | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ namespace OpenSim.Framework | |||
|     /// </summary> | ||||
|     public static class Parallel | ||||
|     { | ||||
|         private static readonly int processorCount = System.Environment.ProcessorCount; | ||||
|         public static readonly int ProcessorCount = System.Environment.ProcessorCount; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Executes a for loop in which iterations may run in parallel | ||||
|  | @ -46,7 +46,7 @@ namespace OpenSim.Framework | |||
|         /// <param name="body">Method body to run for each iteration of the loop</param> | ||||
|         public static void For(int fromInclusive, int toExclusive, Action<int> body) | ||||
|         { | ||||
|             For(processorCount, fromInclusive, toExclusive, body); | ||||
|             For(ProcessorCount, fromInclusive, toExclusive, body); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -103,7 +103,7 @@ namespace OpenSim.Framework | |||
|         /// <param name="body">Method body to run for each object in the collection</param> | ||||
|         public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body) | ||||
|         { | ||||
|             ForEach<T>(processorCount, enumerable, body); | ||||
|             ForEach<T>(ProcessorCount, enumerable, body); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -161,7 +161,7 @@ namespace OpenSim.Framework | |||
|         /// <param name="actions">A series of method bodies to execute</param> | ||||
|         public static void Invoke(params Action[] actions) | ||||
|         { | ||||
|             Invoke(processorCount, actions); | ||||
|             Invoke(ProcessorCount, actions); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -733,10 +733,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
|             // on to en-US to avoid number parsing issues | ||||
|             Culture.SetCurrentCulture(); | ||||
| 
 | ||||
|             IncomingPacket incomingPacket = null; | ||||
| 
 | ||||
|             while (base.IsRunning) | ||||
|             { | ||||
|                 IncomingPacket incomingPacket = null; | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
|                     if (packetInbox.Dequeue(100, ref incomingPacket)) | ||||
|  |  | |||
|  | @ -357,13 +357,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             get { return m_defaultScriptEngine; } | ||||
|         } | ||||
| 
 | ||||
|         // Reference to all of the agents in the scene (root and child) | ||||
|         protected Dictionary<UUID, ScenePresence> m_scenePresences | ||||
|         { | ||||
|             get { return m_sceneGraph.ScenePresences; } | ||||
|             set { m_sceneGraph.ScenePresences = value; } | ||||
|         } | ||||
| 
 | ||||
|         public EntityManager Entities | ||||
|         { | ||||
|             get { return m_sceneGraph.Entities; } | ||||
|  | @ -1183,14 +1176,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         /// <param name="stats">Stats on the Simulator's performance</param> | ||||
|         private void SendSimStatsPackets(SimStats stats) | ||||
|         { | ||||
|             List<ScenePresence> StatSendAgents = GetScenePresences(); | ||||
|             foreach (ScenePresence agent in StatSendAgents) | ||||
|             ForEachScenePresence( | ||||
|                 delegate(ScenePresence agent) | ||||
|                 { | ||||
|                     if (!agent.IsChildAgent) | ||||
|                 { | ||||
|                         agent.ControllingClient.SendSimStats(stats); | ||||
|                 } | ||||
|             } | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -3501,10 +3493,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         { | ||||
|             ScenePresence presence; | ||||
| 
 | ||||
|             lock (m_scenePresences) | ||||
|             { | ||||
|                 m_scenePresences.TryGetValue(agentID, out presence); | ||||
|             } | ||||
|             lock (m_sceneGraph.ScenePresences) | ||||
|                 m_sceneGraph.ScenePresences.TryGetValue(agentID, out presence); | ||||
| 
 | ||||
|             if (presence != null) | ||||
|             { | ||||
|  | @ -3714,12 +3704,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, | ||||
|                                             Vector3 lookAt, uint teleportFlags) | ||||
|         { | ||||
|             ScenePresence sp = null; | ||||
|             lock (m_scenePresences) | ||||
|             { | ||||
|                 if (m_scenePresences.ContainsKey(remoteClient.AgentId)) | ||||
|                     sp = m_scenePresences[remoteClient.AgentId]; | ||||
|             } | ||||
|             ScenePresence sp; | ||||
|             lock (m_sceneGraph.ScenePresences) | ||||
|                 m_sceneGraph.ScenePresences.TryGetValue(remoteClient.AgentId, out sp); | ||||
| 
 | ||||
|             if (sp != null) | ||||
|             { | ||||
|  | @ -4168,7 +4155,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         public void ForEachScenePresence(Action<ScenePresence> action) | ||||
|         { | ||||
|             // We don't want to try to send messages if there are no avatars. | ||||
|             if (m_scenePresences != null) | ||||
|             if (m_sceneGraph != null && m_sceneGraph.ScenePresences != null) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|  |  | |||
|  | @ -3797,9 +3797,9 @@ if (m_shape != null) { | |||
|             remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle, | ||||
|                     (ushort)(m_parentGroup.GetTimeDilation() * | ||||
|                     (float)ushort.MaxValue), LocalId, lPos, | ||||
|                     RotationOffset, Velocity, | ||||
|                     RotationOffset, Velocity, Acceleration, | ||||
|                     RotationalVelocity, state, FromItemID, | ||||
|                     OwnerID, (int)AttachmentPoint, ParentGroup.GetUpdatePriority(remoteClient))); | ||||
|                     OwnerID, (int)AttachmentPoint, null, ParentGroup.GetUpdatePriority(remoteClient))); | ||||
|         } | ||||
|                  | ||||
|         public void AddScriptLPS(int count) | ||||
|  |  | |||
|  | @ -1160,7 +1160,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         /// </summary> | ||||
|         public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||||
|         { | ||||
|             lock (m_agentUpdates) | ||||
|             const int AGENT_UPDATE_TIMEOUT_MS = 1000 * 3; | ||||
| 
 | ||||
|             if (System.Threading.Monitor.TryEnter(m_agentUpdates, AGENT_UPDATE_TIMEOUT_MS)) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     if (m_updatesAllowed) | ||||
|                     { | ||||
|  | @ -1170,6 +1174,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|                     m_agentUpdates.Add(agentData); | ||||
|                 } | ||||
|                 finally { System.Threading.Monitor.Exit(m_agentUpdates); } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void RealHandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||||
|  | @ -2471,7 +2477,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 pos.Z -= m_appearance.HipOffset; | ||||
| 
 | ||||
|                 remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, | ||||
|                     pos, m_velocity, m_rotation, m_uuid, GetUpdatePriority(remoteClient))); | ||||
|                     pos, m_velocity, Vector3.Zero, m_rotation, Vector4.Zero, m_uuid, null, GetUpdatePriority(remoteClient))); | ||||
| 
 | ||||
|                 m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS); | ||||
|                 m_scene.StatsReporter.AddAgentUpdates(1); | ||||
|  | @ -3504,7 +3510,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|         public void Close() | ||||
|         { | ||||
| 
 | ||||
|             lock (m_attachments) | ||||
|             { | ||||
|                 // Delete attachments from scene | ||||
|  | @ -3535,7 +3540,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             m_sceneViewer.Close(); | ||||
| 
 | ||||
|             RemoveFromPhysicalScene(); | ||||
|             GC.Collect(); | ||||
|         } | ||||
| 
 | ||||
|         public ScenePresence() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 John Hurliman
						John Hurliman