SceneGraph.cs 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171
  1. /*
  2. * Copyright (c) Contributors, 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 OpenSimulator 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 System;
  28. using System.Threading;
  29. using System.Collections.Generic;
  30. using System.Reflection;
  31. using OpenMetaverse;
  32. using OpenMetaverse.Packets;
  33. using log4net;
  34. using OpenSim.Framework;
  35. using OpenSim.Region.Framework.Scenes.Types;
  36. using OpenSim.Region.PhysicsModules.SharedBase;
  37. using OpenSim.Region.Framework.Interfaces;
  38. namespace OpenSim.Region.Framework.Scenes
  39. {
  40. public delegate void PhysicsCrash();
  41. public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
  42. public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
  43. public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
  44. /// <summary>
  45. /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
  46. /// should be migrated out over time.
  47. /// </summary>
  48. public class SceneGraph
  49. {
  50. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  51. #region Events
  52. protected internal event PhysicsCrash UnRecoverableError;
  53. private PhysicsCrash handlerPhysicsCrash = null;
  54. public event AttachToBackupDelegate OnAttachToBackup;
  55. public event DetachFromBackupDelegate OnDetachFromBackup;
  56. public event ChangedBackupDelegate OnChangeBackup;
  57. #endregion
  58. #region Fields
  59. protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
  60. protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
  61. protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
  62. protected internal EntityManager Entities = new EntityManager();
  63. protected Scene m_parentScene;
  64. protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
  65. protected int m_numRootAgents = 0;
  66. protected int m_numTotalPrim = 0;
  67. protected int m_numPrim = 0;
  68. protected int m_numMesh = 0;
  69. protected int m_numChildAgents = 0;
  70. protected int m_physicalPrim = 0;
  71. protected int m_activeScripts = 0;
  72. protected int m_scriptLPS = 0;
  73. protected internal PhysicsScene _PhyScene;
  74. /// <summary>
  75. /// Index the SceneObjectGroup for each part by the root part's UUID.
  76. /// </summary>
  77. protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
  78. /// <summary>
  79. /// Index the SceneObjectGroup for each part by that part's UUID.
  80. /// </summary>
  81. protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>();
  82. /// <summary>
  83. /// Index the SceneObjectGroup for each part by that part's local ID.
  84. /// </summary>
  85. protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
  86. /// <summary>
  87. /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently.
  88. /// </summary>
  89. /// <remarks>
  90. /// These operations rely on the parts composition of the object. If allowed to run concurrently then race
  91. /// conditions can occur.
  92. /// </remarks>
  93. private Object m_updateLock = new Object();
  94. #endregion
  95. protected internal SceneGraph(Scene parent)
  96. {
  97. m_parentScene = parent;
  98. }
  99. public PhysicsScene PhysicsScene
  100. {
  101. get
  102. {
  103. if (_PhyScene == null)
  104. _PhyScene = m_parentScene.RequestModuleInterface<PhysicsScene>();
  105. return _PhyScene;
  106. }
  107. set
  108. {
  109. // If we're not doing the initial set
  110. // Then we've got to remove the previous
  111. // event handler
  112. if (_PhyScene != null)
  113. _PhyScene.OnPhysicsCrash -= physicsBasedCrash;
  114. _PhyScene = value;
  115. if (_PhyScene != null)
  116. _PhyScene.OnPhysicsCrash += physicsBasedCrash;
  117. }
  118. }
  119. protected internal void Close()
  120. {
  121. m_scenePresencesLock.EnterWriteLock();
  122. try
  123. {
  124. Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
  125. List<ScenePresence> newlist = new List<ScenePresence>();
  126. m_scenePresenceMap = newmap;
  127. m_scenePresenceArray = newlist;
  128. }
  129. finally
  130. {
  131. m_scenePresencesLock.ExitWriteLock();
  132. }
  133. lock (SceneObjectGroupsByFullID)
  134. SceneObjectGroupsByFullID.Clear();
  135. lock (SceneObjectGroupsByFullPartID)
  136. SceneObjectGroupsByFullPartID.Clear();
  137. lock (SceneObjectGroupsByLocalPartID)
  138. SceneObjectGroupsByLocalPartID.Clear();
  139. Entities.Clear();
  140. }
  141. #region Update Methods
  142. protected internal void UpdatePreparePhysics()
  143. {
  144. // If we are using a threaded physics engine
  145. // grab the latest scene from the engine before
  146. // trying to process it.
  147. // PhysX does this (runs in the background).
  148. if (PhysicsScene.IsThreaded)
  149. {
  150. PhysicsScene.GetResults();
  151. }
  152. }
  153. /// <summary>
  154. /// Update the position of all the scene presences.
  155. /// </summary>
  156. /// <remarks>
  157. /// Called only from the main scene loop.
  158. /// </remarks>
  159. protected internal void UpdatePresences()
  160. {
  161. ForEachScenePresence(delegate(ScenePresence presence)
  162. {
  163. presence.Update();
  164. });
  165. }
  166. /// <summary>
  167. /// Perform a physics frame update.
  168. /// </summary>
  169. /// <param name="elapsed"></param>
  170. /// <returns></returns>
  171. protected internal float UpdatePhysics(double elapsed)
  172. {
  173. // Here is where the Scene calls the PhysicsScene. This is a one-way
  174. // interaction; the PhysicsScene cannot access the calling Scene directly.
  175. // But with joints, we want a PhysicsActor to be able to influence a
  176. // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
  177. // with a joint should be able to move the SceneObjectPart which is the visual
  178. // representation of that joint (for editing and serialization purposes).
  179. // However the PhysicsActor normally cannot directly influence anything outside
  180. // of the PhysicsScene, and the non-physical SceneObjectPart which represents
  181. // the joint in the Scene does not exist in the PhysicsScene.
  182. //
  183. // To solve this, we have an event in the PhysicsScene that is fired when a joint
  184. // has changed position (because one of its associated PhysicsActors has changed
  185. // position).
  186. //
  187. // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
  188. return PhysicsScene.Simulate((float)elapsed);
  189. }
  190. protected internal void ProcessPhysicsPreSimulation()
  191. {
  192. if(PhysicsScene != null)
  193. PhysicsScene.ProcessPreSimulation();
  194. }
  195. protected internal void UpdateScenePresenceMovement()
  196. {
  197. ForEachScenePresence(delegate(ScenePresence presence)
  198. {
  199. presence.UpdateMovement();
  200. });
  201. }
  202. public void GetCoarseLocations(out List<Vector3> coarseLocations, out List<UUID> avatarUUIDs, uint maxLocations)
  203. {
  204. coarseLocations = new List<Vector3>();
  205. avatarUUIDs = new List<UUID>();
  206. // coarse locations are sent as BYTE, so limited to the 255m max of normal regions
  207. // try to work around that scale down X and Y acording to region size, so reducing the resolution
  208. //
  209. // viewers need to scale up
  210. float scaleX = (float)m_parentScene.RegionInfo.RegionSizeX / (float)Constants.RegionSize;
  211. if (scaleX == 0)
  212. scaleX = 1.0f;
  213. scaleX = 1.0f / scaleX;
  214. float scaleY = (float)m_parentScene.RegionInfo.RegionSizeY / (float)Constants.RegionSize;
  215. if (scaleY == 0)
  216. scaleY = 1.0f;
  217. scaleY = 1.0f / scaleY;
  218. List<ScenePresence> presences = GetScenePresences();
  219. for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i)
  220. {
  221. ScenePresence sp = presences[i];
  222. // If this presence is a child agent, we don't want its coarse locations
  223. if (sp.IsChildAgent)
  224. continue;
  225. Vector3 pos = sp.AbsolutePosition;
  226. pos.X *= scaleX;
  227. pos.Y *= scaleY;
  228. coarseLocations.Add(pos);
  229. avatarUUIDs.Add(sp.UUID);
  230. }
  231. }
  232. #endregion
  233. #region Entity Methods
  234. /// <summary>
  235. /// Add an object into the scene that has come from storage
  236. /// </summary>
  237. /// <param name="sceneObject"></param>
  238. /// <param name="attachToBackup">
  239. /// If true, changes to the object will be reflected in its persisted data
  240. /// If false, the persisted data will not be changed even if the object in the scene is changed
  241. /// </param>
  242. /// <param name="alreadyPersisted">
  243. /// If true, we won't persist this object until it changes
  244. /// If false, we'll persist this object immediately
  245. /// </param>
  246. /// <param name="sendClientUpdates">
  247. /// If true, we send updates to the client to tell it about this object
  248. /// If false, we leave it up to the caller to do this
  249. /// </param>
  250. /// <returns>
  251. /// true if the object was added, false if an object with the same uuid was already in the scene
  252. /// </returns>
  253. protected internal bool AddRestoredSceneObject(
  254. SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
  255. {
  256. // temporary checks to remove after varsize suport
  257. float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
  258. if (regionSizeX == 0)
  259. regionSizeX = Constants.RegionSize;
  260. float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
  261. if (regionSizeY == 0)
  262. regionSizeY = Constants.RegionSize;
  263. // KF: Check for out-of-region, move inside and make static.
  264. Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
  265. sceneObject.RootPart.GroupPosition.Y,
  266. sceneObject.RootPart.GroupPosition.Z);
  267. bool clampZ = m_parentScene.ClampNegativeZ;
  268. if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || (npos.Z < 0.0 && clampZ) ||
  269. npos.X > regionSizeX ||
  270. npos.Y > regionSizeY))
  271. {
  272. if (npos.X < 0.0) npos.X = 1.0f;
  273. if (npos.Y < 0.0) npos.Y = 1.0f;
  274. if (npos.Z < 0.0 && clampZ) npos.Z = 0.0f;
  275. if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
  276. if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
  277. SceneObjectPart rootpart = sceneObject.RootPart;
  278. rootpart.GroupPosition = npos;
  279. foreach (SceneObjectPart part in sceneObject.Parts)
  280. {
  281. if (part == rootpart)
  282. continue;
  283. part.GroupPosition = npos;
  284. }
  285. rootpart.Velocity = Vector3.Zero;
  286. rootpart.AngularVelocity = Vector3.Zero;
  287. rootpart.Acceleration = Vector3.Zero;
  288. }
  289. bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
  290. if (attachToBackup && (!alreadyPersisted))
  291. {
  292. sceneObject.ForceInventoryPersistence();
  293. sceneObject.HasGroupChanged = true;
  294. }
  295. sceneObject.InvalidateDeepEffectivePerms();
  296. return ret;
  297. }
  298. /// <summary>
  299. /// Add a newly created object to the scene. This will both update the scene, and send information about the
  300. /// new object to all clients interested in the scene.
  301. /// </summary>
  302. /// <param name="sceneObject"></param>
  303. /// <param name="attachToBackup">
  304. /// If true, the object is made persistent into the scene.
  305. /// If false, the object will not persist over server restarts
  306. /// </param>
  307. /// <returns>
  308. /// true if the object was added, false if an object with the same uuid was already in the scene
  309. /// </returns>
  310. protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
  311. {
  312. bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
  313. // Ensure that we persist this new scene object if it's not an
  314. // attachment
  315. if (attachToBackup)
  316. sceneObject.HasGroupChanged = true;
  317. return ret;
  318. }
  319. /// <summary>
  320. /// Add a newly created object to the scene.
  321. /// </summary>
  322. ///
  323. /// This method does not send updates to the client - callers need to handle this themselves.
  324. /// Caller should also trigger EventManager.TriggerObjectAddedToScene
  325. /// <param name="sceneObject"></param>
  326. /// <param name="attachToBackup"></param>
  327. /// <param name="pos">Position of the object. If null then the position stored in the object is used.</param>
  328. /// <param name="rot">Rotation of the object. If null then the rotation stored in the object is used.</param>
  329. /// <param name="vel">Velocity of the object. This parameter only has an effect if the object is physical</param>
  330. /// <returns></returns>
  331. public bool AddNewSceneObject(
  332. SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
  333. {
  334. if (pos != null)
  335. sceneObject.AbsolutePosition = (Vector3)pos;
  336. if (rot != null)
  337. sceneObject.UpdateGroupRotationR((Quaternion)rot);
  338. AddNewSceneObject(sceneObject, attachToBackup, false);
  339. if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim)
  340. {
  341. sceneObject.ClearPartAttachmentData();
  342. }
  343. PhysicsActor pa = sceneObject.RootPart.PhysActor;
  344. if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
  345. {
  346. sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
  347. }
  348. return true;
  349. }
  350. /// <summary>
  351. /// Add an object to the scene. This will both update the scene, and send information about the
  352. /// new object to all clients interested in the scene.
  353. /// </summary>
  354. /// <remarks>
  355. /// The object's stored position, rotation and velocity are used.
  356. /// </remarks>
  357. /// <param name="sceneObject"></param>
  358. /// <param name="attachToBackup">
  359. /// If true, the object is made persistent into the scene.
  360. /// If false, the object will not persist over server restarts
  361. /// </param>
  362. /// <param name="sendClientUpdates">
  363. /// If true, updates for the new scene object are sent to all viewers in range.
  364. /// If false, it is left to the caller to schedule the update
  365. /// </param>
  366. /// <returns>
  367. /// true if the object was added, false if an object with the same uuid was already in the scene
  368. /// </returns>
  369. protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
  370. {
  371. if (sceneObject == null)
  372. {
  373. m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
  374. return false;
  375. }
  376. if (sceneObject.UUID == UUID.Zero)
  377. {
  378. m_log.ErrorFormat(
  379. "[SCENEGRAPH]: Tried to add scene object {0} to {1} with illegal UUID of {2}",
  380. sceneObject.Name, m_parentScene.RegionInfo.RegionName, UUID.Zero);
  381. return false;
  382. }
  383. if (Entities.ContainsKey(sceneObject.UUID))
  384. {
  385. m_log.DebugFormat(
  386. "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()",
  387. m_parentScene.RegionInfo.RegionName, sceneObject.UUID);
  388. return false;
  389. }
  390. // m_log.DebugFormat(
  391. // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
  392. // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
  393. SceneObjectPart[] parts = sceneObject.Parts;
  394. // Clamp the sizes (scales) of the child prims and add the child prims to the count of all primitives
  395. // (meshes and geometric primitives) in the scene; add child prims to m_numTotalPrim count
  396. if (m_parentScene.m_clampPrimSize)
  397. {
  398. foreach (SceneObjectPart part in parts)
  399. {
  400. Vector3 scale = part.Shape.Scale;
  401. scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
  402. scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
  403. scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
  404. part.Shape.Scale = scale;
  405. }
  406. }
  407. m_numTotalPrim += parts.Length;
  408. // Go through all parts (geometric primitives and meshes) of this Scene Object
  409. foreach (SceneObjectPart part in parts)
  410. {
  411. // Keep track of the total number of meshes or geometric primitives now in the scene;
  412. // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to
  413. // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives
  414. if (part.GetPrimType() == PrimType.SCULPT)
  415. m_numMesh++;
  416. else
  417. m_numPrim++;
  418. }
  419. sceneObject.AttachToScene(m_parentScene);
  420. Entities.Add(sceneObject);
  421. lock (SceneObjectGroupsByFullID)
  422. SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
  423. foreach (SceneObjectPart part in parts)
  424. {
  425. lock (SceneObjectGroupsByFullPartID)
  426. SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
  427. lock (SceneObjectGroupsByLocalPartID)
  428. SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
  429. }
  430. if (sendClientUpdates)
  431. sceneObject.ScheduleGroupForFullUpdate();
  432. if (attachToBackup)
  433. sceneObject.AttachToBackup();
  434. return true;
  435. }
  436. public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
  437. {
  438. // no tests, caller has responsability...
  439. lock (SceneObjectGroupsByFullPartID)
  440. SceneObjectGroupsByFullPartID[part.UUID] = grp;
  441. lock (SceneObjectGroupsByLocalPartID)
  442. SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
  443. }
  444. /// <summary>
  445. /// Delete an object from the scene
  446. /// </summary>
  447. /// <returns>true if the object was deleted, false if there was no object to delete</returns>
  448. public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
  449. {
  450. // m_log.DebugFormat(
  451. // "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
  452. // uuid, resultOfObjectLinked);
  453. EntityBase entity;
  454. if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup)))
  455. return false;
  456. SceneObjectGroup grp = (SceneObjectGroup)entity;
  457. if (entity == null)
  458. return false;
  459. if (!resultOfObjectLinked)
  460. {
  461. // Decrement the total number of primitives (meshes and geometric primitives)
  462. // that are part of the Scene Object being removed
  463. m_numTotalPrim -= grp.PrimCount;
  464. bool isPh = (grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics;
  465. int nphysparts = 0;
  466. // Go through all parts (primitives and meshes) of this Scene Object
  467. foreach (SceneObjectPart part in grp.Parts)
  468. {
  469. // Keep track of the total number of meshes or geometric primitives left in the scene;
  470. // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to
  471. // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives
  472. if (part.GetPrimType() == PrimType.SCULPT)
  473. m_numMesh--;
  474. else
  475. m_numPrim--;
  476. if(isPh && part.PhysicsShapeType != (byte)PhysShapeType.none)
  477. nphysparts++;
  478. }
  479. if (nphysparts > 0 )
  480. RemovePhysicalPrim(nphysparts);
  481. }
  482. bool ret = Entities.Remove(uuid);
  483. lock (SceneObjectGroupsByFullID)
  484. SceneObjectGroupsByFullID.Remove(grp.UUID);
  485. SceneObjectPart[] parts = grp.Parts;
  486. for (int i = 0; i < parts.Length; i++)
  487. {
  488. lock (SceneObjectGroupsByFullPartID)
  489. SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
  490. lock (SceneObjectGroupsByLocalPartID)
  491. SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
  492. }
  493. return ret;
  494. }
  495. /// <summary>
  496. /// Add an object to the list of prims to process on the next update
  497. /// </summary>
  498. /// <param name="obj">
  499. /// A <see cref="SceneObjectGroup"/>
  500. /// </param>
  501. protected internal void AddToUpdateList(SceneObjectGroup obj)
  502. {
  503. lock (m_updateList)
  504. m_updateList[obj.UUID] = obj;
  505. }
  506. public void FireAttachToBackup(SceneObjectGroup obj)
  507. {
  508. if (OnAttachToBackup != null)
  509. {
  510. OnAttachToBackup(obj);
  511. }
  512. }
  513. public void FireDetachFromBackup(SceneObjectGroup obj)
  514. {
  515. if (OnDetachFromBackup != null)
  516. {
  517. OnDetachFromBackup(obj);
  518. }
  519. }
  520. public void FireChangeBackup(SceneObjectGroup obj)
  521. {
  522. if (OnChangeBackup != null)
  523. {
  524. OnChangeBackup(obj);
  525. }
  526. }
  527. /// <summary>
  528. /// Process all pending updates
  529. /// </summary>
  530. protected internal void UpdateObjectGroups()
  531. {
  532. if (!Monitor.TryEnter(m_updateLock))
  533. return;
  534. try
  535. {
  536. List<SceneObjectGroup> updates;
  537. // Some updates add more updates to the updateList.
  538. // Get the current list of updates and clear the list before iterating
  539. lock (m_updateList)
  540. {
  541. updates = new List<SceneObjectGroup>(m_updateList.Values);
  542. m_updateList.Clear();
  543. }
  544. // Go through all updates
  545. for (int i = 0; i < updates.Count; i++)
  546. {
  547. SceneObjectGroup sog = updates[i];
  548. // Don't abort the whole update if one entity happens to give us an exception.
  549. try
  550. {
  551. sog.Update();
  552. }
  553. catch (Exception e)
  554. {
  555. m_log.ErrorFormat(
  556. "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e);
  557. }
  558. }
  559. }
  560. finally
  561. {
  562. Monitor.Exit(m_updateLock);
  563. }
  564. }
  565. protected internal void AddPhysicalPrim(int number)
  566. {
  567. m_physicalPrim += number;
  568. }
  569. protected internal void RemovePhysicalPrim(int number)
  570. {
  571. m_physicalPrim -= number;
  572. }
  573. protected internal void AddToScriptLPS(int number)
  574. {
  575. m_scriptLPS += number;
  576. }
  577. protected internal void AddActiveScripts(int number)
  578. {
  579. m_activeScripts += number;
  580. }
  581. protected internal void HandleUndo(IClientAPI remoteClient, UUID primId)
  582. {
  583. if (primId != UUID.Zero)
  584. {
  585. SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
  586. if (part != null)
  587. part.Undo();
  588. }
  589. }
  590. protected internal void HandleRedo(IClientAPI remoteClient, UUID primId)
  591. {
  592. if (primId != UUID.Zero)
  593. {
  594. SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
  595. if (part != null)
  596. part.Redo();
  597. }
  598. }
  599. protected internal ScenePresence CreateAndAddChildScenePresence(
  600. IClientAPI client, AvatarAppearance appearance, PresenceType type)
  601. {
  602. // ScenePresence always defaults to child agent
  603. ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
  604. Entities[presence.UUID] = presence;
  605. m_scenePresencesLock.EnterWriteLock();
  606. try
  607. {
  608. m_numChildAgents++;
  609. Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
  610. List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
  611. if (!newmap.ContainsKey(presence.UUID))
  612. {
  613. newmap.Add(presence.UUID, presence);
  614. newlist.Add(presence);
  615. }
  616. else
  617. {
  618. // Remember the old presence reference from the dictionary
  619. ScenePresence oldref = newmap[presence.UUID];
  620. // Replace the presence reference in the dictionary with the new value
  621. newmap[presence.UUID] = presence;
  622. // Find the index in the list where the old ref was stored and update the reference
  623. newlist[newlist.IndexOf(oldref)] = presence;
  624. }
  625. // Swap out the dictionary and list with new references
  626. m_scenePresenceMap = newmap;
  627. m_scenePresenceArray = newlist;
  628. }
  629. finally
  630. {
  631. m_scenePresencesLock.ExitWriteLock();
  632. }
  633. return presence;
  634. }
  635. /// <summary>
  636. /// Remove a presence from the scene
  637. /// </summary>
  638. protected internal void RemoveScenePresence(UUID agentID)
  639. {
  640. if (!Entities.Remove(agentID))
  641. {
  642. m_log.WarnFormat(
  643. "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
  644. agentID);
  645. }
  646. m_scenePresencesLock.EnterWriteLock();
  647. try
  648. {
  649. Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
  650. List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
  651. // Remove the presence reference from the dictionary
  652. if (newmap.ContainsKey(agentID))
  653. {
  654. ScenePresence oldref = newmap[agentID];
  655. newmap.Remove(agentID);
  656. // Find the index in the list where the old ref was stored and remove the reference
  657. newlist.RemoveAt(newlist.IndexOf(oldref));
  658. // Swap out the dictionary and list with new references
  659. m_scenePresenceMap = newmap;
  660. m_scenePresenceArray = newlist;
  661. }
  662. else
  663. {
  664. m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
  665. }
  666. }
  667. finally
  668. {
  669. m_scenePresencesLock.ExitWriteLock();
  670. }
  671. }
  672. protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
  673. {
  674. if (direction_RC_CR_T_F)
  675. {
  676. m_numRootAgents--;
  677. m_numChildAgents++;
  678. }
  679. else
  680. {
  681. m_numChildAgents--;
  682. m_numRootAgents++;
  683. }
  684. }
  685. public void removeUserCount(bool TypeRCTF)
  686. {
  687. if (TypeRCTF)
  688. {
  689. m_numRootAgents--;
  690. }
  691. else
  692. {
  693. m_numChildAgents--;
  694. }
  695. }
  696. public void RecalculateStats()
  697. {
  698. int rootcount = 0;
  699. int childcount = 0;
  700. ForEachScenePresence(delegate(ScenePresence presence)
  701. {
  702. if (presence.IsChildAgent)
  703. ++childcount;
  704. else
  705. ++rootcount;
  706. });
  707. m_numRootAgents = rootcount;
  708. m_numChildAgents = childcount;
  709. }
  710. public int GetChildAgentCount()
  711. {
  712. return m_numChildAgents;
  713. }
  714. public int GetRootAgentCount()
  715. {
  716. return m_numRootAgents;
  717. }
  718. public int GetTotalObjectsCount()
  719. {
  720. return m_numTotalPrim;
  721. }
  722. public int GetTotalPrimObjectsCount()
  723. {
  724. return m_numPrim;
  725. }
  726. public int GetTotalMeshObjectsCount()
  727. {
  728. return m_numMesh;
  729. }
  730. public int GetActiveObjectsCount()
  731. {
  732. return m_physicalPrim;
  733. }
  734. public int GetActiveScriptsCount()
  735. {
  736. return m_activeScripts;
  737. }
  738. public int GetScriptLPS()
  739. {
  740. int returnval = m_scriptLPS;
  741. m_scriptLPS = 0;
  742. return returnval;
  743. }
  744. #endregion
  745. #region Get Methods
  746. /// <summary>
  747. /// Get the controlling client for the given avatar, if there is one.
  748. ///
  749. /// FIXME: The only user of the method right now is Caps.cs, in order to resolve a client API since it can't
  750. /// use the ScenePresence. This could be better solved in a number of ways - we could establish an
  751. /// OpenSim.Framework.IScenePresence, or move the caps code into a region package (which might be the more
  752. /// suitable solution).
  753. /// </summary>
  754. /// <param name="agentId"></param>
  755. /// <returns>null if either the avatar wasn't in the scene, or
  756. /// they do not have a controlling client</returns>
  757. /// <remarks>this used to be protected internal, but that
  758. /// prevents CapabilitiesModule from accessing it</remarks>
  759. public IClientAPI GetControllingClient(UUID agentId)
  760. {
  761. ScenePresence presence = GetScenePresence(agentId);
  762. if (presence != null)
  763. {
  764. return presence.ControllingClient;
  765. }
  766. return null;
  767. }
  768. /// <summary>
  769. /// Get a reference to the scene presence list. Changes to the list will be done in a copy
  770. /// There is no guarantee that presences will remain in the scene after the list is returned.
  771. /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
  772. /// pass a delegate to ForEachScenePresence.
  773. /// </summary>
  774. /// <returns></returns>
  775. protected internal List<ScenePresence> GetScenePresences()
  776. {
  777. return m_scenePresenceArray;
  778. }
  779. /// <summary>
  780. /// Request a scene presence by UUID. Fast, indexed lookup.
  781. /// </summary>
  782. /// <param name="agentID"></param>
  783. /// <returns>null if the presence was not found</returns>
  784. protected internal ScenePresence GetScenePresence(UUID agentID)
  785. {
  786. Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
  787. ScenePresence presence;
  788. presences.TryGetValue(agentID, out presence);
  789. return presence;
  790. }
  791. /// <summary>
  792. /// Request the scene presence by name.
  793. /// </summary>
  794. /// <param name="firstName"></param>
  795. /// <param name="lastName"></param>
  796. /// <returns>null if the presence was not found</returns>
  797. protected internal ScenePresence GetScenePresence(string firstName, string lastName)
  798. {
  799. List<ScenePresence> presences = GetScenePresences();
  800. foreach (ScenePresence presence in presences)
  801. {
  802. if (string.Equals(presence.Firstname, firstName, StringComparison.CurrentCultureIgnoreCase)
  803. && string.Equals(presence.Lastname, lastName, StringComparison.CurrentCultureIgnoreCase))
  804. return presence;
  805. }
  806. return null;
  807. }
  808. /// <summary>
  809. /// Request the scene presence by localID.
  810. /// </summary>
  811. /// <param name="localID"></param>
  812. /// <returns>null if the presence was not found</returns>
  813. protected internal ScenePresence GetScenePresence(uint localID)
  814. {
  815. List<ScenePresence> presences = GetScenePresences();
  816. foreach (ScenePresence presence in presences)
  817. if (presence.LocalId == localID)
  818. return presence;
  819. return null;
  820. }
  821. protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
  822. {
  823. Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
  824. presences.TryGetValue(agentID, out avatar);
  825. return (avatar != null);
  826. }
  827. protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar)
  828. {
  829. avatar = null;
  830. foreach (ScenePresence presence in GetScenePresences())
  831. {
  832. if (String.Compare(name, presence.ControllingClient.Name, true) == 0)
  833. {
  834. avatar = presence;
  835. break;
  836. }
  837. }
  838. return (avatar != null);
  839. }
  840. /// <summary>
  841. /// Get a scene object group that contains the prim with the given local id
  842. /// </summary>
  843. /// <param name="localID"></param>
  844. /// <returns>null if no scene object group containing that prim is found</returns>
  845. public SceneObjectGroup GetGroupByPrim(uint localID)
  846. {
  847. EntityBase entity;
  848. if (Entities.TryGetValue(localID, out entity))
  849. return entity as SceneObjectGroup;
  850. // m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID);
  851. SceneObjectGroup sog;
  852. lock (SceneObjectGroupsByLocalPartID)
  853. SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
  854. if (sog != null)
  855. {
  856. if (sog.ContainsPart(localID))
  857. {
  858. // m_log.DebugFormat(
  859. // "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.",
  860. // sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
  861. return sog;
  862. }
  863. else
  864. {
  865. lock (SceneObjectGroupsByLocalPartID)
  866. {
  867. m_log.WarnFormat(
  868. "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
  869. sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
  870. m_log.WarnFormat("stack: {0}", Environment.StackTrace);
  871. SceneObjectGroupsByLocalPartID.Remove(localID);
  872. }
  873. }
  874. }
  875. EntityBase[] entityList = GetEntities();
  876. foreach (EntityBase ent in entityList)
  877. {
  878. //m_log.DebugFormat("Looking at entity {0}", ent.UUID);
  879. if (ent is SceneObjectGroup)
  880. {
  881. sog = (SceneObjectGroup)ent;
  882. if (sog.ContainsPart(localID))
  883. {
  884. lock (SceneObjectGroupsByLocalPartID)
  885. SceneObjectGroupsByLocalPartID[localID] = sog;
  886. return sog;
  887. }
  888. }
  889. }
  890. return null;
  891. }
  892. /// <summary>
  893. /// Get a scene object group that contains the prim with the given uuid
  894. /// </summary>
  895. /// <param name="fullID"></param>
  896. /// <returns>null if no scene object group containing that prim is found</returns>
  897. public SceneObjectGroup GetGroupByPrim(UUID fullID)
  898. {
  899. SceneObjectGroup sog;
  900. lock (SceneObjectGroupsByFullPartID)
  901. SceneObjectGroupsByFullPartID.TryGetValue(fullID, out sog);
  902. if (sog != null)
  903. {
  904. if (sog.ContainsPart(fullID))
  905. return sog;
  906. lock (SceneObjectGroupsByFullPartID)
  907. SceneObjectGroupsByFullPartID.Remove(fullID);
  908. }
  909. EntityBase[] entityList = GetEntities();
  910. foreach (EntityBase ent in entityList)
  911. {
  912. if (ent is SceneObjectGroup)
  913. {
  914. sog = (SceneObjectGroup)ent;
  915. if (sog.ContainsPart(fullID))
  916. {
  917. lock (SceneObjectGroupsByFullPartID)
  918. SceneObjectGroupsByFullPartID[fullID] = sog;
  919. return sog;
  920. }
  921. }
  922. }
  923. return null;
  924. }
  925. protected internal EntityIntersection GetClosestIntersectingPrim(Ray hray, bool frontFacesOnly, bool faceCenters)
  926. {
  927. // Primitive Ray Tracing
  928. float closestDistance = 280f;
  929. EntityIntersection result = new EntityIntersection();
  930. EntityBase[] EntityList = GetEntities();
  931. foreach (EntityBase ent in EntityList)
  932. {
  933. if (ent is SceneObjectGroup)
  934. {
  935. SceneObjectGroup reportingG = (SceneObjectGroup)ent;
  936. EntityIntersection inter = reportingG.TestIntersection(hray, frontFacesOnly, faceCenters);
  937. if (inter.HitTF && inter.distance < closestDistance)
  938. {
  939. closestDistance = inter.distance;
  940. result = inter;
  941. }
  942. }
  943. }
  944. return result;
  945. }
  946. /// <summary>
  947. /// Get all the scene object groups.
  948. /// </summary>
  949. /// <returns>
  950. /// The scene object groups. If the scene is empty then an empty list is returned.
  951. /// </returns>
  952. protected internal List<SceneObjectGroup> GetSceneObjectGroups()
  953. {
  954. lock (SceneObjectGroupsByFullID)
  955. return new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
  956. }
  957. /// <summary>
  958. /// Get a group in the scene
  959. /// </summary>
  960. /// <param name="fullID">UUID of the group</param>
  961. /// <returns>null if no such group was found</returns>
  962. protected internal SceneObjectGroup GetSceneObjectGroup(UUID fullID)
  963. {
  964. lock (SceneObjectGroupsByFullID)
  965. {
  966. if (SceneObjectGroupsByFullID.ContainsKey(fullID))
  967. return SceneObjectGroupsByFullID[fullID];
  968. }
  969. return null;
  970. }
  971. /// <summary>
  972. /// Get a group in the scene
  973. /// </summary>
  974. /// <remarks>
  975. /// This will only return a group if the local ID matches the root part, not other parts.
  976. /// </remarks>
  977. /// <param name="localID">Local id of the root part of the group</param>
  978. /// <returns>null if no such group was found</returns>
  979. protected internal SceneObjectGroup GetSceneObjectGroup(uint localID)
  980. {
  981. lock (SceneObjectGroupsByLocalPartID)
  982. {
  983. if (SceneObjectGroupsByLocalPartID.ContainsKey(localID))
  984. {
  985. SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID];
  986. if (so.LocalId == localID)
  987. return so;
  988. }
  989. }
  990. return null;
  991. }
  992. /// <summary>
  993. /// Get a group by name from the scene (will return the first
  994. /// found, if there are more than one prim with the same name)
  995. /// </summary>
  996. /// <param name="name"></param>
  997. /// <returns>null if the part was not found</returns>
  998. protected internal SceneObjectGroup GetSceneObjectGroup(string name)
  999. {
  1000. SceneObjectGroup so = null;
  1001. Entities.Find(
  1002. delegate(EntityBase entity)
  1003. {
  1004. if (entity is SceneObjectGroup)
  1005. {
  1006. if (entity.Name == name)
  1007. {
  1008. so = (SceneObjectGroup)entity;
  1009. return true;
  1010. }
  1011. }
  1012. return false;
  1013. }
  1014. );
  1015. return so;
  1016. }
  1017. /// <summary>
  1018. /// Get a part contained in this scene.
  1019. /// </summary>
  1020. /// <param name="localID"></param>
  1021. /// <returns>null if the part was not found</returns>
  1022. protected internal SceneObjectPart GetSceneObjectPart(uint localID)
  1023. {
  1024. SceneObjectGroup group = GetGroupByPrim(localID);
  1025. if (group == null || group.IsDeleted)
  1026. return null;
  1027. return group.GetPart(localID);
  1028. }
  1029. /// <summary>
  1030. /// Get a prim by name from the scene (will return the first
  1031. /// found, if there are more than one prim with the same name)
  1032. /// </summary>
  1033. /// <param name="name"></param>
  1034. /// <returns>null if the part was not found</returns>
  1035. protected internal SceneObjectPart GetSceneObjectPart(string name)
  1036. {
  1037. SceneObjectPart sop = null;
  1038. Entities.Find(
  1039. delegate(EntityBase entity)
  1040. {
  1041. if (entity is SceneObjectGroup)
  1042. {
  1043. foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
  1044. {
  1045. // m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name);
  1046. if (p.Name == name)
  1047. {
  1048. sop = p;
  1049. return true;
  1050. }
  1051. }
  1052. }
  1053. return false;
  1054. }
  1055. );
  1056. return sop;
  1057. }
  1058. /// <summary>
  1059. /// Get a part contained in this scene.
  1060. /// </summary>
  1061. /// <param name="fullID"></param>
  1062. /// <returns>null if the part was not found</returns>
  1063. protected internal SceneObjectPart GetSceneObjectPart(UUID fullID)
  1064. {
  1065. SceneObjectGroup group = GetGroupByPrim(fullID);
  1066. if (group == null)
  1067. return null;
  1068. return group.GetPart(fullID);
  1069. }
  1070. /// <summary>
  1071. /// Returns a list of the entities in the scene. This is a new list so no locking is required to iterate over
  1072. /// it
  1073. /// </summary>
  1074. /// <returns></returns>
  1075. protected internal EntityBase[] GetEntities()
  1076. {
  1077. return Entities.GetEntities();
  1078. }
  1079. #endregion
  1080. #region Other Methods
  1081. protected internal void physicsBasedCrash()
  1082. {
  1083. handlerPhysicsCrash = UnRecoverableError;
  1084. if (handlerPhysicsCrash != null)
  1085. {
  1086. handlerPhysicsCrash();
  1087. }
  1088. }
  1089. protected internal UUID ConvertLocalIDToFullID(uint localID)
  1090. {
  1091. SceneObjectGroup group = GetGroupByPrim(localID);
  1092. if (group != null)
  1093. return group.GetPartsFullID(localID);
  1094. else
  1095. return UUID.Zero;
  1096. }
  1097. /// <summary>
  1098. /// Performs action once on all scene object groups.
  1099. /// </summary>
  1100. /// <param name="action"></param>
  1101. protected internal void ForEachSOG(Action<SceneObjectGroup> action)
  1102. {
  1103. foreach (SceneObjectGroup obj in GetSceneObjectGroups())
  1104. {
  1105. try
  1106. {
  1107. action(obj);
  1108. }
  1109. catch (Exception e)
  1110. {
  1111. // Catch it and move on. This includes situations where objlist has inconsistent info
  1112. m_log.WarnFormat(
  1113. "[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}", e.Message, e.StackTrace);
  1114. }
  1115. }
  1116. }
  1117. /// <summary>
  1118. /// Performs action on all ROOT (not child) scene presences.
  1119. /// This is just a shortcut function since frequently actions only appy to root SPs
  1120. /// </summary>
  1121. /// <param name="action"></param>
  1122. public void ForEachAvatar(Action<ScenePresence> action)
  1123. {
  1124. ForEachScenePresence(delegate(ScenePresence sp)
  1125. {
  1126. if (!sp.IsChildAgent)
  1127. action(sp);
  1128. });
  1129. }
  1130. /// <summary>
  1131. /// Performs action on all scene presences. This can ultimately run the actions in parallel but
  1132. /// any delegates passed in will need to implement their own locking on data they reference and
  1133. /// modify outside of the scope of the delegate.
  1134. /// </summary>
  1135. /// <param name="action"></param>
  1136. public void ForEachScenePresence(Action<ScenePresence> action)
  1137. {
  1138. // Once all callers have their delegates configured for parallelism, we can unleash this
  1139. /*
  1140. Action<ScenePresence> protectedAction = new Action<ScenePresence>(delegate(ScenePresence sp)
  1141. {
  1142. try
  1143. {
  1144. action(sp);
  1145. }
  1146. catch (Exception e)
  1147. {
  1148. m_log.Info("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  1149. m_log.Info("[SCENEGRAPH]: Stack Trace: " + e.StackTrace);
  1150. }
  1151. });
  1152. Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
  1153. */
  1154. // For now, perform actions serially
  1155. List<ScenePresence> presences = GetScenePresences();
  1156. foreach (ScenePresence sp in presences)
  1157. {
  1158. try
  1159. {
  1160. action(sp);
  1161. }
  1162. catch (Exception e)
  1163. {
  1164. m_log.Error("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
  1165. }
  1166. }
  1167. }
  1168. #endregion
  1169. #region Client Event handlers
  1170. protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
  1171. {
  1172. SceneObjectPart part = GetSceneObjectPart(localID);
  1173. ObjectChangeData data = (ObjectChangeData)odata;
  1174. if (part != null)
  1175. {
  1176. SceneObjectGroup grp = part.ParentGroup;
  1177. if (grp != null)
  1178. {
  1179. if (m_parentScene.Permissions.CanEditObject(grp, remoteClient))
  1180. {
  1181. // These two are exceptions SL makes in the interpretation
  1182. // of the change flags. Must check them here because otherwise
  1183. // the group flag (see below) would be lost
  1184. if (data.change == ObjectChangeType.groupS)
  1185. data.change = ObjectChangeType.primS;
  1186. if (data.change == ObjectChangeType.groupPS)
  1187. data.change = ObjectChangeType.primPS;
  1188. part.StoreUndoState(data.change); // lets test only saving what we changed
  1189. grp.doChangeObject(part, (ObjectChangeData)data);
  1190. }
  1191. else
  1192. {
  1193. // Is this any kind of group operation?
  1194. if ((data.change & ObjectChangeType.Group) != 0)
  1195. {
  1196. // Is a move and/or rotation requested?
  1197. if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
  1198. {
  1199. // Are we allowed to move it?
  1200. if (m_parentScene.Permissions.CanMoveObject(grp, remoteClient))
  1201. {
  1202. // Strip all but move and rotation from request
  1203. data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
  1204. part.StoreUndoState(data.change);
  1205. grp.doChangeObject(part, (ObjectChangeData)data);
  1206. }
  1207. }
  1208. }
  1209. }
  1210. }
  1211. }
  1212. }
  1213. /// <summary>
  1214. /// Update the scale of an individual prim.
  1215. /// </summary>
  1216. /// <param name="localID"></param>
  1217. /// <param name="scale"></param>
  1218. /// <param name="remoteClient"></param>
  1219. protected internal void UpdatePrimScale(uint localID, Vector3 scale, IClientAPI remoteClient)
  1220. {
  1221. SceneObjectPart part = GetSceneObjectPart(localID);
  1222. if (part != null)
  1223. {
  1224. if (m_parentScene.Permissions.CanEditObject(part.ParentGroup, remoteClient))
  1225. {
  1226. bool physbuild = false;
  1227. if (part.ParentGroup.RootPart.PhysActor != null)
  1228. {
  1229. part.ParentGroup.RootPart.PhysActor.Building = true;
  1230. physbuild = true;
  1231. }
  1232. part.Resize(scale);
  1233. if (physbuild)
  1234. part.ParentGroup.RootPart.PhysActor.Building = false;
  1235. }
  1236. }
  1237. }
  1238. protected internal void UpdatePrimGroupScale(uint localID, Vector3 scale, IClientAPI remoteClient)
  1239. {
  1240. SceneObjectGroup group = GetGroupByPrim(localID);
  1241. if (group != null)
  1242. {
  1243. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1244. {
  1245. bool physbuild = false;
  1246. if (group.RootPart.PhysActor != null)
  1247. {
  1248. group.RootPart.PhysActor.Building = true;
  1249. physbuild = true;
  1250. }
  1251. group.GroupResize(scale);
  1252. if (physbuild)
  1253. group.RootPart.PhysActor.Building = false;
  1254. }
  1255. }
  1256. }
  1257. /// <summary>
  1258. /// This handles the nifty little tool tip that you get when you drag your mouse over an object
  1259. /// Send to the Object Group to process. We don't know enough to service the request
  1260. /// </summary>
  1261. /// <param name="remoteClient"></param>
  1262. /// <param name="AgentID"></param>
  1263. /// <param name="RequestFlags"></param>
  1264. /// <param name="ObjectID"></param>
  1265. protected internal void RequestObjectPropertiesFamily(
  1266. IClientAPI remoteClient, UUID AgentID, uint RequestFlags, UUID ObjectID)
  1267. {
  1268. SceneObjectGroup group = GetGroupByPrim(ObjectID);
  1269. if (group != null)
  1270. {
  1271. group.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
  1272. }
  1273. }
  1274. /// <summary>
  1275. ///
  1276. /// </summary>
  1277. /// <param name="localID"></param>
  1278. /// <param name="rot"></param>
  1279. /// <param name="remoteClient"></param>
  1280. protected internal void UpdatePrimSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
  1281. {
  1282. SceneObjectGroup group = GetGroupByPrim(localID);
  1283. if (group != null)
  1284. {
  1285. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
  1286. {
  1287. group.UpdateSingleRotation(rot, localID);
  1288. }
  1289. }
  1290. }
  1291. /// <summary>
  1292. ///
  1293. /// </summary>
  1294. /// <param name="localID"></param>
  1295. /// <param name="rot"></param>
  1296. /// <param name="remoteClient"></param>
  1297. protected internal void UpdatePrimSingleRotationPosition(uint localID, Quaternion rot, Vector3 pos, IClientAPI remoteClient)
  1298. {
  1299. SceneObjectGroup group = GetGroupByPrim(localID);
  1300. if (group != null)
  1301. {
  1302. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
  1303. {
  1304. group.UpdateSingleRotation(rot, pos, localID);
  1305. }
  1306. }
  1307. }
  1308. /// <summary>
  1309. /// Update the rotation of a whole group.
  1310. /// </summary>
  1311. /// <param name="localID"></param>
  1312. /// <param name="rot"></param>
  1313. /// <param name="remoteClient"></param>
  1314. protected internal void UpdatePrimGroupRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
  1315. {
  1316. SceneObjectGroup group = GetGroupByPrim(localID);
  1317. if (group != null)
  1318. {
  1319. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
  1320. {
  1321. group.UpdateGroupRotationR(rot);
  1322. }
  1323. }
  1324. }
  1325. /// <summary>
  1326. ///
  1327. /// </summary>
  1328. /// <param name="localID"></param>
  1329. /// <param name="pos"></param>
  1330. /// <param name="rot"></param>
  1331. /// <param name="remoteClient"></param>
  1332. protected internal void UpdatePrimGroupRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient)
  1333. {
  1334. SceneObjectGroup group = GetGroupByPrim(localID);
  1335. if (group != null)
  1336. {
  1337. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
  1338. {
  1339. group.UpdateGroupRotationPR(pos, rot);
  1340. }
  1341. }
  1342. }
  1343. /// <summary>
  1344. /// Update the position of the given part
  1345. /// </summary>
  1346. /// <param name="localID"></param>
  1347. /// <param name="pos"></param>
  1348. /// <param name="remoteClient"></param>
  1349. protected internal void UpdatePrimSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient)
  1350. {
  1351. SceneObjectGroup group = GetGroupByPrim(localID);
  1352. if (group != null)
  1353. {
  1354. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) || group.IsAttachment)
  1355. {
  1356. group.UpdateSinglePosition(pos, localID);
  1357. }
  1358. }
  1359. }
  1360. /// <summary>
  1361. /// Update the position of the given group.
  1362. /// </summary>
  1363. /// <param name="localId"></param>
  1364. /// <param name="pos"></param>
  1365. /// <param name="remoteClient"></param>
  1366. public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient)
  1367. {
  1368. SceneObjectGroup group = GetGroupByPrim(localId);
  1369. if (group != null)
  1370. {
  1371. if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
  1372. {
  1373. // Set the new attachment point data in the object
  1374. byte attachmentPoint = (byte)group.AttachmentPoint;
  1375. group.UpdateGroupPosition(pos);
  1376. group.IsAttachment = false;
  1377. group.AbsolutePosition = group.RootPart.AttachedPos;
  1378. group.AttachmentPoint = attachmentPoint;
  1379. group.HasGroupChanged = true;
  1380. }
  1381. else
  1382. {
  1383. if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)
  1384. && m_parentScene.Permissions.CanObjectEntry(group, false, pos))
  1385. {
  1386. group.UpdateGroupPosition(pos);
  1387. }
  1388. }
  1389. }
  1390. }
  1391. /// <summary>
  1392. /// Update the texture entry of the given prim.
  1393. /// </summary>
  1394. /// <remarks>
  1395. /// A texture entry is an object that contains details of all the textures of the prim's face. In this case,
  1396. /// the texture is given in its byte serialized form.
  1397. /// </remarks>
  1398. /// <param name="localID"></param>
  1399. /// <param name="texture"></param>
  1400. /// <param name="remoteClient"></param>
  1401. protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient)
  1402. {
  1403. SceneObjectPart part = GetSceneObjectPart(localID);
  1404. if(part == null)
  1405. return;
  1406. SceneObjectGroup group = part.ParentGroup;
  1407. if (group != null && !group.IsDeleted)
  1408. {
  1409. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1410. {
  1411. part.UpdateTextureEntry(texture);
  1412. }
  1413. }
  1414. }
  1415. /// <summary>
  1416. /// Update the flags on a scene object. This covers properties such as phantom, physics and temporary.
  1417. /// </summary>
  1418. /// <remarks>
  1419. /// This is currently handling the incoming call from the client stack (e.g. LLClientView).
  1420. /// </remarks>
  1421. /// <param name="localID"></param>
  1422. /// <param name="UsePhysics"></param>
  1423. /// <param name="SetTemporary"></param>
  1424. /// <param name="SetPhantom"></param>
  1425. /// <param name="remoteClient"></param>
  1426. protected internal void UpdatePrimFlags(
  1427. uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
  1428. {
  1429. SceneObjectGroup group = GetGroupByPrim(localID);
  1430. if (group != null)
  1431. {
  1432. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1433. {
  1434. // VolumeDetect can't be set via UI and will always be off when a change is made there
  1435. // now only change volume dtc if phantom off
  1436. bool wantedPhys = UsePhysics;
  1437. if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
  1438. {
  1439. bool vdtc;
  1440. if (SetPhantom) // if phantom keep volumedtc
  1441. vdtc = group.RootPart.VolumeDetectActive;
  1442. else // else turn it off
  1443. vdtc = false;
  1444. group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc);
  1445. }
  1446. else
  1447. {
  1448. SceneObjectPart part = GetSceneObjectPart(localID);
  1449. if (part != null)
  1450. {
  1451. part.UpdateExtraPhysics(PhysData);
  1452. if (remoteClient != null)
  1453. remoteClient.SendPartPhysicsProprieties(part);
  1454. }
  1455. }
  1456. if (wantedPhys != group.UsesPhysics && remoteClient != null)
  1457. {
  1458. if(m_parentScene.m_linksetPhysCapacity != 0)
  1459. remoteClient.SendAlertMessage("Object physics cancelled because it exceeds limits for physical prims, either size or number of primswith shape type not set to None");
  1460. else
  1461. remoteClient.SendAlertMessage("Object physics cancelled because it exceeds size limits for physical prims");
  1462. group.RootPart.ScheduleFullUpdate();
  1463. }
  1464. }
  1465. }
  1466. }
  1467. /// <summary>
  1468. ///
  1469. /// </summary>
  1470. /// <param name="primLocalID"></param>
  1471. /// <param name="description"></param>
  1472. protected internal void PrimName(IClientAPI remoteClient, uint primLocalID, string name)
  1473. {
  1474. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1475. if (group != null)
  1476. {
  1477. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1478. {
  1479. group.SetPartName(Util.CleanString(name), primLocalID);
  1480. group.HasGroupChanged = true;
  1481. }
  1482. }
  1483. }
  1484. /// <summary>
  1485. /// Handle a prim description set request from a viewer.
  1486. /// </summary>
  1487. /// <param name="primLocalID"></param>
  1488. /// <param name="description"></param>
  1489. protected internal void PrimDescription(IClientAPI remoteClient, uint primLocalID, string description)
  1490. {
  1491. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1492. if (group != null)
  1493. {
  1494. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1495. {
  1496. group.SetPartDescription(Util.CleanString(description), primLocalID);
  1497. group.HasGroupChanged = true;
  1498. }
  1499. }
  1500. }
  1501. /// <summary>
  1502. /// Set a click action for the prim.
  1503. /// </summary>
  1504. /// <param name="remoteClient"></param>
  1505. /// <param name="primLocalID"></param>
  1506. /// <param name="clickAction"></param>
  1507. protected internal void PrimClickAction(IClientAPI remoteClient, uint primLocalID, string clickAction)
  1508. {
  1509. // m_log.DebugFormat(
  1510. // "[SCENEGRAPH]: User {0} set click action for {1} to {2}", remoteClient.Name, primLocalID, clickAction);
  1511. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1512. if (group != null)
  1513. {
  1514. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1515. {
  1516. SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
  1517. if (part != null)
  1518. {
  1519. part.ClickAction = Convert.ToByte(clickAction);
  1520. group.HasGroupChanged = true;
  1521. }
  1522. }
  1523. }
  1524. }
  1525. protected internal void PrimMaterial(IClientAPI remoteClient, uint primLocalID, string material)
  1526. {
  1527. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1528. if (group != null)
  1529. {
  1530. if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
  1531. {
  1532. SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
  1533. if (part != null)
  1534. {
  1535. part.Material = Convert.ToByte(material);
  1536. group.HasGroupChanged = true;
  1537. remoteClient.SendPartPhysicsProprieties(part);
  1538. }
  1539. }
  1540. }
  1541. }
  1542. protected internal void UpdateExtraParam(UUID agentID, uint primLocalID, ushort type, bool inUse, byte[] data)
  1543. {
  1544. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1545. if (group != null)
  1546. {
  1547. if (m_parentScene.Permissions.CanEditObject(group.UUID, agentID))
  1548. {
  1549. group.UpdateExtraParam(primLocalID, type, inUse, data);
  1550. }
  1551. }
  1552. }
  1553. /// <summary>
  1554. ///
  1555. /// </summary>
  1556. /// <param name="primLocalID"></param>
  1557. /// <param name="shapeBlock"></param>
  1558. protected internal void UpdatePrimShape(UUID agentID, uint primLocalID, UpdateShapeArgs shapeBlock)
  1559. {
  1560. SceneObjectGroup group = GetGroupByPrim(primLocalID);
  1561. if (group != null)
  1562. {
  1563. if (m_parentScene.Permissions.CanEditObject(group.UUID, agentID))
  1564. {
  1565. ObjectShapePacket.ObjectDataBlock shapeData = new ObjectShapePacket.ObjectDataBlock();
  1566. shapeData.ObjectLocalID = shapeBlock.ObjectLocalID;
  1567. shapeData.PathBegin = shapeBlock.PathBegin;
  1568. shapeData.PathCurve = shapeBlock.PathCurve;
  1569. shapeData.PathEnd = shapeBlock.PathEnd;
  1570. shapeData.PathRadiusOffset = shapeBlock.PathRadiusOffset;
  1571. shapeData.PathRevolutions = shapeBlock.PathRevolutions;
  1572. shapeData.PathScaleX = shapeBlock.PathScaleX;
  1573. shapeData.PathScaleY = shapeBlock.PathScaleY;
  1574. shapeData.PathShearX = shapeBlock.PathShearX;
  1575. shapeData.PathShearY = shapeBlock.PathShearY;
  1576. shapeData.PathSkew = shapeBlock.PathSkew;
  1577. shapeData.PathTaperX = shapeBlock.PathTaperX;
  1578. shapeData.PathTaperY = shapeBlock.PathTaperY;
  1579. shapeData.PathTwist = shapeBlock.PathTwist;
  1580. shapeData.PathTwistBegin = shapeBlock.PathTwistBegin;
  1581. shapeData.ProfileBegin = shapeBlock.ProfileBegin;
  1582. shapeData.ProfileCurve = shapeBlock.ProfileCurve;
  1583. shapeData.ProfileEnd = shapeBlock.ProfileEnd;
  1584. shapeData.ProfileHollow = shapeBlock.ProfileHollow;
  1585. group.UpdateShape(shapeData, primLocalID);
  1586. }
  1587. }
  1588. }
  1589. /// <summary>
  1590. /// Initial method invoked when we receive a link objects request from the client.
  1591. /// </summary>
  1592. /// <param name="client"></param>
  1593. /// <param name="parentPrim"></param>
  1594. /// <param name="childPrims"></param>
  1595. protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
  1596. {
  1597. if (root.KeyframeMotion != null)
  1598. {
  1599. root.KeyframeMotion.Stop();
  1600. root.KeyframeMotion = null;
  1601. }
  1602. SceneObjectGroup parentGroup = root.ParentGroup;
  1603. if (parentGroup == null) return;
  1604. // Cowardly refuse to link to a group owned root
  1605. if (parentGroup.OwnerID == parentGroup.GroupID)
  1606. return;
  1607. Monitor.Enter(m_updateLock);
  1608. try
  1609. {
  1610. List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
  1611. // We do this in reverse to get the link order of the prims correct
  1612. for (int i = 0; i < children.Count; i++)
  1613. {
  1614. SceneObjectGroup child = children[i].ParentGroup;
  1615. // Don't try and add a group to itself - this will only cause severe problems later on.
  1616. if (child == parentGroup)
  1617. continue;
  1618. // Make sure no child prim is set for sale
  1619. // So that, on delink, no prims are unwittingly
  1620. // left for sale and sold off
  1621. if (child != null)
  1622. {
  1623. child.RootPart.ObjectSaleType = 0;
  1624. child.RootPart.SalePrice = 10;
  1625. childGroups.Add(child);
  1626. }
  1627. }
  1628. foreach (SceneObjectGroup child in childGroups)
  1629. {
  1630. if (parentGroup.OwnerID == child.OwnerID)
  1631. {
  1632. parentGroup.LinkToGroup(child);
  1633. child.DetachFromBackup();
  1634. // this is here so physics gets updated!
  1635. // Don't remove! Bad juju! Stay away! or fix physics!
  1636. // already done in LinkToGroup
  1637. // child.AbsolutePosition = child.AbsolutePosition;
  1638. }
  1639. }
  1640. // We need to explicitly resend the newly link prim's object properties since no other actions
  1641. // occur on link to invoke this elsewhere (such as object selection)
  1642. if (childGroups.Count > 0)
  1643. {
  1644. parentGroup.RootPart.CreateSelected = true;
  1645. parentGroup.TriggerScriptChangedEvent(Changed.LINK);
  1646. parentGroup.HasGroupChanged = true;
  1647. parentGroup.ScheduleGroupForFullUpdate();
  1648. }
  1649. }
  1650. finally
  1651. {
  1652. /*
  1653. lock (SceneObjectGroupsByLocalPartID)
  1654. {
  1655. foreach (SceneObjectPart part in parentGroup.Parts)
  1656. SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
  1657. }
  1658. */
  1659. parentGroup.AdjustChildPrimPermissions(false);
  1660. parentGroup.HasGroupChanged = true;
  1661. parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
  1662. parentGroup.ScheduleGroupForFullUpdate();
  1663. Monitor.Exit(m_updateLock);
  1664. }
  1665. }
  1666. /// <summary>
  1667. /// Delink a linkset
  1668. /// </summary>
  1669. /// <param name="prims"></param>
  1670. protected internal void DelinkObjects(List<SceneObjectPart> prims)
  1671. {
  1672. Monitor.Enter(m_updateLock);
  1673. try
  1674. {
  1675. List<SceneObjectPart> childParts = new List<SceneObjectPart>();
  1676. List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
  1677. List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
  1678. // Look them all up in one go, since that is comparatively expensive
  1679. //
  1680. foreach (SceneObjectPart part in prims)
  1681. {
  1682. if(part == null)
  1683. continue;
  1684. SceneObjectGroup parentSOG = part.ParentGroup;
  1685. if(parentSOG == null ||
  1686. parentSOG.IsDeleted ||
  1687. parentSOG.inTransit ||
  1688. parentSOG.PrimCount == 1)
  1689. continue;
  1690. if (!affectedGroups.Contains(parentSOG))
  1691. {
  1692. affectedGroups.Add(parentSOG);
  1693. if(parentSOG.RootPart.PhysActor != null)
  1694. parentSOG.RootPart.PhysActor.Building = true;
  1695. }
  1696. if (part.KeyframeMotion != null)
  1697. {
  1698. part.KeyframeMotion.Stop();
  1699. part.KeyframeMotion = null;
  1700. }
  1701. if (part.LinkNum < 2) // Root
  1702. {
  1703. rootParts.Add(part);
  1704. }
  1705. else
  1706. {
  1707. part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID;
  1708. part.RezzerID = part.ParentGroup.RootPart.RezzerID;
  1709. childParts.Add(part);
  1710. }
  1711. }
  1712. if (childParts.Count > 0)
  1713. {
  1714. foreach (SceneObjectPart child in childParts)
  1715. {
  1716. // Unlink all child parts from their groups
  1717. child.ParentGroup.DelinkFromGroup(child, true);
  1718. //child.ParentGroup is now other
  1719. child.ParentGroup.HasGroupChanged = true;
  1720. child.ParentGroup.ScheduleGroupForFullUpdate();
  1721. }
  1722. }
  1723. foreach (SceneObjectPart root in rootParts)
  1724. {
  1725. // In most cases, this will run only one time, and the prim
  1726. // will be a solo prim
  1727. // However, editing linked parts and unlinking may be different
  1728. //
  1729. SceneObjectGroup group = root.ParentGroup;
  1730. List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
  1731. newSet.Remove(root);
  1732. int numChildren = newSet.Count;
  1733. if(numChildren == 0)
  1734. break;
  1735. foreach (SceneObjectPart p in newSet)
  1736. group.DelinkFromGroup(p, false);
  1737. SceneObjectPart newRoot = newSet[0];
  1738. // If there is more than one prim remaining, we
  1739. // need to re-link
  1740. //
  1741. if (numChildren > 1)
  1742. {
  1743. // Determine new root
  1744. //
  1745. newSet.RemoveAt(0);
  1746. foreach (SceneObjectPart newChild in newSet)
  1747. newChild.ClearUpdateSchedule();
  1748. LinkObjects(newRoot, newSet);
  1749. }
  1750. else
  1751. {
  1752. newRoot.TriggerScriptChangedEvent(Changed.LINK);
  1753. newRoot.ParentGroup.HasGroupChanged = true;
  1754. newRoot.ParentGroup.InvalidatePartsLinkMaps();
  1755. newRoot.ParentGroup.ScheduleGroupForFullUpdate();
  1756. }
  1757. }
  1758. // trigger events in the roots
  1759. //
  1760. foreach (SceneObjectGroup g in affectedGroups)
  1761. {
  1762. if(g.RootPart.PhysActor != null)
  1763. g.RootPart.PhysActor.Building = false;
  1764. g.AdjustChildPrimPermissions(false);
  1765. // Child prims that have been unlinked and deleted will
  1766. // return unless the root is deleted. This will remove them
  1767. // from the database. They will be rewritten immediately,
  1768. // minus the rows for the unlinked child prims.
  1769. m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
  1770. g.InvalidatePartsLinkMaps();
  1771. g.TriggerScriptChangedEvent(Changed.LINK);
  1772. g.HasGroupChanged = true; // Persist
  1773. g.ScheduleGroupForFullUpdate();
  1774. }
  1775. }
  1776. finally
  1777. {
  1778. Monitor.Exit(m_updateLock);
  1779. }
  1780. }
  1781. protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID)
  1782. {
  1783. SceneObjectGroup sog = GetGroupByPrim(localID);
  1784. if(sog == null)
  1785. return;
  1786. //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
  1787. //aka ObjectFlags.JointWheel = IncludeInSearch
  1788. //Permissions model: Object can be REMOVED from search IFF:
  1789. // * User owns object
  1790. //use CanEditObject
  1791. //Object can be ADDED to search IFF:
  1792. // * User owns object
  1793. // * Asset/DRM permission bit "modify" is enabled
  1794. //use CanEditObjectPosition
  1795. // libomv will complain about PrimFlags.JointWheel being
  1796. // deprecated, so we
  1797. #pragma warning disable 0612
  1798. if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(sog, remoteClient))
  1799. {
  1800. sog.RootPart.AddFlag(PrimFlags.JointWheel);
  1801. sog.HasGroupChanged = true;
  1802. }
  1803. else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(sog, remoteClient))
  1804. {
  1805. sog.RootPart.RemFlag(PrimFlags.JointWheel);
  1806. sog.HasGroupChanged = true;
  1807. }
  1808. #pragma warning restore 0612
  1809. }
  1810. /// <summary>
  1811. /// Duplicate the given object.
  1812. /// </summary>
  1813. /// <param name="originalPrim"></param>
  1814. /// <param name="offset"></param>
  1815. /// <param name="flags"></param>
  1816. /// <param name="AgentID"></param>
  1817. /// <param name="GroupID"></param>
  1818. /// <param name="rot"></param>
  1819. /// <returns>null if duplication fails, otherwise the duplicated object</returns>
  1820. /// <summary>
  1821. public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, UUID AgentID, UUID GroupID, Quaternion rot, bool createSelected)
  1822. {
  1823. // m_log.DebugFormat(
  1824. // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
  1825. // originalPrimID, offset, AgentID);
  1826. SceneObjectGroup original = GetGroupByPrim(originalPrimID);
  1827. if (original != null)
  1828. {
  1829. if (m_parentScene.Permissions.CanDuplicateObject(original, AgentID))
  1830. {
  1831. SceneObjectGroup copy = original.Copy(true);
  1832. copy.AbsolutePosition = copy.AbsolutePosition + offset;
  1833. SceneObjectPart[] parts = copy.Parts;
  1834. m_numTotalPrim += parts.Length;
  1835. if (original.OwnerID != AgentID)
  1836. {
  1837. copy.SetOwner(AgentID, GroupID);
  1838. if (m_parentScene.Permissions.PropagatePermissions())
  1839. {
  1840. foreach (SceneObjectPart child in parts)
  1841. {
  1842. child.Inventory.ChangeInventoryOwner(AgentID);
  1843. child.TriggerScriptChangedEvent(Changed.OWNER);
  1844. child.ApplyNextOwnerPermissions();
  1845. }
  1846. copy.InvalidateEffectivePerms();
  1847. }
  1848. }
  1849. // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
  1850. Entities.Add(copy);
  1851. lock (SceneObjectGroupsByFullID)
  1852. SceneObjectGroupsByFullID[copy.UUID] = copy;
  1853. foreach (SceneObjectPart part in parts)
  1854. {
  1855. if (part.GetPrimType() == PrimType.SCULPT)
  1856. m_numMesh++;
  1857. else
  1858. m_numPrim++;
  1859. lock (SceneObjectGroupsByFullPartID)
  1860. SceneObjectGroupsByFullPartID[part.UUID] = copy;
  1861. lock (SceneObjectGroupsByLocalPartID)
  1862. SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
  1863. }
  1864. // PROBABLE END OF FIXME
  1865. copy.IsSelected = createSelected;
  1866. if (rot != Quaternion.Identity)
  1867. copy.UpdateGroupRotationR(rot);
  1868. // required for physics to update it's position
  1869. copy.ResetChildPrimPhysicsPositions();
  1870. copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
  1871. copy.ResumeScripts();
  1872. copy.HasGroupChanged = true;
  1873. copy.ScheduleGroupForFullUpdate();
  1874. return copy;
  1875. }
  1876. }
  1877. else
  1878. {
  1879. m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
  1880. }
  1881. return null;
  1882. }
  1883. /// Calculates the distance between two Vector3s
  1884. /// </summary>
  1885. /// <param name="v1"></param>
  1886. /// <param name="v2"></param>
  1887. /// <returns></returns>
  1888. protected internal float Vector3Distance(Vector3 v1, Vector3 v2)
  1889. {
  1890. // We don't really need the double floating point precision...
  1891. // so casting it to a single
  1892. return
  1893. (float)
  1894. 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));
  1895. }
  1896. #endregion
  1897. }
  1898. }