PageRenderTime 73ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Region/SceneObjectGroup.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 4312 lines | 2965 code | 441 blank | 906 comment | 641 complexity | 4ad08d56799c7a9ddeadc1e4d86b728d MD5 | raw 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.Serialization;
  36. using Aurora.Framework.Utilities;
  37. using OpenMetaverse;
  38. using OpenMetaverse.Packets;
  39. using OpenMetaverse.StructuredData;
  40. using ProtoBuf;
  41. using System;
  42. using System.Collections.Generic;
  43. using System.Drawing;
  44. using System.Linq;
  45. using System.Xml.Serialization;
  46. using GridRegion = Aurora.Framework.Services.GridRegion;
  47. namespace Aurora.Region
  48. {
  49. internal struct scriptPosTarget
  50. {
  51. public uint handle;
  52. public Vector3 targetPos;
  53. public float tolerance;
  54. }
  55. internal struct scriptRotTarget
  56. {
  57. public uint handle;
  58. public Quaternion targetRot;
  59. public float tolerance;
  60. }
  61. /// <summary>
  62. /// A scene object group is conceptually an object in the scene. The object is constituted of SceneObjectParts
  63. /// (often known as prims), one of which is considered the root part.
  64. /// </summary>
  65. [Serializable, ProtoContract()]
  66. public partial class SceneObjectGroup : ISceneEntity
  67. //(ISceneObject implements ISceneEntity and IEntity)
  68. {
  69. private readonly List<uint> m_lastColliders = new List<uint>();
  70. private readonly Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>();
  71. private readonly Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
  72. [XmlIgnore] private bool m_ValidgrpOOB; // control recalcutation
  73. [XmlIgnore] private float m_grpBSphereRadiusSQ; // the square of the radius of a sphere containing the oob
  74. [XmlIgnore] private Vector3 m_grpOOBoffset; // the position center of the bounding box relative to it's Position
  75. [XmlIgnore] private Vector3 m_grpOOBsize;
  76. // the size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
  77. public bool IsInTransit { get; set; }
  78. private UUID m_lastParcelUUID = UUID.Zero;
  79. private Vector3 m_lastSignificantPosition = Vector3.Zero;
  80. protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
  81. //Same as m_parts, but this is used for fast linear operations
  82. protected List<SceneObjectPart> m_partsList = new List<SceneObjectPart>();
  83. //This is the lock for m_parts and m_partsList
  84. protected object m_partsLock = new object();
  85. protected ulong m_regionHandle;
  86. protected SceneObjectPart m_rootPart;
  87. private bool m_scriptListens_atRotTarget;
  88. private bool m_scriptListens_atTarget;
  89. private bool m_scriptListens_notAtRotTarget;
  90. private bool m_scriptListens_notAtTarget;
  91. #region Properties
  92. private List<ISceneChildEntity> m_LoopSoundSlavePrims = new List<ISceneChildEntity>();
  93. private List<ISceneChildEntity> m_PlaySoundSlavePrims = new List<ISceneChildEntity>();
  94. /// <summary>
  95. /// Added because the Parcel code seems to use it
  96. /// but not sure a object should have this
  97. /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
  98. /// think really there should be a list (or whatever) in each scenepresence
  99. /// saying what prim(s) that user has selected.
  100. /// </summary>
  101. protected bool m_isSelected;
  102. protected Quaternion m_rotation = Quaternion.Identity;
  103. public SceneObjectPart[] Parts
  104. {
  105. get { return m_partsList.ToArray(); }
  106. }
  107. /// <value>
  108. /// The parts of this scene object group. You must lock this property before using it.
  109. /// </value>
  110. [ProtoMember(1)]
  111. public List<SceneObjectPart> ChildrenList
  112. {
  113. get { return m_partsList; }
  114. set { m_partsList = value; }
  115. }
  116. /// <value>
  117. /// The root part of this scene object
  118. /// </value>
  119. public SceneObjectPart RootPart
  120. {
  121. get { return m_rootPart; }
  122. }
  123. public Color Color
  124. {
  125. get { return m_rootPart.Color; }
  126. set
  127. {
  128. if (m_rootPart != null)
  129. m_rootPart.UpdateColor(value, true);
  130. }
  131. }
  132. public string Text
  133. {
  134. get
  135. {
  136. string returnstr = m_rootPart.Text;
  137. if (returnstr.Length > 255)
  138. {
  139. returnstr = returnstr.Substring(0, 255);
  140. }
  141. return returnstr;
  142. }
  143. set
  144. {
  145. if (m_rootPart != null && m_rootPart.Text != value)
  146. m_rootPart.Text = value;
  147. }
  148. }
  149. public ISceneChildEntity PlaySoundMasterPrim { get; set; }
  150. public List<ISceneChildEntity> PlaySoundSlavePrims
  151. {
  152. get { return m_PlaySoundSlavePrims; }
  153. set { m_PlaySoundSlavePrims = value; }
  154. }
  155. public UUID RegionUUID
  156. {
  157. get
  158. {
  159. if (m_scene != null)
  160. {
  161. return m_scene.RegionInfo.RegionID;
  162. }
  163. return UUID.Zero;
  164. }
  165. }
  166. /// <summary>
  167. /// The name of an object grouping is always the same as its root part
  168. /// </summary>
  169. public override string Name
  170. {
  171. get
  172. {
  173. if (RootPart == null)
  174. return String.Empty;
  175. return RootPart.Name;
  176. }
  177. set { RootPart.Name = value; }
  178. }
  179. /// <summary>
  180. /// Number of prims in this group
  181. /// </summary>
  182. public int PrimCount
  183. {
  184. get { return m_parts.Count; }
  185. }
  186. public override Quaternion Rotation
  187. {
  188. get { return m_rotation; }
  189. set
  190. {
  191. HasGroupChanged = true;
  192. m_rotation = value;
  193. }
  194. }
  195. public Quaternion GroupRotation
  196. {
  197. get { return m_rootPart.GetRotationOffset(); }
  198. }
  199. public UUID GroupID
  200. {
  201. get { return m_rootPart.GroupID; }
  202. set
  203. {
  204. HasGroupChanged = true;
  205. m_rootPart.GroupID = value;
  206. }
  207. }
  208. public List<ISceneChildEntity> ChildrenEntities()
  209. {
  210. return new List<SceneObjectPart>(m_partsList).Cast<ISceneChildEntity>().ToList();
  211. }
  212. public List<UUID> SitTargetAvatar
  213. {
  214. get
  215. {
  216. List<UUID> sittingAvatars = new List<UUID>();
  217. foreach (var prim in ChildrenEntities())
  218. sittingAvatars.AddRange(new List<UUID>(prim.SitTargetAvatar));
  219. return sittingAvatars;
  220. }
  221. }
  222. /// <summary>
  223. /// The absolute position of this scene object in the scene
  224. /// </summary>
  225. public override Vector3 AbsolutePosition
  226. {
  227. get { return m_rootPart.GroupPosition; }
  228. set { SetAbsolutePosition(true, value); }
  229. }
  230. public override uint LocalId
  231. {
  232. get { return m_rootPart.LocalId; }
  233. set { m_rootPart.LocalId = value; }
  234. }
  235. public override UUID UUID
  236. {
  237. get { return m_rootPart.UUID; }
  238. set { Scene.SceneGraph.UpdateEntity(this, value); }
  239. }
  240. public UUID OwnerID
  241. {
  242. get { return m_rootPart.OwnerID; }
  243. set
  244. {
  245. HasGroupChanged = true;
  246. m_rootPart.OwnerID = value;
  247. }
  248. }
  249. public float Damage
  250. {
  251. get { return m_rootPart.Damage; }
  252. set
  253. {
  254. HasGroupChanged = true;
  255. m_rootPart.Damage = value;
  256. }
  257. }
  258. public bool IsSelected
  259. {
  260. get { return m_isSelected; }
  261. set
  262. {
  263. m_isSelected = value;
  264. // Tell physics engine that group is selected
  265. if (m_rootPart.PhysActor != null)
  266. {
  267. m_rootPart.PhysActor.Selected = value;
  268. // Pass it on to the children.
  269. foreach (SceneObjectPart child in ChildrenList.Where(child => child.PhysActor != null))
  270. {
  271. child.PhysActor.Selected = value;
  272. }
  273. }
  274. }
  275. }
  276. public ISceneChildEntity LoopSoundMasterPrim { get; set; }
  277. public List<ISceneChildEntity> LoopSoundSlavePrims
  278. {
  279. get { return m_LoopSoundSlavePrims; }
  280. set { m_LoopSoundSlavePrims = value; }
  281. }
  282. public bool ContainsPart(UUID partID)
  283. {
  284. return m_parts.ContainsKey(partID);
  285. }
  286. /// <summary>
  287. /// Check both the attachment property and the relevant properties of the underlying root part.
  288. /// </summary>
  289. /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
  290. /// have the IsAttachment property yet checked.
  291. ///
  292. /// FIXME: However, this should be fixed so that this property
  293. /// propertly reflects the underlying status.
  294. /// <returns></returns>
  295. public bool IsAttachmentCheckFull()
  296. {
  297. return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
  298. }
  299. // The UUID for the Region this Object is in.
  300. #endregion
  301. #region Constructors
  302. public SceneObjectGroup()
  303. {
  304. }
  305. /// <summary>
  306. /// THIS IS ONLY FOR SERIALIZATION AND AS A BASE CONSTRUCTOR
  307. /// </summary>
  308. public SceneObjectGroup(IScene scene)
  309. {
  310. m_scene = scene;
  311. }
  312. /// <summary>
  313. /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
  314. /// The original SceneObjectPart will be used rather than a copy, preserving
  315. /// its existing localID and UUID.
  316. /// </summary>
  317. public SceneObjectGroup(SceneObjectPart part, IScene scene) : this(scene)
  318. {
  319. SetRootPart(part);
  320. part.Scale = part.Shape.Scale; // temporary hack to update oobb
  321. m_ValidgrpOOB = false;
  322. }
  323. public SceneObjectGroup(SceneObjectPart part, IScene scene, bool AddToScene)
  324. : this(scene)
  325. {
  326. if (!AddToScene)
  327. m_isDeleted = true;
  328. SetRootPart(part);
  329. part.Scale = part.Shape.Scale; // temporary hack to update oobb
  330. m_ValidgrpOOB = false;
  331. }
  332. /// <summary>
  333. /// Constructor. This object is added to the scene later via AttachToScene()
  334. /// </summary>
  335. public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape, string name,
  336. IScene scene) : this(scene)
  337. {
  338. SceneObjectPart part = new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero, name);
  339. SetRootPart(part);
  340. //This has to be set, otherwise it will break things like rezzing objects in an area where crossing is disabled, but rez isn't
  341. m_lastSignificantPosition = pos;
  342. m_ValidgrpOOB = false;
  343. }
  344. public void SetFromItemID(UUID itemID, UUID assetID)
  345. {
  346. foreach (SceneObjectPart part in m_partsList)
  347. {
  348. part.FromUserInventoryItemID = itemID;
  349. part.FromUserInventoryAssetID = assetID;
  350. }
  351. }
  352. /// <summary>
  353. /// Attach this object to a scene. It will also now apply to agents.
  354. /// </summary>
  355. /// <param name="scene"></param>
  356. public void AttachToScene(IScene scene)
  357. {
  358. m_scene = scene;
  359. if (m_rootPart.Shape == null)
  360. {
  361. MainConsole.Instance.Warn("[SceneObjectGroup]: Found null shape for prim " + UUID +
  362. ", creating default box shape");
  363. m_rootPart.Shape = new PrimitiveBaseShape();
  364. }
  365. IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  366. if (WSModule != null)
  367. {
  368. foreach (SceneObjectPart part in ChildrenList)
  369. {
  370. //It's being rezzed, add it to the scene if it doesn't already have a rez date
  371. if (part.Rezzed != Util.ToDateTime(Util.EnvironmentTickCount()))
  372. part.Rezzed = DateTime.UtcNow;
  373. if (part.Shape == null)
  374. continue;
  375. Vector3 scale = part.Shape.Scale;
  376. if (WSModule.MinimumPrimScale != -1)
  377. {
  378. if (scale.X < WSModule.MinimumPrimScale)
  379. scale.X = WSModule.MinimumPrimScale;
  380. if (scale.Y < WSModule.MinimumPrimScale)
  381. scale.Y = WSModule.MinimumPrimScale;
  382. if (scale.Z < WSModule.MinimumPrimScale)
  383. scale.Z = WSModule.MinimumPrimScale;
  384. }
  385. if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical &&
  386. WSModule.MaximumPhysPrimScale != -1)
  387. {
  388. if (scale.X > WSModule.MaximumPhysPrimScale)
  389. scale.X = WSModule.MaximumPhysPrimScale;
  390. if (scale.Y > WSModule.MaximumPhysPrimScale)
  391. scale.Y = WSModule.MaximumPhysPrimScale;
  392. if (scale.Z > WSModule.MaximumPhysPrimScale)
  393. scale.Z = WSModule.MaximumPhysPrimScale;
  394. }
  395. if (WSModule.MaximumPrimScale != -1)
  396. {
  397. if (scale.X > WSModule.MaximumPrimScale)
  398. scale.X = WSModule.MaximumPrimScale;
  399. if (scale.Y > WSModule.MaximumPrimScale)
  400. scale.Y = WSModule.MaximumPrimScale;
  401. if (scale.Z > WSModule.MaximumPrimScale)
  402. scale.Z = WSModule.MaximumPrimScale;
  403. }
  404. part.Scale = scale;
  405. }
  406. }
  407. //Trigger our event
  408. Scene.EventManager.TriggerObjectBeingAddedToScene(this);
  409. RebuildPhysicalRepresentation(false);
  410. m_ValidgrpOOB = false;
  411. }
  412. public Vector3 GroupScale()
  413. {
  414. if (m_partsList.Count == 1)
  415. return RootPart.Scale;
  416. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  417. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  418. Vector3 finalScale;
  419. foreach (SceneObjectPart part in m_partsList)
  420. {
  421. Vector3 partscale = part.Scale*0.5f;
  422. // not assuming root is at index 0
  423. if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
  424. {
  425. // if root is always at index 0 this can be just assigns
  426. if (partscale.X > maxScale.X)
  427. maxScale.X = partscale.X;
  428. if (partscale.Y > maxScale.Y)
  429. maxScale.Y = partscale.Y;
  430. if (partscale.Z > maxScale.Z)
  431. maxScale.Z = partscale.Z;
  432. partscale = -partscale;
  433. if (partscale.X < minScale.X)
  434. minScale.X = partscale.X;
  435. if (partscale.Y < minScale.Y)
  436. minScale.Y = partscale.Y;
  437. if (partscale.Z < minScale.Z)
  438. minScale.Z = partscale.Z;
  439. }
  440. else // prims are in their local frame of reference
  441. {
  442. Vector3 partoffset = part.OffsetPosition;
  443. Quaternion partrot = part.GetRotationOffset();
  444. // bring into this frame
  445. partscale *= partrot;
  446. partoffset *= partrot;
  447. partoffset += part.OffsetPosition;
  448. // now just 2 vertices in a diagonal
  449. Vector3 deltam = partoffset - partscale;
  450. Vector3 deltaM = partoffset + partscale;
  451. if (deltaM.X > deltam.X) // right vertices order for extrem X
  452. {
  453. if (deltam.X < minScale.X)
  454. minScale.X = deltam.X;
  455. if (deltaM.X > maxScale.X)
  456. maxScale.X = deltaM.X;
  457. }
  458. else // nopes inverse one
  459. {
  460. if (deltaM.X < minScale.X)
  461. minScale.X = deltaM.X;
  462. if (deltam.X > maxScale.X)
  463. maxScale.X = deltam.X;
  464. }
  465. if (deltaM.Y > deltam.Y)
  466. {
  467. if (deltam.Y < minScale.Y)
  468. minScale.Y = deltam.Y;
  469. if (deltaM.Y > maxScale.Y)
  470. maxScale.Y = deltaM.Y;
  471. }
  472. else
  473. {
  474. if (deltaM.Y < minScale.Y)
  475. minScale.Y = deltaM.Y;
  476. if (deltam.Y > maxScale.Y)
  477. maxScale.Y = deltam.Y;
  478. }
  479. if (deltaM.Z > deltam.Z)
  480. {
  481. if (deltam.Z < minScale.Z)
  482. minScale.Z = deltam.Z;
  483. if (deltaM.Z > maxScale.Z)
  484. maxScale.Z = deltaM.Z;
  485. }
  486. else
  487. {
  488. if (deltaM.Z < minScale.Z)
  489. minScale.Z = deltaM.Z;
  490. if (deltam.Z > maxScale.Z)
  491. maxScale.Z = deltam.Z;
  492. }
  493. }
  494. }
  495. finalScale.X = Math.Abs(maxScale.X - minScale.X);
  496. finalScale.Y = Math.Abs(maxScale.Y - minScale.Y);
  497. finalScale.Z = Math.Abs(maxScale.Z - minScale.Z);
  498. return finalScale;
  499. }
  500. public override int GetHashCode()
  501. {
  502. return UUID.GetHashCode();
  503. }
  504. public bool IsPhysical()
  505. {
  506. return ((RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics);
  507. }
  508. public void UpdateOOBfromOOBs()
  509. {
  510. if (m_partsList.Count == 1)
  511. {
  512. SceneObjectPart part = m_partsList.First();
  513. m_grpOOBsize = part.OOBsize;
  514. m_grpOOBoffset = part.OOBoffset;
  515. m_grpBSphereRadiusSQ = part.BSphereRadiusSQ;
  516. m_ValidgrpOOB = true;
  517. return;
  518. }
  519. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  520. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  521. foreach (SceneObjectPart part in m_partsList)
  522. {
  523. Vector3 partscale = part.OOBsize; // (oobsize == vector with box vertice with all coords positive)
  524. Vector3 partoffset = part.OOBoffset;
  525. // not assuming root is at index 0
  526. Vector3 deltam;
  527. Vector3 deltaM;
  528. if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
  529. {
  530. //2 vertices in the right extrem sides:
  531. deltam = partoffset - partscale;
  532. deltaM = partoffset + partscale;
  533. // if root is always at index 0 this can be just assigns
  534. if (deltam.X < minScale.X)
  535. minScale.X = deltam.X;
  536. if (deltam.Y < minScale.Y)
  537. minScale.Y = deltam.Y;
  538. if (deltam.Z < minScale.Z)
  539. minScale.Z = deltam.Z;
  540. if (deltaM.X > maxScale.X)
  541. maxScale.X = deltaM.X;
  542. if (deltaM.Y > maxScale.Y)
  543. maxScale.Y = deltaM.Y;
  544. if (deltaM.Z > maxScale.Z)
  545. maxScale.Z = deltaM.Z;
  546. }
  547. else // prims are in their local frame of reference
  548. {
  549. // bring into this frame
  550. Quaternion partrot = part.GetRotationOffset();
  551. partscale *= partrot;
  552. partoffset *= partrot;
  553. partoffset += part.OffsetPosition;
  554. // now just 2 vertices in a diagonal
  555. deltam = partoffset - partscale;
  556. deltaM = partoffset + partscale;
  557. if (deltaM.X > deltam.X) // right vertices order for extrem X
  558. {
  559. if (deltam.X < minScale.X)
  560. minScale.X = deltam.X;
  561. if (deltaM.X > maxScale.X)
  562. maxScale.X = deltaM.X;
  563. }
  564. else // nopes inverse one
  565. {
  566. if (deltaM.X < minScale.X)
  567. minScale.X = deltaM.X;
  568. if (deltam.X > maxScale.X)
  569. maxScale.X = deltam.X;
  570. }
  571. if (deltaM.Y > deltam.Y)
  572. {
  573. if (deltam.Y < minScale.Y)
  574. minScale.Y = deltam.Y;
  575. if (deltaM.Y > maxScale.Y)
  576. maxScale.Y = deltaM.Y;
  577. }
  578. else
  579. {
  580. if (deltaM.Y < minScale.Y)
  581. minScale.Y = deltaM.Y;
  582. if (deltam.Y > maxScale.Y)
  583. maxScale.Y = deltam.Y;
  584. }
  585. if (deltaM.Z > deltam.Z)
  586. {
  587. if (deltam.Z < minScale.Z)
  588. minScale.Z = deltam.Z;
  589. if (deltaM.Z > maxScale.Z)
  590. maxScale.Z = deltaM.Z;
  591. }
  592. else
  593. {
  594. if (deltaM.Z < minScale.Z)
  595. minScale.Z = deltaM.Z;
  596. if (deltam.Z > maxScale.Z)
  597. maxScale.Z = deltam.Z;
  598. }
  599. }
  600. }
  601. // size == the vertice of box with all coords positive
  602. m_grpOOBsize.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
  603. m_grpOOBsize.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
  604. m_grpOOBsize.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
  605. // centroid:
  606. m_grpOOBoffset.X = 0.5f*(maxScale.X + minScale.X);
  607. m_grpOOBoffset.Y = 0.5f*(maxScale.Y + minScale.Y);
  608. m_grpOOBoffset.Z = 0.5f*(maxScale.Z + minScale.Z);
  609. // containing sphere:
  610. m_grpBSphereRadiusSQ = m_grpOOBsize.LengthSquared();
  611. m_ValidgrpOOB = true;
  612. }
  613. public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
  614. {
  615. // We got a request from the inner_scene to raytrace along the Ray hRay
  616. // We're going to check all of the prim in this group for intersection with the ray
  617. // If we get a result, we're going to find the closest result to the origin of the ray
  618. // and send back the intersection information back to the innerscene.
  619. EntityIntersection result = new EntityIntersection();
  620. foreach (SceneObjectPart part in m_partsList)
  621. {
  622. // Temporary commented to stop compiler warning
  623. //Vector3 partPosition =
  624. // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
  625. Quaternion parentrotation = GroupRotation;
  626. // Telling the prim to raytrace.
  627. //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
  628. EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
  629. // This may need to be updated to the maximum draw distance possible..
  630. // We might (and probably will) be checking for prim creation from other sims
  631. // when the camera crosses the border.
  632. if (m_scene != null)
  633. {
  634. float idist = (m_scene.RegionInfo.RegionSizeX + m_scene.RegionInfo.RegionSizeY)/2;
  635. if (inter.HitTF)
  636. {
  637. // We need to find the closest prim to return to the testcaller along the ray
  638. if (inter.distance < idist)
  639. {
  640. result.HitTF = true;
  641. result.ipoint = inter.ipoint;
  642. result.obj = part;
  643. result.normal = inter.normal;
  644. result.distance = inter.distance;
  645. }
  646. }
  647. }
  648. }
  649. return result;
  650. }
  651. /// <summary>
  652. /// Gets a vector representing the size of the bounding box containing all the prims in the group
  653. /// Treats all prims as rectangular, so no shape (cut etc) is taken into account
  654. /// offsetHeight is the offset in the Z axis from the centre of the bounding box to the centre of the root prim
  655. /// </summary>
  656. /// <returns></returns>
  657. public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY,
  658. out float minZ, out float maxZ)
  659. {
  660. Vector3 pos = m_rootPart.AbsolutePosition;
  661. Quaternion rot = m_rootPart.GetRotationOffset();
  662. // Vector3 size = GroupScale();
  663. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  664. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  665. //limits in group frame
  666. foreach (SceneObjectPart part in m_partsList)
  667. {
  668. Vector3 partscale = part.Scale*0.5f;
  669. Vector3 partoffset = part.OffsetPosition;
  670. if (part.ParentID != 0) // prims are rotated in group
  671. {
  672. partscale *= part.GetRotationOffset();
  673. partscale.X = Math.Abs(partscale.X);
  674. partscale.Y = Math.Abs(partscale.Y);
  675. partscale.Z = Math.Abs(partscale.Z);
  676. }
  677. Vector3 deltam = partoffset - partscale;
  678. Vector3 deltaM = partoffset + partscale;
  679. if (deltam.X < minScale.X)
  680. minScale.X = deltam.X;
  681. if (deltam.Y < minScale.Y)
  682. minScale.Y = deltam.Y;
  683. if (deltam.Z < minScale.Z)
  684. minScale.Z = deltam.Z;
  685. if (deltaM.X > maxScale.X)
  686. maxScale.X = deltaM.X;
  687. if (deltaM.Y > maxScale.Y)
  688. maxScale.Y = deltaM.Y;
  689. if (deltaM.Z > maxScale.Z)
  690. maxScale.Z = deltaM.Z;
  691. }
  692. Vector3 tmp;
  693. tmp.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
  694. tmp.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
  695. tmp.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
  696. // tmp has half scale
  697. // group rotation
  698. tmp = tmp*rot;
  699. // scale is positive
  700. tmp.X = Math.Abs(tmp.X);
  701. tmp.Y = Math.Abs(tmp.Y);
  702. tmp.Z = Math.Abs(tmp.Z);
  703. // group position
  704. minX = pos.X - tmp.X;
  705. minY = pos.Y - tmp.Y;
  706. minZ = pos.Z - tmp.Z;
  707. maxX = pos.X + tmp.X;
  708. maxY = pos.Y + tmp.Y;
  709. maxZ = pos.Z + tmp.Z;
  710. /*
  711. maxX = -256f;
  712. maxY = -256f;
  713. maxZ = -256f;
  714. minX = 256f;
  715. minY = 256f;
  716. minZ = 8192f;
  717. foreach (SceneObjectPart part in m_partsList)
  718. {
  719. Vector3 worldPos = part.GetWorldPosition();
  720. Vector3 offset = worldPos - AbsolutePosition;
  721. Quaternion worldRot;
  722. if (part.ParentID == 0)
  723. worldRot = part.RotationOffset;
  724. else
  725. worldRot = part.GetWorldRotation();
  726. Vector3 frontTopLeft;
  727. Vector3 frontTopRight;
  728. Vector3 frontBottomLeft;
  729. Vector3 frontBottomRight;
  730. Vector3 backTopLeft;
  731. Vector3 backTopRight;
  732. Vector3 backBottomLeft;
  733. Vector3 backBottomRight;
  734. Vector3 orig = Vector3.Zero;
  735. frontTopLeft.X = orig.X - (part.Scale.X / 2);
  736. frontTopLeft.Y = orig.Y - (part.Scale.Y / 2);
  737. frontTopLeft.Z = orig.Z + (part.Scale.Z / 2);
  738. frontTopRight.X = orig.X - (part.Scale.X / 2);
  739. frontTopRight.Y = orig.Y + (part.Scale.Y / 2);
  740. frontTopRight.Z = orig.Z + (part.Scale.Z / 2);
  741. frontBottomLeft.X = orig.X - (part.Scale.X / 2);
  742. frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
  743. frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
  744. frontBottomRight.X = orig.X - (part.Scale.X / 2);
  745. frontBottomRight.Y = orig.Y + (part.Scale.Y / 2);
  746. frontBottomRight.Z = orig.Z - (part.Scale.Z / 2);
  747. backTopLeft.X = orig.X + (part.Scale.X / 2);
  748. backTopLeft.Y = orig.Y - (part.Scale.Y / 2);
  749. backTopLeft.Z = orig.Z + (part.Scale.Z / 2);
  750. backTopRight.X = orig.X + (part.Scale.X / 2);
  751. backTopRight.Y = orig.Y + (part.Scale.Y / 2);
  752. backTopRight.Z = orig.Z + (part.Scale.Z / 2);
  753. backBottomLeft.X = orig.X + (part.Scale.X / 2);
  754. backBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
  755. backBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
  756. backBottomRight.X = orig.X + (part.Scale.X / 2);
  757. backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
  758. backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
  759. frontTopLeft = frontTopLeft * worldRot;
  760. frontTopRight = frontTopRight * worldRot;
  761. frontBottomLeft = frontBottomLeft * worldRot;
  762. frontBottomRight = frontBottomRight * worldRot;
  763. backBottomLeft = backBottomLeft * worldRot;
  764. backBottomRight = backBottomRight * worldRot;
  765. backTopLeft = backTopLeft * worldRot;
  766. backTopRight = backTopRight * worldRot;
  767. frontTopLeft += offset;
  768. frontTopRight += offset;
  769. frontBottomLeft += offset;
  770. frontBottomRight += offset;
  771. backBottomLeft += offset;
  772. backBottomRight += offset;
  773. backTopLeft += offset;
  774. backTopRight += offset;
  775. if (frontTopRight.X > maxX)
  776. maxX = frontTopRight.X;
  777. if (frontTopLeft.X > maxX)
  778. maxX = frontTopLeft.X;
  779. if (frontBottomRight.X > maxX)
  780. maxX = frontBottomRight.X;
  781. if (frontBottomLeft.X > maxX)
  782. maxX = frontBottomLeft.X;
  783. if (backTopRight.X > maxX)
  784. maxX = backTopRight.X;
  785. if (backTopLeft.X > maxX)
  786. maxX = backTopLeft.X;
  787. if (backBottomRight.X > maxX)
  788. maxX = backBottomRight.X;
  789. if (backBottomLeft.X > maxX)
  790. maxX = backBottomLeft.X;
  791. if (frontTopRight.X < minX)
  792. minX = frontTopRight.X;
  793. if (frontTopLeft.X < minX)
  794. minX = frontTopLeft.X;
  795. if (frontBottomRight.X < minX)
  796. minX = frontBottomRight.X;
  797. if (frontBottomLeft.X < minX)
  798. minX = frontBottomLeft.X;
  799. if (backTopRight.X < minX)
  800. minX = backTopRight.X;
  801. if (backTopLeft.X < minX)
  802. minX = backTopLeft.X;
  803. if (backBottomRight.X < minX)
  804. minX = backBottomRight.X;
  805. if (backBottomLeft.X < minX)
  806. minX = backBottomLeft.X;
  807. if (frontTopRight.Y > maxY)
  808. maxY = frontTopRight.Y;
  809. if (frontTopLeft.Y > maxY)
  810. maxY = frontTopLeft.Y;
  811. if (frontBottomRight.Y > maxY)
  812. maxY = frontBottomRight.Y;
  813. if (frontBottomLeft.Y > maxY)
  814. maxY = frontBottomLeft.Y;
  815. if (backTopRight.Y > maxY)
  816. maxY = backTopRight.Y;
  817. if (backTopLeft.Y > maxY)
  818. maxY = backTopLeft.Y;
  819. if (backBottomRight.Y > maxY)
  820. maxY = backBottomRight.Y;
  821. if (backBottomLeft.Y > maxY)
  822. maxY = backBottomLeft.Y;
  823. if (backTopRight.Y < minY)
  824. minY = backTopRight.Y;
  825. if (backTopLeft.Y < minY)
  826. minY = backTopLeft.Y;
  827. if (backBottomRight.Y < minY)
  828. minY = backBottomRight.Y;
  829. if (backBottomLeft.Y < minY)
  830. minY = backBottomLeft.Y;
  831. if (backTopRight.Y < minY)
  832. minY = backTopRight.Y;
  833. if (backTopLeft.Y < minY)
  834. minY = backTopLeft.Y;
  835. if (backBottomRight.Y < minY)
  836. minY = backBottomRight.Y;
  837. if (backBottomLeft.Y < minY)
  838. minY = backBottomLeft.Y;
  839. if (frontTopRight.Z > maxZ)
  840. maxZ = frontTopRight.Z;
  841. if (frontTopLeft.Z > maxZ)
  842. maxZ = frontTopLeft.Z;
  843. if (frontBottomRight.Z > maxZ)
  844. maxZ = frontBottomRight.Z;
  845. if (frontBottomLeft.Z > maxZ)
  846. maxZ = frontBottomLeft.Z;
  847. if (backTopRight.Z > maxZ)
  848. maxZ = backTopRight.Z;
  849. if (backTopLeft.Z > maxZ)
  850. maxZ = backTopLeft.Z;
  851. if (backBottomRight.Z > maxZ)
  852. maxZ = backBottomRight.Z;
  853. if (backBottomLeft.Z > maxZ)
  854. maxZ = backBottomLeft.Z;
  855. if (frontTopRight.Z < minZ)
  856. minZ = frontTopRight.Z;
  857. if (frontTopLeft.Z < minZ)
  858. minZ = frontTopLeft.Z;
  859. if (frontBottomRight.Z < minZ)
  860. minZ = frontBottomRight.Z;
  861. if (frontBottomLeft.Z < minZ)
  862. minZ = frontBottomLeft.Z;
  863. if (backTopRight.Z < minZ)
  864. minZ = backTopRight.Z;
  865. if (backTopLeft.Z < minZ)
  866. minZ = backTopLeft.Z;
  867. if (backBottomRight.Z < minZ)
  868. minZ = backBottomRight.Z;
  869. if (backBottomLeft.Z < minZ)
  870. minZ = backBottomLeft.Z;
  871. }
  872. */
  873. }
  874. public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
  875. {
  876. float minX;
  877. float maxX;
  878. float minY;
  879. float maxY;
  880. float minZ;
  881. float maxZ;
  882. GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
  883. Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
  884. offsetHeight = 0.5f*(maxZ + minZ);
  885. offsetHeight -= m_rootPart.AbsolutePosition.Z;
  886. /*
  887. offsetHeight = 0;
  888. float lower = (minZ * -1);
  889. if (lower > maxZ)
  890. {
  891. offsetHeight = lower - (boundingBox.Z / 2);
  892. }
  893. else if (maxZ > lower)
  894. {
  895. offsetHeight = maxZ - (boundingBox.Z / 2);
  896. offsetHeight *= -1;
  897. }
  898. */
  899. // MainConsole.Instance.InfoFormat("BoundingBox is {0} , {1} , {2} ", boundingBox.X, boundingBox.Y, boundingBox.Z);
  900. return boundingBox;
  901. }
  902. #region Adding/Removing children from this group
  903. /// <summary>
  904. /// Clear all children from this group
  905. /// </summary>
  906. public void ClearChildren()
  907. {
  908. lock (m_partsLock)
  909. {
  910. m_parts.Clear();
  911. m_partsList.Clear();
  912. m_ValidgrpOOB = false;
  913. }
  914. }
  915. /// <summary>
  916. /// Add a child to the group, set the parent id's and then set the link number
  917. /// </summary>
  918. /// <param name="child"></param>
  919. /// <param name="linkNum"></param>
  920. /// <returns></returns>
  921. public bool AddChild(ISceneChildEntity child, int linkNum)
  922. {
  923. lock (m_partsLock)
  924. {
  925. if (child is SceneObjectPart)
  926. {
  927. SceneObjectPart part = (SceneObjectPart) child;
  928. //Root part is first
  929. if (m_partsList.Count == 0)
  930. {
  931. m_rootPart = part;
  932. }
  933. //Set the parent prim
  934. part.SetParent(this);
  935. if (m_rootPart.LocalId != 0 && !part.IsRoot)
  936. part.SetParentLocalId(m_rootPart.LocalId);
  937. else
  938. part.SetParentLocalId(0);
  939. //Fix the link num
  940. part.LinkNum = linkNum;
  941. if (!m_parts.ContainsKey(child.UUID))
  942. {
  943. m_parts.Add(child.UUID, part);
  944. m_partsList.Add(part);
  945. m_ValidgrpOOB = false;
  946. }
  947. return true;
  948. }
  949. }
  950. return false;
  951. }
  952. /// <summary>
  953. /// Add this child to the group and set the parent ID's,
  954. /// but do NOT set the link number,
  955. /// the caller wants to deal with it if they call this
  956. /// </summary>
  957. /// <param name="child"></param>
  958. /// <returns></returns>
  959. public bool LinkChild(ISceneChildEntity child)
  960. {
  961. lock (m_partsLock)
  962. {
  963. if (child is SceneObjectPart)
  964. {
  965. SceneObjectPart part = (SceneObjectPart) child;
  966. //Root part is first
  967. if (m_partsList.Count == 0)
  968. {
  969. m_rootPart = part;
  970. }
  971. //Set the parent prim
  972. part.SetParent(this);
  973. part.SetParentLocalId(m_rootPart.LocalId);
  974. if (!m_parts.ContainsKey(child.UUID))
  975. {
  976. m_parts.Add(child.UUID, part);
  977. m_partsList.Add(part);
  978. m_ValidgrpOOB = false;
  979. }
  980. m_partsList.Sort(m_scene.SceneGraph.LinkSetSorter);
  981. return true;
  982. }
  983. }
  984. return false;
  985. }
  986. /// <summary>
  987. /// Remove this child from the group and then update the link numbers so that there is not a hole
  988. /// </summary>
  989. /// <param name="child"></param>
  990. /// <returns></returns>
  991. public bool RemoveChild(ISceneChildEntity child)
  992. {
  993. lock (m_partsLock)
  994. {
  995. if (child is SceneObjectPart)
  996. {
  997. SceneObjectPart part = (SceneObjectPart) child;
  998. m_parts.Remove(part.UUID);
  999. m_partsList.Remove(part);
  1000. m_ValidgrpOOB = false;
  1001. //Fix the link numbers now
  1002. FixLinkNumbers();
  1003. return true;
  1004. }
  1005. }
  1006. return false;
  1007. }
  1008. /// <summary>
  1009. /// After a prim is removed, fix the link numbers so that they are correct
  1010. /// </summary>
  1011. private void FixLinkNumbers()
  1012. {
  1013. if (m_partsList.Count == 1)
  1014. {
  1015. m_partsList[0].LinkNum = 0;
  1016. return;
  1017. }
  1018. lock (m_partsLock)
  1019. {
  1020. // has prims so starts at 1
  1021. int lastSeenLinkNum = 1;
  1022. m_partsList.Sort(Scene.SceneGraph.LinkSetSorter);
  1023. foreach (SceneObjectPart t in m_partsList)
  1024. {
  1025. //If it isn't the same as the last seen +1, fix it
  1026. if (t != null && t.LinkNum != lastSeenLinkNum)
  1027. t.LinkNum = lastSeenLinkNum;
  1028. //Go onto the next prim
  1029. lastSeenLinkNum++;
  1030. }
  1031. }
  1032. }
  1033. #endregion
  1034. #endregion
  1035. /// <summary>
  1036. /// The position center of the bounding box relative to it's Position
  1037. /// </summary>
  1038. [XmlIgnore]
  1039. public Vector3 OOBoffset
  1040. {
  1041. get
  1042. {
  1043. if (!m_ValidgrpOOB)
  1044. UpdateOOBfromOOBs();
  1045. return m_grpOOBoffset;
  1046. }
  1047. }
  1048. public object ChildrenListLock
  1049. {
  1050. get { return m_partsLock; }
  1051. }
  1052. #region ISceneObject Members
  1053. public event BlankHandler OnFinishedPhysicalRepresentationBuilding;
  1054. public Vector3 LastSignificantPosition
  1055. {
  1056. get { return m_lastSignificantPosition; }
  1057. }
  1058. public UUID LastParcelUUID
  1059. {
  1060. get { return m_lastParcelUUID; }
  1061. set { m_lastParcelUUID = value; }
  1062. }
  1063. /// <summary>
  1064. /// The size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
  1065. /// </summary>
  1066. [XmlIgnore]
  1067. public Vector3 OOBsize
  1068. {
  1069. get
  1070. {
  1071. if (!m_ValidgrpOOB)
  1072. UpdateOOBfromOOBs();
  1073. return m_grpOOBsize;
  1074. }
  1075. }
  1076. /// <summary>
  1077. /// The square of the radius of a sphere containing the oob
  1078. /// </summary>
  1079. [XmlIgnore]
  1080. public float BSphereRadiusSQ
  1081. {
  1082. get
  1083. {
  1084. if (!m_ValidgrpOOB)
  1085. UpdateOOBfromOOBs();
  1086. return m_grpBSphereRadiusSQ;
  1087. }
  1088. }
  1089. public override bool HasGroupChanged
  1090. {
  1091. get { return m_hasGroupChanged; }
  1092. set
  1093. {
  1094. if (value)
  1095. {
  1096. if (m_scene != null)
  1097. {
  1098. IBackupModule backup = m_scene.RequestModuleInterface<IBackupModule>();
  1099. if (backup != null)
  1100. {
  1101. if (!backup.LoadingPrims) //Do NOT add to backup while still loading prims
  1102. backup.AddPrimBackupTaint(this);
  1103. }
  1104. }
  1105. }
  1106. m_hasGroupChanged = value;
  1107. }
  1108. }
  1109. /// <summary>
  1110. /// Force all prims in the scene object to persist
  1111. /// </summary>
  1112. public void ForcePersistence()
  1113. {
  1114. //Force normal backup
  1115. HasGroupChanged = true;
  1116. ForceInventoryPersistence();
  1117. }
  1118. /// <summary>
  1119. /// Clears all undo states from this group
  1120. /// </summary>
  1121. public void ClearUndoState()
  1122. {
  1123. foreach (SceneObjectPart child in ChildrenList)
  1124. {
  1125. child.ClearUndoState();
  1126. }
  1127. }
  1128. /// <value>
  1129. /// Is this scene object acting as an attachment?
  1130. /// We return false if the group has already been deleted.
  1131. /// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I
  1132. /// presume either all or no parts in a linkset can be part of an attachment (in which
  1133. /// case the value would get proprogated down into all the descendent parts).
  1134. /// </value>
  1135. public bool IsAttachment
  1136. {
  1137. get { return m_rootPart.IsAttachment; }
  1138. }
  1139. //private bool m_isBackedUp = false;
  1140. public byte GetAttachmentPoint()
  1141. {
  1142. return m_rootPart.Shape.State;
  1143. }
  1144. public Vector3 GetAttachmentPos()
  1145. {
  1146. return m_rootPart.SavedAttachedPos;
  1147. }
  1148. public byte GetSavedAttachmentPoint()
  1149. {
  1150. return (byte) m_rootPart.SavedAttachmentPoint;
  1151. }
  1152. public void FinishedSerializingGenericProperties()
  1153. {
  1154. foreach (ISceneChildEntity ent in ChildrenEntities())
  1155. ent.FinishedSerializingGenericProperties();
  1156. }
  1157. public void DetachToGround()
  1158. {
  1159. IScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
  1160. if (avatar == null)
  1161. return;
  1162. RootPart.FromUserInventoryItemID = UUID.Zero;
  1163. AbsolutePosition = avatar.AbsolutePosition;
  1164. m_rootPart.AttachedAvatar = UUID.Zero;
  1165. //Anakin Lohner bug #3839
  1166. foreach (SceneObjectPart p in m_partsList)
  1167. {
  1168. p.AttachedAvatar = UUID.Zero;
  1169. }
  1170. m_rootPart.SetParentLocalId(0);
  1171. SetAttachmentPoint(0);
  1172. RebuildPhysicalRepresentation(false);
  1173. HasGroupChanged = true;
  1174. m_ValidgrpOOB = false;
  1175. RootPart.Rezzed = DateTime.UtcNow;
  1176. RootPart.RemFlag(PrimFlags.TemporaryOnRez);
  1177. m_rootPart.ScheduleUpdate(PrimUpdateFlags.ForcedFullUpdate);
  1178. }
  1179. public void DetachToInventoryPrep()
  1180. {
  1181. m_rootPart.AttachedAvatar = UUID.Zero;
  1182. //Anakin Lohner bug #3839
  1183. foreach (SceneObjectPart p in m_partsList)
  1184. {
  1185. p.AttachedAvatar = UUID.Zero;
  1186. }
  1187. m_rootPart.SetParentLocalId(0);
  1188. //m_rootPart.SetAttachmentPoint((byte)0);
  1189. m_rootPart.IsAttachment = false;
  1190. AbsolutePosition = m_rootPart.AttachedPos;
  1191. m_ValidgrpOOB = false;
  1192. //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
  1193. //AttachToBackup();
  1194. //m_rootPart.ScheduleFullUpdate();
  1195. }
  1196. // justincc: I don't believe this hack is needed any longer, especially since the physics
  1197. // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
  1198. // this method was preventing proper reload of scene objects.
  1199. // dahlia: I had to uncomment it, without it meshing was failing on some prims and objects
  1200. // at region startup
  1201. // teravus: After this was removed from the linking algorithm, Linked prims no longer collided
  1202. // properly when non-physical if they havn't been moved. This breaks ALL builds.
  1203. // see: http://opensimulator.org/mantis/view.php?id=3108
  1204. // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
  1205. // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
  1206. // unmoved prims! As soon as you move a Prim/group, it will collide properly because Absolute
  1207. // Position has been set!
  1208. public void ResetChildPrimPhysicsPositions()
  1209. {
  1210. AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
  1211. // teravus: AbsolutePosition is NOT a normal property!
  1212. // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
  1213. // jhurliman: Then why is it a property instead of two methods?
  1214. }
  1215. public void SetOwnerId(UUID userId)
  1216. {
  1217. ForEachPart(delegate(SceneObjectPart part)
  1218. {
  1219. part.LastOwnerID = part.OwnerID;
  1220. part.OwnerID = userId;
  1221. });
  1222. }
  1223. public float GetMass()
  1224. {
  1225. return RootChild.GetMass();
  1226. }
  1227. /// <summary>
  1228. /// Set the user group to which this scene object belongs.
  1229. /// </summary>
  1230. /// <param name="GroupID2"></param>
  1231. /// <param name="attemptingUserID"></param>
  1232. /// <param name="needsUpdate"></param>
  1233. public void SetGroup(UUID GroupID2, UUID attemptingUserID, bool needsUpdate)
  1234. {
  1235. IGroupsModule module = Scene.RequestModuleInterface<IGroupsModule>();
  1236. if (module != null)
  1237. if (GroupID2 != UUID.Zero && !module.GroupPermissionCheck(attemptingUserID, GroupID2, GroupPowers.None))
  1238. return; // No settings to groups you arn't in
  1239. foreach (SceneObjectPart part in m_partsList)
  1240. {
  1241. part.SetGroup(GroupID2);
  1242. part.Inventory.ChangeInventoryGroup(GroupID2);
  1243. }
  1244. HasGroupChanged = true;
  1245. IScenePresence sp = Scene.GetScenePresence(attemptingUserID);
  1246. if (sp != null && needsUpdate)
  1247. GetProperties(sp.ControllingClient);
  1248. }
  1249. public void TriggerScriptChangedEvent(Changed val)
  1250. {
  1251. foreach (SceneObjectPart part in ChildrenList)
  1252. {
  1253. part.TriggerScriptChangedEvent(val);
  1254. }
  1255. }
  1256. public void SetAttachmentPoint(byte point)
  1257. {
  1258. foreach (SceneObjectPart part in m_partsList)
  1259. part.SetAttachmentPoint(point);
  1260. }
  1261. public void FireAttachmentCollisionEvents(EventArgs e)
  1262. {
  1263. CollisionEventUpdate a = (CollisionEventUpdate) e;
  1264. Dictionary<uint, ContactPoint> collissionswith = a.GetCollisionEvents();
  1265. List<uint> thisHitColliders = new List<uint>();
  1266. List<uint> startedColliders = new List<uint>();
  1267. // calculate things that started colliding this time
  1268. // and build up list of colliders this time
  1269. foreach (uint localid in collissionswith.Keys)
  1270. {
  1271. thisHitColliders.Add(localid);
  1272. if (!m_lastColliders.Contains(localid))
  1273. {
  1274. startedColliders.Add(localid);
  1275. }
  1276. //MainConsole.Instance.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
  1277. }
  1278. // calculate things that ended colliding
  1279. List<uint> endedColliders = m_lastColliders.Where(localID => !thisHitColliders.Contains(localID)).ToList();
  1280. //add the items that started colliding this time to the last colliders list.
  1281. foreach (uint localID in startedColliders)
  1282. {
  1283. m_lastColliders.Add(localID);
  1284. }
  1285. // remove things that ended colliding from the last colliders list
  1286. foreach (uint localID in endedColliders)
  1287. {
  1288. m_lastColliders.Remove(localID);
  1289. }
  1290. if (IsDeleted)
  1291. return;
  1292. // play the sound.
  1293. if (startedColliders.Count > 0 && RootPart.CollisionSound != UUID.Zero &&
  1294. RootPart.CollisionSoundVolume > 0.0f)
  1295. {
  1296. RootPart.SendSound(RootPart.CollisionSound.ToString(), RootPart.CollisionSoundVolume, true, 0, 0, false,
  1297. false);
  1298. }
  1299. if (RootPart.CollisionSprite != UUID.Zero && RootPart.CollisionSoundVolume > 0.0f)
  1300. // The collision volume isn't a mistake, its an SL feature/bug
  1301. {
  1302. // TODO: make a sprite!
  1303. }
  1304. if ((RootPart.ScriptEvents & scriptEvents.collision_start) != 0)
  1305. {
  1306. // do event notification
  1307. if (startedColliders.Count > 0)
  1308. {
  1309. ColliderArgs StartCollidingMessage = new ColliderArgs();
  1310. List<DetectedObject> colliding = new List<DetectedObject>();
  1311. foreach (uint localId in startedColliders)
  1312. {
  1313. if (localId != 0)
  1314. {
  1315. if (Scene == null)
  1316. return;
  1317. ISceneChildEntity obj = Scene.GetSceneObjectPart(localId);
  1318. string data = "";
  1319. if (obj != null)
  1320. {
  1321. if (RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  1322. RootPart.CollisionFilter.ContainsValue(obj.Name))
  1323. {
  1324. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1325. //If it is 1, it is to accept ONLY collisions from this object
  1326. if (found)
  1327. {
  1328. DetectedObject detobj = new DetectedObject
  1329. {
  1330. keyUUID = obj.UUID,
  1331. nameStr = obj.Name,
  1332. ownerUUID = obj.OwnerID,
  1333. posVector = obj.AbsolutePosition,
  1334. rotQuat = obj.GetWorldRotation(),
  1335. velVector = obj.Velocity,
  1336. colliderType = 0,
  1337. groupUUID = obj.GroupID
  1338. };
  1339. colliding.Add(detobj);
  1340. }
  1341. //If it is 0, it is to not accept collisions from this object
  1342. }
  1343. else
  1344. {
  1345. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1346. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  1347. if (!found)
  1348. {
  1349. DetectedObject detobj = new DetectedObject
  1350. {
  1351. keyUUID = obj.UUID,
  1352. nameStr = obj.Name,
  1353. ownerUUID = obj.OwnerID,
  1354. posVector = obj.AbsolutePosition,
  1355. rotQuat = obj.GetWorldRotation(),
  1356. velVector = obj.Velocity,
  1357. colliderType = 0,
  1358. groupUUID = obj.GroupID
  1359. };
  1360. colliding.Add(detobj);
  1361. }
  1362. }
  1363. }
  1364. else
  1365. {
  1366. IScenePresence av = Scene.GetScenePresence(localId);
  1367. if (av.LocalId == localId)
  1368. {
  1369. if (RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  1370. RootPart.CollisionFilter.ContainsValue(av.Name))
  1371. {
  1372. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1373. //If it is 1, it is to accept ONLY collisions from this avatar
  1374. if (found)
  1375. {
  1376. DetectedObject detobj = new DetectedObject
  1377. {
  1378. keyUUID = av.UUID,
  1379. nameStr = av.ControllingClient.Name,
  1380. ownerUUID = av.UUID,
  1381. posVector = av.AbsolutePosition,
  1382. rotQuat = av.Rotation,
  1383. velVector = av.Velocity,
  1384. colliderType = 0,
  1385. groupUUID =
  1386. av.ControllingClient.ActiveGroupId
  1387. };
  1388. colliding.Add(detobj);
  1389. }
  1390. //If it is 0, it is to not accept collisions from this avatar
  1391. }
  1392. else
  1393. {
  1394. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1395. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  1396. if (!found)
  1397. {
  1398. DetectedObject detobj = new DetectedObject
  1399. {
  1400. keyUUID = av.UUID,
  1401. nameStr = av.ControllingClient.Name,
  1402. ownerUUID = av.UUID,
  1403. posVector = av.AbsolutePosition,
  1404. rotQuat = av.Rotation,
  1405. velVector = av.Velocity,
  1406. colliderType = 0,
  1407. groupUUID =
  1408. av.ControllingClient.ActiveGroupId
  1409. };
  1410. colliding.Add(detobj);
  1411. }
  1412. }
  1413. }
  1414. }
  1415. }
  1416. }
  1417. if (colliding.Count > 0)
  1418. {
  1419. StartCollidingMessage.Colliders = colliding;
  1420. // always running this check because if the user deletes the object it would return a null reference.
  1421. if (Scene == null)
  1422. return;
  1423. Scene.EventManager.TriggerScriptCollidingStart(RootPart, StartCollidingMessage);
  1424. }
  1425. }
  1426. }
  1427. if ((RootPart.ScriptEvents & scriptEvents.collision) != 0)
  1428. {
  1429. if (m_lastColliders.Count > 0)
  1430. {
  1431. ColliderArgs CollidingMessage = new ColliderArgs();
  1432. List<DetectedObject> colliding = new List<DetectedObject>();
  1433. foreach (uint localId in m_lastColliders)
  1434. {
  1435. if (localId != 0)
  1436. {
  1437. if (Scene == null)
  1438. return;
  1439. ISceneChildEntity obj = Scene.GetSceneObjectPart(localId);
  1440. string data = "";
  1441. if (obj != null)
  1442. {
  1443. if (RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  1444. RootPart.CollisionFilter.ContainsValue(obj.Name))
  1445. {
  1446. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1447. //If it is 1, it is to accept ONLY collisions from this object
  1448. if (found)
  1449. {
  1450. DetectedObject detobj = new DetectedObject
  1451. {
  1452. keyUUID = obj.UUID,
  1453. nameStr = obj.Name,
  1454. ownerUUID = obj.OwnerID,
  1455. posVector = obj.AbsolutePosition,
  1456. rotQuat = obj.GetWorldRotation(),
  1457. velVector = obj.Velocity,
  1458. colliderType = 0,
  1459. groupUUID = obj.GroupID
  1460. };
  1461. colliding.Add(detobj);
  1462. }
  1463. //If it is 0, it is to not accept collisions from this object
  1464. }
  1465. else
  1466. {
  1467. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1468. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  1469. if (!found)
  1470. {
  1471. DetectedObject detobj = new DetectedObject
  1472. {
  1473. keyUUID = obj.UUID,
  1474. nameStr = obj.Name,
  1475. ownerUUID = obj.OwnerID,
  1476. posVector = obj.AbsolutePosition,
  1477. rotQuat = obj.GetWorldRotation(),
  1478. velVector = obj.Velocity,
  1479. colliderType = 0,
  1480. groupUUID = obj.GroupID
  1481. };
  1482. colliding.Add(detobj);
  1483. }
  1484. }
  1485. }
  1486. else
  1487. {
  1488. IScenePresence av = Scene.GetScenePresence(localId);
  1489. if (av != null && av.LocalId == localId)
  1490. {
  1491. if (RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  1492. RootPart.CollisionFilter.ContainsValue(av.Name))
  1493. {
  1494. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1495. //If it is 1, it is to accept ONLY collisions from this avatar
  1496. if (found)
  1497. {
  1498. DetectedObject detobj = new DetectedObject
  1499. {
  1500. keyUUID = av.UUID,
  1501. nameStr = av.ControllingClient.Name,
  1502. ownerUUID = av.UUID,
  1503. posVector = av.AbsolutePosition,
  1504. rotQuat = av.Rotation,
  1505. velVector = av.Velocity,
  1506. colliderType = 0,
  1507. groupUUID =
  1508. av.ControllingClient.ActiveGroupId
  1509. };
  1510. colliding.Add(detobj);
  1511. }
  1512. //If it is 0, it is to not accept collisions from this avatar
  1513. }
  1514. else
  1515. {
  1516. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1517. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  1518. if (!found)
  1519. {
  1520. DetectedObject detobj = new DetectedObject
  1521. {
  1522. keyUUID = av.UUID,
  1523. nameStr = av.ControllingClient.Name,
  1524. ownerUUID = av.UUID,
  1525. posVector = av.AbsolutePosition,
  1526. rotQuat = av.Rotation,
  1527. velVector = av.Velocity,
  1528. colliderType = 0,
  1529. groupUUID =
  1530. av.ControllingClient.ActiveGroupId
  1531. };
  1532. colliding.Add(detobj);
  1533. }
  1534. }
  1535. }
  1536. }
  1537. }
  1538. }
  1539. if (colliding.Count > 0)
  1540. {
  1541. CollidingMessage.Colliders = colliding;
  1542. if (Scene == null)
  1543. return;
  1544. Scene.EventManager.TriggerScriptColliding(RootPart, CollidingMessage);
  1545. }
  1546. }
  1547. }
  1548. if ((RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
  1549. {
  1550. if (endedColliders.Count > 0)
  1551. {
  1552. ColliderArgs EndCollidingMessage = new ColliderArgs();
  1553. List<DetectedObject> colliding = new List<DetectedObject>();
  1554. foreach (uint localId in endedColliders)
  1555. {
  1556. if (localId != 0)
  1557. {
  1558. // always running this check because if the user deletes the object it would return a null reference.
  1559. if (Scene == null)
  1560. return;
  1561. ISceneChildEntity obj = Scene.GetSceneObjectPart(localId);
  1562. string data = "";
  1563. if (obj != null)
  1564. {
  1565. if (RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  1566. RootPart.CollisionFilter.ContainsValue(obj.Name))
  1567. {
  1568. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1569. //If it is 1, it is to accept ONLY collisions from this object
  1570. if (found)
  1571. {
  1572. DetectedObject detobj = new DetectedObject
  1573. {
  1574. keyUUID = obj.UUID,
  1575. nameStr = obj.Name,
  1576. ownerUUID = obj.OwnerID,
  1577. posVector = obj.AbsolutePosition,
  1578. rotQuat = obj.GetWorldRotation(),
  1579. velVector = obj.Velocity,
  1580. colliderType = 0,
  1581. groupUUID = obj.GroupID
  1582. };
  1583. colliding.Add(detobj);
  1584. }
  1585. //If it is 0, it is to not accept collisions from this object
  1586. }
  1587. else
  1588. {
  1589. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1590. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  1591. if (!found)
  1592. {
  1593. DetectedObject detobj = new DetectedObject
  1594. {
  1595. keyUUID = obj.UUID,
  1596. nameStr = obj.Name,
  1597. ownerUUID = obj.OwnerID,
  1598. posVector = obj.AbsolutePosition,
  1599. rotQuat = obj.GetWorldRotation(),
  1600. velVector = obj.Velocity,
  1601. colliderType = 0,
  1602. groupUUID = obj.GroupID
  1603. };
  1604. colliding.Add(detobj);
  1605. }
  1606. }
  1607. }
  1608. else
  1609. {
  1610. IScenePresence av = Scene.GetScenePresence(localId);
  1611. if (av != null && av.LocalId == localId)
  1612. {
  1613. if (RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  1614. RootPart.CollisionFilter.ContainsValue(av.Name))
  1615. {
  1616. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1617. //If it is 1, it is to accept ONLY collisions from this avatar
  1618. if (found)
  1619. {
  1620. DetectedObject detobj = new DetectedObject
  1621. {
  1622. keyUUID = av.UUID,
  1623. nameStr = av.ControllingClient.Name,
  1624. ownerUUID = av.UUID,
  1625. posVector = av.AbsolutePosition,
  1626. rotQuat = av.Rotation,
  1627. velVector = av.Velocity,
  1628. colliderType = 0,
  1629. groupUUID =
  1630. av.ControllingClient.ActiveGroupId
  1631. };
  1632. colliding.Add(detobj);
  1633. }
  1634. //If it is 0, it is to not accept collisions from this avatar
  1635. }
  1636. else
  1637. {
  1638. bool found = RootPart.CollisionFilter.TryGetValue(1, out data);
  1639. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  1640. if (!found)
  1641. {
  1642. DetectedObject detobj = new DetectedObject
  1643. {
  1644. keyUUID = av.UUID,
  1645. nameStr = av.ControllingClient.Name,
  1646. ownerUUID = av.UUID,
  1647. posVector = av.AbsolutePosition,
  1648. rotQuat = av.Rotation,
  1649. velVector = av.Velocity,
  1650. colliderType = 0,
  1651. groupUUID =
  1652. av.ControllingClient.ActiveGroupId
  1653. };
  1654. colliding.Add(detobj);
  1655. }
  1656. }
  1657. }
  1658. }
  1659. }
  1660. }
  1661. if (colliding.Count > 0)
  1662. {
  1663. EndCollidingMessage.Colliders = colliding;
  1664. if (Scene == null)
  1665. return;
  1666. Scene.EventManager.TriggerScriptCollidingEnd(RootPart, EndCollidingMessage);
  1667. }
  1668. }
  1669. }
  1670. if ((RootPart.ScriptEvents & scriptEvents.land_collision_start) != 0)
  1671. {
  1672. if (startedColliders.Count > 0)
  1673. {
  1674. ColliderArgs LandStartCollidingMessage = new ColliderArgs();
  1675. List<DetectedObject> colliding = (from localId in startedColliders
  1676. where localId == 0
  1677. select new DetectedObject
  1678. {
  1679. keyUUID = UUID.Zero,
  1680. nameStr = "",
  1681. ownerUUID = UUID.Zero,
  1682. posVector = RootPart.AbsolutePosition,
  1683. rotQuat = Quaternion.Identity,
  1684. velVector = Vector3.Zero,
  1685. colliderType = 0,
  1686. groupUUID = UUID.Zero
  1687. }).ToList();
  1688. if (colliding.Count > 0)
  1689. {
  1690. LandStartCollidingMessage.Colliders = colliding;
  1691. if (Scene == null)
  1692. return;
  1693. Scene.EventManager.TriggerScriptLandCollidingStart(RootPart, LandStartCollidingMessage);
  1694. }
  1695. }
  1696. }
  1697. if ((RootPart.ScriptEvents & scriptEvents.land_collision) != 0)
  1698. {
  1699. if (m_lastColliders.Count > 0)
  1700. {
  1701. ColliderArgs LandCollidingMessage = new ColliderArgs();
  1702. List<DetectedObject> colliding = (from localId in startedColliders
  1703. where localId == 0
  1704. select new DetectedObject
  1705. {
  1706. keyUUID = UUID.Zero,
  1707. nameStr = "",
  1708. ownerUUID = UUID.Zero,
  1709. posVector = RootPart.AbsolutePosition,
  1710. rotQuat = Quaternion.Identity,
  1711. velVector = Vector3.Zero,
  1712. colliderType = 0,
  1713. groupUUID = UUID.Zero
  1714. }).ToList();
  1715. if (colliding.Count > 0)
  1716. {
  1717. LandCollidingMessage.Colliders = colliding;
  1718. if (Scene == null)
  1719. return;
  1720. Scene.EventManager.TriggerScriptLandColliding(RootPart, LandCollidingMessage);
  1721. }
  1722. }
  1723. }
  1724. if ((RootPart.ScriptEvents & scriptEvents.land_collision_end) != 0)
  1725. {
  1726. if (endedColliders.Count > 0)
  1727. {
  1728. ColliderArgs LandEndCollidingMessage = new ColliderArgs();
  1729. List<DetectedObject> colliding = (from localId in startedColliders
  1730. where localId == 0
  1731. select new DetectedObject
  1732. {
  1733. keyUUID = UUID.Zero,
  1734. nameStr = "",
  1735. ownerUUID = UUID.Zero,
  1736. posVector = RootPart.AbsolutePosition,
  1737. rotQuat = Quaternion.Identity,
  1738. velVector = Vector3.Zero,
  1739. colliderType = 0,
  1740. groupUUID = UUID.Zero
  1741. }).ToList();
  1742. if (colliding.Count > 0)
  1743. {
  1744. LandEndCollidingMessage.Colliders = colliding;
  1745. // always running this check because if the user deletes the object it would return a null reference.
  1746. if (Scene == null)
  1747. return;
  1748. Scene.EventManager.TriggerScriptLandCollidingEnd(RootPart, LandEndCollidingMessage);
  1749. }
  1750. }
  1751. }
  1752. }
  1753. public ISceneChildEntity RootChild
  1754. {
  1755. get { return m_rootPart; }
  1756. set { m_rootPart = (SceneObjectPart) value; }
  1757. }
  1758. #endregion
  1759. #region ISceneObject
  1760. public virtual string ToXml2()
  1761. {
  1762. return SceneEntitySerializer.SceneObjectSerializer.ToXml2Format(this);
  1763. }
  1764. public virtual byte[] ToBinaryXml2()
  1765. {
  1766. return SceneEntitySerializer.SceneObjectSerializer.ToBinaryXml2Format(this);
  1767. }
  1768. #endregion
  1769. public void ClearPartAttachmentData()
  1770. {
  1771. SetAttachmentPoint(0);
  1772. }
  1773. /// <summary>
  1774. /// Set a part to act as the root part for this scene object
  1775. /// </summary>
  1776. /// <param name="part"></param>
  1777. public void SetRootPart(SceneObjectPart part)
  1778. {
  1779. if (part == null)
  1780. throw new ArgumentNullException("part");
  1781. m_rootPart = part;
  1782. if (!IsAttachment)
  1783. part.SetParentLocalId(0);
  1784. AddChild(part, part.LinkNum);
  1785. }
  1786. public void ObjectGrabHandler(uint localId, Vector3 offsetPos, IClientAPI remoteClient)
  1787. {
  1788. if (m_rootPart.LocalId == localId)
  1789. {
  1790. OnGrabGroup(offsetPos, remoteClient);
  1791. }
  1792. else
  1793. {
  1794. SceneObjectPart part = (SceneObjectPart) GetChildPart(localId);
  1795. OnGrabPart(part, offsetPos, remoteClient);
  1796. }
  1797. }
  1798. public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
  1799. {
  1800. part.StoreUndoState();
  1801. part.OnGrab(offsetPos, remoteClient);
  1802. }
  1803. public virtual void OnGrabGroup(Vector3 offsetPos, IClientAPI remoteClient)
  1804. {
  1805. m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
  1806. }
  1807. public void aggregateScriptEvents()
  1808. {
  1809. PrimFlags objectflagupdate = (PrimFlags) RootPart.GetEffectiveObjectFlags();
  1810. scriptEvents aggregateScriptEvents = 0;
  1811. foreach (SceneObjectPart part in m_partsList.Where(part => part != null))
  1812. {
  1813. if (part != RootPart)
  1814. part.Flags = objectflagupdate;
  1815. aggregateScriptEvents |= part.AggregateScriptEvents;
  1816. }
  1817. m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
  1818. m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
  1819. if (!m_scriptListens_atTarget && !m_scriptListens_notAtTarget)
  1820. {
  1821. lock (m_targets)
  1822. m_targets.Clear();
  1823. RemoveGroupTarget(this);
  1824. }
  1825. m_scriptListens_atRotTarget = ((aggregateScriptEvents & scriptEvents.at_rot_target) != 0);
  1826. m_scriptListens_notAtRotTarget = ((aggregateScriptEvents & scriptEvents.not_at_rot_target) != 0);
  1827. if (!m_scriptListens_atRotTarget && !m_scriptListens_notAtRotTarget)
  1828. {
  1829. lock (m_rotTargets)
  1830. m_rotTargets.Clear();
  1831. RemoveGroupTarget(this);
  1832. }
  1833. ScheduleGroupUpdate(PrimUpdateFlags.PrimFlags);
  1834. }
  1835. public void SetText(string text, Vector3 color, double alpha)
  1836. {
  1837. Color = Color.FromArgb(0xff - (int) (alpha*0xff),
  1838. (int) (color.X*0xff),
  1839. (int) (color.Y*0xff),
  1840. (int) (color.Z*0xff));
  1841. Text = text;
  1842. m_rootPart.ScheduleUpdate(PrimUpdateFlags.Text);
  1843. }
  1844. public void ForEachPart(Action<SceneObjectPart> whatToDo)
  1845. {
  1846. lock (m_partsLock)
  1847. {
  1848. foreach (SceneObjectPart part in m_partsList)
  1849. {
  1850. whatToDo(part);
  1851. }
  1852. }
  1853. }
  1854. internal void SetAxisRotation(int axis, int rotate10)
  1855. {
  1856. const int xaxis = 2;
  1857. const int yaxis = 4;
  1858. const int zaxis = 8;
  1859. if (m_rootPart != null)
  1860. {
  1861. bool setX = ((axis & xaxis) != 0);
  1862. bool setY = ((axis & yaxis) != 0);
  1863. bool setZ = ((axis & zaxis) != 0);
  1864. float setval = (rotate10 > 0) ? 1f : 0f;
  1865. if (setX)
  1866. m_rootPart.RotationAxis.X = setval;
  1867. if (setY)
  1868. m_rootPart.RotationAxis.Y = setval;
  1869. if (setZ)
  1870. m_rootPart.RotationAxis.Z = setval;
  1871. if (setX || setY || setZ)
  1872. {
  1873. m_rootPart.SetPhysicsAxisRotation();
  1874. }
  1875. }
  1876. }
  1877. public int registerRotTargetWaypoint(Quaternion target, float tolerance)
  1878. {
  1879. scriptRotTarget waypoint = new scriptRotTarget {targetRot = target, tolerance = tolerance};
  1880. uint handle = m_scene.SceneGraph.AllocateLocalId();
  1881. waypoint.handle = handle;
  1882. lock (m_rotTargets)
  1883. {
  1884. m_rotTargets.Add(handle, waypoint);
  1885. }
  1886. AddGroupTarget(this);
  1887. return (int) handle;
  1888. }
  1889. public void unregisterRotTargetWaypoint(int handle)
  1890. {
  1891. lock (m_targets)
  1892. {
  1893. m_rotTargets.Remove((uint) handle);
  1894. if (m_targets.Count == 0)
  1895. RemoveGroupTarget(this);
  1896. }
  1897. }
  1898. public int registerTargetWaypoint(Vector3 target, float tolerance)
  1899. {
  1900. scriptPosTarget waypoint = new scriptPosTarget {targetPos = target, tolerance = tolerance};
  1901. uint handle = m_scene.SceneGraph.AllocateLocalId();
  1902. waypoint.handle = handle;
  1903. lock (m_targets)
  1904. {
  1905. m_targets.Add(handle, waypoint);
  1906. }
  1907. AddGroupTarget(this);
  1908. return (int) handle;
  1909. }
  1910. public void unregisterTargetWaypoint(int handle)
  1911. {
  1912. lock (m_targets)
  1913. {
  1914. m_targets.Remove((uint) handle);
  1915. if (m_targets.Count == 0)
  1916. RemoveGroupTarget(this);
  1917. }
  1918. }
  1919. public void AddGroupTarget(SceneObjectGroup grp)
  1920. {
  1921. m_scene.EventManager.OnFrame += checkAtTargets;
  1922. }
  1923. public void RemoveGroupTarget(SceneObjectGroup grp)
  1924. {
  1925. m_scene.EventManager.OnFrame -= checkAtTargets;
  1926. }
  1927. public void AddKeyframedMotion(KeyframeAnimation animation, KeyframeAnimation.Commands command)
  1928. {
  1929. if (command == KeyframeAnimation.Commands.Play)
  1930. {
  1931. m_rootPart.KeyframeAnimation = animation;
  1932. m_scene.EventManager.OnFrame += moveKeyframeMotion;
  1933. }
  1934. else
  1935. {
  1936. m_scene.EventManager.OnFrame -= moveKeyframeMotion;
  1937. if (command == KeyframeAnimation.Commands.Stop)
  1938. m_rootPart.KeyframeAnimation = null;
  1939. }
  1940. }
  1941. public void moveKeyframeMotion()
  1942. {
  1943. if (m_rootPart.KeyframeAnimation == null || m_rootPart.KeyframeAnimation.TimeList.Length == 0)
  1944. {
  1945. m_scene.EventManager.OnFrame -= moveKeyframeMotion;
  1946. return;
  1947. }
  1948. try
  1949. {
  1950. int currentTime =
  1951. m_rootPart.KeyframeAnimation.TimeList[m_rootPart.KeyframeAnimation.CurrentAnimationPosition];
  1952. float timeAmt = (1f/(float) currentTime);
  1953. Vector3 currentTarget = m_rootPart.KeyframeAnimation.PositionList.Length == 0
  1954. ? Vector3.Zero
  1955. : m_rootPart.KeyframeAnimation.PositionList[
  1956. m_rootPart.KeyframeAnimation.CurrentAnimationPosition];
  1957. Quaternion target = m_rootPart.KeyframeAnimation.RotationList.Length == 0
  1958. ? Quaternion.Identity
  1959. : m_rootPart.KeyframeAnimation.RotationList[
  1960. m_rootPart.KeyframeAnimation.CurrentAnimationPosition];
  1961. m_rootPart.KeyframeAnimation.CurrentFrame++;
  1962. //Add one to the current frame so that we know when to stops
  1963. bool AllDoneMoving = false;
  1964. bool MadeItToCheckpoint = false;
  1965. if (m_rootPart.KeyframeAnimation.CurrentFrame == currentTime)
  1966. {
  1967. if (m_rootPart.KeyframeAnimation.CurrentMode == KeyframeAnimation.Modes.Forward)
  1968. {
  1969. m_rootPart.KeyframeAnimation.CurrentAnimationPosition += 1;
  1970. if (m_rootPart.KeyframeAnimation.CurrentAnimationPosition ==
  1971. m_rootPart.KeyframeAnimation.TimeList.Length)
  1972. {
  1973. //All done moving...
  1974. AllDoneMoving = true;
  1975. m_scene.EventManager.OnFrame -= moveKeyframeMotion;
  1976. }
  1977. }
  1978. else if (m_rootPart.KeyframeAnimation.CurrentMode == KeyframeAnimation.Modes.Reverse)
  1979. {
  1980. m_rootPart.KeyframeAnimation.CurrentAnimationPosition -= 1;
  1981. if (m_rootPart.KeyframeAnimation.CurrentAnimationPosition < 0)
  1982. {
  1983. //All done moving...
  1984. AllDoneMoving = true;
  1985. m_scene.EventManager.OnFrame -= moveKeyframeMotion;
  1986. }
  1987. }
  1988. else if (m_rootPart.KeyframeAnimation.CurrentMode == KeyframeAnimation.Modes.Loop)
  1989. {
  1990. m_rootPart.KeyframeAnimation.CurrentAnimationPosition += 1;
  1991. if (m_rootPart.KeyframeAnimation.CurrentAnimationPosition ==
  1992. m_rootPart.KeyframeAnimation.TimeList.Length)
  1993. m_rootPart.KeyframeAnimation.CurrentAnimationPosition = 0;
  1994. }
  1995. else if (m_rootPart.KeyframeAnimation.CurrentMode == KeyframeAnimation.Modes.PingPong)
  1996. {
  1997. if (m_rootPart.KeyframeAnimation.PingPongForwardMotion)
  1998. {
  1999. m_rootPart.KeyframeAnimation.CurrentAnimationPosition += 1;
  2000. if (m_rootPart.KeyframeAnimation.CurrentAnimationPosition ==
  2001. m_rootPart.KeyframeAnimation.TimeList.Length)
  2002. {
  2003. m_rootPart.KeyframeAnimation.PingPongForwardMotion =
  2004. !m_rootPart.KeyframeAnimation.PingPongForwardMotion;
  2005. m_rootPart.KeyframeAnimation.CurrentAnimationPosition -= 2;
  2006. }
  2007. }
  2008. else
  2009. {
  2010. m_rootPart.KeyframeAnimation.CurrentAnimationPosition -= 1;
  2011. if (m_rootPart.KeyframeAnimation.CurrentAnimationPosition < 0)
  2012. {
  2013. m_rootPart.KeyframeAnimation.PingPongForwardMotion =
  2014. !m_rootPart.KeyframeAnimation.PingPongForwardMotion;
  2015. m_rootPart.KeyframeAnimation.CurrentAnimationPosition += 2;
  2016. }
  2017. }
  2018. }
  2019. m_rootPart.KeyframeAnimation.CurrentFrame = 0;
  2020. MadeItToCheckpoint = true;
  2021. }
  2022. if (m_rootPart.KeyframeAnimation.PositionList.Length != 0)
  2023. {
  2024. Vector3 _target_velocity =
  2025. new Vector3(
  2026. (currentTarget.X - m_rootPart.KeyframeAnimation.InitialPosition.X)*timeAmt,
  2027. (currentTarget.Y - m_rootPart.KeyframeAnimation.InitialPosition.Y)*timeAmt,
  2028. (currentTarget.Z - m_rootPart.KeyframeAnimation.InitialPosition.Z)*timeAmt
  2029. );
  2030. if (MadeItToCheckpoint)
  2031. {
  2032. if (AllDoneMoving)
  2033. Velocity = Vector3.Zero;
  2034. SetAbsolutePosition(true, currentTarget);
  2035. m_rootPart.KeyframeAnimation.InitialPosition = currentTarget;
  2036. }
  2037. else
  2038. {
  2039. SetAbsolutePosition(true, m_rootPart.AbsolutePosition + _target_velocity);
  2040. m_rootPart.Velocity = _target_velocity/45f;
  2041. }
  2042. }
  2043. if (m_rootPart.KeyframeAnimation.RotationList.Length != 0)
  2044. {
  2045. Quaternion source = m_rootPart.GetRotationOffset();
  2046. Quaternion newInterpolation = Quaternion.Slerp(source, target,
  2047. 1f/
  2048. ((float) currentTime -
  2049. (float) m_rootPart.KeyframeAnimation.CurrentFrame));
  2050. m_rootPart.UpdateRotation(newInterpolation);
  2051. if (MadeItToCheckpoint)
  2052. {
  2053. //Force set it to the right position, just to be sure
  2054. m_rootPart.UpdateRotation(target);
  2055. m_rootPart.KeyframeAnimation.InitialRotation = target;
  2056. }
  2057. }
  2058. }
  2059. catch
  2060. {
  2061. m_scene.EventManager.OnFrame -= moveKeyframeMotion;
  2062. }
  2063. ScheduleGroupTerseUpdate();
  2064. }
  2065. public void checkAtTargets()
  2066. {
  2067. if (m_scriptListens_atTarget || m_scriptListens_notAtTarget)
  2068. {
  2069. if (m_targets.Count > 0)
  2070. {
  2071. bool at_target = false;
  2072. //Vector3 targetPos;
  2073. //uint targetHandle;
  2074. Dictionary<uint, scriptPosTarget> atTargets = new Dictionary<uint, scriptPosTarget>();
  2075. lock (m_targets)
  2076. {
  2077. foreach (uint idx in m_targets.Keys)
  2078. {
  2079. scriptPosTarget target = m_targets[idx];
  2080. if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
  2081. {
  2082. // trigger at_target
  2083. if (m_scriptListens_atTarget)
  2084. {
  2085. at_target = true;
  2086. scriptPosTarget att = new scriptPosTarget
  2087. {
  2088. targetPos = target.targetPos,
  2089. tolerance = target.tolerance,
  2090. handle = target.handle
  2091. };
  2092. atTargets.Add(idx, att);
  2093. }
  2094. }
  2095. }
  2096. }
  2097. if (atTargets.Count > 0)
  2098. {
  2099. uint[] localids = new uint[0];
  2100. localids = new uint[m_parts.Count];
  2101. int cntr = 0;
  2102. foreach (SceneObjectPart part in m_partsList)
  2103. {
  2104. localids[cntr] = part.LocalId;
  2105. cntr++;
  2106. }
  2107. foreach (uint t in localids)
  2108. {
  2109. foreach (scriptPosTarget att in atTargets.Values)
  2110. {
  2111. m_scene.EventManager.TriggerAtTargetEvent(
  2112. t, att.handle, att.targetPos, m_rootPart.GroupPosition);
  2113. }
  2114. }
  2115. return;
  2116. }
  2117. if (m_scriptListens_notAtTarget && !at_target)
  2118. {
  2119. //trigger not_at_target
  2120. uint[] localids = new uint[0];
  2121. localids = new uint[m_parts.Count];
  2122. int cntr = 0;
  2123. foreach (SceneObjectPart part in m_partsList)
  2124. {
  2125. localids[cntr] = part.LocalId;
  2126. cntr++;
  2127. }
  2128. foreach (uint t in localids)
  2129. {
  2130. m_scene.EventManager.TriggerNotAtTargetEvent(t);
  2131. }
  2132. }
  2133. }
  2134. }
  2135. if (m_scriptListens_atRotTarget || m_scriptListens_notAtRotTarget)
  2136. {
  2137. if (m_rotTargets.Count > 0)
  2138. {
  2139. bool at_Rottarget = false;
  2140. Dictionary<uint, scriptRotTarget> atRotTargets = new Dictionary<uint, scriptRotTarget>();
  2141. lock (m_rotTargets)
  2142. {
  2143. foreach (uint idx in m_rotTargets.Keys)
  2144. {
  2145. scriptRotTarget target = m_rotTargets[idx];
  2146. double angle =
  2147. Math.Acos(target.targetRot.X*m_rootPart.GetRotationOffset().X +
  2148. target.targetRot.Y*m_rootPart.GetRotationOffset().Y +
  2149. target.targetRot.Z*m_rootPart.GetRotationOffset().Z +
  2150. target.targetRot.W*m_rootPart.GetRotationOffset().W)*2;
  2151. if (angle < 0) angle = -angle;
  2152. if (angle > Math.PI) angle = (Math.PI*2 - angle);
  2153. if (angle <= target.tolerance)
  2154. {
  2155. // trigger at_rot_target
  2156. if (m_scriptListens_atRotTarget)
  2157. {
  2158. at_Rottarget = true;
  2159. scriptRotTarget att = new scriptRotTarget
  2160. {
  2161. targetRot = target.targetRot,
  2162. tolerance = target.tolerance,
  2163. handle = target.handle
  2164. };
  2165. atRotTargets.Add(idx, att);
  2166. }
  2167. }
  2168. }
  2169. }
  2170. if (atRotTargets.Count > 0)
  2171. {
  2172. uint[] localids = new uint[0];
  2173. localids = new uint[m_parts.Count];
  2174. int cntr = 0;
  2175. foreach (SceneObjectPart part in m_partsList)
  2176. {
  2177. localids[cntr] = part.LocalId;
  2178. cntr++;
  2179. }
  2180. foreach (uint t in localids)
  2181. {
  2182. foreach (scriptRotTarget att in atRotTargets.Values)
  2183. {
  2184. m_scene.EventManager.TriggerAtRotTargetEvent(
  2185. t, att.handle, att.targetRot, m_rootPart.GetRotationOffset());
  2186. }
  2187. }
  2188. return;
  2189. }
  2190. if (m_scriptListens_notAtRotTarget && !at_Rottarget)
  2191. {
  2192. //trigger not_at_target
  2193. uint[] localids = new uint[0];
  2194. localids = new uint[m_parts.Count];
  2195. int cntr = 0;
  2196. foreach (SceneObjectPart part in m_partsList)
  2197. {
  2198. localids[cntr] = part.LocalId;
  2199. cntr++;
  2200. }
  2201. foreach (uint t in localids)
  2202. {
  2203. m_scene.EventManager.TriggerNotAtRotTargetEvent(t);
  2204. }
  2205. }
  2206. }
  2207. }
  2208. }
  2209. public void CheckSculptAndLoad()
  2210. {
  2211. foreach (SceneObjectPart part in m_partsList)
  2212. {
  2213. if (part.Shape == null)
  2214. continue;
  2215. if (!(RootPart.PhysicsType == (byte) PhysicsShapeType.None ||
  2216. part.PhysicsType == (byte) PhysicsShapeType.None ||
  2217. ((part.Flags & PrimFlags.Phantom) == PrimFlags.Phantom &&
  2218. !part.VolumeDetectActive) ||
  2219. ((RootPart.Flags & PrimFlags.Phantom) == PrimFlags.Phantom &&
  2220. !RootPart.VolumeDetectActive)))
  2221. {
  2222. if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero)
  2223. {
  2224. // If no sculpt data exists, we need to get the data
  2225. m_scene.AssetService.Get(part.Shape.SculptTexture.ToString(), true, part.AssetReceived);
  2226. //In the mean time...
  2227. //part.Shape.SculptEntry = false;
  2228. part.Shape.SculptData = new byte[0];
  2229. }
  2230. }
  2231. }
  2232. }
  2233. public void GeneratedMesh(ISceneChildEntity part, IMesh mesh)
  2234. {
  2235. //This destroys the mesh if it is added... this needs added in a way that won't corrupt the mesh
  2236. /*if (part.Shape.SculptType == (byte)SculptType.Mesh && !mesh.WasCached)//If it was cached, we don't want to resave it
  2237. {
  2238. //We can cache meshes into the mesh itself, saving time generating it next time around
  2239. OSDMap meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(part.Shape.SculptData);
  2240. meshOsd["physics_cached"] = new OSDMap();
  2241. mesh.Serialize();
  2242. mesh.WasCached = true;
  2243. UUID newSculptTexture;
  2244. if (m_scene.AssetService.UpdateContent(part.Shape.SculptTexture,
  2245. OSDParser.SerializeLLSDBinary(meshOsd), out newSculptTexture))
  2246. {
  2247. part.Shape.SculptTexture = newSculptTexture;
  2248. HasGroupChanged = true;
  2249. }
  2250. }*/
  2251. }
  2252. public void TriggerScriptMovingStartEvent()
  2253. {
  2254. foreach (SceneObjectPart part in ChildrenList)
  2255. {
  2256. part.TriggerScriptMovingStartEvent();
  2257. }
  2258. }
  2259. public void TriggerScriptMovingEndEvent()
  2260. {
  2261. foreach (SceneObjectPart part in ChildrenList)
  2262. {
  2263. part.TriggerScriptMovingEndEvent();
  2264. }
  2265. }
  2266. public override string ToString()
  2267. {
  2268. return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
  2269. }
  2270. #region Copying
  2271. /// <summary>
  2272. /// Make an exact copy of this group.
  2273. /// This does NOT reset any UUIDs, localIDs, or anything, as this is an EXACT copy.
  2274. /// </summary>
  2275. /// <returns></returns>
  2276. public ISceneEntity Copy(bool clonePhys)
  2277. {
  2278. SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
  2279. dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
  2280. dupe.m_partsList = new List<SceneObjectPart>();
  2281. dupe.m_scene = Scene;
  2282. // Warning, The following code related to previousAttachmentStatus is needed so that clones of
  2283. // attachments do not bordercross while they're being duplicated. This is hacktastic!
  2284. // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
  2285. // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
  2286. // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
  2287. // then restore it's attachment state
  2288. // This is only necessary when userExposed is false!
  2289. dupe.ClearChildren();
  2290. dupe.AddChild(m_rootPart.Copy(dupe, clonePhys), m_rootPart.LinkNum);
  2291. bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
  2292. dupe.RootPart.IsAttachment = true;
  2293. dupe.AbsolutePosition = AbsolutePosition;
  2294. dupe.RootPart.IsAttachment = previousAttachmentStatus;
  2295. dupe.m_rootPart.TrimPermissions();
  2296. List<SceneObjectPart> partList = new List<SceneObjectPart>();
  2297. lock (m_partsLock)
  2298. {
  2299. partList.AddRange(m_partsList);
  2300. }
  2301. //Sort the list by link number so that we get them in the right order
  2302. partList.Sort(Scene.SceneGraph.LinkSetSorter);
  2303. foreach (SceneObjectPart part in partList)
  2304. {
  2305. if (part.UUID != m_rootPart.UUID)
  2306. {
  2307. SceneObjectPart copy = part.Copy(dupe, clonePhys);
  2308. copy.LinkNum = part.LinkNum;
  2309. dupe.LinkChild(copy);
  2310. }
  2311. }
  2312. dupe.m_ValidgrpOOB = false;
  2313. return dupe;
  2314. }
  2315. /// <summary>
  2316. /// Rebuild the physical representation of all the prims.
  2317. /// This is used after copying the prim so that all of the object is readded to the physics scene.
  2318. /// </summary>
  2319. public void RebuildPhysicalRepresentation(bool keepSelectedStatuses)
  2320. {
  2321. // long lock or array copy? in this case lets try array
  2322. SceneObjectPart[] parts;
  2323. SceneObjectPart part;
  2324. int i;
  2325. lock (m_partsLock)
  2326. parts = m_partsList.ToArray();
  2327. if (RootPart.PhysActor != null)
  2328. RootPart.PhysActor.BlockPhysicalReconstruction = true;
  2329. for (i = 0; i < parts.Length; i++)
  2330. {
  2331. part = parts[i];
  2332. // PhysicsObject oldActor = part.PhysActor;
  2333. // PrimitiveBaseShape pbs = part.Shape;
  2334. if (part.PhysActor != null)
  2335. {
  2336. part.PhysActor.RotationalVelocity = Vector3.Zero;
  2337. part.m_hasSubscribedToCollisionEvent = false;
  2338. part.PhysActor.OnCollisionUpdate -= part.PhysicsCollision;
  2339. part.PhysActor.OnRequestTerseUpdate -= part.PhysicsRequestingTerseUpdate;
  2340. part.PhysActor.OnSignificantMovement -= part.ParentGroup.CheckForSignificantMovement;
  2341. part.PhysActor.OnOutOfBounds -= part.PhysicsOutOfBounds;
  2342. //part.PhysActor.delink ();
  2343. //Remove the old one so that we don't have more than we should,
  2344. // as when we copy, it readds it to the PhysicsScene somehow
  2345. //if (part.IsRoot)//The root removes all children
  2346. m_scene.PhysicsScene.RemovePrim(part.PhysActor);
  2347. part.FireOnRemovedPhysics();
  2348. part.PhysActor = null;
  2349. }
  2350. //Reset any old data that we have
  2351. part.Velocity = Vector3.Zero;
  2352. part.AngularVelocity = Vector3.Zero;
  2353. part.Acceleration = Vector3.Zero;
  2354. part.GenerateRotationalVelocityFromOmega();
  2355. }
  2356. //Check for meshes and stuff
  2357. CheckSculptAndLoad();
  2358. // check root part setting that make the entire object not having physics rep
  2359. if (RootPart.PhysicsType == (byte) PhysicsShapeType.None ||
  2360. ((RootPart.Flags & PrimFlags.Phantom) == PrimFlags.Phantom && !RootPart.VolumeDetectActive))
  2361. {
  2362. Scene.AuroraEventManager.FireGenericEventHandler("ObjectChangedPhysicalStatus", this);
  2363. if (OnFinishedPhysicalRepresentationBuilding != null)
  2364. OnFinishedPhysicalRepresentationBuilding();
  2365. OnFinishedPhysicalRepresentationBuilding = null;
  2366. return;
  2367. }
  2368. // create the root part
  2369. RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(RootPart);
  2370. if (RootPart.PhysActor == null)
  2371. return;
  2372. // RootPart.PhysActor.BuildingRepresentation = true;
  2373. RootPart.PhysActor.BlockPhysicalReconstruction = true;
  2374. //Don't let it rebuild it until we have all the links done
  2375. //Fix the localID!
  2376. RootPart.PhysActor.LocalID = RootPart.LocalId;
  2377. RootPart.PhysActor.UUID = RootPart.UUID;
  2378. RootPart.PhysActor.VolumeDetect = RootPart.VolumeDetectActive;
  2379. //Force deselection here so that it isn't stuck forever
  2380. RootPart.PhysActor.Selected = keepSelectedStatuses && RootPart.IsSelected;
  2381. RootPart.PhysActor.SetMaterial(RootPart.Material, false);
  2382. // bool rootIsPhysical;
  2383. if ((RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  2384. {
  2385. // rootIsPhysical = true;
  2386. RootPart.PhysActor.IsPhysical = true;
  2387. }
  2388. // else
  2389. // rootIsPhysical = false;
  2390. //Add collision updates
  2391. //part.PhysActor.OnCollisionUpdate += RootPart.PhysicsCollision;
  2392. RootPart.PhysActor.OnRequestTerseUpdate += RootPart.PhysicsRequestingTerseUpdate;
  2393. RootPart.PhysActor.OnSignificantMovement += RootPart.ParentGroup.CheckForSignificantMovement;
  2394. RootPart.PhysActor.OnOutOfBounds += RootPart.PhysicsOutOfBounds;
  2395. RootPart.FireOnAddedPhysics();
  2396. RootPart.aggregateScriptEvents();
  2397. for (i = 0; i < parts.Length; i++)
  2398. {
  2399. part = parts[i];
  2400. if (part == RootPart ||
  2401. part.PhysicsType == (byte) PhysicsShapeType.None ||
  2402. ((part.Flags & PrimFlags.Phantom) == PrimFlags.Phantom && !part.VolumeDetectActive))
  2403. {
  2404. continue; // ignore phantom prims
  2405. }
  2406. //Now read the physics actor to the physics scene
  2407. part.PhysActor = m_scene.PhysicsScene.AddPrimShape(part);
  2408. if (part.PhysActor == null)
  2409. continue;
  2410. // part.PhysActor.BuildingRepresentation = true;
  2411. // if(part.IsRoot)
  2412. part.PhysActor.BlockPhysicalReconstruction = true;
  2413. //Don't let it rebuild it until we have all the links done
  2414. //Fix the localID!
  2415. part.PhysActor.LocalID = part.LocalId;
  2416. part.PhysActor.UUID = part.UUID;
  2417. part.PhysActor.VolumeDetect = part.VolumeDetectActive;
  2418. //Force deselection here so that it isn't stuck forever
  2419. part.PhysActor.Selected = keepSelectedStatuses && part.IsSelected;
  2420. part.PhysActor.SetMaterial(part.Material, false);
  2421. if ((part.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  2422. part.PhysActor.IsPhysical = true;
  2423. //Add collision updates
  2424. //part.PhysActor.OnCollisionUpdate += part.PhysicsCollision;
  2425. part.PhysActor.OnRequestTerseUpdate += part.PhysicsRequestingTerseUpdate;
  2426. part.PhysActor.OnSignificantMovement += part.ParentGroup.CheckForSignificantMovement;
  2427. part.PhysActor.OnOutOfBounds += part.PhysicsOutOfBounds;
  2428. part.FireOnAddedPhysics();
  2429. part.aggregateScriptEvents();
  2430. //Link the prim then
  2431. // if(rootIsPhysical)
  2432. part.PhysActor.link(RootPart.PhysActor);
  2433. }
  2434. Scene.AuroraEventManager.FireGenericEventHandler("ObjectChangedPhysicalStatus", this);
  2435. RootPart.PhysActor.BlockPhysicalReconstruction = false; // this sets children also (in AODE at least)
  2436. // RootPart.PhysActor.BuildingRepresentation = false;
  2437. FixVehicleParams(RootPart);
  2438. if (OnFinishedPhysicalRepresentationBuilding != null)
  2439. OnFinishedPhysicalRepresentationBuilding();
  2440. OnFinishedPhysicalRepresentationBuilding = null;
  2441. }
  2442. /*
  2443. lock (m_partsLock)
  2444. {
  2445. foreach (SceneObjectPart part in m_partsList)
  2446. {
  2447. PhysicsObject oldActor = part.PhysActor;
  2448. PrimitiveBaseShape pbs = part.Shape;
  2449. //Reset any old data that we have
  2450. part.Velocity = Vector3.Zero;
  2451. part.Acceleration = Vector3.Zero;
  2452. if (part.PhysActor != null)
  2453. {
  2454. part.PhysActor.RotationalVelocity = Vector3.Zero;
  2455. part.PhysActor.UnSubscribeEvents ();
  2456. part.m_hasSubscribedToCollisionEvent = false;
  2457. part.PhysActor.OnCollisionUpdate -= part.PhysicsCollision;
  2458. part.PhysActor.OnRequestTerseUpdate -= part.PhysicsRequestingTerseUpdate;
  2459. part.PhysActor.OnSignificantMovement -= part.ParentGroup.CheckForSignificantMovement;
  2460. part.PhysActor.OnOutOfBounds -= part.PhysicsOutOfBounds;
  2461. //part.PhysActor.delink ();
  2462. //Remove the old one so that we don't have more than we should,
  2463. // as when we copy, it readds it to the PhysicsScene somehow
  2464. //if (part.IsRoot)//The root removes all children
  2465. m_scene.PhysicsScene.RemovePrim (part.PhysActor);
  2466. part.FireOnRemovedPhysics ();
  2467. }
  2468. part.AngularVelocity = Vector3.Zero;
  2469. part.GenerateRotationalVelocityFromOmega ();
  2470. }
  2471. }
  2472. //Check for meshes and stuff
  2473. CheckSculptAndLoad ();
  2474. //This is a heavy operation... it is really bad to lock this, but if we don't, we could have multiple threads in here... which would be baaad
  2475. lock (m_partsLock)
  2476. {
  2477. foreach (SceneObjectPart part in m_partsList)
  2478. {
  2479. if (RootPart.PhysicsType == (byte)PhysicsShapeType.None ||
  2480. part.PhysicsType == (byte)PhysicsShapeType.None ||
  2481. ((part.Flags & PrimFlags.Phantom) == PrimFlags.Phantom &&
  2482. !part.VolumeDetectActive) ||
  2483. ((RootPart.Flags & PrimFlags.Phantom) == PrimFlags.Phantom &&
  2484. !RootPart.VolumeDetectActive))
  2485. {
  2486. part.PhysActor = null;
  2487. continue; //Don't rebuild! All phantom if the root is phantom
  2488. }
  2489. //Now readd the physics actor to the physics scene
  2490. part.PhysActor = m_scene.PhysicsScene.AddPrimShape (part);
  2491. // part.PhysActor.BuildingRepresentation = true;
  2492. // if(part.IsRoot)
  2493. // part.PhysActor.BlockPhysicalReconstruction = true;//Don't let it rebuild it until we have all the links done
  2494. //Fix the localID!
  2495. part.PhysActor.LocalID = part.LocalId;
  2496. part.PhysActor.UUID = part.UUID;
  2497. part.PhysActor.VolumeDetect = part.VolumeDetectActive;
  2498. //Force deselection here so that it isn't stuck forever
  2499. if (!keepSelectedStatuses)
  2500. part.PhysActor.Selected = false;
  2501. else
  2502. part.PhysActor.Selected = part.IsSelected;
  2503. part.PhysActor.SetMaterial (part.Material, false);
  2504. //Add collision updates
  2505. //part.PhysActor.OnCollisionUpdate += part.PhysicsCollision;
  2506. part.PhysActor.OnRequestTerseUpdate += part.PhysicsRequestingTerseUpdate;
  2507. part.PhysActor.OnSignificantMovement += part.ParentGroup.CheckForSignificantMovement;
  2508. part.PhysActor.OnOutOfBounds += part.PhysicsOutOfBounds;
  2509. part.FireOnAddedPhysics ();
  2510. part.aggregateScriptEvents ();
  2511. }
  2512. Scene.AuroraEventManager.FireGenericEventHandler ("ObjectChangedPhysicalStatus", this);
  2513. }
  2514. lock (m_partsLock)
  2515. {
  2516. foreach (SceneObjectPart part in m_partsList)
  2517. {
  2518. if (!part.IsRoot && RootPart.PhysActor != null && part.PhysActor != null)//Link the prim then
  2519. part.PhysActor.link (RootPart.PhysActor);
  2520. }
  2521. foreach (SceneObjectPart part in m_partsList)
  2522. {
  2523. if (part.PhysActor != null)
  2524. {
  2525. FixVehicleParams(part);
  2526. // *
  2527. if(part.IsRoot)
  2528. {
  2529. //All done linking, build the body
  2530. part.PhysActor.BlockPhysicalReconstruction = false;
  2531. }
  2532. part.PhysActor.BuildingRepresentation = false;
  2533. // *
  2534. }
  2535. }
  2536. if(OnFinishedPhysicalRepresentationBuilding != null)
  2537. OnFinishedPhysicalRepresentationBuilding();
  2538. }
  2539. }
  2540. */
  2541. /// <summary>
  2542. /// Fix all the vehicle params after rebuilding the representation
  2543. /// </summary>
  2544. /// <param name="part"></param>
  2545. private void FixVehicleParams(SceneObjectPart part)
  2546. {
  2547. part.PhysActor.VehicleType = part.VehicleType;
  2548. // OSD o = part.GetComponentState("VehicleParameters");
  2549. foreach (OSD param in part.VehicleFlags)
  2550. {
  2551. part.PhysActor.VehicleFlags(param.AsInteger(), false);
  2552. }
  2553. foreach (KeyValuePair<string, OSD> param in part.VehicleParameters)
  2554. {
  2555. if (param.Value.Type == OSDType.Real)
  2556. part.PhysActor.VehicleFloatParam(int.Parse(param.Key), (float) param.Value.AsReal());
  2557. else if (param.Value.Type == OSDType.Array)
  2558. {
  2559. OSDArray a = (OSDArray) param.Value;
  2560. if (a.Count == 3)
  2561. part.PhysActor.VehicleVectorParam(int.Parse(param.Key), param.Value.AsVector3());
  2562. else
  2563. part.PhysActor.VehicleRotationParam(int.Parse(param.Key), param.Value.AsQuaternion());
  2564. }
  2565. }
  2566. }
  2567. #endregion
  2568. #region Script methods
  2569. public Vector3 GetTorque()
  2570. {
  2571. // We check if rootpart is null here because scripts don't delete if you delete the host.
  2572. // This means that unfortunately, we can pass a null physics actor to Simulate!
  2573. // Make sure we don't do that!
  2574. SceneObjectPart rootpart = m_rootPart;
  2575. if (rootpart != null)
  2576. {
  2577. if (rootpart.PhysActor != null)
  2578. {
  2579. if (!IsAttachment)
  2580. {
  2581. Vector3 torque = rootpart.PhysActor.Torque;
  2582. return torque;
  2583. }
  2584. }
  2585. }
  2586. return Vector3.Zero;
  2587. }
  2588. /// <summary>
  2589. /// Set the owner of the root part.
  2590. /// </summary>
  2591. /// <param name="part"></param>
  2592. /// <param name="cAgentID"></param>
  2593. /// <param name="cGroupID"></param>
  2594. public void SetRootPartOwner(ISceneChildEntity part, UUID cAgentID, UUID cGroupID)
  2595. {
  2596. part.LastOwnerID = part.OwnerID;
  2597. part.OwnerID = cAgentID;
  2598. part.GroupID = cGroupID;
  2599. if (part.OwnerID != cAgentID)
  2600. {
  2601. // Apply Next Owner Permissions if we're not bypassing permissions
  2602. if (!m_scene.Permissions.BypassPermissions())
  2603. ApplyNextOwnerPermissions();
  2604. }
  2605. part.ScheduleUpdate(PrimUpdateFlags.ForcedFullUpdate);
  2606. }
  2607. public void ScriptSetPhysicsStatus(bool UsePhysics)
  2608. {
  2609. bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
  2610. bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
  2611. bool IsVolumeDetect = RootPart.VolumeDetectActive;
  2612. UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect, null);
  2613. }
  2614. public void ScriptSetTemporaryStatus(bool TemporaryStatus)
  2615. {
  2616. bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
  2617. bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
  2618. bool IsVolumeDetect = RootPart.VolumeDetectActive;
  2619. UpdatePrimFlags(RootPart.LocalId, UsePhysics, TemporaryStatus, IsPhantom, IsVolumeDetect, null);
  2620. }
  2621. public void ScriptSetPhantomStatus(bool PhantomStatus)
  2622. {
  2623. bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
  2624. bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
  2625. bool IsVolumeDetect = RootPart.VolumeDetectActive;
  2626. UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, PhantomStatus, IsVolumeDetect, null);
  2627. }
  2628. public void ScriptSetVolumeDetect(bool VDStatus)
  2629. {
  2630. bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
  2631. bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
  2632. bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
  2633. UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, VDStatus, null);
  2634. }
  2635. public void applyImpulse(Vector3 impulse)
  2636. {
  2637. // We check if rootpart is null here because scripts don't delete if you delete the host.
  2638. // This means that unfortunately, we can pass a null physics actor to Simulate!
  2639. // Make sure we don't do that!
  2640. SceneObjectPart rootpart = m_rootPart;
  2641. if (rootpart != null)
  2642. {
  2643. if (IsAttachment)
  2644. {
  2645. IScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
  2646. if (avatar != null)
  2647. {
  2648. avatar.PushForce(impulse);
  2649. }
  2650. }
  2651. else
  2652. {
  2653. if (rootpart.PhysActor != null)
  2654. rootpart.PhysActor.AddForce(impulse, true);
  2655. }
  2656. }
  2657. }
  2658. public void applyAngularImpulse(Vector3 impulse)
  2659. {
  2660. // We check if rootpart is null here because scripts don't delete if you delete the host.
  2661. // This means that unfortunately, we can pass a null physics actor to Simulate!
  2662. // Make sure we don't do that!
  2663. SceneObjectPart rootpart = m_rootPart;
  2664. if (rootpart != null)
  2665. {
  2666. if (rootpart.PhysActor != null)
  2667. {
  2668. if (!IsAttachment)
  2669. rootpart.PhysActor.AddAngularForce(impulse, true);
  2670. }
  2671. }
  2672. }
  2673. public void setAngularImpulse(Vector3 impulse)
  2674. {
  2675. // We check if rootpart is null here because scripts don't delete if you delete the host.
  2676. // This means that unfortunately, we can pass a null physics actor to Simulate!
  2677. // Make sure we don't do that!
  2678. SceneObjectPart rootpart = m_rootPart;
  2679. if (rootpart != null)
  2680. {
  2681. if (rootpart.PhysActor != null)
  2682. {
  2683. if (!IsAttachment)
  2684. rootpart.PhysActor.Torque = impulse;
  2685. }
  2686. }
  2687. }
  2688. public void moveToTarget(Vector3 target, float tau)
  2689. {
  2690. SceneObjectPart rootpart = m_rootPart;
  2691. if (rootpart != null)
  2692. {
  2693. if (IsAttachment)
  2694. {
  2695. IScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
  2696. if (avatar != null)
  2697. {
  2698. List<string> coords = new List<string>();
  2699. uint regionX = 0;
  2700. uint regionY = 0;
  2701. Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
  2702. target.X += regionX;
  2703. target.Y += regionY;
  2704. coords.Add(target.X.ToString());
  2705. coords.Add(target.Y.ToString());
  2706. coords.Add(target.Z.ToString());
  2707. avatar.DoMoveToPosition(avatar, "", coords);
  2708. }
  2709. }
  2710. else
  2711. {
  2712. rootpart.SetMoveToTarget(true, target, tau);
  2713. }
  2714. }
  2715. }
  2716. public void stopMoveToTarget()
  2717. {
  2718. SceneObjectPart rootpart = m_rootPart;
  2719. if (rootpart != null)
  2720. {
  2721. if (rootpart.PhysActor != null)
  2722. {
  2723. rootpart.SetMoveToTarget(false, Vector3.Zero, 0);
  2724. }
  2725. }
  2726. }
  2727. /// <summary>
  2728. /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
  2729. /// </summary>
  2730. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  2731. /// <param name="hoverType">Determines what the height is relative to </param>
  2732. /// <param name="tau">Number of seconds over which to reach target</param>
  2733. public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
  2734. {
  2735. SceneObjectPart rootpart = m_rootPart;
  2736. if (rootpart != null)
  2737. {
  2738. if (rootpart.PhysActor != null)
  2739. {
  2740. if (height != 0f)
  2741. {
  2742. rootpart.PIDHoverHeight = height;
  2743. rootpart.PIDHoverType = hoverType;
  2744. rootpart.PIDTau = tau;
  2745. rootpart.PIDHoverActive = true;
  2746. }
  2747. else
  2748. {
  2749. rootpart.PIDHoverActive = false;
  2750. }
  2751. }
  2752. }
  2753. }
  2754. public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID)
  2755. {
  2756. part.OwnerID = cAgentID;
  2757. part.GroupID = cGroupID;
  2758. }
  2759. #endregion
  2760. #region Scheduling
  2761. /// <summary>
  2762. /// Send an update to all prims in the group to a specific avatar
  2763. /// </summary>
  2764. /// <param name="presence"></param>
  2765. /// <param name="UpdateFlags"></param>
  2766. public void ScheduleGroupUpdateToAvatar(IScenePresence presence, PrimUpdateFlags UpdateFlags)
  2767. {
  2768. //We have to send the root part first as the client wants it that way
  2769. presence.AddUpdateToAvatar(RootPart, UpdateFlags);
  2770. foreach (SceneObjectPart part in m_partsList.Where(part => part != RootPart))
  2771. {
  2772. presence.AddUpdateToAvatar(part, UpdateFlags);
  2773. }
  2774. }
  2775. /// <summary>
  2776. /// Send an update to all prims in the group
  2777. /// </summary>
  2778. /// <param name="UpdateFlags"></param>
  2779. public void ScheduleGroupUpdate(PrimUpdateFlags UpdateFlags)
  2780. {
  2781. //We have to send the root part first as the client wants it that way
  2782. RootPart.ScheduleUpdate(UpdateFlags);
  2783. foreach (SceneObjectPart part in m_partsList.Where(part => part != RootPart))
  2784. {
  2785. part.ScheduleUpdate(UpdateFlags);
  2786. }
  2787. }
  2788. /// <summary>
  2789. /// Schedule a terse update (position, rotation, velocity, and rotational velocity update) for this object to all clients
  2790. /// </summary>
  2791. public void ScheduleGroupTerseUpdate()
  2792. {
  2793. //We have to send the root part first as the client wants it that way
  2794. RootPart.ScheduleTerseUpdate();
  2795. foreach (SceneObjectPart part in m_partsList.Where(part => part != RootPart))
  2796. {
  2797. part.ScheduleTerseUpdate();
  2798. }
  2799. }
  2800. public void Update()
  2801. {
  2802. }
  2803. /// <summary>
  2804. /// </summary>
  2805. /// <param name="remoteClient"></param>
  2806. /// <param name="AgentID"></param>
  2807. /// <param name="RequestFlags"></param>
  2808. public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
  2809. {
  2810. remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID,
  2811. RootPart.BaseMask,
  2812. RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask,
  2813. RootPart.NextOwnerMask,
  2814. RootPart.OwnershipCost, RootPart.ObjectSaleType,
  2815. RootPart.SalePrice, RootPart.Category,
  2816. RootPart.CreatorID, RootPart.Name, RootPart.Description);
  2817. }
  2818. /// <summary>
  2819. /// See if the object has moved enough to trigger the Significant Movement event
  2820. /// </summary>
  2821. protected internal void CheckForSignificantMovement()
  2822. {
  2823. m_scene.EventManager.TriggerSignificantObjectMovement(this);
  2824. //Do this second! This is important, otherwise
  2825. // if the object isn't allowed, we will not be able
  2826. // to reset its position to the last known good pos
  2827. m_lastSignificantPosition = AbsolutePosition;
  2828. }
  2829. #endregion
  2830. #region Get Children Methods
  2831. /// <summary>
  2832. /// Get the child part by LinkNum
  2833. /// </summary>
  2834. /// <param name="linknum"></param>
  2835. /// <returns>null if no child part with that linknum or child part</returns>
  2836. public IEntity GetLinkNumPart(int linknum)
  2837. {
  2838. if (linknum <= m_parts.Count)
  2839. {
  2840. if (m_parts.Count == 1)
  2841. return RootPart;
  2842. foreach (SceneObjectPart part in m_partsList.Where(part => part.LinkNum == linknum))
  2843. {
  2844. return part;
  2845. }
  2846. }
  2847. //Check sitting avatars
  2848. int count = m_parts.Count + 1;
  2849. foreach (UUID agentID in SitTargetAvatar)
  2850. {
  2851. if (count == linknum)
  2852. {
  2853. return m_scene.GetScenePresence(agentID);
  2854. }
  2855. count++;
  2856. }
  2857. return null;
  2858. }
  2859. /// <summary>
  2860. /// Get a child prim of this group by LocalID
  2861. /// </summary>
  2862. /// <param name="LocalID"></param>
  2863. /// <param name="entity"></param>
  2864. /// <returns></returns>
  2865. public bool GetChildPrim(uint LocalID, out ISceneChildEntity entity)
  2866. {
  2867. entity = GetChildPart(LocalID);
  2868. return entity != null;
  2869. }
  2870. /// <summary>
  2871. /// Get a child prim of this group by UUID
  2872. /// </summary>
  2873. /// <param name="UUID2"></param>
  2874. /// <param name="entity"></param>
  2875. /// <returns></returns>
  2876. public bool GetChildPrim(UUID UUID2, out ISceneChildEntity entity)
  2877. {
  2878. entity = GetChildPart(UUID2);
  2879. return entity != null;
  2880. }
  2881. /// <summary>
  2882. /// Get a part with a given UUID
  2883. /// </summary>
  2884. /// <param name="primID"></param>
  2885. /// <returns>null if a child part with the primID was not found</returns>
  2886. public ISceneChildEntity GetChildPart(UUID primID)
  2887. {
  2888. SceneObjectPart childPart = null;
  2889. m_parts.TryGetValue(primID, out childPart);
  2890. return childPart;
  2891. }
  2892. /// <summary>
  2893. /// Get a part with a given UUID
  2894. /// </summary>
  2895. /// <param name="primID"></param>
  2896. /// <returns>null if a child part with the primID was not found</returns>
  2897. public ISceneChildEntity GetChildPart(uint primID)
  2898. {
  2899. return m_partsList.Cast<ISceneChildEntity>().FirstOrDefault(part => part.LocalId == primID);
  2900. }
  2901. #endregion
  2902. #region Packet Handlers
  2903. #region Linking and Delinking
  2904. /// <summary>
  2905. /// Link the prims in a given group to this group
  2906. /// </summary>
  2907. /// <param name="grp">The group of prims which should be linked to this group</param>
  2908. public void LinkToGroup(ISceneEntity grp)
  2909. {
  2910. //MainConsole.Instance.DebugFormat(
  2911. // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
  2912. // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
  2913. if (!(grp is SceneObjectGroup))
  2914. return;
  2915. SceneObjectGroup objectGroup = (SceneObjectGroup) grp;
  2916. if (m_rootPart.PhysActor != null)
  2917. m_rootPart.PhysActor.BlockPhysicalReconstruction = true;
  2918. SceneObjectPart linkPart = objectGroup.m_rootPart;
  2919. Vector3 oldGroupPosition = linkPart.GroupPosition;
  2920. Quaternion oldRootRotation = linkPart.GetRotationOffset();
  2921. Quaternion parentRot = m_rootPart.GetRotationOffset();
  2922. linkPart.SetGroupPosition(AbsolutePosition); // just change it without doing anything else
  2923. Vector3 axPos = oldGroupPosition - AbsolutePosition;
  2924. axPos *= Quaternion.Inverse(parentRot);
  2925. linkPart.SetOffsetPosition(axPos);
  2926. Quaternion newRot = Quaternion.Inverse(parentRot)*oldRootRotation;
  2927. linkPart.SetRotationOffset(false, newRot, false);
  2928. //Fix the link number for the root
  2929. if (m_rootPart.LinkNum == 0)
  2930. m_rootPart.LinkNum = 1;
  2931. SceneObjectPart[] objectGroupChildren = new SceneObjectPart[objectGroup.ChildrenList.Count];
  2932. objectGroup.ChildrenList.CopyTo(objectGroupChildren, 0);
  2933. //Destroy the old group
  2934. m_scene.SceneGraph.DeleteEntity(objectGroup);
  2935. objectGroup.IsDeleted = true;
  2936. objectGroup.ClearChildren();
  2937. lock (m_partsLock)
  2938. {
  2939. int linkNum = 2;
  2940. //Add the root part to our group!
  2941. m_scene.SceneGraph.LinkPartToSOG(this, linkPart, linkNum++);
  2942. linkPart.CreateSelected = true;
  2943. linkPart.FixOffsetPosition(linkPart.OffsetPosition, true); // nasty let all know about where this is
  2944. // let physics link it
  2945. if (linkPart.PhysActor != null && m_rootPart.PhysActor != null)
  2946. {
  2947. if (linkPart.PhysicsType != (byte) PhysicsShapeType.None)
  2948. linkPart.PhysActor.link(m_rootPart.PhysActor);
  2949. }
  2950. //rest of parts
  2951. foreach (
  2952. SceneObjectPart part in objectGroupChildren.Where(part => part.UUID != objectGroup.m_rootPart.UUID))
  2953. {
  2954. LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
  2955. part.FixOffsetPosition(part.OffsetPosition, true);
  2956. if (part.PhysActor != null && m_rootPart.PhysActor != null)
  2957. part.PhysActor.link(m_rootPart.PhysActor);
  2958. }
  2959. }
  2960. // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
  2961. // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
  2962. // unmoved prims!
  2963. m_ValidgrpOOB = false;
  2964. ResetChildPrimPhysicsPositions();
  2965. if (m_rootPart.PhysActor != null)
  2966. m_rootPart.PhysActor.BlockPhysicalReconstruction = false;
  2967. }
  2968. /// <summary>
  2969. /// Delink the given prim from this group. The delinked prim is established as
  2970. /// an independent SceneObjectGroup.
  2971. /// </summary>
  2972. /// <param name="part"></param>
  2973. /// <param name="sendEvents"></param>
  2974. /// <returns>The object group of the newly delinked prim.</returns>
  2975. public ISceneEntity DelinkFromGroup(ISceneChildEntity part, bool sendEvents)
  2976. {
  2977. if (!(part is SceneObjectPart))
  2978. return null;
  2979. SceneObjectPart linkPart = part as SceneObjectPart;
  2980. // MainConsole.Instance.DebugFormat(
  2981. // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
  2982. // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
  2983. Quaternion worldRot = linkPart.GetWorldRotation();
  2984. // Remove the part from this object
  2985. m_scene.SceneGraph.DeLinkPartFromEntity(this, linkPart);
  2986. linkPart.SetParentLocalId(0);
  2987. linkPart.LinkNum = 0;
  2988. if (linkPart.PhysActor != null)
  2989. {
  2990. m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
  2991. }
  2992. // We need to reset the child part's position
  2993. // ready for life as a separate object after being a part of another object
  2994. Quaternion parentRot = m_rootPart.GetRotationOffset();
  2995. Vector3 axPos = linkPart.OffsetPosition;
  2996. axPos *= parentRot;
  2997. linkPart.SetOffsetPosition(axPos);
  2998. linkPart.FixGroupPosition(AbsolutePosition + linkPart.OffsetPosition, false);
  2999. linkPart.FixOffsetPosition(Vector3.Zero, false);
  3000. linkPart.SetRotationOffset(true, worldRot, true);
  3001. SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart, Scene);
  3002. m_scene.SceneGraph.DelinkPartToScene(objectGroup);
  3003. if (sendEvents)
  3004. linkPart.TriggerScriptChangedEvent(Changed.LINK);
  3005. linkPart.Rezzed = RootPart.Rezzed;
  3006. //This is already set multiple places, no need to do it again
  3007. //HasGroupChanged = true;
  3008. //We need to send this so that we don't have issues with the client not realizing that the prims were unlinked
  3009. ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3010. m_ValidgrpOOB = false;
  3011. return objectGroup;
  3012. }
  3013. private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation,
  3014. int linkNum)
  3015. {
  3016. Quaternion WorldRot = oldGroupRotation*part.GetRotationOffset();
  3017. // first fix from old local to world
  3018. // position
  3019. Vector3 axPos = part.OffsetPosition;
  3020. axPos *= oldGroupRotation;
  3021. part.SetGroupPosition(oldGroupPosition + axPos);
  3022. //offset
  3023. part.SetRotationOffset(false, WorldRot, false);
  3024. // have it in world coords lets fix other things
  3025. m_scene.SceneGraph.LinkPartToSOG(this, part, linkNum);
  3026. part.CreateSelected = true;
  3027. // now lets move to the new parent frame
  3028. Quaternion rootRotation = m_rootPart.GetRotationOffset();
  3029. Vector3 pos = part.GroupPosition - AbsolutePosition;
  3030. pos *= Quaternion.Inverse(rootRotation);
  3031. part.SetOffsetPosition(pos);
  3032. Quaternion newRot = Quaternion.Inverse(rootRotation)*WorldRot;
  3033. part.SetRotationOffset(false, newRot, false);
  3034. // caller will tell the rest about this position changes..
  3035. }
  3036. #endregion
  3037. /// <summary>
  3038. /// Return metadata about a prim (name, description, sale price, etc.)
  3039. /// </summary>
  3040. /// <param name="client"></param>
  3041. public void GetProperties(IClientAPI client)
  3042. {
  3043. m_rootPart.GetProperties(client);
  3044. }
  3045. public void UpdatePermissions(UUID AgentID, byte field, uint localID,
  3046. uint mask, byte addRemTF)
  3047. {
  3048. foreach (SceneObjectPart part in m_partsList)
  3049. part.UpdatePermissions(AgentID, field, localID, mask,
  3050. addRemTF);
  3051. HasGroupChanged = true;
  3052. }
  3053. /// <summary>
  3054. /// If object is physical, apply force to move it around
  3055. /// If object is not physical, just put it at the resulting location
  3056. /// </summary>
  3057. /// <param name="offset">Always seems to be 0,0,0, so ignoring</param>
  3058. /// <param name="pos">New position. We do the math here to turn it into a force</param>
  3059. /// <param name="remoteClient"></param>
  3060. public void GrabMovement(Vector3 offset, Vector3 pos, IClientAPI remoteClient)
  3061. {
  3062. if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
  3063. {
  3064. if (m_rootPart.PhysActor != null)
  3065. {
  3066. if (m_rootPart.PhysActor.IsPhysical)
  3067. {
  3068. if (!m_rootPart.BlockGrab && !m_rootPart.BlockGrabObject)
  3069. {
  3070. Vector3 grabforce = pos - AbsolutePosition;
  3071. grabforce = grabforce*m_rootPart.PhysActor.Mass;
  3072. m_rootPart.PhysActor.AddForce(grabforce, true);
  3073. // This is outside the above permissions condition
  3074. // so that if the object is locked the client moving the object
  3075. // get's it's position on the simulator even if it was the same as before
  3076. // This keeps the moving user's client in sync with the rest of the world.
  3077. ScheduleGroupTerseUpdate();
  3078. }
  3079. }
  3080. }
  3081. }
  3082. }
  3083. public void NonPhysicalGrabMovement(Vector3 pos)
  3084. {
  3085. AbsolutePosition = pos;
  3086. m_rootPart.ScheduleTerseUpdate();
  3087. }
  3088. /// <summary>
  3089. /// If object is physical, prepare for spinning torques (set flag to save old orientation)
  3090. /// </summary>
  3091. /// <param name="remoteClient"></param>
  3092. public void SpinStart(IClientAPI remoteClient)
  3093. {
  3094. if (m_scene.EventManager.TriggerGroupSpinStart(UUID))
  3095. {
  3096. if (m_rootPart.PhysActor != null)
  3097. {
  3098. if (m_rootPart.PhysActor.IsPhysical)
  3099. {
  3100. m_rootPart.IsWaitingForFirstSpinUpdatePacket = true;
  3101. }
  3102. }
  3103. }
  3104. }
  3105. /// <summary>
  3106. /// If object is physical, apply torque to spin it around
  3107. /// </summary>
  3108. /// <param name="newOrientation">Rotation. We do the math here to turn it into a torque</param>
  3109. /// <param name="remoteClient"></param>
  3110. public void SpinMovement(Quaternion newOrientation, IClientAPI remoteClient)
  3111. {
  3112. // The incoming newOrientation, sent by the client, "seems" to be the
  3113. // desired target orientation. This needs further verification; in particular,
  3114. // one would expect that the initial incoming newOrientation should be
  3115. // fairly close to the original prim's physical orientation,
  3116. // m_rootPart.PhysActor.Orientation. This however does not seem to be the
  3117. // case (might just be an issue with different quaternions representing the
  3118. // same rotation, or it might be a coordinate system issue).
  3119. //
  3120. // Since it's not clear what the relationship is between the PhysActor.Orientation
  3121. // and the incoming orientations sent by the client, we take an alternative approach
  3122. // of calculating the delta rotation between the orientations being sent by the
  3123. // client. (Since a spin is invoked by ctrl+shift+drag in the client, we expect
  3124. // a steady stream of several new orientations coming in from the client.)
  3125. // This ensures that the delta rotations are being calculated from self-consistent
  3126. // pairs of old/new rotations. Given the delta rotation, we apply a torque around
  3127. // the delta rotation axis, scaled by the object mass times an arbitrary scaling
  3128. // factor (to ensure the resulting torque is not "too strong" or "too weak").
  3129. //
  3130. // Ideally we need to calculate (probably iteratively) the exact torque or series
  3131. // of torques needed to arrive exactly at the destination orientation. However, since
  3132. // it is not yet clear how to map the destination orientation (provided by the viewer)
  3133. // into PhysActor orientations (needed by the physics engine), we omit this step.
  3134. // This means that the resulting torque will at least be in the correct direction,
  3135. // but it will result in over-shoot or under-shoot of the target orientation.
  3136. // For the end user, this means that ctrl+shift+drag can be used for relative,
  3137. // but not absolute, adjustments of orientation for physical prims.
  3138. if (m_scene.EventManager.TriggerGroupSpin(UUID, newOrientation))
  3139. {
  3140. if (m_rootPart.PhysActor != null)
  3141. {
  3142. if (m_rootPart.PhysActor.IsPhysical)
  3143. {
  3144. if (m_rootPart.IsWaitingForFirstSpinUpdatePacket)
  3145. {
  3146. // first time initialization of "old" orientation for calculation of delta rotations
  3147. m_rootPart.SpinOldOrientation = newOrientation;
  3148. m_rootPart.IsWaitingForFirstSpinUpdatePacket = false;
  3149. }
  3150. else
  3151. {
  3152. // save and update old orientation
  3153. Quaternion old = m_rootPart.SpinOldOrientation;
  3154. m_rootPart.SpinOldOrientation = newOrientation;
  3155. //MainConsole.Instance.Error("[SCENE OBJECT GROUP]: Old orientation is " + old);
  3156. //MainConsole.Instance.Error("[SCENE OBJECT GROUP]: Incoming new orientation is " + newOrientation);
  3157. // compute difference between previous old rotation and new incoming rotation
  3158. Quaternion minimalRotationFromQ1ToQ2 = Quaternion.Inverse(old)*newOrientation;
  3159. float rotationAngle;
  3160. Vector3 rotationAxis;
  3161. minimalRotationFromQ1ToQ2.GetAxisAngle(out rotationAxis, out rotationAngle);
  3162. rotationAxis.Normalize();
  3163. //MainConsole.Instance.Error("SCENE OBJECT GROUP]: rotation axis is " + rotationAxis);
  3164. Vector3 spinforce = new Vector3(rotationAxis.X, rotationAxis.Y, rotationAxis.Z);
  3165. spinforce = (spinforce/8)*m_rootPart.PhysActor.Mass;
  3166. // 8 is an arbitrary torque scaling factor
  3167. m_rootPart.PhysActor.AddAngularForce(spinforce, true);
  3168. }
  3169. }
  3170. }
  3171. }
  3172. }
  3173. /// <summary>
  3174. /// Set the name of a prim
  3175. /// </summary>
  3176. /// <param name="name"></param>
  3177. /// <param name="localID"></param>
  3178. public void SetPartName(string name, uint localID)
  3179. {
  3180. ISceneChildEntity part = GetChildPart(localID);
  3181. if (part != null)
  3182. {
  3183. part.Name = name;
  3184. }
  3185. }
  3186. public void SetPartDescription(string des, uint localID)
  3187. {
  3188. ISceneChildEntity part = GetChildPart(localID);
  3189. if (part != null)
  3190. {
  3191. part.Description = des;
  3192. }
  3193. }
  3194. public string GetPartName(uint localID)
  3195. {
  3196. ISceneChildEntity part = GetChildPart(localID);
  3197. if (part != null)
  3198. {
  3199. return part.Name;
  3200. }
  3201. return String.Empty;
  3202. }
  3203. public string GetPartDescription(uint localID)
  3204. {
  3205. ISceneChildEntity part = GetChildPart(localID);
  3206. if (part != null)
  3207. {
  3208. return part.Description;
  3209. }
  3210. return String.Empty;
  3211. }
  3212. /// <summary>
  3213. /// Update prim flags for this group.
  3214. /// </summary>
  3215. /// <param name="localID"></param>
  3216. /// <param name="UsePhysics"></param>
  3217. /// <param name="IsTemporary"></param>
  3218. /// <param name="IsPhantom"></param>
  3219. /// <param name="IsVolumeDetect"></param>
  3220. /// <param name="blocks"></param>
  3221. public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect,
  3222. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks)
  3223. {
  3224. ISceneChildEntity selectionPart = GetChildPart(localID);
  3225. if (IsTemporary)
  3226. {
  3227. // Remove from database and parcel prim count
  3228. // Temporary objects arn't saved to the database ever, so we don't need to do anything
  3229. }
  3230. if (selectionPart != null)
  3231. {
  3232. foreach (SceneObjectPart part in m_partsList)
  3233. {
  3234. IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  3235. if (WSModule != null)
  3236. {
  3237. if (WSModule.MaximumPhysPrimScale == -1)
  3238. break;
  3239. if (part.Scale.X > WSModule.MaximumPhysPrimScale ||
  3240. part.Scale.Y > WSModule.MaximumPhysPrimScale ||
  3241. part.Scale.Z > WSModule.MaximumPhysPrimScale)
  3242. {
  3243. UsePhysics = false; // Reset physics
  3244. break;
  3245. }
  3246. }
  3247. }
  3248. bool needsPhysicalRebuild = ((SceneObjectPart) selectionPart).UpdatePrimFlags(UsePhysics, IsTemporary,
  3249. IsPhantom, IsVolumeDetect,
  3250. blocks);
  3251. foreach (SceneObjectPart part in m_partsList.Where(part => selectionPart != part))
  3252. {
  3253. if (needsPhysicalRebuild)
  3254. part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect, null);
  3255. else
  3256. needsPhysicalRebuild = part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom,
  3257. IsVolumeDetect, null);
  3258. }
  3259. if (needsPhysicalRebuild)
  3260. RebuildPhysicalRepresentation(true);
  3261. }
  3262. }
  3263. public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
  3264. {
  3265. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3266. if (part != null)
  3267. {
  3268. part.UpdateExtraParam(type, inUse, data);
  3269. }
  3270. }
  3271. /// <summary>
  3272. /// Update the texture entry for this part
  3273. /// </summary>
  3274. /// <param name="localID"></param>
  3275. /// <param name="textureEntry"></param>
  3276. /// <param name="sendChangedEvent"></param>
  3277. public void UpdateTextureEntry(uint localID, byte[] textureEntry, bool sendChangedEvent)
  3278. {
  3279. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3280. if (part != null)
  3281. {
  3282. part.UpdateTextureEntry(textureEntry, sendChangedEvent);
  3283. }
  3284. }
  3285. #endregion
  3286. #region Shape
  3287. /// <summary>
  3288. /// </summary>
  3289. /// <param name="shapeBlock"></param>
  3290. /// <param name="localID"></param>
  3291. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
  3292. {
  3293. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3294. if (part != null)
  3295. {
  3296. part.UpdateShape(shapeBlock);
  3297. m_ValidgrpOOB = false;
  3298. }
  3299. }
  3300. #endregion
  3301. #region Resize
  3302. /// <summary>
  3303. /// Resize the given part
  3304. /// </summary>
  3305. /// <param name="scale"></param>
  3306. /// <param name="localID"></param>
  3307. public void Resize(Vector3 scale, uint localID)
  3308. {
  3309. CheckSculptAndLoad();
  3310. //Grab the mesh again if it is a sculpty/mesh as we remove it after the first mesh is built
  3311. IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  3312. if (WSModule != null)
  3313. {
  3314. if (WSModule.MinimumPrimScale != -1)
  3315. {
  3316. if (scale.X < WSModule.MinimumPrimScale)
  3317. scale.X = WSModule.MinimumPrimScale;
  3318. if (scale.Y < WSModule.MinimumPrimScale)
  3319. scale.Y = WSModule.MinimumPrimScale;
  3320. if (scale.Z < WSModule.MinimumPrimScale)
  3321. scale.Z = WSModule.MinimumPrimScale;
  3322. }
  3323. if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical &&
  3324. WSModule.MaximumPhysPrimScale != -1)
  3325. {
  3326. if (scale.X > WSModule.MaximumPhysPrimScale)
  3327. scale.X = WSModule.MaximumPhysPrimScale;
  3328. if (scale.Y > WSModule.MaximumPhysPrimScale)
  3329. scale.Y = WSModule.MaximumPhysPrimScale;
  3330. if (scale.Z > WSModule.MaximumPhysPrimScale)
  3331. scale.Z = WSModule.MaximumPhysPrimScale;
  3332. }
  3333. if (WSModule.MaximumPrimScale != -1)
  3334. {
  3335. if (scale.X > WSModule.MaximumPrimScale)
  3336. scale.X = WSModule.MaximumPrimScale;
  3337. if (scale.Y > WSModule.MaximumPrimScale)
  3338. scale.Y = WSModule.MaximumPrimScale;
  3339. if (scale.Z > WSModule.MaximumPrimScale)
  3340. scale.Z = WSModule.MaximumPrimScale;
  3341. }
  3342. }
  3343. m_ValidgrpOOB = false;
  3344. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3345. if (part != null)
  3346. {
  3347. part.Resize(scale);
  3348. if (part.PhysActor != null)
  3349. part.PhysActor.Size = scale;
  3350. //if (part.UUID != m_rootPart.UUID)
  3351. HasGroupChanged = true;
  3352. ScheduleGroupUpdate(PrimUpdateFlags.Shape);
  3353. //if (part.UUID == m_rootPart.UUID)
  3354. //{
  3355. //if (m_rootPart.PhysActor != null)
  3356. //{
  3357. //m_rootPart.PhysActor.Size =
  3358. //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
  3359. //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  3360. //}
  3361. //}
  3362. }
  3363. }
  3364. public void GroupResize(Vector3 scale, uint localID)
  3365. {
  3366. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3367. if (part != null)
  3368. {
  3369. CheckSculptAndLoad();
  3370. //Grab the mesh again if it is a sculpty/mesh as we remove it after the first mesh is built
  3371. part.IgnoreUndoUpdate = true;
  3372. IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  3373. if (WSModule != null)
  3374. {
  3375. if (WSModule.MinimumPrimScale != -1)
  3376. {
  3377. if (scale.X < WSModule.MinimumPrimScale)
  3378. scale.X = WSModule.MinimumPrimScale;
  3379. if (scale.Y < WSModule.MinimumPrimScale)
  3380. scale.Y = WSModule.MinimumPrimScale;
  3381. if (scale.Z < WSModule.MinimumPrimScale)
  3382. scale.Z = WSModule.MinimumPrimScale;
  3383. }
  3384. if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical &&
  3385. WSModule.MaximumPhysPrimScale != -1)
  3386. {
  3387. if (scale.X > WSModule.MaximumPhysPrimScale)
  3388. scale.X = WSModule.MaximumPhysPrimScale;
  3389. if (scale.Y > WSModule.MaximumPhysPrimScale)
  3390. scale.Y = WSModule.MaximumPhysPrimScale;
  3391. if (scale.Z > WSModule.MaximumPhysPrimScale)
  3392. scale.Z = WSModule.MaximumPhysPrimScale;
  3393. }
  3394. if (WSModule.MaximumPrimScale != -1)
  3395. {
  3396. if (scale.X > WSModule.MaximumPrimScale)
  3397. scale.X = WSModule.MaximumPrimScale;
  3398. if (scale.Y > WSModule.MaximumPrimScale)
  3399. scale.Y = WSModule.MaximumPrimScale;
  3400. if (scale.Z > WSModule.MaximumPrimScale)
  3401. scale.Z = WSModule.MaximumPrimScale;
  3402. }
  3403. }
  3404. float x = (scale.X/part.Scale.X);
  3405. float y = (scale.Y/part.Scale.Y);
  3406. float z = (scale.Z/part.Scale.Z);
  3407. foreach (SceneObjectPart obPart in m_partsList)
  3408. {
  3409. obPart.StoreUndoState();
  3410. }
  3411. Vector3 prevScale = part.Scale;
  3412. prevScale.X *= x;
  3413. prevScale.Y *= y;
  3414. prevScale.Z *= z;
  3415. part.Resize(prevScale);
  3416. foreach (SceneObjectPart obPart in m_partsList.Where(obPart => obPart.UUID != m_rootPart.UUID))
  3417. {
  3418. obPart.IgnoreUndoUpdate = true;
  3419. Vector3 currentpos = new Vector3(obPart.OffsetPosition);
  3420. currentpos.X *= x;
  3421. currentpos.Y *= y;
  3422. currentpos.Z *= z;
  3423. Vector3 newSize = new Vector3(obPart.Scale);
  3424. newSize.X *= x;
  3425. newSize.Y *= y;
  3426. newSize.Z *= z;
  3427. obPart.Resize(newSize);
  3428. obPart.UpdateOffSet(currentpos);
  3429. obPart.IgnoreUndoUpdate = false;
  3430. }
  3431. if (part.PhysActor != null)
  3432. part.PhysActor.Size = prevScale;
  3433. part.IgnoreUndoUpdate = false;
  3434. m_rootPart.IgnoreUndoUpdate = false;
  3435. HasGroupChanged = true;
  3436. ScheduleGroupTerseUpdate();
  3437. m_ValidgrpOOB = false;
  3438. }
  3439. }
  3440. #endregion
  3441. #region Position
  3442. private Vector3 m_lastSigInfiniteRegionPos = Vector3.Zero;
  3443. private List<GridRegion> m_nearbyInfiniteRegions = new List<GridRegion>();
  3444. /// <summary>
  3445. /// Move this scene object
  3446. /// </summary>
  3447. /// <param name="pos"></param>
  3448. /// <param name="SaveUpdate"></param>
  3449. public void UpdateGroupPosition(Vector3 pos, bool SaveUpdate)
  3450. {
  3451. if (SaveUpdate)
  3452. {
  3453. foreach (SceneObjectPart part in ChildrenList)
  3454. {
  3455. part.StoreUndoState();
  3456. }
  3457. }
  3458. if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
  3459. {
  3460. if (IsAttachment)
  3461. {
  3462. m_rootPart.AttachedPos = pos;
  3463. }
  3464. if (RootPart.GetStatusSandbox())
  3465. {
  3466. if (Util.GetDistanceTo(RootPart.StatusSandboxPos, pos) > 10)
  3467. {
  3468. ScriptSetPhysicsStatus(false);
  3469. pos = AbsolutePosition;
  3470. IChatModule chatModule = Scene.RequestModuleInterface<IChatModule>();
  3471. if (chatModule != null)
  3472. chatModule.SimChat("Hit Sandbox Limit", ChatTypeEnum.DebugChannel, 0x7FFFFFFF,
  3473. RootPart.AbsolutePosition, Name, UUID, false, Scene);
  3474. }
  3475. }
  3476. AbsolutePosition = pos;
  3477. HasGroupChanged = true;
  3478. }
  3479. //we need to do a terse update even if the move wasn't allowed
  3480. // so that the position is reset in the client (the object snaps back)
  3481. ScheduleGroupTerseUpdate();
  3482. if (SitTargetAvatar.Count != 0)
  3483. {
  3484. foreach (UUID clientID in SitTargetAvatar)
  3485. {
  3486. //Send full updates to the avatar as well so that they move as well
  3487. IScenePresence SP;
  3488. if (m_scene.TryGetScenePresence(clientID, out SP))
  3489. {
  3490. SP.ParentPosition = AbsolutePosition;
  3491. SP.SendTerseUpdateToAllClients();
  3492. }
  3493. }
  3494. }
  3495. }
  3496. public void SetAbsolutePosition(bool UpdatePrimActor, Vector3 val)
  3497. {
  3498. if (!IsAttachment && RootPart != null && RootPart.Shape != null && Scene != null && Scene.RegionInfo != null &&
  3499. RootPart.Shape.State == 0 && !IsDeleted)
  3500. {
  3501. IBackupModule backup = Scene.RequestModuleInterface<IBackupModule>();
  3502. if ((val.X < 0f || val.Y < 0f || val.Z < 0f ||
  3503. val.X > Scene.RegionInfo.RegionSizeX || val.Y > Scene.RegionInfo.RegionSizeY)
  3504. && !IsAttachmentCheckFull() && (backup != null && !backup.LoadingPrims))
  3505. //Don't do it when backup is loading prims, otherwise it lags the region out
  3506. {
  3507. if (Scene.RegionInfo.InfiniteRegion && !IsInTransit)
  3508. {
  3509. IsInTransit = true;
  3510. double TargetX = Scene.RegionInfo.RegionLocX + (double) val.X;
  3511. double TargetY = Scene.RegionInfo.RegionLocY + (double) val.Y;
  3512. if (m_lastSigInfiniteRegionPos.X - AbsolutePosition.X > 256 ||
  3513. m_lastSigInfiniteRegionPos.X - AbsolutePosition.X < -256 ||
  3514. m_lastSigInfiniteRegionPos.Y - AbsolutePosition.Y > 256 ||
  3515. m_lastSigInfiniteRegionPos.Y - AbsolutePosition.Y < -256)
  3516. {
  3517. m_lastSigInfiniteRegionPos = AbsolutePosition;
  3518. m_nearbyInfiniteRegions = Scene.GridService.GetRegionRange(null,
  3519. (int)
  3520. (TargetX -
  3521. Scene.GridService
  3522. .GetMaxRegionSize()),
  3523. (int) (TargetX + 256),
  3524. (int)
  3525. (TargetY -
  3526. Scene.GridService
  3527. .GetMaxRegionSize()),
  3528. (int) (TargetY + 256));
  3529. }
  3530. GridRegion neighborRegion =
  3531. m_nearbyInfiniteRegions.FirstOrDefault(
  3532. region =>
  3533. TargetX >= region.RegionLocX && TargetY >= region.RegionLocY &&
  3534. TargetX < (region.RegionLocX + region.RegionSizeX) &&
  3535. TargetY < (region.RegionLocY + region.RegionSizeY));
  3536. if (neighborRegion != null)
  3537. {
  3538. //Fix the location that the prim will land
  3539. if (val.X < 0)
  3540. val.X += neighborRegion.RegionSizeX;
  3541. if (val.X > Scene.RegionInfo.RegionSizeX)
  3542. val.X -= Scene.RegionInfo.RegionSizeX;
  3543. if (val.Y < 0)
  3544. val.Y += neighborRegion.RegionSizeY;
  3545. if (val.Y > Scene.RegionInfo.RegionSizeY)
  3546. val.Y -= Scene.RegionInfo.RegionSizeY;
  3547. IEntityTransferModule transferModule = Scene.RequestModuleInterface<IEntityTransferModule>();
  3548. if (transferModule != null)
  3549. {
  3550. if (transferModule.CrossGroupToNewRegion(this, val, neighborRegion))
  3551. {
  3552. IsInTransit = false;
  3553. return;
  3554. }
  3555. }
  3556. }
  3557. IsInTransit = false;
  3558. return;
  3559. }
  3560. //If we are headed out of the region, make sure we have a region there
  3561. IGridRegisterModule neighborService = Scene.RequestModuleInterface<IGridRegisterModule>();
  3562. if (neighborService != null && !IsInTransit)
  3563. {
  3564. IsInTransit = true;
  3565. List<GridRegion> neighbors = neighborService.GetNeighbors(Scene);
  3566. int RegionCrossX = Scene.RegionInfo.RegionLocX;
  3567. int RegionCrossY = Scene.RegionInfo.RegionLocY;
  3568. if (val.X < 0f)
  3569. RegionCrossX -= Constants.RegionSize;
  3570. if (val.Y < 0f)
  3571. RegionCrossY -= Constants.RegionSize;
  3572. if (val.X > Scene.RegionInfo.RegionSizeX)
  3573. RegionCrossX += Scene.RegionInfo.RegionSizeX;
  3574. if (val.Y > Scene.RegionInfo.RegionSizeY)
  3575. RegionCrossY += Scene.RegionInfo.RegionSizeY;
  3576. GridRegion neighborRegion =
  3577. neighbors.FirstOrDefault(
  3578. region => region.RegionLocX == RegionCrossX && region.RegionLocY == RegionCrossY);
  3579. if (neighborRegion != null)
  3580. {
  3581. //Fix the location that the prim will land
  3582. if (val.X < 0)
  3583. val.X += neighborRegion.RegionSizeX;
  3584. if (val.X > Scene.RegionInfo.RegionSizeX)
  3585. val.X -= Scene.RegionInfo.RegionSizeX;
  3586. if (val.Y < 0)
  3587. val.Y += neighborRegion.RegionSizeY;
  3588. if (val.Y > Scene.RegionInfo.RegionSizeY)
  3589. val.Y -= Scene.RegionInfo.RegionSizeY;
  3590. IEntityTransferModule transferModule =
  3591. Scene.RequestModuleInterface<IEntityTransferModule>();
  3592. if (transferModule != null)
  3593. {
  3594. if (transferModule.CrossGroupToNewRegion(this, val, neighborRegion))
  3595. {
  3596. IsInTransit = false;
  3597. return;
  3598. }
  3599. }
  3600. }
  3601. IsInTransit = false;
  3602. //The group should have crossed a region, but no region was found so return it instead
  3603. MainConsole.Instance.Info("[SceneObjectGroup]: Returning prim " + Name + " @ " +
  3604. AbsolutePosition +
  3605. " because it has gone out of bounds.");
  3606. ILLClientInventory inventoryModule = Scene.RequestModuleInterface<ILLClientInventory>();
  3607. if (inventoryModule != null)
  3608. inventoryModule.ReturnObjects(new ISceneEntity[] {this}, UUID.Zero);
  3609. return;
  3610. }
  3611. }
  3612. }
  3613. if (RootPart != null && RootPart.GetStatusSandbox())
  3614. {
  3615. if (Util.GetDistanceTo(RootPart.StatusSandboxPos, val) > 10)
  3616. {
  3617. ScriptSetPhysicsStatus(false);
  3618. if (Scene != null)
  3619. {
  3620. IChatModule chatModule = Scene.RequestModuleInterface<IChatModule>();
  3621. if (chatModule != null)
  3622. chatModule.SimChat("Hit Sandbox Limit",
  3623. ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name,
  3624. UUID,
  3625. false, Scene);
  3626. }
  3627. return;
  3628. }
  3629. }
  3630. foreach (SceneObjectPart part in m_partsList)
  3631. {
  3632. part.FixGroupPositionComum(UpdatePrimActor, val, false);
  3633. }
  3634. //if (m_rootPart.PhysActor != null)
  3635. //{
  3636. //m_rootPart.PhysActor.Position =
  3637. //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
  3638. //m_rootPart.GroupPosition.Z);
  3639. //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  3640. //}
  3641. }
  3642. /// <summary>
  3643. /// Update the position of a single part of this scene object
  3644. /// </summary>
  3645. /// <param name="pos"></param>
  3646. /// <param name="localID"></param>
  3647. /// <param name="SaveUpdate"></param>
  3648. public void UpdateSinglePosition(Vector3 pos, uint localID, bool SaveUpdate)
  3649. {
  3650. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3651. if (part != null)
  3652. {
  3653. if (!SaveUpdate)
  3654. part.IgnoreUndoUpdate = true;
  3655. if (part.UUID == m_rootPart.UUID)
  3656. {
  3657. UpdateRootPosition(pos);
  3658. }
  3659. else
  3660. {
  3661. part.UpdateOffSet(pos);
  3662. }
  3663. if (!SaveUpdate)
  3664. part.IgnoreUndoUpdate = false;
  3665. HasGroupChanged = true;
  3666. }
  3667. }
  3668. /// <summary>
  3669. /// </summary>
  3670. /// <param name="pos"></param>
  3671. public void UpdateRootPosition(Vector3 pos)
  3672. {
  3673. foreach (SceneObjectPart part in ChildrenList)
  3674. {
  3675. part.StoreUndoState();
  3676. }
  3677. Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
  3678. Vector3 oldPos =
  3679. IsAttachment
  3680. ? new Vector3(m_rootPart.OffsetPosition.X, m_rootPart.OffsetPosition.Y,
  3681. m_rootPart.OffsetPosition.Z)
  3682. : new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
  3683. AbsolutePosition.Y + m_rootPart.OffsetPosition.Y,
  3684. AbsolutePosition.Z + m_rootPart.OffsetPosition.Z);
  3685. Vector3 diff = oldPos - newPos;
  3686. Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
  3687. Quaternion partRotation = m_rootPart.GetRotationOffset();
  3688. axDiff *= Quaternion.Inverse(partRotation);
  3689. diff = axDiff;
  3690. if (IsAttachment)
  3691. {
  3692. m_rootPart.FixOffsetPosition((newPos), false);
  3693. foreach (SceneObjectPart obPart in m_partsList)
  3694. {
  3695. if (obPart.UUID != m_rootPart.UUID)
  3696. {
  3697. obPart.OffsetPosition += diff;
  3698. obPart.SetGroupPosition(AbsolutePosition);
  3699. }
  3700. }
  3701. }
  3702. else
  3703. {
  3704. foreach (SceneObjectPart obPart in m_partsList)
  3705. {
  3706. if (obPart.UUID != m_rootPart.UUID)
  3707. obPart.FixOffsetPosition((obPart.OffsetPosition + diff), false);
  3708. }
  3709. AbsolutePosition = newPos;
  3710. }
  3711. HasGroupChanged = true;
  3712. ScheduleGroupTerseUpdate();
  3713. }
  3714. public void OffsetForNewRegion(Vector3 offset)
  3715. {
  3716. m_rootPart.FixGroupPosition(offset, false);
  3717. }
  3718. #endregion
  3719. #region Rotation
  3720. /// <summary>
  3721. /// </summary>
  3722. /// <param name="rot"></param>
  3723. public void UpdateGroupRotationR(Quaternion rot)
  3724. {
  3725. foreach (SceneObjectPart parts in ChildrenList)
  3726. {
  3727. parts.StoreUndoState();
  3728. }
  3729. m_rootPart.UpdateRotation(rot);
  3730. PhysicsObject actor = m_rootPart.PhysActor;
  3731. if (actor != null)
  3732. actor.Orientation = m_rootPart.GetRotationOffset();
  3733. HasGroupChanged = true;
  3734. ScheduleGroupTerseUpdate();
  3735. }
  3736. /// <summary>
  3737. /// </summary>
  3738. /// <param name="pos"></param>
  3739. /// <param name="rot"></param>
  3740. public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
  3741. {
  3742. foreach (SceneObjectPart part in ChildrenList)
  3743. {
  3744. part.StoreUndoState();
  3745. }
  3746. m_rootPart.UpdateRotation(rot);
  3747. PhysicsObject actor = m_rootPart.PhysActor;
  3748. if (actor != null)
  3749. actor.Orientation = m_rootPart.GetRotationOffset();
  3750. AbsolutePosition = pos;
  3751. HasGroupChanged = true;
  3752. ScheduleGroupTerseUpdate();
  3753. }
  3754. /// <summary>
  3755. /// </summary>
  3756. /// <param name="rot"></param>
  3757. /// <param name="localID"></param>
  3758. public void UpdateSingleRotation(Quaternion rot, uint localID)
  3759. {
  3760. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3761. foreach (SceneObjectPart parts in ChildrenList)
  3762. {
  3763. parts.StoreUndoState();
  3764. }
  3765. if (part != null)
  3766. {
  3767. if (part.UUID == m_rootPart.UUID)
  3768. {
  3769. UpdateRootRotation(rot);
  3770. }
  3771. else
  3772. {
  3773. part.UpdateRotation(rot);
  3774. }
  3775. }
  3776. }
  3777. /// <summary>
  3778. /// </summary>
  3779. /// <param name="rot"></param>
  3780. /// <param name="pos"></param>
  3781. /// <param name="localID"></param>
  3782. public void UpdateSingleRotation(Quaternion rot, Vector3 pos, uint localID)
  3783. {
  3784. SceneObjectPart part = (SceneObjectPart) GetChildPart(localID);
  3785. if (part != null)
  3786. {
  3787. if (part.UUID == m_rootPart.UUID)
  3788. {
  3789. UpdateRootRotation(rot);
  3790. AbsolutePosition = pos;
  3791. }
  3792. else
  3793. {
  3794. part.StoreUndoState();
  3795. part.IgnoreUndoUpdate = true;
  3796. part.UpdateRotation(rot);
  3797. part.FixOffsetPosition(pos, true);
  3798. part.IgnoreUndoUpdate = false;
  3799. }
  3800. }
  3801. }
  3802. /// <summary>
  3803. /// </summary>
  3804. /// <param name="rot"></param>
  3805. private void UpdateRootRotation(Quaternion rot)
  3806. {
  3807. Quaternion new_global_group_rot = rot;
  3808. Quaternion old_global_group_rot = m_rootPart.GetRotationOffset();
  3809. m_rootPart.UpdateRotation(rot);
  3810. if (m_rootPart.PhysActor != null)
  3811. m_rootPart.PhysActor.Orientation = m_rootPart.GetRotationOffset();
  3812. foreach (SceneObjectPart childPrim in m_partsList.Where(childPrim => childPrim.UUID != m_rootPart.UUID))
  3813. {
  3814. childPrim.StoreUndoState();
  3815. childPrim.IgnoreUndoUpdate = true;
  3816. // fix rotation
  3817. // get in world coords
  3818. Quaternion primsRot = old_global_group_rot*childPrim.GetRotationOffset();
  3819. // set new offset as inverse of the one on root
  3820. // so world is right
  3821. primsRot = Quaternion.Inverse(new_global_group_rot)*primsRot;
  3822. // just store it
  3823. childPrim.SetRotationOffset(false, primsRot, false);
  3824. // fix position offset
  3825. Vector3 axPos = childPrim.OffsetPosition;
  3826. axPos *= old_global_group_rot;
  3827. axPos *= Quaternion.Inverse(new_global_group_rot);
  3828. // store it and let physics know about both changes
  3829. childPrim.FixOffsetPosition(axPos, true);
  3830. childPrim.ScheduleTerseUpdate();
  3831. childPrim.IgnoreUndoUpdate = false;
  3832. }
  3833. m_rootPart.ScheduleTerseUpdate();
  3834. }
  3835. #endregion
  3836. }
  3837. }