PageRenderTime 66ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Region/SceneGraph.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 2252 lines | 1471 code | 225 blank | 556 comment | 263 complexity | 22755561143feb731883e7805a0c001e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.Physics;
  32. using Aurora.Framework.PresenceInfo;
  33. using Aurora.Framework.SceneInfo;
  34. using Aurora.Framework.SceneInfo.Entities;
  35. using Aurora.Framework.Services;
  36. using Aurora.Framework.Utilities;
  37. using Nini.Config;
  38. using OpenMetaverse;
  39. using OpenMetaverse.Packets;
  40. using System;
  41. using System.Collections.Generic;
  42. using System.Linq;
  43. using System.Threading;
  44. namespace Aurora.Region
  45. {
  46. /// <summary>
  47. /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
  48. /// should be migrated out over time.
  49. /// </summary>
  50. public class SceneGraph : ISceneGraph
  51. {
  52. #region Declares
  53. protected internal EntityManager Entities = new EntityManager();
  54. protected RegionInfo m_regInfo;
  55. protected IScene m_parentScene;
  56. protected bool EnableFakeRaycasting = false;
  57. protected string m_DefaultObjectName = "Primitive";
  58. /// <summary>
  59. /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
  60. /// dispensed.
  61. /// </summary>
  62. protected uint m_lastAllocatedLocalId = 720000;
  63. private readonly object _primAllocateLock = new object();
  64. protected internal object m_syncRoot = new object();
  65. protected internal PhysicsScene _PhyScene;
  66. private readonly Object m_updateLock = new Object();
  67. public PhysicsScene PhysicsScene
  68. {
  69. get { return _PhyScene; }
  70. set { _PhyScene = value; }
  71. }
  72. #endregion
  73. #region Constructor and close
  74. protected internal SceneGraph(IScene parent, RegionInfo regInfo)
  75. {
  76. Random random = new Random();
  77. m_lastAllocatedLocalId = (uint) (random.NextDouble()*(uint.MaxValue/2)) + uint.MaxValue/4;
  78. m_parentScene = parent;
  79. m_regInfo = regInfo;
  80. //Subscript to the scene events
  81. m_parentScene.EventManager.OnNewClient += SubscribeToClientEvents;
  82. m_parentScene.EventManager.OnClosingClient += UnSubscribeToClientEvents;
  83. IConfig aurorastartupConfig = parent.Config.Configs["AuroraStartup"];
  84. if (aurorastartupConfig != null)
  85. {
  86. m_DefaultObjectName = aurorastartupConfig.GetString("DefaultObjectName", m_DefaultObjectName);
  87. EnableFakeRaycasting = aurorastartupConfig.GetBoolean("EnableFakeRaycasting", false);
  88. }
  89. }
  90. protected internal void Close()
  91. {
  92. Entities.Clear();
  93. //Remove the events
  94. m_parentScene.EventManager.OnNewClient -= SubscribeToClientEvents;
  95. m_parentScene.EventManager.OnClosingClient -= UnSubscribeToClientEvents;
  96. }
  97. #endregion
  98. #region Update Methods
  99. protected internal void UpdatePreparePhysics()
  100. {
  101. // If we are using a threaded physics engine
  102. // grab the latest scene from the engine before
  103. // trying to process it.
  104. // PhysX does this (runs in the background).
  105. if (_PhyScene != null && _PhyScene.IsThreaded)
  106. {
  107. _PhyScene.GetResults();
  108. }
  109. }
  110. private readonly object m_taintedPresencesLock = new object();
  111. private readonly List<IScenePresence> m_taintedPresences = new List<IScenePresence>();
  112. public void TaintPresenceForUpdate(IScenePresence presence, PresenceTaint taint)
  113. {
  114. lock (m_taintedPresencesLock)
  115. {
  116. if (!presence.IsTainted) //We ONLY set the IsTainted under this lock, so we can trust it
  117. m_taintedPresences.Add(presence);
  118. presence.Taints |= taint;
  119. }
  120. }
  121. protected internal void UpdateEntities()
  122. {
  123. IScenePresence[] presences;
  124. lock (m_taintedPresencesLock)
  125. {
  126. presences = new IScenePresence[m_taintedPresences.Count];
  127. m_taintedPresences.CopyTo(presences);
  128. m_taintedPresences.Clear();
  129. }
  130. foreach (IScenePresence presence in presences)
  131. {
  132. presence.IsTainted = false;
  133. //We set this first so that it is cleared out, but also so that the method can re-taint us
  134. presence.Update();
  135. }
  136. }
  137. protected internal void UpdatePhysics(double elapsed)
  138. {
  139. if (_PhyScene == null)
  140. return;
  141. lock (m_syncRoot)
  142. {
  143. // Update DisableCollisions
  144. _PhyScene.DisableCollisions = m_regInfo.RegionSettings.DisableCollisions;
  145. // Here is where the Scene calls the PhysicsScene. This is a one-way
  146. // interaction; the PhysicsScene cannot access the calling Scene directly.
  147. // But with joints, we want a PhysicsActor to be able to influence a
  148. // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
  149. // with a joint should be able to move the SceneObjectPart which is the visual
  150. // representation of that joint (for editing and serialization purposes).
  151. // However the PhysicsActor normally cannot directly influence anything outside
  152. // of the PhysicsScene, and the non-physical SceneObjectPart which represents
  153. // the joint in the Scene does not exist in the PhysicsScene.
  154. //
  155. // To solve this, we have an event in the PhysicsScene that is fired when a joint
  156. // has changed position (because one of its associated PhysicsActors has changed
  157. // position).
  158. //
  159. // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
  160. _PhyScene.Simulate((float) elapsed);
  161. }
  162. }
  163. private List<Vector3> m_oldCoarseLocations = new List<Vector3>();
  164. private List<UUID> m_oldAvatarUUIDs = new List<UUID>();
  165. public bool GetCoarseLocations(out List<Vector3> coarseLocations, out List<UUID> avatarUUIDs, uint maxLocations)
  166. {
  167. coarseLocations = new List<Vector3>();
  168. avatarUUIDs = new List<UUID>();
  169. List<IScenePresence> presences = GetScenePresences();
  170. for (int i = 0; i < Math.Min(presences.Count, maxLocations); i++)
  171. {
  172. IScenePresence sp = presences[i];
  173. // If this presence is a child agent, we don't want its coarse locations
  174. if (sp.IsChildAgent)
  175. continue;
  176. if (sp.ParentID != UUID.Zero)
  177. {
  178. // sitting avatar
  179. ISceneChildEntity sop = m_parentScene.GetSceneObjectPart(sp.ParentID);
  180. if (sop != null)
  181. {
  182. coarseLocations.Add(sop.AbsolutePosition + sp.OffsetPosition);
  183. avatarUUIDs.Add(sp.UUID);
  184. }
  185. else
  186. {
  187. // we can't find the parent.. ! arg!
  188. MainConsole.Instance.Warn("Could not find parent prim for avatar " + sp.Name);
  189. coarseLocations.Add(sp.AbsolutePosition);
  190. avatarUUIDs.Add(sp.UUID);
  191. }
  192. }
  193. else
  194. {
  195. coarseLocations.Add(sp.AbsolutePosition);
  196. avatarUUIDs.Add(sp.UUID);
  197. }
  198. }
  199. if (m_oldCoarseLocations.Count == coarseLocations.Count)
  200. {
  201. List<UUID> foundAvies = new List<UUID>(m_oldAvatarUUIDs);
  202. foreach (UUID t in avatarUUIDs)
  203. {
  204. foundAvies.Remove(t);
  205. }
  206. if (foundAvies.Count == 0)
  207. {
  208. //All avies are still the same, check their locations now
  209. for (int i = 0; i < avatarUUIDs.Count; i++)
  210. {
  211. if (m_oldCoarseLocations[i].ApproxEquals(coarseLocations[i], 5))
  212. continue;
  213. m_oldCoarseLocations = coarseLocations;
  214. m_oldAvatarUUIDs = avatarUUIDs;
  215. return true;
  216. }
  217. //Things are still close enough to the same
  218. return false;
  219. }
  220. }
  221. m_oldCoarseLocations = coarseLocations;
  222. m_oldAvatarUUIDs = avatarUUIDs;
  223. //Its changed, tell it to send new
  224. return true;
  225. }
  226. #endregion
  227. #region Entity Methods
  228. protected internal void HandleUndo(IClientAPI remoteClient, UUID primId)
  229. {
  230. if (primId != UUID.Zero)
  231. {
  232. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(primId);
  233. if (part != null)
  234. if (m_parentScene.Permissions.CanEditObject(part.UUID, remoteClient.AgentId))
  235. part.Undo();
  236. }
  237. }
  238. protected internal void HandleRedo(IClientAPI remoteClient, UUID primId)
  239. {
  240. if (primId != UUID.Zero)
  241. {
  242. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(primId);
  243. if (part != null)
  244. if (m_parentScene.Permissions.CanEditObject(part.UUID, remoteClient.AgentId))
  245. part.Redo();
  246. }
  247. }
  248. protected internal void HandleObjectGroupUpdate(
  249. IClientAPI remoteClient, UUID GroupID, uint LocalID, UUID Garbage)
  250. {
  251. IEntity entity;
  252. if (TryGetEntity(LocalID, out entity))
  253. {
  254. if (m_parentScene.Permissions.CanEditObject(entity.UUID, remoteClient.AgentId))
  255. if (((ISceneEntity) entity).OwnerID == remoteClient.AgentId)
  256. ((ISceneEntity) entity).SetGroup(GroupID, remoteClient.AgentId, true);
  257. }
  258. }
  259. /// <summary>
  260. /// Add a presence to the scene
  261. /// </summary>
  262. /// <param name="presence"></param>
  263. protected internal void AddScenePresence(IScenePresence presence)
  264. {
  265. AddEntity(presence, true);
  266. }
  267. /// <summary>
  268. /// Remove a presence from the scene
  269. /// </summary>
  270. protected internal void RemoveScenePresence(IEntity agent)
  271. {
  272. if (!Entities.Remove(agent))
  273. {
  274. MainConsole.Instance.WarnFormat(
  275. "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
  276. agent.UUID);
  277. return;
  278. }
  279. }
  280. #endregion
  281. #region Get Methods
  282. /// <summary>
  283. /// Get a reference to the scene presence list. Changes to the list will be done in a copy
  284. /// There is no guarantee that presences will remain in the scene after the list is returned.
  285. /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
  286. /// pass a delegate to ForEachScenePresence.
  287. /// </summary>
  288. /// <returns></returns>
  289. public List<IScenePresence> GetScenePresences()
  290. {
  291. return Entities.GetPresences();
  292. }
  293. /// <summary>
  294. /// Request a scene presence by UUID. Fast, indexed lookup.
  295. /// </summary>
  296. /// <param name="agentID"></param>
  297. /// <returns>null if the presence was not found</returns>
  298. protected internal IScenePresence GetScenePresence(UUID agentID)
  299. {
  300. IScenePresence sp;
  301. Entities.TryGetPresenceValue(agentID, out sp);
  302. return sp;
  303. }
  304. /// <summary>
  305. /// Request the scene presence by name.
  306. /// NOTE: Depricated, use the ScenePresence GetScenePresence (string Name) instead!
  307. /// </summary>
  308. /// <param name="firstName"></param>
  309. /// <param name="lastName"></param>
  310. /// <returns>null if the presence was not found</returns>
  311. public IScenePresence GetScenePresence(string firstName, string lastName)
  312. {
  313. List<IScenePresence> presences = GetScenePresences();
  314. return presences.FirstOrDefault(presence => presence.Firstname == firstName && presence.Lastname == lastName);
  315. }
  316. /// <summary>
  317. /// Request the scene presence by localID.
  318. /// </summary>
  319. /// <param name="localID"></param>
  320. /// <returns>null if the presence was not found</returns>
  321. public IScenePresence GetScenePresence(uint localID)
  322. {
  323. List<IScenePresence> presences = GetScenePresences();
  324. return presences.FirstOrDefault(presence => presence.LocalId == localID);
  325. }
  326. protected internal bool TryGetScenePresence(UUID agentID, out IScenePresence avatar)
  327. {
  328. return Entities.TryGetPresenceValue(agentID, out avatar);
  329. }
  330. protected internal bool TryGetAvatarByName(string name, out IScenePresence avatar)
  331. {
  332. avatar =
  333. GetScenePresences()
  334. .FirstOrDefault(presence => String.Compare(name, presence.ControllingClient.Name, true) == 0);
  335. return (avatar != null);
  336. }
  337. /// <summary>
  338. /// Get a scene object group that contains the prim with the given uuid
  339. /// </summary>
  340. /// <param name="hray"></param>
  341. /// <param name="frontFacesOnly"></param>
  342. /// <param name="faceCenters"></param>
  343. /// <returns>null if no scene object group containing that prim is found</returns>
  344. protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
  345. {
  346. // Primitive Ray Tracing
  347. float closestDistance = 280f;
  348. EntityIntersection result = new EntityIntersection();
  349. ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, closestDistance);
  350. foreach (ISceneEntity ent in EntityList)
  351. {
  352. if (ent is SceneObjectGroup)
  353. {
  354. SceneObjectGroup reportingG = (SceneObjectGroup) ent;
  355. EntityIntersection inter = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
  356. if (inter.HitTF && inter.distance < closestDistance)
  357. {
  358. closestDistance = inter.distance;
  359. result = inter;
  360. }
  361. }
  362. }
  363. return result;
  364. }
  365. /// <summary>
  366. /// Gets a list of scene object group that intersect with the given ray
  367. /// </summary>
  368. public List<EntityIntersection> GetIntersectingPrims(Ray hray, float length, int count,
  369. bool frontFacesOnly, bool faceCenters, bool getAvatars,
  370. bool getLand, bool getPrims)
  371. {
  372. // Primitive Ray Tracing
  373. List<EntityIntersection> result = new List<EntityIntersection>(count);
  374. if (getPrims)
  375. {
  376. ISceneEntity[] EntityList = Entities.GetEntities(hray.Origin, length);
  377. result.AddRange(
  378. EntityList.OfType<SceneObjectGroup>()
  379. .Select(reportingG => reportingG.TestIntersection(hray, frontFacesOnly, faceCenters))
  380. .Where(inter => inter.HitTF));
  381. }
  382. if (getAvatars)
  383. {
  384. List<IScenePresence> presenceList = Entities.GetPresences();
  385. foreach (IScenePresence ent in presenceList)
  386. {
  387. //Do rough approximation and keep the # of loops down
  388. Vector3 newPos = hray.Origin;
  389. for (int i = 0; i < 100; i++)
  390. {
  391. newPos += ((Vector3.One*(length*(i/100)))*hray.Direction);
  392. if (ent.AbsolutePosition.ApproxEquals(newPos, ent.PhysicsActor.Size.X*2))
  393. {
  394. EntityIntersection intersection = new EntityIntersection();
  395. intersection.distance = length*(i/100);
  396. intersection.face = 0;
  397. intersection.HitTF = true;
  398. intersection.obj = ent;
  399. intersection.ipoint = newPos;
  400. intersection.normal = newPos;
  401. result.Add(intersection);
  402. break;
  403. }
  404. }
  405. }
  406. }
  407. if (getLand)
  408. {
  409. //TODO
  410. }
  411. result.Sort((a, b) => a.distance.CompareTo(b.distance));
  412. if (result.Count > count)
  413. result.RemoveRange(count, result.Count - count);
  414. return result;
  415. }
  416. #endregion
  417. #region ForEach* Methods
  418. /// <summary>
  419. /// Performs action on all scene object groups.
  420. /// </summary>
  421. /// <param name="action"></param>
  422. protected internal void ForEachSceneEntity(Action<ISceneEntity> action)
  423. {
  424. ISceneEntity[] objlist = Entities.GetEntities();
  425. foreach (ISceneEntity obj in objlist)
  426. {
  427. try
  428. {
  429. action(obj);
  430. }
  431. catch (Exception e)
  432. {
  433. // Catch it and move on. This includes situations where splist has inconsistent info
  434. MainConsole.Instance.WarnFormat("[SCENE]: Problem processing action in ForEachSOG: {0}",
  435. e.ToString());
  436. }
  437. }
  438. }
  439. /// <summary>
  440. /// Performs action on all scene presences. This can ultimately run the actions in parallel but
  441. /// any delegates passed in will need to implement their own locking on data they reference and
  442. /// modify outside of the scope of the delegate.
  443. /// </summary>
  444. /// <param name="action"></param>
  445. public void ForEachScenePresence(Action<IScenePresence> action)
  446. {
  447. // Once all callers have their delegates configured for parallelism, we can unleash this
  448. /*
  449. Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp)
  450. {
  451. try
  452. {
  453. action(sp);
  454. }
  455. catch (Exception e)
  456. {
  457. MainConsole.Instance.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  458. MainConsole.Instance.Info("[BUG] Stack Trace: " + e.StackTrace);
  459. }
  460. });
  461. Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
  462. */
  463. // For now, perform actions serially
  464. List<IScenePresence> presences = new List<IScenePresence>(GetScenePresences());
  465. foreach (IScenePresence sp in presences)
  466. {
  467. try
  468. {
  469. action(sp);
  470. }
  471. catch (Exception e)
  472. {
  473. MainConsole.Instance.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  474. MainConsole.Instance.Info("[BUG] Stack Trace: " + e.StackTrace);
  475. }
  476. }
  477. }
  478. #endregion ForEach* Methods
  479. #region Client Event handlers
  480. public void SubscribeToClientEvents(IClientAPI client)
  481. {
  482. client.OnUpdatePrimGroupPosition += UpdatePrimPosition;
  483. client.OnUpdatePrimSinglePosition += UpdatePrimSinglePosition;
  484. client.OnUpdatePrimGroupRotation += UpdatePrimRotation;
  485. client.OnUpdatePrimGroupMouseRotation += UpdatePrimRotation;
  486. client.OnUpdatePrimSingleRotation += UpdatePrimSingleRotation;
  487. client.OnUpdatePrimSingleRotationPosition += UpdatePrimSingleRotationPosition;
  488. client.OnUpdatePrimScale += UpdatePrimScale;
  489. client.OnUpdatePrimGroupScale += UpdatePrimGroupScale;
  490. client.OnUpdateExtraParams += UpdateExtraParam;
  491. client.OnUpdatePrimShape += UpdatePrimShape;
  492. client.OnUpdatePrimTexture += UpdatePrimTexture;
  493. client.OnGrabUpdate += MoveObject;
  494. client.OnSpinStart += SpinStart;
  495. client.OnSpinUpdate += SpinObject;
  496. client.OnObjectName += PrimName;
  497. client.OnObjectClickAction += PrimClickAction;
  498. client.OnObjectMaterial += PrimMaterial;
  499. client.OnLinkObjects += LinkObjects;
  500. client.OnDelinkObjects += DelinkObjects;
  501. client.OnObjectDuplicate += DuplicateObject;
  502. client.OnUpdatePrimFlags += UpdatePrimFlags;
  503. client.OnRequestObjectPropertiesFamily += RequestObjectPropertiesFamily;
  504. client.OnObjectPermissions += HandleObjectPermissionsUpdate;
  505. client.OnGrabObject += ProcessObjectGrab;
  506. client.OnGrabUpdate += ProcessObjectGrabUpdate;
  507. client.OnDeGrabObject += ProcessObjectDeGrab;
  508. client.OnUndo += HandleUndo;
  509. client.OnRedo += HandleRedo;
  510. client.OnObjectDescription += PrimDescription;
  511. client.OnObjectIncludeInSearch += MakeObjectSearchable;
  512. client.OnObjectOwner += ObjectOwner;
  513. client.OnObjectGroupRequest += HandleObjectGroupUpdate;
  514. client.OnAddPrim += AddNewPrim;
  515. client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay;
  516. }
  517. public void UnSubscribeToClientEvents(IClientAPI client)
  518. {
  519. client.OnUpdatePrimGroupPosition -= UpdatePrimPosition;
  520. client.OnUpdatePrimSinglePosition -= UpdatePrimSinglePosition;
  521. client.OnUpdatePrimGroupRotation -= UpdatePrimRotation;
  522. client.OnUpdatePrimGroupMouseRotation -= UpdatePrimRotation;
  523. client.OnUpdatePrimSingleRotation -= UpdatePrimSingleRotation;
  524. client.OnUpdatePrimSingleRotationPosition -= UpdatePrimSingleRotationPosition;
  525. client.OnUpdatePrimScale -= UpdatePrimScale;
  526. client.OnUpdatePrimGroupScale -= UpdatePrimGroupScale;
  527. client.OnUpdateExtraParams -= UpdateExtraParam;
  528. client.OnUpdatePrimShape -= UpdatePrimShape;
  529. client.OnUpdatePrimTexture -= UpdatePrimTexture;
  530. client.OnGrabUpdate -= MoveObject;
  531. client.OnSpinStart -= SpinStart;
  532. client.OnSpinUpdate -= SpinObject;
  533. client.OnObjectName -= PrimName;
  534. client.OnObjectClickAction -= PrimClickAction;
  535. client.OnObjectMaterial -= PrimMaterial;
  536. client.OnLinkObjects -= LinkObjects;
  537. client.OnDelinkObjects -= DelinkObjects;
  538. client.OnObjectDuplicate -= DuplicateObject;
  539. client.OnUpdatePrimFlags -= UpdatePrimFlags;
  540. client.OnRequestObjectPropertiesFamily -= RequestObjectPropertiesFamily;
  541. client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
  542. client.OnGrabObject -= ProcessObjectGrab;
  543. client.OnGrabUpdate -= ProcessObjectGrabUpdate;
  544. client.OnDeGrabObject -= ProcessObjectDeGrab;
  545. client.OnUndo -= HandleUndo;
  546. client.OnRedo -= HandleRedo;
  547. client.OnObjectDescription -= PrimDescription;
  548. client.OnObjectIncludeInSearch -= MakeObjectSearchable;
  549. client.OnObjectOwner -= ObjectOwner;
  550. client.OnObjectGroupRequest -= HandleObjectGroupUpdate;
  551. client.OnAddPrim -= AddNewPrim;
  552. client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay;
  553. }
  554. public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient,
  555. List<SurfaceTouchEventArgs> surfaceArgs)
  556. {
  557. SurfaceTouchEventArgs surfaceArg = null;
  558. if (surfaceArgs != null && surfaceArgs.Count > 0)
  559. surfaceArg = surfaceArgs[0];
  560. ISceneChildEntity childPrim;
  561. if (TryGetPart(localID, out childPrim))
  562. {
  563. SceneObjectPart part = childPrim as SceneObjectPart;
  564. if (part != null)
  565. {
  566. SceneObjectGroup obj = part.ParentGroup;
  567. if (obj.RootPart.BlockGrab || obj.RootPart.BlockGrabObject)
  568. return;
  569. // Currently only grab/touch for the single prim
  570. // the client handles rez correctly
  571. obj.ObjectGrabHandler(localID, offsetPos, remoteClient);
  572. // If the touched prim handles touches, deliver it
  573. // If not, deliver to root prim
  574. m_parentScene.EventManager.TriggerObjectGrab(part, part, part.OffsetPosition, remoteClient,
  575. surfaceArg);
  576. // Deliver to the root prim if the touched prim doesn't handle touches
  577. // or if we're meant to pass on touches anyway. Don't send to root prim
  578. // if prim touched is the root prim as we just did it
  579. if ((part.LocalId != obj.RootPart.LocalId))
  580. {
  581. const int PASS_IF_NOT_HANDLED = 0;
  582. const int PASS_ALWAYS = 1;
  583. const int PASS_NEVER = 2;
  584. if (part.PassTouch == PASS_NEVER)
  585. {
  586. }
  587. if (part.PassTouch == PASS_ALWAYS)
  588. {
  589. m_parentScene.EventManager.TriggerObjectGrab(obj.RootPart, part, part.OffsetPosition,
  590. remoteClient, surfaceArg);
  591. }
  592. else if (((part.ScriptEvents & scriptEvents.touch_start) == 0) &&
  593. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  594. {
  595. m_parentScene.EventManager.TriggerObjectGrab(obj.RootPart, part, part.OffsetPosition,
  596. remoteClient, surfaceArg);
  597. }
  598. }
  599. }
  600. }
  601. }
  602. public virtual void ProcessObjectGrabUpdate(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient,
  603. List<SurfaceTouchEventArgs> surfaceArgs)
  604. {
  605. SurfaceTouchEventArgs surfaceArg = null;
  606. if (surfaceArgs != null && surfaceArgs.Count > 0)
  607. surfaceArg = surfaceArgs[0];
  608. ISceneChildEntity childPrim;
  609. if (TryGetPart(objectID, out childPrim))
  610. {
  611. SceneObjectPart part = childPrim as SceneObjectPart;
  612. if (part != null)
  613. {
  614. SceneObjectGroup obj = part.ParentGroup;
  615. if (obj.RootPart.BlockGrab || obj.RootPart.BlockGrabObject)
  616. return;
  617. // If the touched prim handles touches, deliver it
  618. // If not, deliver to root prim
  619. m_parentScene.EventManager.TriggerObjectGrabbing(part, part, part.OffsetPosition, remoteClient,
  620. surfaceArg);
  621. // Deliver to the root prim if the touched prim doesn't handle touches
  622. // or if we're meant to pass on touches anyway. Don't send to root prim
  623. // if prim touched is the root prim as we just did it
  624. if ((part.LocalId != obj.RootPart.LocalId))
  625. {
  626. const int PASS_IF_NOT_HANDLED = 0;
  627. const int PASS_ALWAYS = 1;
  628. const int PASS_NEVER = 2;
  629. if (part.PassTouch == PASS_NEVER)
  630. {
  631. }
  632. if (part.PassTouch == PASS_ALWAYS)
  633. {
  634. m_parentScene.EventManager.TriggerObjectGrabbing(obj.RootPart, part, part.OffsetPosition,
  635. remoteClient, surfaceArg);
  636. }
  637. else if ((((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
  638. ((part.ScriptEvents & scriptEvents.touch) == 0)) &&
  639. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  640. {
  641. m_parentScene.EventManager.TriggerObjectGrabbing(obj.RootPart, part, part.OffsetPosition,
  642. remoteClient, surfaceArg);
  643. }
  644. }
  645. }
  646. }
  647. }
  648. public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient,
  649. List<SurfaceTouchEventArgs> surfaceArgs)
  650. {
  651. SurfaceTouchEventArgs surfaceArg = null;
  652. if (surfaceArgs != null && surfaceArgs.Count > 0)
  653. surfaceArg = surfaceArgs[0];
  654. ISceneChildEntity childPrim;
  655. if (TryGetPart(localID, out childPrim))
  656. {
  657. SceneObjectPart part = childPrim as SceneObjectPart;
  658. if (part != null)
  659. {
  660. SceneObjectGroup obj = part.ParentGroup;
  661. // If the touched prim handles touches, deliver it
  662. // If not, deliver to root prim
  663. m_parentScene.EventManager.TriggerObjectDeGrab(part, part, remoteClient, surfaceArg);
  664. if ((part.LocalId != obj.RootPart.LocalId))
  665. {
  666. const int PASS_IF_NOT_HANDLED = 0;
  667. const int PASS_ALWAYS = 1;
  668. const int PASS_NEVER = 2;
  669. if (part.PassTouch == PASS_NEVER)
  670. {
  671. }
  672. if (part.PassTouch == PASS_ALWAYS)
  673. {
  674. m_parentScene.EventManager.TriggerObjectDeGrab(obj.RootPart, part, remoteClient, surfaceArg);
  675. }
  676. else if ((((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
  677. ((part.ScriptEvents & scriptEvents.touch_end) == 0)) &&
  678. part.PassTouch == PASS_IF_NOT_HANDLED) //If no event in this prim, pass to parent
  679. {
  680. m_parentScene.EventManager.TriggerObjectDeGrab(obj.RootPart, part, remoteClient,
  681. surfaceArg);
  682. }
  683. }
  684. }
  685. }
  686. }
  687. /// <summary>
  688. /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
  689. /// </summary>
  690. /// <param name="RayStart"></param>
  691. /// <param name="RayEnd"></param>
  692. /// <param name="RayTargetID"></param>
  693. /// <param name="rot"></param>
  694. /// <param name="bypassRayCast"></param>
  695. /// <param name="RayEndIsIntersection"></param>
  696. /// <param name="frontFacesOnly"></param>
  697. /// <param name="scale"></param>
  698. /// <param name="FaceCenter"></param>
  699. /// <returns></returns>
  700. public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot,
  701. byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly,
  702. Vector3 scale, bool FaceCenter)
  703. {
  704. Vector3 pos = Vector3.Zero;
  705. if (RayEndIsIntersection == 1)
  706. {
  707. pos = RayEnd;
  708. return pos;
  709. }
  710. if (RayTargetID != UUID.Zero)
  711. {
  712. ISceneChildEntity target = m_parentScene.GetSceneObjectPart(RayTargetID);
  713. Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
  714. Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
  715. Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
  716. if (target != null)
  717. {
  718. pos = target.AbsolutePosition;
  719. //MainConsole.Instance.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
  720. // TODO: Raytrace better here
  721. //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
  722. Ray NewRay = new Ray(AXOrigin, AXdirection);
  723. // Ray Trace against target here
  724. EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
  725. FaceCenter);
  726. // Un-comment out the following line to Get Raytrace results printed to the console.
  727. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  728. float ScaleOffset = 0.5f;
  729. // If we hit something
  730. if (ei.HitTF)
  731. {
  732. Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
  733. if (scaleComponent.X != 0) ScaleOffset = scale.X;
  734. if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
  735. if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
  736. ScaleOffset = Math.Abs(ScaleOffset);
  737. Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
  738. Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
  739. // Set the position to the intersection point
  740. Vector3 offset = (normal*(ScaleOffset/2f));
  741. pos = (intersectionpoint + offset);
  742. //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
  743. //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
  744. // Un-offset the prim (it gets offset later by the consumer method)
  745. //pos.Z -= 0.25F;
  746. }
  747. return pos;
  748. }
  749. else
  750. {
  751. // We don't have a target here, so we're going to raytrace all the objects in the scene.
  752. EntityIntersection ei = GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
  753. // Un-comment the following line to print the raytrace results to the console.
  754. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  755. pos = ei.HitTF ? new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z) : RayEnd;
  756. return pos;
  757. }
  758. }
  759. // fall back to our stupid functionality
  760. pos = RayEnd;
  761. //increase height so its above the ground.
  762. //should be getting the normal of the ground at the rez point and using that?
  763. pos.Z += scale.Z/2f;
  764. return pos;
  765. }
  766. public virtual void AddNewPrim(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot,
  767. PrimitiveBaseShape shape,
  768. byte bypassRaycast, Vector3 RayStart, UUID RayTargetID,
  769. byte RayEndIsIntersection)
  770. {
  771. Vector3 pos = GetNewRezLocation(RayStart, RayEnd, RayTargetID, rot, bypassRaycast, RayEndIsIntersection,
  772. true, new Vector3(0.5f, 0.5f, 0.5f), false);
  773. string reason;
  774. if (m_parentScene.Permissions.CanRezObject(1, ownerID, pos, out reason))
  775. {
  776. AddNewPrim(ownerID, groupID, pos, rot, shape);
  777. }
  778. else
  779. {
  780. GetScenePresence(ownerID)
  781. .ControllingClient.SendAlertMessage("You do not have permission to rez objects here: " + reason);
  782. }
  783. }
  784. /// <summary>
  785. /// Create a New SceneObjectGroup/Part by raycasting
  786. /// </summary>
  787. /// <param name="ownerID"></param>
  788. /// <param name="groupID"></param>
  789. /// <param name="pos"></param>
  790. /// <param name="rot"></param>
  791. /// <param name="shape"></param>
  792. public virtual ISceneEntity AddNewPrim(
  793. UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
  794. {
  795. SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape, m_DefaultObjectName,
  796. m_parentScene);
  797. // If an entity creator has been registered for this prim type then use that
  798. if (m_entityCreators.ContainsKey((PCode) shape.PCode))
  799. {
  800. sceneObject =
  801. (SceneObjectGroup)
  802. m_entityCreators[(PCode) shape.PCode].CreateEntity(sceneObject, ownerID, groupID, pos, rot, shape);
  803. }
  804. else
  805. {
  806. // Otherwise, use this default creation code;
  807. sceneObject.SetGroup(groupID, ownerID, false);
  808. AddPrimToScene(sceneObject);
  809. sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  810. }
  811. return sceneObject;
  812. }
  813. /// <summary>
  814. /// Duplicates object specified by localID at position raycasted against RayTargetObject using
  815. /// RayEnd and RayStart to determine what the angle of the ray is
  816. /// </summary>
  817. /// <param name="localID">ID of object to duplicate</param>
  818. /// <param name="dupeFlags"></param>
  819. /// <param name="AgentID">Agent doing the duplication</param>
  820. /// <param name="GroupID">Group of new object</param>
  821. /// <param name="RayTargetObj">The target of the Ray</param>
  822. /// <param name="RayEnd">The ending of the ray (farthest away point)</param>
  823. /// <param name="RayStart">The Beginning of the ray (closest point)</param>
  824. /// <param name="BypassRaycast">Bool to bypass raycasting</param>
  825. /// <param name="RayEndIsIntersection">The End specified is the place to add the object</param>
  826. /// <param name="CopyCenters">Position the object at the center of the face that it's colliding with</param>
  827. /// <param name="CopyRotates">Rotate the object the same as the localID object</param>
  828. public void doObjectDuplicateOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID,
  829. UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart,
  830. bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters,
  831. bool CopyRotates)
  832. {
  833. const bool frontFacesOnly = true;
  834. //MainConsole.Instance.Info("HITTARGET: " + RayTargetObj.ToString() + ", COPYTARGET: " + localID.ToString());
  835. ISceneChildEntity target = m_parentScene.GetSceneObjectPart(localID);
  836. ISceneChildEntity target2 = m_parentScene.GetSceneObjectPart(RayTargetObj);
  837. IScenePresence Sp = GetScenePresence(AgentID);
  838. if (target != null && target2 != null)
  839. {
  840. Vector3 pos;
  841. if (EnableFakeRaycasting)
  842. {
  843. RayStart = Sp.CameraPosition;
  844. RayEnd = pos = target2.AbsolutePosition;
  845. }
  846. Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
  847. Vector3 AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z);
  848. Vector3 AXdirection = new Vector3(direction.X, direction.Y, direction.Z);
  849. if (target2.ParentEntity != null)
  850. {
  851. pos = target2.AbsolutePosition;
  852. // TODO: Raytrace better here
  853. //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), false, false);
  854. Ray NewRay = new Ray(AXOrigin, AXdirection);
  855. // Ray Trace against target here
  856. EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly,
  857. CopyCenters);
  858. // Un-comment out the following line to Get Raytrace results printed to the console.
  859. //MainConsole.Instance.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
  860. float ScaleOffset = 0.5f;
  861. // If we hit something
  862. if (ei.HitTF)
  863. {
  864. Vector3 scale = target.Scale;
  865. Vector3 scaleComponent = new Vector3(ei.AAfaceNormal.X, ei.AAfaceNormal.Y, ei.AAfaceNormal.Z);
  866. if (scaleComponent.X != 0) ScaleOffset = scale.X;
  867. if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
  868. if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
  869. ScaleOffset = Math.Abs(ScaleOffset);
  870. Vector3 intersectionpoint = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
  871. Vector3 normal = new Vector3(ei.normal.X, ei.normal.Y, ei.normal.Z);
  872. Vector3 offset = normal*(ScaleOffset/2f);
  873. pos = intersectionpoint + offset;
  874. // stick in offset format from the original prim
  875. pos = pos - target.ParentEntity.AbsolutePosition;
  876. if (CopyRotates)
  877. {
  878. Quaternion worldRot = target2.GetWorldRotation();
  879. // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
  880. DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
  881. //obj.Rotation = worldRot;
  882. //obj.UpdateGroupRotationR(worldRot);
  883. }
  884. else
  885. {
  886. DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID,
  887. Quaternion.Identity);
  888. }
  889. }
  890. return;
  891. }
  892. return;
  893. }
  894. }
  895. /// <value>
  896. /// Registered classes that are capable of creating entities.
  897. /// </value>
  898. protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
  899. public void RegisterEntityCreatorModule(IEntityCreator entityCreator)
  900. {
  901. lock (m_entityCreators)
  902. {
  903. foreach (PCode pcode in entityCreator.CreationCapabilities)
  904. {
  905. m_entityCreators[pcode] = entityCreator;
  906. }
  907. }
  908. }
  909. /// <summary>
  910. /// Unregister a module commander and all its commands
  911. /// </summary>
  912. /// <param name="entityCreator"></param>
  913. public void UnregisterEntityCreatorCommander(IEntityCreator entityCreator)
  914. {
  915. lock (m_entityCreators)
  916. {
  917. foreach (PCode pcode in entityCreator.CreationCapabilities)
  918. {
  919. m_entityCreators[pcode] = null;
  920. }
  921. }
  922. }
  923. protected internal void ObjectOwner(IClientAPI remoteClient, UUID ownerID, UUID groupID, List<uint> localIDs)
  924. {
  925. if (!m_parentScene.Permissions.IsGod(remoteClient.AgentId))
  926. {
  927. if (ownerID != UUID.Zero)
  928. return;
  929. if (!m_parentScene.Permissions.CanDeedObject(remoteClient.AgentId, groupID))
  930. return;
  931. }
  932. List<ISceneEntity> groups = new List<ISceneEntity>();
  933. foreach (uint localID in localIDs)
  934. {
  935. ISceneChildEntity part = m_parentScene.GetSceneObjectPart(localID);
  936. if (!groups.Contains(part.ParentEntity))
  937. groups.Add(part.ParentEntity);
  938. }
  939. foreach (ISceneEntity sog in groups)
  940. {
  941. if (ownerID != UUID.Zero)
  942. {
  943. sog.SetOwnerId(ownerID);
  944. sog.SetGroup(groupID, remoteClient.AgentId, true);
  945. sog.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  946. foreach (ISceneChildEntity child in sog.ChildrenEntities())
  947. child.Inventory.ChangeInventoryOwner(ownerID);
  948. }
  949. else
  950. {
  951. if (!m_parentScene.Permissions.CanEd

Large files files are truncated, but you can click here to view the full file