PageRenderTime 38ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Region/SceneObjectPart.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 5066 lines | 3904 code | 578 blank | 584 comment | 952 complexity | f84011cfed60a59e4ced048a602d43bd 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.Services.ClassHelpers.Assets;
  37. using Aurora.Framework.Utilities;
  38. using OpenMetaverse;
  39. using OpenMetaverse.Packets;
  40. using OpenMetaverse.StructuredData;
  41. using ProtoBuf;
  42. using System;
  43. using System.Collections.Generic;
  44. using System.Drawing;
  45. using System.Linq;
  46. using System.Xml;
  47. using System.Xml.Serialization;
  48. using PrimType = Aurora.Framework.SceneInfo.PrimType;
  49. namespace Aurora.Region
  50. {
  51. [Serializable, ProtoContract()]
  52. public class SceneObjectPart : ISceneChildEntity
  53. {
  54. /// <value>
  55. /// Denote all sides of the prim
  56. /// </value>
  57. public const int ALL_SIDES = -1;
  58. public virtual Quaternion GroupRotation
  59. {
  60. get { return ParentGroup.GroupRotation; }
  61. }
  62. #region ISceneChildEntity Members
  63. /// <value>
  64. /// Is this sop a root part?
  65. /// </value>
  66. [XmlIgnore]
  67. public bool IsRoot
  68. {
  69. get { return ParentGroup.RootPart == this; }
  70. }
  71. public virtual Quaternion Rotation
  72. {
  73. get { return ParentGroup.GroupRotation; }
  74. set { }
  75. }
  76. //---------------
  77. public void ApplyNextOwnerPermissions()
  78. {
  79. _baseMask &= _nextOwnerMask;
  80. _ownerMask &= _nextOwnerMask;
  81. _everyoneMask &= _nextOwnerMask;
  82. Inventory.ApplyNextOwnerPermissions();
  83. }
  84. public Color4 GetTextColor()
  85. {
  86. Color color = Color;
  87. return new Color4(color.R, color.G, color.B, (byte) (0xFF - color.A));
  88. }
  89. public void SetSoundQueueing(int queue)
  90. {
  91. UseSoundQueue = queue;
  92. }
  93. public void SetConeOfSilence(double radius)
  94. {
  95. ISoundModule module = m_parentGroup.Scene.RequestModuleInterface<ISoundModule>();
  96. //TODO: Save SetConeOfSilence
  97. if (module != null)
  98. {
  99. if (radius != 0)
  100. module.AddConeOfSilence(UUID, AbsolutePosition, radius);
  101. else
  102. module.RemoveConeOfSilence(UUID);
  103. }
  104. }
  105. #endregion
  106. #region Fields
  107. private readonly List<uint> m_lastColliders = new List<uint>();
  108. [XmlIgnore] public scriptEvents AggregateScriptEvents;
  109. [XmlIgnore] public bool IgnoreUndoUpdate;
  110. [XmlIgnore] public bool IsWaitingForFirstSpinUpdatePacket;
  111. [XmlIgnore] private PrimFlags LocalFlags;
  112. [XmlIgnore] public Vector3 RotationAxis = Vector3.One;
  113. [XmlIgnore] public Quaternion SpinOldOrientation = Quaternion.Identity;
  114. [XmlIgnore] public uint TimeStampLastActivity; // Will be used for AutoReturn
  115. [XmlIgnore]
  116. public bool Undoing { get; set; }
  117. private UUID _creatorID;
  118. [XmlIgnore] private UUID m_AttachedAvatar;
  119. [XmlIgnore] private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
  120. [XmlIgnore] private bool m_IsAttachment;
  121. [XmlIgnore] private bool m_IsSelected;
  122. [XmlIgnore] private int[] m_PayPrice = {-2, -2, -2, -2, -2};
  123. [XmlIgnore] private bool m_ValidpartOOB; // control recalcutation
  124. protected Vector3 m_acceleration;
  125. protected Vector3 m_angularVelocity;
  126. private byte m_clickAction;
  127. private UUID m_collisionSound;
  128. private float m_collisionSoundVolume;
  129. private UUID m_collisionSprite;
  130. protected uint m_crc;
  131. private string m_creatorData = string.Empty;
  132. private string m_description = String.Empty;
  133. protected Vector3 m_groupPosition;
  134. private Vector3 m_initialPIDLocation = Vector3.Zero;
  135. protected SceneObjectPartInventory m_inventory;
  136. protected Vector3 m_lastAcceleration;
  137. protected Vector3 m_lastAngularVelocity;
  138. protected Vector3 m_lastGroupPosition;
  139. protected Vector3 m_lastPosition;
  140. protected Quaternion m_lastRotation;
  141. protected Vector3 m_lastVelocity;
  142. private int m_linkNum;
  143. protected uint m_localId;
  144. /// <summary>
  145. /// Stores media texture data
  146. /// </summary>
  147. protected string m_mediaUrl;
  148. protected string m_name;
  149. protected Vector3 m_offsetPosition;
  150. protected SceneObjectGroup m_parentGroup;
  151. [XmlIgnore] private float m_partBSphereRadiusSQ; // the square of the radius of a sphere containing the oob
  152. [XmlIgnore] private Vector3 m_partOOBoffset;
  153. // the position center of the bounding box relative to it's Position
  154. [XmlIgnore] private Vector3 m_partOOBsize;
  155. // the size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
  156. protected byte[] m_particleSystem = Utils.EmptyBytes;
  157. private int m_passTouches;
  158. private PhysicsObject m_physActor;
  159. private bool m_pidActive;
  160. private bool m_pidhoverActive;
  161. private UndoStack<UndoState> m_redo = new UndoStack<UndoState>(5);
  162. protected ulong m_regionHandle;
  163. [XmlIgnore] private int m_scriptAccessPin;
  164. [XmlIgnore] private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
  165. protected PrimitiveBaseShape m_shape;
  166. private string m_sitAnimation = "SIT";
  167. private string m_sitName = String.Empty;
  168. private UUID m_sound;
  169. private string m_text = String.Empty;
  170. private string m_touchName = String.Empty;
  171. private UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
  172. protected UUID m_uuid;
  173. private bool m_volumeDetectActive;
  174. [XmlIgnore]
  175. [ProtoMember(92)]
  176. public bool RETURN_AT_EDGE { get; set; }
  177. [XmlIgnore]
  178. [ProtoMember(93)]
  179. public bool BlockGrab { get; set; }
  180. [XmlIgnore]
  181. [ProtoMember(94)]
  182. public bool BlockGrabObject { get; set; }
  183. [XmlIgnore]
  184. public bool IsLoading { get; set; }
  185. [XmlIgnore]
  186. [ProtoMember(96)]
  187. public bool StatusSandbox { get; set; }
  188. [XmlIgnore]
  189. [ProtoMember(97)]
  190. public Vector3 StatusSandboxPos { get; set; }
  191. [XmlIgnore]
  192. [ProtoMember(98)]
  193. public int STATUS_ROTATE_X { get; set; }
  194. [XmlIgnore]
  195. [ProtoMember(99)]
  196. public int STATUS_ROTATE_Y { get; set; }
  197. [XmlIgnore]
  198. [ProtoMember(100)]
  199. public int STATUS_ROTATE_Z { get; set; }
  200. [XmlIgnore]
  201. public bool ValidpartOOB
  202. {
  203. set { m_ValidpartOOB = value; }
  204. }
  205. // the size of a bounding box oriented as the prim, is future will consider cutted prims, meshs etc
  206. [XmlIgnore]
  207. public Vector3 OOBsize
  208. {
  209. get
  210. {
  211. if (!m_ValidpartOOB)
  212. UpdateOOBfromOOBs();
  213. return m_partOOBsize;
  214. }
  215. }
  216. // the position center of the bounding box relative to it's Position
  217. // on complex forms this will not be zero
  218. [XmlIgnore]
  219. public Vector3 OOBoffset
  220. {
  221. get
  222. {
  223. if (!m_ValidpartOOB)
  224. UpdateOOBfromOOBs();
  225. return m_partOOBoffset;
  226. }
  227. }
  228. // the square of the radius of a sphere containing the oobb
  229. [XmlIgnore]
  230. public float BSphereRadiusSQ
  231. {
  232. get
  233. {
  234. if (!m_ValidpartOOB)
  235. UpdateOOBfromOOBs();
  236. return m_partBSphereRadiusSQ;
  237. }
  238. }
  239. [ProtoMember(1)]
  240. public bool AllowedDrop { get; set; }
  241. [XmlIgnore]
  242. [ProtoMember(91)]
  243. public bool DIE_AT_EDGE { get; set; }
  244. [XmlIgnore]
  245. [ProtoMember(90)]
  246. public int UseSoundQueue { get; set; }
  247. [ProtoMember(70, OverwriteList = true)]
  248. public int[] PayPrice
  249. {
  250. get { return m_PayPrice; }
  251. set { m_PayPrice = value; }
  252. }
  253. [XmlIgnore]
  254. public PhysicsObject PhysActor
  255. {
  256. get { return m_physActor; }
  257. set
  258. {
  259. // MainConsole.Instance.DebugFormat("[SOP]: PhysActor set to {0} for {1} {2}", value, Name, UUID);
  260. m_physActor = value;
  261. }
  262. }
  263. [XmlIgnore]
  264. [ProtoMember(71)]
  265. public UUID Sound
  266. {
  267. get { return m_sound; }
  268. set { m_sound = value; }
  269. }
  270. [XmlIgnore]
  271. [ProtoMember(72)]
  272. public byte SoundFlags { get; set; }
  273. [XmlIgnore]
  274. [ProtoMember(73)]
  275. public double SoundGain { get; set; }
  276. [XmlIgnore]
  277. [ProtoMember(74)]
  278. public double SoundRadius { get; set; }
  279. [XmlIgnore]
  280. [ProtoMember(75)]
  281. public Vector3 PIDTarget { get; set; }
  282. [XmlIgnore]
  283. [ProtoMember(76)]
  284. public bool PIDActive
  285. {
  286. get { return m_pidActive; }
  287. set
  288. {
  289. IScene s = ParentGroup == null ? null : ParentGroup.Scene ?? null;
  290. if (s != null)
  291. {
  292. if (value)
  293. s.EventManager.OnFrame += UpdateLookAt;
  294. else
  295. s.EventManager.OnFrame -= UpdateLookAt;
  296. }
  297. m_pidActive = value;
  298. }
  299. }
  300. [XmlIgnore]
  301. [ProtoMember(77)]
  302. public float PIDTau { get; set; }
  303. [ProtoMember(78)]
  304. public float PIDHoverHeight { get; set; }
  305. [ProtoMember(79)]
  306. public float PIDHoverTau { get; set; }
  307. [ProtoMember(80)]
  308. public bool PIDHoverActive
  309. {
  310. get { return m_pidhoverActive; }
  311. set { m_pidhoverActive = value; }
  312. }
  313. [ProtoMember(81)]
  314. public PIDHoverType PIDHoverType { get; set; }
  315. [XmlIgnore]
  316. [ProtoMember(82)]
  317. public UUID FromUserInventoryItemID { get; set; }
  318. [XmlIgnore]
  319. [ProtoMember(83)]
  320. public UUID FromUserInventoryAssetID { get; set; }
  321. [XmlIgnore]
  322. public bool IsAttachment
  323. {
  324. get { return m_IsAttachment; }
  325. set { m_IsAttachment = value; }
  326. }
  327. [XmlIgnore]
  328. public UUID AttachedAvatar
  329. {
  330. get { return m_AttachedAvatar; }
  331. set { m_AttachedAvatar = value; }
  332. }
  333. [XmlIgnore]
  334. public Vector3 AttachedPos { get; set; }
  335. /// <summary>
  336. /// NOTE: THIS WILL NOT BE UP TO DATE AS THEY WILL BE ONE REV BEHIND
  337. /// Used to save attachment pos and point over rezzing/taking
  338. /// </summary>
  339. [XmlIgnore]
  340. public int AttachmentPoint { get; set; }
  341. /// <summary>
  342. /// NOTE: THIS WILL NOT BE UP TO DATE AS THEY WILL BE ONE REV BEHIND
  343. /// Used to save attachment pos and point over rezzing/taking
  344. /// </summary>
  345. [ProtoMember(84)]
  346. public Vector3 SavedAttachedPos { get; set; }
  347. [ProtoMember(85)]
  348. public int SavedAttachmentPoint { get; set; }
  349. [XmlIgnore]
  350. [ProtoMember(86)]
  351. public bool VolumeDetectActive
  352. {
  353. get { return m_volumeDetectActive; }
  354. set { m_volumeDetectActive = value; }
  355. }
  356. /// <summary>
  357. /// This part's inventory
  358. /// </summary>
  359. [XmlIgnore]
  360. public IEntityInventory Inventory
  361. {
  362. get { return m_inventory; }
  363. }
  364. [ProtoMember(87)]
  365. public Vector3 CameraEyeOffset { get; set; }
  366. [ProtoMember(88)]
  367. public Vector3 CameraAtOffset { get; set; }
  368. [ProtoMember(89)]
  369. public bool ForceMouselook { get; set; }
  370. [ProtoMember(102)]
  371. public KeyframeAnimation KeyframeAnimation { get; set; }
  372. [ProtoMember(103)]
  373. public Dictionary<UUID, StateSave> StateSaves { get; set; }
  374. public Vector3 GroupScale()
  375. {
  376. return m_parentGroup.GroupScale();
  377. }
  378. #endregion Fields
  379. #region Constructors
  380. /// <summary>
  381. /// No arg constructor called by region restore db code
  382. /// </summary>
  383. public SceneObjectPart()
  384. {
  385. SitTargetAvatar = new List<UUID>();
  386. StateSaves = new Dictionary<UUID, StateSave>();
  387. m_inventory = new SceneObjectPartInventory(this);
  388. m_shape = new PrimitiveBaseShape();
  389. Material = (int) OpenMetaverse.Material.Wood;
  390. }
  391. /// <summary>
  392. /// Create a completely new SceneObjectPart (prim). This will need to be added separately to a SceneObjectGroup
  393. /// </summary>
  394. /// <param name="ownerID"></param>
  395. /// <param name="shape"></param>
  396. /// <param name="groupPosition"></param>
  397. /// <param name="rotationOffset"></param>
  398. /// <param name="offsetPosition"></param>
  399. /// <param name="name"></param>
  400. public SceneObjectPart(
  401. UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
  402. Quaternion rotationOffset, Vector3 offsetPosition, string name)
  403. {
  404. m_name = name;
  405. CreationDate = (int) Utils.DateTimeToUnixTime(DateTime.Now);
  406. _ownerID = ownerID;
  407. _creatorID = _ownerID;
  408. LastOwnerID = UUID.Zero;
  409. UUID = UUID.Random();
  410. Shape = shape;
  411. CRC = 1;
  412. _ownershipCost = 0;
  413. _flags = 0;
  414. _groupID = UUID.Zero;
  415. _objectSaleType = 0;
  416. _salePrice = 0;
  417. _category = 0;
  418. LastOwnerID = _creatorID;
  419. m_groupPosition = groupPosition;
  420. m_offsetPosition = offsetPosition;
  421. RotationOffset = rotationOffset;
  422. Velocity = Vector3.Zero;
  423. AngularVelocity = Vector3.Zero;
  424. Acceleration = Vector3.Zero;
  425. SitTargetAvatar = new List<UUID>();
  426. StateSaves = new Dictionary<UUID, StateSave>();
  427. ValidpartOOB = false;
  428. // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
  429. // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
  430. // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
  431. Flags = 0;
  432. CreateSelected = true;
  433. TrimPermissions();
  434. //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
  435. m_inventory = new SceneObjectPartInventory(this);
  436. Material = (int) OpenMetaverse.Material.Wood;
  437. }
  438. public override int GetHashCode()
  439. {
  440. return UUID.GetHashCode();
  441. }
  442. #endregion Constructors
  443. #region XML Schema
  444. private uint _baseMask = (uint) PermissionMask.All;
  445. private uint _category;
  446. private uint _everyoneMask = (uint) PermissionMask.None;
  447. private PrimFlags _flags = PrimFlags.None;
  448. private UUID _groupID;
  449. private uint _groupMask = (uint) PermissionMask.None;
  450. private uint _nextOwnerMask = (uint) PermissionMask.All;
  451. private byte _objectSaleType;
  452. private UUID _ownerID;
  453. private uint _ownerMask = (uint) PermissionMask.All;
  454. private int _ownershipCost;
  455. private uint _parentID;
  456. private int _salePrice;
  457. private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
  458. private byte[] m_ParticleSystem;
  459. private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
  460. private string m_currentMediaVersion = "x-mv:0000000001/00000000-0000-0000-0000-000000000000";
  461. private int m_passCollision;
  462. private byte[] m_textureAnimation;
  463. [XmlIgnore]
  464. public string CurrentMediaVersion
  465. {
  466. get { return m_currentMediaVersion; }
  467. set { m_currentMediaVersion = value; }
  468. }
  469. /// <summary>
  470. /// Used by the DB layer to retrieve / store the entire user identification.
  471. /// The identification can either be a simple UUID or a string of the form
  472. /// uuid[;profile_url[;name]]
  473. /// </summary>
  474. public string CreatorIdentification
  475. {
  476. get
  477. {
  478. if (!string.IsNullOrEmpty(m_creatorData))
  479. return _creatorID.ToString() + ';' + m_creatorData;
  480. else
  481. return _creatorID.ToString();
  482. }
  483. set
  484. {
  485. if ((value == null) || (value != null && value == string.Empty))
  486. {
  487. m_creatorData = string.Empty;
  488. return;
  489. }
  490. if (!value.Contains(";")) // plain UUID
  491. {
  492. UUID uuid = UUID.Zero;
  493. UUID.TryParse(value, out uuid);
  494. _creatorID = uuid;
  495. }
  496. else // <uuid>[;<endpoint>[;name]]
  497. {
  498. string name = "Unknown User";
  499. string[] parts = value.Split(';');
  500. if (parts.Length >= 1)
  501. {
  502. UUID uuid = UUID.Zero;
  503. UUID.TryParse(parts[0], out uuid);
  504. _creatorID = uuid;
  505. }
  506. if (parts.Length >= 2)
  507. m_creatorData = parts[1];
  508. if (parts.Length >= 3)
  509. name = parts[2];
  510. m_creatorData += ';' + name;
  511. }
  512. }
  513. }
  514. /// <summary>
  515. /// This is idential to the Flags property, except that the returned value is uint rather than PrimFlags
  516. /// </summary>
  517. [Obsolete("Use Flags property instead")]
  518. public uint ObjectFlags
  519. {
  520. get { return (uint) Flags; }
  521. set
  522. {
  523. if (ParentGroup != null)
  524. ParentGroup.HasGroupChanged = true;
  525. Flags = (PrimFlags) value;
  526. }
  527. }
  528. private Quaternion m_APIDTarget;
  529. [XmlIgnore, ProtoMember(65)]
  530. public Quaternion APIDTarget
  531. {
  532. get { return m_APIDTarget; }
  533. set
  534. {
  535. IScene s = ParentGroup == null ? null : ParentGroup.Scene ?? null;
  536. if (s != null)
  537. {
  538. if (value != Quaternion.Identity)
  539. s.EventManager.OnFrame += UpdateLookAt;
  540. else
  541. s.EventManager.OnFrame -= UpdateLookAt;
  542. }
  543. m_APIDTarget = value;
  544. }
  545. }
  546. [XmlIgnore, ProtoMember(66)]
  547. public float APIDDamp { get; set; }
  548. [XmlIgnore, ProtoMember(67)]
  549. public float APIDStrength { get; set; }
  550. [ProtoMember(68)]
  551. public int APIDIterations { get; set; }
  552. [ProtoMember(69)]
  553. public bool APIDEnabled { get; set; }
  554. [XmlIgnore]
  555. public SceneObjectPart PlaySoundMasterPrim { get; set; }
  556. [XmlIgnore]
  557. public List<SceneObjectPart> PlaySoundSlavePrims
  558. {
  559. get { return m_PlaySoundSlavePrims; }
  560. set { m_PlaySoundSlavePrims = value; }
  561. }
  562. [XmlIgnore]
  563. public SceneObjectPart LoopSoundMasterPrim { get; set; }
  564. [XmlIgnore]
  565. public List<SceneObjectPart> LoopSoundSlavePrims
  566. {
  567. get { return m_LoopSoundSlavePrims; }
  568. set { m_LoopSoundSlavePrims = value; }
  569. }
  570. [XmlIgnore, ProtoMember(64)]
  571. public float Damage { get; set; }
  572. public Vector3 RelativePosition
  573. {
  574. get
  575. {
  576. if (IsRoot)
  577. {
  578. if (IsAttachment)
  579. return OffsetPosition;
  580. else
  581. return AbsolutePosition;
  582. }
  583. else
  584. {
  585. return OffsetPosition;
  586. }
  587. }
  588. }
  589. [ProtoMember(2)]
  590. public UUID CreatorID
  591. {
  592. get { return _creatorID; }
  593. set { _creatorID = value; }
  594. }
  595. /// <summary>
  596. /// Data about the creator in the form profile_url;name
  597. /// </summary>
  598. [ProtoMember(3)]
  599. public string CreatorData
  600. {
  601. get { return m_creatorData; }
  602. set { m_creatorData = value; }
  603. }
  604. /// <value>
  605. /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
  606. /// </value>
  607. [ProtoMember(4)]
  608. public uint InventorySerial
  609. {
  610. get { return m_inventory.Serial; }
  611. set { m_inventory.Serial = value; }
  612. }
  613. /// <value>
  614. /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes
  615. /// </value>
  616. [ProtoMember(5)]
  617. public TaskInventoryDictionary TaskInventory
  618. {
  619. get { return m_inventory.Items; }
  620. set { m_inventory.Items = value; }
  621. }
  622. [ProtoMember(6)]
  623. public UUID UUID
  624. {
  625. get { return m_uuid; }
  626. set
  627. {
  628. UUID oldID = m_uuid;
  629. if (ParentGroup != null)
  630. ParentGroup.HasGroupChanged = true;
  631. m_uuid = value;
  632. // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part
  633. if (Inventory != null)
  634. Inventory.ResetObjectID();
  635. }
  636. }
  637. [ProtoMember(7)]
  638. public uint LocalId
  639. {
  640. get { return m_localId; }
  641. set { m_localId = value; }
  642. }
  643. [XmlIgnore]
  644. public uint CRC { get; set; }
  645. [ProtoMember(8)]
  646. public virtual string Name
  647. {
  648. get { return m_name; }
  649. set
  650. {
  651. if (m_name != value)
  652. {
  653. if (ParentGroup != null)
  654. ParentGroup.HasGroupChanged = true;
  655. m_name = value;
  656. }
  657. }
  658. }
  659. [ProtoMember(9)]
  660. public int Material { get; set; }
  661. public void UpdateMaterial(int val)
  662. {
  663. if (Material == val)
  664. return;
  665. if (ParentGroup != null)
  666. ParentGroup.HasGroupChanged = true;
  667. Material = val;
  668. if (PhysActor != null)
  669. PhysActor.SetMaterial(val, true);
  670. }
  671. [ProtoMember(10)]
  672. public int PassTouch
  673. {
  674. get { return m_passTouches; }
  675. set
  676. {
  677. m_passTouches = value;
  678. if (ParentGroup != null)
  679. ParentGroup.HasGroupChanged = true;
  680. }
  681. }
  682. [ProtoMember(11)]
  683. public int PassCollisions
  684. {
  685. get { return m_passCollision; }
  686. set
  687. {
  688. if (ParentGroup != null)
  689. ParentGroup.HasGroupChanged = true;
  690. m_passCollision = value;
  691. }
  692. }
  693. [XmlIgnore, ProtoMember(12)]
  694. public Dictionary<int, string> CollisionFilter
  695. {
  696. get { return m_CollisionFilter; }
  697. set
  698. {
  699. if (ParentGroup != null)
  700. ParentGroup.HasGroupChanged = true;
  701. m_CollisionFilter = value;
  702. }
  703. }
  704. [ProtoMember(13)]
  705. public int ScriptAccessPin
  706. {
  707. get { return m_scriptAccessPin; }
  708. set { m_scriptAccessPin = value; }
  709. }
  710. [ProtoMember(60, OverwriteList = true)]
  711. public Byte[] TextureAnimation
  712. {
  713. get { return m_textureAnimation; }
  714. set { m_textureAnimation = value; }
  715. }
  716. [XmlIgnore]
  717. [ProtoMember(61, OverwriteList = true)]
  718. public Byte[] ParticleSystem
  719. {
  720. get { return m_ParticleSystem; }
  721. set { m_ParticleSystem = value; }
  722. }
  723. [XmlIgnore, ProtoMember(62)]
  724. public DateTime Expires { get; set; }
  725. [XmlIgnore, ProtoMember(63)]
  726. public DateTime Rezzed { get; set; }
  727. /// <summary>
  728. /// The position of the entire group that this prim belongs to.
  729. /// </summary>
  730. [ProtoMember(14)]
  731. public Vector3 GroupPosition
  732. {
  733. get { return GetGroupPosition(); }
  734. set { FixGroupPosition(value, false); }
  735. }
  736. public Vector3 GetGroupPosition()
  737. {
  738. // If this is a linkset, we don't want the physics engine mucking up our group position here.
  739. PhysicsObject actor = PhysActor;
  740. if (actor != null && _parentID == 0)
  741. {
  742. m_groupPosition = actor.Position;
  743. }
  744. if (IsAttachment)
  745. {
  746. IScenePresence sp = m_parentGroup.Scene.GetScenePresence(AttachedAvatar);
  747. if (sp != null)
  748. return sp.AbsolutePosition;
  749. }
  750. return m_groupPosition;
  751. }
  752. [ProtoMember(15)]
  753. public Vector3 OffsetPosition
  754. {
  755. get { return m_offsetPosition; }
  756. set
  757. {
  758. m_offsetPosition = value;
  759. ValidpartOOB = false;
  760. }
  761. }
  762. [ProtoMember(16)]
  763. public Quaternion RotationOffset { get; set; }
  764. public Quaternion GetRotationOffset()
  765. {
  766. PhysicsObject actor = m_physActor;
  767. if (_parentID == 0 && (m_shape.PCode != 9 || m_shape.State == 0) && actor != null)
  768. {
  769. if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
  770. || actor.Orientation.Z != 0f || actor.Orientation.W != 0f)
  771. {
  772. RotationOffset = actor.Orientation;
  773. }
  774. }
  775. return RotationOffset;
  776. }
  777. private Vector3 m_tempVelocity = Vector3.Zero;
  778. /// <summary>
  779. /// </summary>
  780. [ProtoMember(17)]
  781. public Vector3 Velocity
  782. {
  783. get
  784. {
  785. PhysicsObject actor = PhysActor;
  786. if (actor != null)
  787. {
  788. if (actor.IsPhysical)
  789. {
  790. return actor.Velocity;
  791. }
  792. }
  793. return m_tempVelocity;
  794. }
  795. set
  796. {
  797. PhysicsObject actor = PhysActor;
  798. if (actor != null)
  799. {
  800. if (actor.IsPhysical)
  801. {
  802. actor.Velocity = value;
  803. m_tempVelocity = Vector3.Zero;
  804. }
  805. else
  806. m_tempVelocity = value;
  807. }
  808. else
  809. m_tempVelocity = value;
  810. }
  811. }
  812. /// <summary>
  813. /// </summary>
  814. [ProtoMember(18)]
  815. public Vector3 AngularVelocity
  816. {
  817. get
  818. {
  819. PhysicsObject actor = PhysActor;
  820. if ((actor != null) && actor.IsPhysical)
  821. {
  822. m_angularVelocity = actor.RotationalVelocity;
  823. }
  824. return m_angularVelocity;
  825. }
  826. set { m_angularVelocity = value; }
  827. }
  828. public void GenerateRotationalVelocityFromOmega()
  829. {
  830. if (OmegaGain == 0.0f) //Disable spin
  831. AngularVelocity = Vector3.Zero;
  832. else
  833. AngularVelocity = new Vector3((float) (OmegaAxis.X*OmegaSpinRate),
  834. (float) (OmegaAxis.Y*OmegaSpinRate),
  835. (float) (OmegaAxis.Z*OmegaSpinRate));
  836. }
  837. /// <summary>
  838. /// </summary>
  839. [ProtoMember(19)]
  840. public Vector3 Acceleration
  841. {
  842. get { return m_acceleration; }
  843. set { m_acceleration = value; }
  844. }
  845. [ProtoMember(20)]
  846. public string Description
  847. {
  848. get { return m_description; }
  849. set
  850. {
  851. if (m_description == value)
  852. return;
  853. if (ParentGroup != null)
  854. ParentGroup.HasGroupChanged = true;
  855. m_description = value;
  856. }
  857. }
  858. /// <value>
  859. /// Text color.
  860. /// </value>
  861. [XmlIgnore]
  862. [ProtoMember(21)]
  863. public Color Color { get; set; }
  864. public void UpdateColor(Color c, bool triggerChangedColor)
  865. {
  866. if (c.A != Color.A ||
  867. c.B != Color.B ||
  868. c.G != Color.G ||
  869. c.R != Color.R)
  870. {
  871. if (ParentGroup != null)
  872. ParentGroup.HasGroupChanged = true;
  873. Color = c;
  874. if (triggerChangedColor)
  875. TriggerScriptChangedEvent(Changed.COLOR);
  876. /* ScheduleFullUpdate() need not be called b/c after
  877. * setting the color, the text will be set, so then
  878. * ScheduleFullUpdate() will be called. */
  879. //ScheduleFullUpdate();
  880. }
  881. }
  882. [ProtoMember(22)]
  883. public string Text
  884. {
  885. get
  886. {
  887. string returnstr = m_text;
  888. if (returnstr.Length > 255)
  889. {
  890. returnstr = returnstr.Substring(0, 254);
  891. }
  892. return returnstr;
  893. }
  894. set
  895. {
  896. if (m_text == value)
  897. return;
  898. if (ParentGroup != null)
  899. ParentGroup.HasGroupChanged = true;
  900. m_text = value;
  901. }
  902. }
  903. [ProtoMember(23)]
  904. public string SitName
  905. {
  906. get { return m_sitName; }
  907. set
  908. {
  909. if (m_sitName == value)
  910. return;
  911. if (ParentGroup != null)
  912. ParentGroup.HasGroupChanged = true;
  913. m_sitName = value;
  914. }
  915. }
  916. [ProtoMember(24)]
  917. public string TouchName
  918. {
  919. get { return m_touchName; }
  920. set
  921. {
  922. if (m_touchName == value)
  923. return;
  924. if (ParentGroup != null)
  925. ParentGroup.HasGroupChanged = true;
  926. m_touchName = value;
  927. }
  928. }
  929. [ProtoMember(25)]
  930. public int LinkNum
  931. {
  932. get { return m_linkNum; }
  933. set
  934. {
  935. if (m_linkNum == value)
  936. return;
  937. if (ParentGroup != null)
  938. ParentGroup.HasGroupChanged = true;
  939. m_linkNum = value;
  940. }
  941. }
  942. [ProtoMember(26)]
  943. public byte ClickAction
  944. {
  945. get { return m_clickAction; }
  946. set
  947. {
  948. if (m_clickAction == value)
  949. return;
  950. if (ParentGroup != null)
  951. ParentGroup.HasGroupChanged = true;
  952. m_clickAction = value;
  953. }
  954. }
  955. [ProtoMember(27)]
  956. public PrimitiveBaseShape Shape
  957. {
  958. get { return m_shape; }
  959. set
  960. {
  961. ValidpartOOB = false;
  962. if (ParentGroup != null)
  963. ParentGroup.HasGroupChanged = true;
  964. bool shape_changed = false;
  965. // TODO: this should really be restricted to the right
  966. // set of attributes on shape change. For instance,
  967. // changing the lighting on a shape shouldn't cause
  968. // this.
  969. if (m_shape != null)
  970. shape_changed = true;
  971. m_shape = value;
  972. if (shape_changed)
  973. TriggerScriptChangedEvent(Changed.SHAPE);
  974. }
  975. }
  976. public Vector3 Scale
  977. {
  978. get { return m_shape.Scale; }
  979. set
  980. {
  981. ValidpartOOB = false;
  982. if (m_shape != null)
  983. {
  984. if (m_shape.Scale != value)
  985. {
  986. StoreUndoState();
  987. if (ParentGroup != null)
  988. ParentGroup.HasGroupChanged = true;
  989. m_shape.Scale = value;
  990. PhysicsActor actor = PhysActor;
  991. if (actor != null && m_parentGroup != null &&
  992. m_parentGroup.Scene != null &&
  993. m_parentGroup.Scene.PhysicsScene != null)
  994. actor.Size = m_shape.Scale;
  995. TriggerScriptChangedEvent(Changed.SCALE);
  996. }
  997. }
  998. }
  999. }
  1000. /// <summary>
  1001. /// Used for media on a prim.
  1002. /// </summary>
  1003. /// Do not change this value directly - always do it through an IMoapModule.
  1004. [ProtoMember(29)]
  1005. public string MediaUrl
  1006. {
  1007. get { return m_mediaUrl; }
  1008. set
  1009. {
  1010. if (m_mediaUrl == value)
  1011. return;
  1012. m_mediaUrl = value;
  1013. if (ParentGroup != null)
  1014. ParentGroup.HasGroupChanged = true;
  1015. }
  1016. }
  1017. [XmlIgnore]
  1018. public bool CreateSelected { get; set; }
  1019. [XmlIgnore]
  1020. public bool IsSelected
  1021. {
  1022. get { return m_IsSelected; }
  1023. set
  1024. {
  1025. if (m_IsSelected != value)
  1026. {
  1027. if (PhysActor != null)
  1028. {
  1029. PhysActor.Selected = value;
  1030. }
  1031. if (ParentID != 0 && ParentGroup != null &&
  1032. ParentGroup.RootPart != null && ParentGroup.RootPart != this &&
  1033. ParentGroup.RootPart.IsSelected != value)
  1034. ParentGroup.RootPart.IsSelected = value;
  1035. m_IsSelected = value;
  1036. }
  1037. }
  1038. }
  1039. #endregion
  1040. #region Public Properties with only Get
  1041. private UUID _parentUUID = UUID.Zero;
  1042. private float m_friction;
  1043. private float m_density;
  1044. private float m_gravityMultiplier;
  1045. private float m_restitution;
  1046. public SceneObjectGroup ParentGroup
  1047. {
  1048. get { return m_parentGroup; }
  1049. }
  1050. public scriptEvents ScriptEvents
  1051. {
  1052. get { return AggregateScriptEvents; }
  1053. }
  1054. public bool Stopped
  1055. {
  1056. get
  1057. {
  1058. double threshold = 0.02;
  1059. return (Math.Abs(Velocity.X) < threshold &&
  1060. Math.Abs(Velocity.Y) < threshold &&
  1061. Math.Abs(Velocity.Z) < threshold &&
  1062. Math.Abs(AngularVelocity.X) < threshold &&
  1063. Math.Abs(AngularVelocity.Y) < threshold &&
  1064. Math.Abs(AngularVelocity.Z) < threshold);
  1065. }
  1066. }
  1067. [ProtoMember(39)]
  1068. public uint Category
  1069. {
  1070. get { return _category; }
  1071. set { _category = value; }
  1072. }
  1073. [ProtoMember(40)]
  1074. public int OwnershipCost
  1075. {
  1076. get { return _ownershipCost; }
  1077. set { _ownershipCost = value; }
  1078. }
  1079. [XmlIgnore]
  1080. public virtual UUID RegionID
  1081. {
  1082. get
  1083. {
  1084. if (ParentGroup != null && ParentGroup.Scene != null)
  1085. return ParentGroup.Scene.RegionInfo.RegionID;
  1086. else
  1087. return UUID.Zero;
  1088. }
  1089. set { } // read only
  1090. }
  1091. public Vector3 AbsolutePosition
  1092. {
  1093. get
  1094. {
  1095. if (IsAttachment)
  1096. return GroupPosition;
  1097. return GetWorldPosition();
  1098. }
  1099. set { }
  1100. }
  1101. public ISceneEntity ParentEntity
  1102. {
  1103. get { return m_parentGroup; }
  1104. }
  1105. [ProtoMember(30)]
  1106. public Quaternion SitTargetOrientation { get; set; }
  1107. [ProtoMember(31)]
  1108. public Vector3 SitTargetPosition { get; set; }
  1109. [ProtoMember(32)]
  1110. public Vector3 OmegaAxis { get; set; }
  1111. [ProtoMember(33)]
  1112. public double OmegaSpinRate { get; set; }
  1113. [ProtoMember(34)]
  1114. public double OmegaGain { get; set; }
  1115. [ProtoMember(35)]
  1116. public uint ParentID
  1117. {
  1118. get { return _parentID; }
  1119. set { _parentID = value; }
  1120. }
  1121. [ProtoMember(36)]
  1122. public int CreationDate { get; set; }
  1123. [ProtoMember(37)]
  1124. public int SalePrice
  1125. {
  1126. get { return _salePrice; }
  1127. set { _salePrice = value; }
  1128. }
  1129. [ProtoMember(38)]
  1130. public byte ObjectSaleType
  1131. {
  1132. get { return _objectSaleType; }
  1133. set { _objectSaleType = value; }
  1134. }
  1135. [ProtoMember(43)]
  1136. public UUID GroupID
  1137. {
  1138. get { return _groupID; }
  1139. set { _groupID = value; }
  1140. }
  1141. [ProtoMember(44)]
  1142. public UUID OwnerID
  1143. {
  1144. get { return _ownerID; }
  1145. set { _ownerID = value; }
  1146. }
  1147. [ProtoMember(45)]
  1148. public UUID LastOwnerID { get; set; }
  1149. [ProtoMember(46)]
  1150. public uint BaseMask
  1151. {
  1152. get { return _baseMask; }
  1153. set { _baseMask = value; }
  1154. }
  1155. [ProtoMember(101)]
  1156. public uint OwnerMask
  1157. {
  1158. get { return _ownerMask; }
  1159. set { _ownerMask = value; }
  1160. }
  1161. [ProtoMember(47)]
  1162. public uint GroupMask
  1163. {
  1164. get { return _groupMask; }
  1165. set { _groupMask = value; }
  1166. }
  1167. [ProtoMember(48)]
  1168. public uint EveryoneMask
  1169. {
  1170. get { return _everyoneMask; }
  1171. set { _everyoneMask = value; }
  1172. }
  1173. [ProtoMember(49)]
  1174. public uint NextOwnerMask
  1175. {
  1176. get { return _nextOwnerMask; }
  1177. set { _nextOwnerMask = value; }
  1178. }
  1179. [ProtoMember(50)]
  1180. public byte PhysicsType { get; set; }
  1181. [ProtoMember(51)]
  1182. public float Density
  1183. {
  1184. get
  1185. {
  1186. if (m_density != 0)
  1187. return m_density;
  1188. return (m_density = 1000f);
  1189. }
  1190. set { m_density = value; }
  1191. }
  1192. [ProtoMember(52)]
  1193. public float Friction
  1194. {
  1195. get
  1196. {
  1197. if (m_friction != 0)
  1198. return m_friction;
  1199. return (m_friction = 0.6f);
  1200. }
  1201. set { m_friction = value; }
  1202. }
  1203. [ProtoMember(53)]
  1204. public float Restitution
  1205. {
  1206. get
  1207. {
  1208. if (m_restitution != 0)
  1209. return m_restitution;
  1210. return (m_restitution = 0.5f);
  1211. }
  1212. set { m_restitution = value; }
  1213. }
  1214. [ProtoMember(54)]
  1215. public float GravityMultiplier
  1216. {
  1217. get
  1218. {
  1219. if (m_gravityMultiplier != 0)
  1220. return m_gravityMultiplier;
  1221. return (m_gravityMultiplier = 1);
  1222. }
  1223. set { m_gravityMultiplier = value; }
  1224. }
  1225. /// <summary>
  1226. /// Property flags. See OpenMetaverse.PrimFlags
  1227. /// </summary>
  1228. /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge
  1229. [ProtoMember(55)]
  1230. public PrimFlags Flags
  1231. {
  1232. get { return _flags; }
  1233. set
  1234. {
  1235. // MainConsole.Instance.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
  1236. //if (ParentGroup != null && _flags != value)
  1237. // ParentGroup.HasGroupChanged = true;
  1238. _flags = value;
  1239. }
  1240. }
  1241. [XmlIgnore]
  1242. public List<UUID> SitTargetAvatar { get; set; }
  1243. [XmlIgnore]
  1244. public UUID ParentUUID
  1245. {
  1246. get
  1247. {
  1248. if (ParentGroup != null)
  1249. _parentUUID = ParentGroup.UUID;
  1250. return _parentUUID;
  1251. }
  1252. set
  1253. {
  1254. if (ParentGroup != null)
  1255. ParentGroup.HasGroupChanged = true;
  1256. _parentUUID = value;
  1257. }
  1258. }
  1259. [XmlIgnore]
  1260. [ProtoMember(56)]
  1261. public string SitAnimation
  1262. {
  1263. get { return m_sitAnimation; }
  1264. set
  1265. {
  1266. if (ParentGroup != null)
  1267. ParentGroup.HasGroupChanged = true;
  1268. m_sitAnimation = value;
  1269. }
  1270. }
  1271. [ProtoMember(57)]
  1272. public UUID CollisionSound
  1273. {
  1274. get { return m_collisionSound; }
  1275. set
  1276. {
  1277. if (ParentGroup != null)
  1278. ParentGroup.HasGroupChanged = true;
  1279. m_collisionSound = value;
  1280. //Why?
  1281. //aggregateScriptEvents();
  1282. }
  1283. }
  1284. [ProtoMember(58)]
  1285. public UUID CollisionSprite
  1286. {
  1287. get { return m_collisionSprite; }
  1288. set
  1289. {
  1290. if (ParentGroup != null)
  1291. ParentGroup.HasGroupChanged = true;
  1292. m_collisionSprite = value;
  1293. }
  1294. }
  1295. [ProtoMember(59)]
  1296. public float CollisionSoundVolume
  1297. {
  1298. get { return m_collisionSoundVolume; }
  1299. set
  1300. {
  1301. if (ParentGroup != null)
  1302. ParentGroup.HasGroupChanged = true;
  1303. m_collisionSoundVolume = value;
  1304. }
  1305. }
  1306. #endregion Public Properties with only Get
  1307. #region Private Methods
  1308. public void FinishedSerializingGenericProperties()
  1309. {
  1310. if ((APIDEnabled || PIDActive) && this.ParentEntity != null) //Make sure to activate it
  1311. this.ParentEntity.Scene.EventManager.OnFrame += UpdateLookAt;
  1312. }
  1313. private void UpdateOOBfromOOBs()
  1314. {
  1315. m_partOOBoffset = Vector3.Zero;
  1316. Vector3 ts = Scale;
  1317. m_partOOBsize.X = ts.X*0.5f;
  1318. m_partOOBsize.Y = ts.Y*0.5f;
  1319. m_partOOBsize.Z = ts.Z*0.5f;
  1320. m_partBSphereRadiusSQ = m_partOOBsize.LengthSquared();
  1321. ValidpartOOB = true;
  1322. }
  1323. // distance from aabb to point ( untested)
  1324. public float AABdistanceToSQ(Vector3 target)
  1325. {
  1326. // distance to group in world
  1327. Vector3 vtmp = target - m_groupPosition; // assume this updated
  1328. if (ParentID != 0)
  1329. {
  1330. // rotate into group reference
  1331. vtmp *= Quaternion.Inverse(ParentGroup.GroupRotation);
  1332. // move into offseted local ref
  1333. vtmp -= m_offsetPosition;
  1334. }
  1335. // rotate into local reference ( part or grp )
  1336. vtmp *= Quaternion.Inverse(GetRotationOffset());
  1337. // now oob pos
  1338. vtmp -= OOBoffset; // force update
  1339. Vector3 box = OOBsize;
  1340. // hack distance to box: inside == 0
  1341. if (vtmp.X > 0)
  1342. {
  1343. vtmp.X -= box.X;
  1344. if (vtmp.X < 0.0)
  1345. vtmp.X = 0.0f;
  1346. }
  1347. else
  1348. {
  1349. vtmp.X += box.X;
  1350. if (vtmp.X > 0.0)
  1351. vtmp.X = 0.0f;
  1352. }
  1353. if (vtmp.Y > 0)
  1354. {
  1355. vtmp.Y -= box.Y;
  1356. if (vtmp.Y < 0.0)
  1357. vtmp.Y = 0.0f;
  1358. }
  1359. else
  1360. {
  1361. vtmp.Y += box.Y;
  1362. if (vtmp.Y > 0.0)
  1363. vtmp.Y = 0.0f;
  1364. }
  1365. if (vtmp.Z > 0)
  1366. {
  1367. vtmp.Z -= box.Z;
  1368. if (vtmp.Z < 0.0)
  1369. vtmp.Z = 0.0f;
  1370. }
  1371. else
  1372. {
  1373. vtmp.Z += box.Z;
  1374. if (vtmp.Z > 0.0)
  1375. vtmp.Z = 0.0f;
  1376. }
  1377. return vtmp.LengthSquared();
  1378. }
  1379. // distance from aabb to point ( untested)
  1380. // if smaller than simplied distance to group returns that one
  1381. // hack to send root prims first
  1382. public float clampedAABdistanceToSQ(Vector3 target)
  1383. {
  1384. float grpdSQ = 0;
  1385. // distance to group in world
  1386. Vector3 vtmp = target - m_groupPosition; // assume this updated
  1387. if (ParentID != 0)
  1388. {
  1389. // rotate into group reference
  1390. vtmp *= Quaternion.Inverse(ParentGroup.GroupRotation);
  1391. // compute distance to grp oob
  1392. Vector3 grpv = vtmp - ParentGroup.OOBoffset;
  1393. grpdSQ = grpv.LengthSquared() - ParentGroup.BSphereRadiusSQ;
  1394. if (grpdSQ < 0)
  1395. grpdSQ = 0;
  1396. // back
  1397. // move into offseted local ref
  1398. vtmp -= m_offsetPosition;
  1399. }
  1400. // rotate into local reference
  1401. vtmp *= Quaternion.Inverse(GetRotationOffset());
  1402. // now oob pos
  1403. vtmp -= OOBoffset; // force update
  1404. Vector3 box = OOBsize;
  1405. // hack distance to box: inside == 0
  1406. if (vtmp.X > 0)
  1407. {
  1408. vtmp.X -= box.X;
  1409. if (vtmp.X < 0.0)
  1410. vtmp.X = 0.0f;
  1411. }
  1412. else
  1413. {
  1414. vtmp.X += box.X;
  1415. if (vtmp.X > 0.0)
  1416. vtmp.X = 0.0f;
  1417. }
  1418. if (vtmp.Y > 0)
  1419. {
  1420. vtmp.Y -= box.Y;
  1421. if (vtmp.Y < 0.0)
  1422. vtmp.Y = 0.0f;
  1423. }
  1424. else
  1425. {
  1426. vtmp.Y += box.Y;
  1427. if (vtmp.Y > 0.0)
  1428. vtmp.Y = 0.0f;
  1429. }
  1430. if (vtmp.Z > 0)
  1431. {
  1432. vtmp.Z -= box.Z;
  1433. if (vtmp.Z < 0.0)
  1434. vtmp.Z = 0.0f;
  1435. }
  1436. else
  1437. {
  1438. vtmp.Z += box.Z;
  1439. if (vtmp.Z > 0.0)
  1440. vtmp.Z = 0.0f;
  1441. }
  1442. float distSQ = vtmp.LengthSquared();
  1443. if (ParentID != 0 && distSQ < grpdSQ)
  1444. return grpdSQ;
  1445. else
  1446. return distSQ;
  1447. }
  1448. private uint ApplyMask(uint val, bool set, uint mask)
  1449. {
  1450. if (set)
  1451. {
  1452. return val |= mask;
  1453. }
  1454. else
  1455. {
  1456. return val &= ~mask;
  1457. }
  1458. }
  1459. private void SendObjectPropertiesToClient(UUID AgentID)
  1460. {
  1461. IScenePresence SP = ParentGroup.Scene.GetScenePresence(AgentID);
  1462. if (SP != null)
  1463. m_parentGroup.GetProperties(SP.ControllingClient);
  1464. }
  1465. #endregion Private Methods
  1466. #region Public Methods
  1467. internal bool m_hasSubscribedToCollisionEvent;
  1468. public void FixOffsetPosition(Vector3 value, bool single)
  1469. {
  1470. bool triggerMoving_End = false;
  1471. if (m_offsetPosition != value)
  1472. {
  1473. triggerMoving_End = true;
  1474. TriggerScriptMovingStartEvent();
  1475. }
  1476. StoreUndoState();
  1477. m_offsetPosition = value;
  1478. if (ParentEntity != null)
  1479. ParentEntity.ScheduleGroupTerseUpdate();
  1480. ValidpartOOB = false;
  1481. if (ParentGroup != null && !ParentGroup.IsDeleted)
  1482. {
  1483. ParentGroup.HasGroupChanged = true;
  1484. PhysicsObject actor = PhysActor;
  1485. if (_parentID != 0 && actor != null && (single || !actor.IsPhysical))
  1486. {
  1487. actor.Position = GetWorldPosition();
  1488. actor.Orientation = GetWorldRotation();
  1489. }
  1490. }
  1491. if (triggerMoving_End)
  1492. TriggerScriptMovingEndEvent();
  1493. }
  1494. public bool AddFlag(PrimFlags flag)
  1495. {
  1496. // PrimFlags prevflag = Flags;
  1497. if ((Flags & flag) == 0)
  1498. {
  1499. //MainConsole.Instance.Debug("Adding flag: " + ((PrimFlags) flag).ToString());
  1500. Flags |= flag;
  1501. if (flag == PrimFlags.TemporaryOnRez)
  1502. ResetExpire();
  1503. object[] o = new object[2];
  1504. o[0] = this;
  1505. o[1] = flag;
  1506. m_parentGroup.Scene.AuroraEventManager.FireGenericEventHandler("ObjectAddedFlag", o);
  1507. return true;
  1508. }
  1509. return false;
  1510. // MainConsole.Instance.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
  1511. }
  1512. public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
  1513. {
  1514. ParticleSystem = pSystem.GetBytes();
  1515. }
  1516. public void RemoveParticleSystem()
  1517. {
  1518. ParticleSystem = Utils.EmptyBytes;
  1519. }
  1520. public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
  1521. {
  1522. byte[] data = new byte[16];
  1523. int pos = 0;
  1524. // The flags don't like conversion from uint to byte, so we have to do
  1525. // it the crappy way. See the above function :(
  1526. data[pos] = ConvertScriptUintToByte((uint) pTexAnim.Flags);
  1527. pos++;
  1528. data[pos] = (byte) pTexAnim.Face;
  1529. pos++;
  1530. data[pos] = (byte) pTexAnim.SizeX;
  1531. pos++;
  1532. data[pos] = (byte) pTexAnim.SizeY;
  1533. pos++;
  1534. Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
  1535. Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
  1536. Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
  1537. TextureAnimation = data;
  1538. }
  1539. public void AdjustSoundGain(double volume)
  1540. {
  1541. if (volume > 1)
  1542. volume = 1;
  1543. if (volume < 0)
  1544. volume = 0;
  1545. m_parentGroup.Scene.ForEachScenePresence(delegate(IScenePresence sp)
  1546. {
  1547. if (!sp.IsChildAgent)
  1548. sp.ControllingClient.SendAttachedSoundGainChange(UUID,
  1549. (float
  1550. )
  1551. volume);
  1552. });
  1553. }
  1554. /// <summary>
  1555. /// hook to the physics scene to apply impulse
  1556. /// This is sent up to the group, which then finds the root prim
  1557. /// and applies the force on the root prim of the group
  1558. /// </summary>
  1559. /// <param name="impulsei">Vector force</param>
  1560. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1561. public void ApplyImpulse(Vector3 impulsei, bool localGlobalTF)
  1562. {
  1563. Vector3 impulse = impulsei;
  1564. if (localGlobalTF)
  1565. {
  1566. Quaternion grot = GetWorldRotation();
  1567. Quaternion AXgrot = grot;
  1568. Vector3 AXimpulsei = impulsei;
  1569. Vector3 newimpulse = AXimpulsei*AXgrot;
  1570. impulse = newimpulse;
  1571. }
  1572. if (m_parentGroup != null)
  1573. {
  1574. m_parentGroup.applyImpulse(impulse);
  1575. }
  1576. }
  1577. /// <summary>
  1578. /// hook to the physics scene to apply angular impulse
  1579. /// This is sent up to the group, which then finds the root prim
  1580. /// and applies the force on the root prim of the group
  1581. /// </summary>
  1582. /// <param name="impulsei">Vector force</param>
  1583. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1584. public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF)
  1585. {
  1586. Vector3 impulse = impulsei;
  1587. if (localGlobalTF)
  1588. {
  1589. Quaternion grot = GetWorldRotation();
  1590. Quaternion AXgrot = grot;
  1591. Vector3 AXimpulsei = impulsei;
  1592. Vector3 newimpulse = AXimpulsei*AXgrot;
  1593. impulse = newimpulse;
  1594. }
  1595. if (m_parentGroup != null)
  1596. {
  1597. m_parentGroup.applyAngularImpulse(impulse);
  1598. }
  1599. }
  1600. /// <summary>
  1601. /// hook to the physics scene to apply angular impulse
  1602. /// This is sent up to the group, which then finds the root prim
  1603. /// and applies the force on the root prim of the group
  1604. /// </summary>
  1605. /// <param name="impulsei">Vector force</param>
  1606. /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
  1607. public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF)
  1608. {
  1609. Vector3 impulse = impulsei;
  1610. if (localGlobalTF)
  1611. {
  1612. Quaternion grot = GetWorldRotation();
  1613. Quaternion AXgrot = grot;
  1614. Vector3 AXimpulsei = impulsei;
  1615. Vector3 newimpulse = AXimpulsei*AXgrot;
  1616. impulse = newimpulse;
  1617. }
  1618. if (m_parentGroup != null)
  1619. {
  1620. m_parentGroup.setAngularImpulse(impulse);
  1621. }
  1622. }
  1623. public bool GetDieAtEdge()
  1624. {
  1625. if (m_parentGroup == null)
  1626. return false;
  1627. if (m_parentGroup.IsDeleted)
  1628. return false;
  1629. return m_parentGroup.RootPart.DIE_AT_EDGE;
  1630. }
  1631. public bool GetReturnAtEdge()
  1632. {
  1633. if (m_parentGroup == null)
  1634. return false;
  1635. if (m_parentGroup.IsDeleted)
  1636. return false;
  1637. return m_parentGroup.RootPart.RETURN_AT_EDGE;
  1638. }
  1639. public void SetReturnAtEdge(bool p)
  1640. {
  1641. if (m_parentGroup == null)
  1642. return;
  1643. if (m_parentGroup.IsDeleted)
  1644. return;
  1645. m_parentGroup.RootPart.RETURN_AT_EDGE = p;
  1646. }
  1647. public bool GetBlockGrab(bool wholeObjectBlock)
  1648. {
  1649. if (m_parentGroup == null)
  1650. return false;
  1651. if (m_parentGroup.IsDeleted)
  1652. return false;
  1653. if (wholeObjectBlock)
  1654. return m_parentGroup.RootPart.BlockGrabObject;
  1655. else
  1656. return m_parentGroup.RootPart.BlockGrab;
  1657. }
  1658. public void SetBlockGrab(bool block, bool wholeObjectBlock)
  1659. {
  1660. if (m_parentGroup == null)
  1661. return;
  1662. if (m_parentGroup.IsDeleted)
  1663. return;
  1664. if (wholeObjectBlock)
  1665. m_parentGroup.RootPart.BlockGrabObject = block;
  1666. else
  1667. m_parentGroup.RootPart.BlockGrab = block;
  1668. }
  1669. public void SetStatusSandbox(bool p)
  1670. {
  1671. if (m_parentGroup == null)
  1672. return;
  1673. if (m_parentGroup.IsDeleted)
  1674. return;
  1675. StatusSandboxPos = m_parentGroup.RootPart.AbsolutePosition;
  1676. m_parentGroup.RootPart.StatusSandbox = p;
  1677. }
  1678. public bool GetStatusSandbox()
  1679. {
  1680. if (m_parentGroup == null)
  1681. return false;
  1682. if (m_parentGroup.IsDeleted)
  1683. return false;
  1684. return m_parentGroup.RootPart.StatusSandbox;
  1685. }
  1686. public int GetAxisRotation(int axis)
  1687. {
  1688. //Cannot use ScriptBaseClass constants as no referance to it currently.
  1689. if (axis == 2) //STATUS_ROTATE_X
  1690. return STATUS_ROTATE_X;
  1691. if (axis == 4) //STATUS_ROTATE_Y
  1692. return STATUS_ROTATE_Y;
  1693. if (axis == 8) //STATUS_ROTATE_Z
  1694. return STATUS_ROTATE_Z;
  1695. return 0;
  1696. }
  1697. public uint GetEffectiveObjectFlags()
  1698. {
  1699. // Commenting this section of code out since it doesn't actually do anything, as enums are handled by
  1700. // value rather than reference
  1701. // PrimFlags f = _flags;
  1702. // if (m_parentGroup == null || m_parentGroup.RootPart == this)
  1703. // f &= ~(PrimFlags.Touch | PrimFlags.Money);
  1704. return (uint) Flags | (uint) LocalFlags;
  1705. }
  1706. public Vector3 GetGeometricCenter()
  1707. {
  1708. if (PhysActor != null)
  1709. {
  1710. return new Vector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z);
  1711. }
  1712. else
  1713. {
  1714. return new Vector3(0, 0, 0);
  1715. }
  1716. }
  1717. public float GetMass()
  1718. {
  1719. if (ParentGroup.RootPart.UUID == UUID)
  1720. {
  1721. if (PhysActor != null)
  1722. {
  1723. return PhysActor.Mass;
  1724. }
  1725. else
  1726. {
  1727. return 0;
  1728. }
  1729. }
  1730. else
  1731. {
  1732. return ParentGroup.RootPart.GetMass();
  1733. }
  1734. }
  1735. public Vector3 GetForce()
  1736. {
  1737. if (PhysActor != null)
  1738. return PhysActor.Force;
  1739. else
  1740. return Vector3.Zero;
  1741. }
  1742. public void GetProperties(IClientAPI client)
  1743. {
  1744. IScenePresence sp;
  1745. if (ParentGroup != null && ParentGroup.Scene != null &&
  1746. (sp = ParentGroup.Scene.GetScenePresence(client.AgentId)) != null)
  1747. sp.SceneViewer.QueuePartsForPropertiesUpdate(new ISceneChildEntity[1] {this});
  1748. }
  1749. /// <summary>
  1750. /// Method for a prim to get it's world position from the group.
  1751. /// Remember, the Group Position simply gives the position of the group itself
  1752. /// </summary>
  1753. /// <returns>A Linked Child Prim objects position in world</returns>
  1754. public Vector3 GetWorldPosition()
  1755. {
  1756. return IsRoot ? GroupPosition : GroupPosition + OffsetPosition*ParentGroup.RootPart.GetRotationOffset();
  1757. }
  1758. /// <summary>
  1759. /// Gets the rotation of this prim offset by the group rotation
  1760. /// </summary>
  1761. /// <returns></returns>
  1762. public Quaternion GetWorldRotation()
  1763. {
  1764. Quaternion newRot = GetRotationOffset();
  1765. if (_parentID != 0)
  1766. {
  1767. Quaternion parentRot = ParentGroup.RootPart.GetRotationOffset();
  1768. newRot = parentRot*newRot;
  1769. }
  1770. return newRot;
  1771. }
  1772. public void MoveToTarget(Vector3 target, float tau)
  1773. {
  1774. if (tau > 0)
  1775. {
  1776. m_parentGroup.moveToTarget(target, tau);
  1777. }
  1778. else
  1779. {
  1780. StopMoveToTarget();
  1781. }
  1782. }
  1783. /// <summary>
  1784. /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
  1785. /// </summary>
  1786. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  1787. /// <param name="hoverType">Determines what the height is relative to </param>
  1788. /// <param name="tau">Number of seconds over which to reach target</param>
  1789. public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
  1790. {
  1791. m_parentGroup.SetHoverHeight(height, hoverType, tau);
  1792. }
  1793. public void PreloadSound(string sound)
  1794. {
  1795. // UUID ownerID = OwnerID;
  1796. UUID objectID = ParentGroup.RootPart.UUID;
  1797. UUID soundID = UUID.Zero;
  1798. if (!UUID.TryParse(sound, out soundID))
  1799. {
  1800. //Trys to fetch sound id from prim's inventory.
  1801. //Prim's inventory doesn't support non script items yet
  1802. lock (TaskInventory)
  1803. {
  1804. #if (!ISWIN)
  1805. foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
  1806. {
  1807. if (item.Value.Name == sound)
  1808. {
  1809. soundID = item.Value.ItemID;
  1810. break;
  1811. }
  1812. }
  1813. #else
  1814. foreach (
  1815. KeyValuePair<UUID, TaskInventoryItem> item in
  1816. TaskInventory.Where(item => item.Value.Name == sound))
  1817. {
  1818. soundID = item.Value.ItemID;
  1819. break;
  1820. }
  1821. #endif
  1822. }
  1823. }
  1824. m_parentGroup.Scene.ForEachScenePresence(delegate(IScenePresence sp)
  1825. {
  1826. if (sp.IsChildAgent)
  1827. return;
  1828. if (
  1829. !(Util.GetDistanceTo(sp.AbsolutePosition,
  1830. AbsolutePosition) >= 100))
  1831. sp.ControllingClient.SendPreLoadSound(objectID,
  1832. objectID, soundID);
  1833. });
  1834. }
  1835. public bool RemFlag(PrimFlags flag)
  1836. {
  1837. // PrimFlags prevflag = Flags;
  1838. if ((Flags & flag) != 0)
  1839. {
  1840. //MainConsole.Instance.Debug("Removing flag: " + ((PrimFlags)flag).ToString());
  1841. Flags &= ~flag;
  1842. object[] o = new object[2];
  1843. o[0] = this;
  1844. o[1] = flag;
  1845. m_parentGroup.Scene.AuroraEventManager.FireGenericEventHandler("ObjectRemovedFlag", o);
  1846. return true;
  1847. }
  1848. return false;
  1849. //MainConsole.Instance.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
  1850. //ScheduleFullUpdate();
  1851. }
  1852. public void ResetEntityIDs()
  1853. {
  1854. UUID = UUID.Random();
  1855. //LinkNum = linkNum;
  1856. Inventory.ResetInventoryIDs(false);
  1857. LocalId = ParentGroup.Scene.SceneGraph.AllocateLocalId();
  1858. //Fix the localID now for the physics engine
  1859. if (m_physActor != null)
  1860. {
  1861. m_physActor.LocalID = LocalId;
  1862. PhysActor.UUID = UUID;
  1863. }
  1864. //Fix the rezzed attribute
  1865. Rezzed = DateTime.UtcNow;
  1866. }
  1867. public void RotLookAt(Quaternion target, float strength, float damping)
  1868. {
  1869. if (IsAttachment)
  1870. {
  1871. /*
  1872. ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
  1873. if (avatar != null)
  1874. {
  1875. Rotate the Av?
  1876. } */
  1877. }
  1878. else
  1879. {
  1880. APIDEnabled = true;
  1881. APIDDamp = damping;
  1882. APIDStrength = strength;
  1883. APIDTarget = target;
  1884. }
  1885. }
  1886. public void startLookAt(Quaternion rot, float damp, float strength)
  1887. {
  1888. APIDEnabled = true;
  1889. APIDDamp = damp;
  1890. APIDStrength = strength;
  1891. APIDTarget = rot;
  1892. APIDIterations = 1 + (int) (Math.PI*APIDStrength);
  1893. }
  1894. /// <summary>
  1895. /// Schedule a terse update for this prim. Terse updates only send position,
  1896. /// rotation, velocity, and rotational velocity information.
  1897. /// </summary>
  1898. public void ScheduleTerseUpdate()
  1899. {
  1900. ScheduleUpdate(PrimUpdateFlags.TerseUpdate);
  1901. }
  1902. /// <summary>
  1903. /// Tell all avatars in the Scene about the new update
  1904. /// </summary>
  1905. /// <param name="UpdateFlags"></param>
  1906. public void ScheduleUpdate(PrimUpdateFlags UpdateFlags)
  1907. {
  1908. if (m_parentGroup != null && m_parentGroup.Scene != null)
  1909. m_parentGroup.Scene.ForEachScenePresence(avatar => avatar.AddUpdateToAvatar(this, UpdateFlags));
  1910. }
  1911. public void ScriptSetPhantomStatus(bool Phantom)
  1912. {
  1913. if (m_parentGroup != null)
  1914. {
  1915. m_parentGroup.ScriptSetPhantomStatus(Phantom);
  1916. }
  1917. }
  1918. public void ScriptSetTemporaryStatus(bool Temporary)
  1919. {
  1920. if (m_parentGroup != null)
  1921. {
  1922. m_parentGroup.ScriptSetTemporaryStatus(Temporary);
  1923. }
  1924. }
  1925. public void ScriptSetVolumeDetect(bool SetVD)
  1926. {
  1927. if (m_parentGroup != null)
  1928. {
  1929. m_parentGroup.ScriptSetVolumeDetect(SetVD);
  1930. }
  1931. }
  1932. /// <summary>
  1933. /// Trigger or play an attached sound in this part's inventory.
  1934. /// </summary>
  1935. /// <param name="sound"></param>
  1936. /// <param name="volume"></param>
  1937. /// <param name="triggered"></param>
  1938. /// <param name="flags"></param>
  1939. /// <param name="radius"></param>
  1940. /// <param name="useMaster"></param>
  1941. /// <param name="isMaster"></param>
  1942. public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster,
  1943. bool isMaster)
  1944. {
  1945. if (volume > 1)
  1946. volume = 1;
  1947. if (volume < 0)
  1948. volume = 0;
  1949. UUID ownerID = _ownerID;
  1950. UUID objectID = ParentGroup.RootPart.UUID;
  1951. UUID parentID = GetRootPartUUID();
  1952. UUID soundID = UUID.Zero;
  1953. Vector3 position = AbsolutePosition; // region local
  1954. ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle;
  1955. if (!UUID.TryParse(sound, out soundID))
  1956. {
  1957. // search sound file from inventory
  1958. lock (TaskInventory)
  1959. {
  1960. #if (!ISWIN)
  1961. foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
  1962. {
  1963. if (item.Value.Name == sound && item.Value.Type == (int) AssetType.Sound)
  1964. {
  1965. soundID = item.Value.ItemID;
  1966. break;
  1967. }
  1968. }
  1969. #else
  1970. foreach (
  1971. KeyValuePair<UUID, TaskInventoryItem> item in
  1972. TaskInventory.Where(
  1973. item => item.Value.Name == sound && item.Value.Type == (int) AssetType.Sound))
  1974. {
  1975. soundID = item.Value.ItemID;
  1976. break;
  1977. }
  1978. #endif
  1979. }
  1980. }
  1981. if (soundID == UUID.Zero)
  1982. return;
  1983. ISoundModule soundModule = m_parentGroup.Scene.RequestModuleInterface<ISoundModule>();
  1984. if (soundModule != null)
  1985. {
  1986. if (useMaster)
  1987. {
  1988. if (isMaster)
  1989. {
  1990. if (triggered)
  1991. soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position,
  1992. regionHandle, radius);
  1993. else
  1994. soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
  1995. ParentGroup.PlaySoundMasterPrim = this;
  1996. ownerID = _ownerID;
  1997. objectID = ParentGroup.RootPart.UUID;
  1998. parentID = GetRootPartUUID();
  1999. position = AbsolutePosition; // region local
  2000. regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
  2001. if (triggered)
  2002. soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position,
  2003. regionHandle, radius);
  2004. else
  2005. soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
  2006. foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
  2007. {
  2008. ownerID = prim._ownerID;
  2009. objectID = prim.ParentGroup.RootPart.UUID;
  2010. parentID = prim.GetRootPartUUID();
  2011. position = prim.AbsolutePosition; // region local
  2012. regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
  2013. if (triggered)
  2014. soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position,
  2015. regionHandle, radius);
  2016. else
  2017. soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags,
  2018. radius);
  2019. }
  2020. ParentGroup.PlaySoundSlavePrims.Clear();
  2021. ParentGroup.PlaySoundMasterPrim = null;
  2022. }
  2023. else
  2024. {
  2025. ParentGroup.PlaySoundSlavePrims.Add(this);
  2026. }
  2027. }
  2028. else
  2029. {
  2030. if (triggered)
  2031. soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle,
  2032. radius);
  2033. else
  2034. soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
  2035. }
  2036. }
  2037. }
  2038. public void SetAvatarOnSitTarget(UUID avatarID)
  2039. {
  2040. lock (SitTargetAvatar)
  2041. {
  2042. if (!SitTargetAvatar.Contains(avatarID))
  2043. SitTargetAvatar.Add(avatarID);
  2044. }
  2045. TriggerScriptChangedEvent(Changed.LINK);
  2046. }
  2047. public void RemoveAvatarOnSitTarget(UUID avatarID)
  2048. {
  2049. lock (SitTargetAvatar)
  2050. {
  2051. if (SitTargetAvatar.Contains(avatarID))
  2052. SitTargetAvatar.Remove(avatarID);
  2053. }
  2054. TriggerScriptChangedEvent(Changed.LINK);
  2055. }
  2056. public void SetAxisRotation(int axis, int rotate)
  2057. {
  2058. if (m_parentGroup != null)
  2059. {
  2060. m_parentGroup.SetAxisRotation(axis, rotate);
  2061. }
  2062. //Cannot use ScriptBaseClass constants as no referance to it currently.
  2063. if ((axis & 2) == 2) //STATUS_ROTATE_X
  2064. STATUS_ROTATE_X = rotate;
  2065. if ((axis & 4) == 4) //STATUS_ROTATE_Y
  2066. STATUS_ROTATE_Y = rotate;
  2067. if ((axis & 8) == 8) //STATUS_ROTATE_Z
  2068. STATUS_ROTATE_Z = rotate;
  2069. }
  2070. public void SetBuoyancy(float fvalue)
  2071. {
  2072. if (PhysActor != null)
  2073. {
  2074. PhysActor.Buoyancy = fvalue;
  2075. }
  2076. }
  2077. public void SetDieAtEdge(bool p)
  2078. {
  2079. if (m_parentGroup == null)
  2080. return;
  2081. if (m_parentGroup.IsDeleted)
  2082. return;
  2083. m_parentGroup.RootPart.DIE_AT_EDGE = p;
  2084. }
  2085. public void SetFloatOnWater(int floatYN)
  2086. {
  2087. if (PhysActor != null)
  2088. {
  2089. PhysActor.FloatOnWater = floatYN == 1;
  2090. }
  2091. }
  2092. public void SetForce(Vector3 force)
  2093. {
  2094. if (PhysActor != null)
  2095. {
  2096. PhysActor.Force = force;
  2097. }
  2098. }
  2099. public void SetVehicleFlags(int param, bool remove)
  2100. {
  2101. if (remove)
  2102. VehicleFlags.Remove(param);
  2103. else
  2104. VehicleFlags.Add(param);
  2105. if (PhysActor != null)
  2106. PhysActor.VehicleFlags(param, remove);
  2107. }
  2108. public void SetVehicleType(int type)
  2109. {
  2110. VehicleType = type;
  2111. if (PhysActor != null)
  2112. PhysActor.VehicleType = type;
  2113. }
  2114. public void SetVehicleFloatParam(int param, float value)
  2115. {
  2116. VehicleParameters[param.ToString()] = value;
  2117. if (PhysActor != null)
  2118. PhysActor.VehicleFloatParam(param, value);
  2119. }
  2120. public void SetVehicleVectorParam(int param, Vector3 value)
  2121. {
  2122. VehicleParameters[param.ToString()] = value;
  2123. if (PhysActor != null)
  2124. PhysActor.VehicleVectorParam(param, value);
  2125. }
  2126. public void SetVehicleRotationParam(int param, Quaternion value)
  2127. {
  2128. VehicleParameters[param.ToString()] = value;
  2129. if (PhysActor != null)
  2130. PhysActor.VehicleRotationParam(param, value);
  2131. }
  2132. /// <summary>
  2133. /// Set the color of prim faces
  2134. /// </summary>
  2135. /// <param name="color"></param>
  2136. /// <param name="face"></param>
  2137. public void SetFaceColor(Vector3 color, int face)
  2138. {
  2139. Primitive.TextureEntry tex = Shape.Textures;
  2140. Color4 texcolor;
  2141. if (face >= 0 && face < GetNumberOfSides())
  2142. {
  2143. texcolor = tex.CreateFace((uint) face).RGBA;
  2144. texcolor.R = Util.Clip(color.X, 0.0f, 1.0f);
  2145. texcolor.G = Util.Clip(color.Y, 0.0f, 1.0f);
  2146. texcolor.B = Util.Clip(color.Z, 0.0f, 1.0f);
  2147. if (!(tex.FaceTextures[face].RGBA.R == texcolor.R &&
  2148. tex.FaceTextures[face].RGBA.G == texcolor.G &&
  2149. tex.FaceTextures[face].RGBA.B == texcolor.B))
  2150. {
  2151. tex.FaceTextures[face].RGBA = texcolor;
  2152. UpdateTexture(tex, true);
  2153. }
  2154. }
  2155. else if (face == ALL_SIDES)
  2156. {
  2157. bool changed = false;
  2158. for (uint i = 0; i < GetNumberOfSides(); i++)
  2159. {
  2160. if (tex.FaceTextures[i] != null)
  2161. {
  2162. texcolor = tex.FaceTextures[i].RGBA;
  2163. texcolor.R = Util.Clip(color.X, 0.0f, 1.0f);
  2164. texcolor.G = Util.Clip(color.Y, 0.0f, 1.0f);
  2165. texcolor.B = Util.Clip(color.Z, 0.0f, 1.0f);
  2166. if (!(tex.FaceTextures[i].RGBA.R == texcolor.R &&
  2167. tex.FaceTextures[i].RGBA.G == texcolor.G &&
  2168. tex.FaceTextures[i].RGBA.B == texcolor.B))
  2169. changed = true;
  2170. tex.FaceTextures[i].RGBA = texcolor;
  2171. }
  2172. texcolor = tex.DefaultTexture.RGBA;
  2173. texcolor.R = Util.Clip(color.X, 0.0f, 1.0f);
  2174. texcolor.G = Util.Clip(color.Y, 0.0f, 1.0f);
  2175. texcolor.B = Util.Clip(color.Z, 0.0f, 1.0f);
  2176. if (!(tex.DefaultTexture.RGBA.R == texcolor.R &&
  2177. tex.DefaultTexture.RGBA.G == texcolor.G &&
  2178. tex.DefaultTexture.RGBA.B == texcolor.B))
  2179. changed = true;
  2180. tex.DefaultTexture.RGBA = texcolor;
  2181. }
  2182. if (changed)
  2183. UpdateTexture(tex, true);
  2184. }
  2185. }
  2186. /// <summary>
  2187. /// Get the number of sides that this part has.
  2188. /// </summary>
  2189. /// <returns></returns>
  2190. public int GetNumberOfSides()
  2191. {
  2192. int ret = 0;
  2193. bool hasCut;
  2194. bool hasHollow;
  2195. bool hasDimple;
  2196. bool hasProfileCut;
  2197. PrimType primType = GetPrimType();
  2198. HasCutHollowDimpleProfileCut(primType, Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
  2199. switch (primType)
  2200. {
  2201. case PrimType.BOX:
  2202. ret = 6;
  2203. if (hasCut) ret += 2;
  2204. if (hasHollow) ret += 1;
  2205. break;
  2206. case PrimType.CYLINDER:
  2207. ret = 3;
  2208. if (hasCut) ret += 2;
  2209. if (hasHollow) ret += 1;
  2210. break;
  2211. case PrimType.PRISM:
  2212. ret = 5;
  2213. if (hasCut) ret += 2;
  2214. if (hasHollow) ret += 1;
  2215. break;
  2216. case PrimType.SPHERE:
  2217. ret = 1;
  2218. if (hasCut) ret += 2;
  2219. if (hasDimple) ret += 2;
  2220. if (hasHollow) ret += 1;
  2221. break;
  2222. case PrimType.TORUS:
  2223. ret = 1;
  2224. if (hasCut) ret += 2;
  2225. if (hasProfileCut) ret += 2;
  2226. if (hasHollow) ret += 1;
  2227. break;
  2228. case PrimType.TUBE:
  2229. ret = 4;
  2230. if (hasCut) ret += 2;
  2231. if (hasProfileCut) ret += 2;
  2232. if (hasHollow) ret += 1;
  2233. break;
  2234. case PrimType.RING:
  2235. ret = 3;
  2236. if (hasCut) ret += 2;
  2237. if (hasProfileCut) ret += 2;
  2238. if (hasHollow) ret += 1;
  2239. break;
  2240. case PrimType.SCULPT:
  2241. // Special mesh handling
  2242. if (this.Shape.SculptType == 5)
  2243. {
  2244. ret = 8; // its a mesh then max 8 faces
  2245. }
  2246. else
  2247. {
  2248. ret = 1; // its a sculpt then max 1 faces
  2249. }
  2250. break;
  2251. }
  2252. return ret;
  2253. }
  2254. /// <summary>
  2255. /// Tell us what type this prim is
  2256. /// </summary>
  2257. /// <returns></returns>
  2258. public PrimType GetPrimType()
  2259. {
  2260. if (Shape.SculptEntry)
  2261. return PrimType.SCULPT;
  2262. if ((Shape.ProfileCurve & 0x07) == (byte) ProfileShape.Square)
  2263. {
  2264. if (Shape.PathCurve == (byte) Extrusion.Straight)
  2265. return PrimType.BOX;
  2266. else if (Shape.PathCurve == (byte) Extrusion.Curve1)
  2267. return PrimType.TUBE;
  2268. }
  2269. else if ((Shape.ProfileCurve & 0x07) == (byte) ProfileShape.Circle)
  2270. {
  2271. if (Shape.PathCurve == (byte) Extrusion.Straight)
  2272. return PrimType.CYLINDER;
  2273. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  2274. else if (Shape.PathCurve == (byte) Extrusion.Curve1)
  2275. return PrimType.TORUS;
  2276. }
  2277. else if ((Shape.ProfileCurve & 0x07) == (byte) ProfileShape.HalfCircle)
  2278. {
  2279. if (Shape.PathCurve == (byte) Extrusion.Curve1 || Shape.PathCurve == (byte) Extrusion.Curve2)
  2280. return PrimType.SPHERE;
  2281. }
  2282. else if ((Shape.ProfileCurve & 0x07) == (byte) ProfileShape.EquilateralTriangle)
  2283. {
  2284. if (Shape.PathCurve == (byte) Extrusion.Straight)
  2285. return PrimType.PRISM;
  2286. else if (Shape.PathCurve == (byte) Extrusion.Curve1)
  2287. return PrimType.RING;
  2288. }
  2289. return PrimType.BOX;
  2290. }
  2291. /// <summary>
  2292. /// </summary>
  2293. public void SetParent(ISceneEntity parent)
  2294. {
  2295. m_parentGroup = (SceneObjectGroup) parent;
  2296. }
  2297. // Use this for attachments! LocalID should be avatar's localid
  2298. public void SetParentLocalId(uint localID)
  2299. {
  2300. _parentID = localID;
  2301. }
  2302. /// <summary>
  2303. /// Set the events that this part will pass on to listeners.
  2304. /// </summary>
  2305. /// <param name="scriptid"></param>
  2306. /// <param name="events"></param>
  2307. public void SetScriptEvents(UUID scriptid, long events)
  2308. {
  2309. // scriptEvents oldparts;
  2310. lock (m_scriptEvents)
  2311. {
  2312. if (m_scriptEvents.ContainsKey(scriptid))
  2313. {
  2314. // oldparts = m_scriptEvents[scriptid];
  2315. // remove values from aggregated script events
  2316. //if (m_scriptEvents[scriptid] == (scriptEvents) events)
  2317. // return;
  2318. m_scriptEvents[scriptid] = (scriptEvents) events;
  2319. }
  2320. else
  2321. {
  2322. m_scriptEvents.Add(scriptid, (scriptEvents) events);
  2323. }
  2324. }
  2325. aggregateScriptEvents();
  2326. }
  2327. public void StopLookAt()
  2328. {
  2329. m_parentGroup.RootPart.stopLookAt();
  2330. m_parentGroup.ScheduleGroupTerseUpdate();
  2331. }
  2332. /// <summary>
  2333. /// Set the text displayed for this part.
  2334. /// </summary>
  2335. /// <param name="text"></param>
  2336. /// <param name="color"></param>
  2337. /// <param name="alpha"></param>
  2338. public void SetText(string text, Vector3 color, double alpha)
  2339. {
  2340. //No triggering Changed_Color, so not using Color
  2341. //Color = ...
  2342. UpdateColor(Color.FromArgb((int) (alpha*0xff),
  2343. (int) (color.X*0xff),
  2344. (int) (color.Y*0xff),
  2345. (int) (color.Z*0xff)), false);
  2346. Text = text;
  2347. ScheduleUpdate(PrimUpdateFlags.Text);
  2348. }
  2349. public void StopMoveToTarget()
  2350. {
  2351. m_parentGroup.stopMoveToTarget();
  2352. m_parentGroup.ScheduleGroupTerseUpdate();
  2353. //m_parentGroup.ScheduleGroupForFullUpdate();
  2354. }
  2355. public void StoreUndoState()
  2356. {
  2357. if (!Undoing)
  2358. {
  2359. if (!IgnoreUndoUpdate)
  2360. {
  2361. IBackupModule backup = null;
  2362. if (ParentGroup != null &&
  2363. ParentGroup.Scene != null)
  2364. backup = ParentGroup.Scene.RequestModuleInterface<IBackupModule>();
  2365. if (m_parentGroup != null &&
  2366. ParentGroup.Scene != null &&
  2367. (backup == null || (backup != null && !backup.LoadingPrims)))
  2368. {
  2369. lock (m_undo)
  2370. {
  2371. if (m_undo.Count > 0)
  2372. {
  2373. UndoState last = m_undo.Peek();
  2374. if (last != null)
  2375. {
  2376. if (last.Compare(this))
  2377. return;
  2378. }
  2379. }
  2380. UndoState nUndo = new UndoState(this);
  2381. m_undo.Push(nUndo);
  2382. }
  2383. }
  2384. }
  2385. }
  2386. }
  2387. public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly,
  2388. bool faceCenters)
  2389. {
  2390. // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes
  2391. // This breaks down into the ray---> plane equation.
  2392. // TODO: Change to take shape into account
  2393. Vector3[] vertexes = new Vector3[8];
  2394. // float[] distance = new float[6];
  2395. Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
  2396. Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
  2397. Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
  2398. Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
  2399. Vector3[] normals = new Vector3[6]; // Normal for Facei
  2400. Vector3[] AAfacenormals = new Vector3[6]; // Axis Aligned face normals
  2401. AAfacenormals[0] = new Vector3(1, 0, 0);
  2402. AAfacenormals[1] = new Vector3(0, 1, 0);
  2403. AAfacenormals[2] = new Vector3(-1, 0, 0);
  2404. AAfacenormals[3] = new Vector3(0, -1, 0);
  2405. AAfacenormals[4] = new Vector3(0, 0, 1);
  2406. AAfacenormals[5] = new Vector3(0, 0, -1);
  2407. Vector3 AmBa = new Vector3(0, 0, 0); // Vertex A - Vertex B
  2408. Vector3 AmBb = new Vector3(0, 0, 0); // Vertex B - Vertex C
  2409. Vector3 cross = new Vector3();
  2410. Vector3 pos = GetWorldPosition();
  2411. Quaternion rot = GetWorldRotation();
  2412. // Variables prefixed with AX are Axiom.Math copies of the LL variety.
  2413. Quaternion AXrot = rot;
  2414. AXrot.Normalize();
  2415. Vector3 AXpos = pos;
  2416. // tScale is the offset to derive the vertex based on the scale.
  2417. // it's different for each vertex because we've got to rotate it
  2418. // to get the world position of the vertex to produce the Oriented Bounding Box
  2419. Vector3 tScale = Vector3.Zero;
  2420. Vector3 AXscale = new Vector3(m_shape.Scale.X*0.5f, m_shape.Scale.Y*0.5f, m_shape.Scale.Z*0.5f);
  2421. //Vector3 pScale = (AXscale) - (AXrot.Inverse() * (AXscale));
  2422. //Vector3 nScale = (AXscale * -1) - (AXrot.Inverse() * (AXscale * -1));
  2423. // rScale is the rotated offset to find a vertex based on the scale and the world rotation.
  2424. Vector3 rScale = new Vector3();
  2425. // Get Vertexes for Faces Stick them into ABCD for each Face
  2426. // Form: Face<vertex>[face] that corresponds to the below diagram
  2427. #region ABCD Face Vertex Map Comment Diagram
  2428. // A _________ B
  2429. // | |
  2430. // | 4 top |
  2431. // |_________|
  2432. // C D
  2433. // A _________ B
  2434. // | Back |
  2435. // | 3 |
  2436. // |_________|
  2437. // C D
  2438. // A _________ B B _________ A
  2439. // | Left | | Right |
  2440. // | 0 | | 2 |
  2441. // |_________| |_________|
  2442. // C D D C
  2443. // A _________ B
  2444. // | Front |
  2445. // | 1 |
  2446. // |_________|
  2447. // C D
  2448. // C _________ D
  2449. // | |
  2450. // | 5 bot |
  2451. // |_________|
  2452. // A B
  2453. #endregion
  2454. #region Plane Decomposition of Oriented Bounding Box
  2455. tScale = new Vector3(AXscale.X, -AXscale.Y, AXscale.Z);
  2456. rScale = tScale*AXrot;
  2457. vertexes[0] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2458. // vertexes[0].X = pos.X + vertexes[0].X;
  2459. //vertexes[0].Y = pos.Y + vertexes[0].Y;
  2460. //vertexes[0].Z = pos.Z + vertexes[0].Z;
  2461. FaceA[0] = vertexes[0];
  2462. FaceB[3] = vertexes[0];
  2463. FaceA[4] = vertexes[0];
  2464. tScale = AXscale;
  2465. rScale = tScale*AXrot;
  2466. vertexes[1] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2467. // vertexes[1].X = pos.X + vertexes[1].X;
  2468. // vertexes[1].Y = pos.Y + vertexes[1].Y;
  2469. //vertexes[1].Z = pos.Z + vertexes[1].Z;
  2470. FaceB[0] = vertexes[1];
  2471. FaceA[1] = vertexes[1];
  2472. FaceC[4] = vertexes[1];
  2473. tScale = new Vector3(AXscale.X, -AXscale.Y, -AXscale.Z);
  2474. rScale = tScale*AXrot;
  2475. vertexes[2] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2476. //vertexes[2].X = pos.X + vertexes[2].X;
  2477. //vertexes[2].Y = pos.Y + vertexes[2].Y;
  2478. //vertexes[2].Z = pos.Z + vertexes[2].Z;
  2479. FaceC[0] = vertexes[2];
  2480. FaceD[3] = vertexes[2];
  2481. FaceC[5] = vertexes[2];
  2482. tScale = new Vector3(AXscale.X, AXscale.Y, -AXscale.Z);
  2483. rScale = tScale*AXrot;
  2484. vertexes[3] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2485. //vertexes[3].X = pos.X + vertexes[3].X;
  2486. // vertexes[3].Y = pos.Y + vertexes[3].Y;
  2487. // vertexes[3].Z = pos.Z + vertexes[3].Z;
  2488. FaceD[0] = vertexes[3];
  2489. FaceC[1] = vertexes[3];
  2490. FaceA[5] = vertexes[3];
  2491. tScale = new Vector3(-AXscale.X, AXscale.Y, AXscale.Z);
  2492. rScale = tScale*AXrot;
  2493. vertexes[4] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2494. // vertexes[4].X = pos.X + vertexes[4].X;
  2495. // vertexes[4].Y = pos.Y + vertexes[4].Y;
  2496. // vertexes[4].Z = pos.Z + vertexes[4].Z;
  2497. FaceB[1] = vertexes[4];
  2498. FaceA[2] = vertexes[4];
  2499. FaceD[4] = vertexes[4];
  2500. tScale = new Vector3(-AXscale.X, AXscale.Y, -AXscale.Z);
  2501. rScale = tScale*AXrot;
  2502. vertexes[5] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2503. // vertexes[5].X = pos.X + vertexes[5].X;
  2504. // vertexes[5].Y = pos.Y + vertexes[5].Y;
  2505. // vertexes[5].Z = pos.Z + vertexes[5].Z;
  2506. FaceD[1] = vertexes[5];
  2507. FaceC[2] = vertexes[5];
  2508. FaceB[5] = vertexes[5];
  2509. tScale = new Vector3(-AXscale.X, -AXscale.Y, AXscale.Z);
  2510. rScale = tScale*AXrot;
  2511. vertexes[6] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2512. // vertexes[6].X = pos.X + vertexes[6].X;
  2513. // vertexes[6].Y = pos.Y + vertexes[6].Y;
  2514. // vertexes[6].Z = pos.Z + vertexes[6].Z;
  2515. FaceB[2] = vertexes[6];
  2516. FaceA[3] = vertexes[6];
  2517. FaceB[4] = vertexes[6];
  2518. tScale = new Vector3(-AXscale.X, -AXscale.Y, -AXscale.Z);
  2519. rScale = tScale*AXrot;
  2520. vertexes[7] = (new Vector3((pos.X + rScale.X), (pos.Y + rScale.Y), (pos.Z + rScale.Z)));
  2521. // vertexes[7].X = pos.X + vertexes[7].X;
  2522. // vertexes[7].Y = pos.Y + vertexes[7].Y;
  2523. // vertexes[7].Z = pos.Z + vertexes[7].Z;
  2524. FaceD[2] = vertexes[7];
  2525. FaceC[3] = vertexes[7];
  2526. FaceD[5] = vertexes[7];
  2527. #endregion
  2528. // Get our plane normals
  2529. for (int i = 0; i < 6; i++)
  2530. {
  2531. //MainConsole.Instance.Info("[FACECALCULATION]: FaceA[" + i + "]=" + FaceA[i] + " FaceB[" + i + "]=" + FaceB[i] + " FaceC[" + i + "]=" + FaceC[i] + " FaceD[" + i + "]=" + FaceD[i]);
  2532. // Our Plane direction
  2533. AmBa = FaceA[i] - FaceB[i];
  2534. AmBb = FaceB[i] - FaceC[i];
  2535. cross = Vector3.Cross(AmBb, AmBa);
  2536. // normalize the cross product to get the normal.
  2537. normals[i] = cross/cross.Length();
  2538. //MainConsole.Instance.Info("[NORMALS]: normals[ " + i + "]" + normals[i].ToString());
  2539. //distance[i] = (normals[i].X * AmBa.X + normals[i].Y * AmBa.Y + normals[i].Z * AmBa.Z) * -1;
  2540. }
  2541. EntityIntersection result = new EntityIntersection {distance = 1024};
  2542. float c = 0;
  2543. float a = 0;
  2544. float d = 0;
  2545. Vector3 q = new Vector3();
  2546. #region OBB Version 2 Experiment
  2547. //float fmin = 999999;
  2548. //float fmax = -999999;
  2549. //float s = 0;
  2550. //for (int i=0;i<6;i++)
  2551. //{
  2552. //s = iray.Direction.Dot(normals[i]);
  2553. //d = normals[i].Dot(FaceB[i]);
  2554. //if (s == 0)
  2555. //{
  2556. //if (iray.Origin.Dot(normals[i]) > d)
  2557. //{
  2558. //return result;
  2559. //}
  2560. // else
  2561. //{
  2562. //continue;
  2563. //}
  2564. //}
  2565. //a = (d - iray.Origin.Dot(normals[i])) / s;
  2566. //if (iray.Direction.Dot(normals[i]) < 0)
  2567. //{
  2568. //if (a > fmax)
  2569. //{
  2570. //if (a > fmin)
  2571. //{
  2572. //return result;
  2573. //}
  2574. //fmax = a;
  2575. //}
  2576. //}
  2577. //else
  2578. //{
  2579. //if (a < fmin)
  2580. //{
  2581. //if (a < 0 || a < fmax)
  2582. //{
  2583. //return result;
  2584. //}
  2585. //fmin = a;
  2586. //}
  2587. //}
  2588. //}
  2589. //if (fmax > 0)
  2590. // a= fmax;
  2591. //else
  2592. // a=fmin;
  2593. //q = iray.Origin + a * iray.Direction;
  2594. #endregion
  2595. // Loop over faces (6 of them)
  2596. for (int i = 0; i < 6; i++)
  2597. {
  2598. AmBa = FaceA[i] - FaceB[i];
  2599. AmBb = FaceB[i] - FaceC[i];
  2600. d = Vector3.Dot(normals[i], FaceB[i]);
  2601. //if (faceCenters)
  2602. //{
  2603. // c = normals[i].Dot(normals[i]);
  2604. //}
  2605. //else
  2606. //{
  2607. c = Vector3.Dot(iray.Direction, normals[i]);
  2608. //}
  2609. if (c == 0)
  2610. continue;
  2611. a = (d - Vector3.Dot(iray.Origin, normals[i]))/c;
  2612. if (a < 0)
  2613. continue;
  2614. // If the normal is pointing outside the object
  2615. if (Vector3.Dot(iray.Direction, normals[i]) < 0 || !frontFacesOnly)
  2616. {
  2617. //if (faceCenters)
  2618. //{ //(FaceA[i] + FaceB[i] + FaceC[1] + FaceD[i]) / 4f;
  2619. // q = iray.Origin + a * normals[i];
  2620. //}
  2621. //else
  2622. //{
  2623. q = iray.Origin + iray.Direction*a;
  2624. //}
  2625. float distance2 = (float) GetDistanceTo(q, AXpos);
  2626. // Is this the closest hit to the object's origin?
  2627. //if (faceCenters)
  2628. //{
  2629. // distance2 = (float)GetDistanceTo(q, iray.Origin);
  2630. //}
  2631. if (distance2 < result.distance)
  2632. {
  2633. result.distance = distance2;
  2634. result.HitTF = true;
  2635. result.ipoint = q;
  2636. //MainConsole.Instance.Info("[FACE]:" + i.ToString());
  2637. //MainConsole.Instance.Info("[POINT]: " + q.ToString());
  2638. //MainConsole.Instance.Info("[DIST]: " + distance2.ToString());
  2639. if (faceCenters)
  2640. {
  2641. result.normal = AAfacenormals[i]*AXrot;
  2642. Vector3 scaleComponent = AAfacenormals[i];
  2643. float ScaleOffset = 0.5f;
  2644. if (scaleComponent.X != 0) ScaleOffset = AXscale.X;
  2645. if (scaleComponent.Y != 0) ScaleOffset = AXscale.Y;
  2646. if (scaleComponent.Z != 0) ScaleOffset = AXscale.Z;
  2647. ScaleOffset = Math.Abs(ScaleOffset);
  2648. Vector3 offset = result.normal*ScaleOffset;
  2649. result.ipoint = AXpos + offset;
  2650. //pos = (intersectionpoint + offset);
  2651. }
  2652. else
  2653. {
  2654. result.normal = normals[i];
  2655. }
  2656. result.AAfaceNormal = AAfacenormals[i];
  2657. }
  2658. }
  2659. }
  2660. return result;
  2661. }
  2662. public void TriggerScriptChangedEvent(Changed val)
  2663. {
  2664. if (m_parentGroup != null && m_parentGroup.Scene != null)
  2665. m_parentGroup.Scene.EventManager.TriggerOnScriptChangedEvent(this, (uint) val);
  2666. }
  2667. public void TrimPermissions()
  2668. {
  2669. _baseMask &= (uint) PermissionMask.All;
  2670. _ownerMask &= (uint) PermissionMask.All;
  2671. _groupMask &= (uint) PermissionMask.All;
  2672. _everyoneMask &= (uint) PermissionMask.All;
  2673. _nextOwnerMask &= (uint) PermissionMask.All;
  2674. }
  2675. public void Undo()
  2676. {
  2677. lock (m_undo)
  2678. {
  2679. if (m_undo.Count > 0)
  2680. {
  2681. m_redo.Push(new UndoState(this));
  2682. UndoState goback = m_undo.Pop();
  2683. if (goback != null)
  2684. {
  2685. goback.PlaybackState(this);
  2686. }
  2687. }
  2688. }
  2689. }
  2690. public void Redo()
  2691. {
  2692. lock (m_redo)
  2693. {
  2694. if (m_redo.Count > 0)
  2695. {
  2696. UndoState nUndo = new UndoState(this);
  2697. m_undo.Push(nUndo);
  2698. UndoState gofwd = m_redo.Pop();
  2699. if (gofwd != null)
  2700. gofwd.PlayfwdState(this);
  2701. }
  2702. }
  2703. }
  2704. /// <summary>
  2705. /// </summary>
  2706. /// <param name="pos"></param>
  2707. public void UpdateOffSet(Vector3 pos)
  2708. {
  2709. if ((pos.X != OffsetPosition.X) ||
  2710. (pos.Y != OffsetPosition.Y) ||
  2711. (pos.Z != OffsetPosition.Z))
  2712. {
  2713. Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
  2714. if (ParentGroup.RootPart.GetStatusSandbox())
  2715. {
  2716. if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
  2717. {
  2718. ParentGroup.ScriptSetPhysicsStatus(false);
  2719. newPos = OffsetPosition;
  2720. IChatModule chatModule = ParentGroup.Scene.RequestModuleInterface<IChatModule>();
  2721. if (chatModule != null)
  2722. chatModule.SimChat("Hit Sandbox Limit", ChatTypeEnum.DebugChannel, 0x7FFFFFFF,
  2723. ParentGroup.RootPart.AbsolutePosition, Name, UUID, false,
  2724. ParentGroup.Scene);
  2725. }
  2726. }
  2727. ValidpartOOB = false;
  2728. FixOffsetPosition(newPos, true);
  2729. ScheduleTerseUpdate();
  2730. }
  2731. }
  2732. public bool UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD,
  2733. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks)
  2734. {
  2735. bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
  2736. bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
  2737. bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
  2738. bool wasVD = VolumeDetectActive;
  2739. bool needsPhysicalRebuild = false;
  2740. if (blocks != null && blocks.Length != 0)
  2741. {
  2742. ObjectFlagUpdatePacket.ExtraPhysicsBlock block = blocks[0];
  2743. //These 2 are static properties, and do require rebuilding the entire physical representation
  2744. if (PhysicsType != block.PhysicsShapeType)
  2745. {
  2746. PhysicsType = block.PhysicsShapeType;
  2747. needsPhysicalRebuild = true; //Gotta rebuild now
  2748. }
  2749. if (Density != block.Density)
  2750. {
  2751. Density = block.Density;
  2752. needsPhysicalRebuild = true; //Gotta rebuild now
  2753. }
  2754. //These 3 are dynamic properties, and don't require rebuilding the physics representation
  2755. if (Friction != block.Friction)
  2756. Friction = block.Friction;
  2757. if (Restitution != block.Restitution)
  2758. Restitution = block.Restitution;
  2759. if (GravityMultiplier != block.GravityMultiplier)
  2760. GravityMultiplier = block.GravityMultiplier;
  2761. }
  2762. if ((UsePhysics == wasUsingPhysics) && (wasTemporary == IsTemporary) && (wasPhantom == IsPhantom) &&
  2763. (IsVD == wasVD))
  2764. return needsPhysicalRebuild;
  2765. // Special cases for VD. VD can only be called from a script
  2766. // and can't be combined with changes to other states. So we can rely
  2767. // that...
  2768. // ... if VD is changed, all others are not.
  2769. // ... if one of the others is changed, VD is not.
  2770. if (IsVD) // VD is active, special logic applies
  2771. {
  2772. // State machine logic for VolumeDetect
  2773. // More logic below
  2774. bool phanReset = (IsPhantom != wasPhantom) && !IsPhantom;
  2775. if (phanReset) // Phantom changes from on to off switch VD off too
  2776. {
  2777. IsVD = false; // Switch it of for the course of this routine
  2778. VolumeDetectActive = false; // and also permanently
  2779. if (PhysActor != null)
  2780. PhysActor.VolumeDetect = false; // Let physics know about it too
  2781. }
  2782. else
  2783. {
  2784. IsPhantom = false;
  2785. // If volumedetect is active we don't want phantom to be applied.
  2786. // If this is a new call to VD out of the state "phantom"
  2787. // this will also cause the prim to be visible to physics
  2788. }
  2789. }
  2790. if (UsePhysics)
  2791. AddFlag(PrimFlags.Physics);
  2792. else
  2793. RemFlag(PrimFlags.Physics);
  2794. if (PhysActor != null)
  2795. {
  2796. PhysActor.IsPhysical = UsePhysics;
  2797. if (!UsePhysics)
  2798. {
  2799. //Clear out old data
  2800. Velocity = Vector3.Zero;
  2801. Acceleration = Vector3.Zero;
  2802. AngularVelocity = Vector3.Zero;
  2803. PhysActor.RotationalVelocity = Vector3.Zero;
  2804. PhysActor.ClearVelocity();
  2805. GenerateRotationalVelocityFromOmega();
  2806. if (wasUsingPhysics)
  2807. ScheduleTerseUpdate(); //Force it out of the client too
  2808. }
  2809. }
  2810. if (IsPhantom || IsAttachment || (Shape.PathCurve == (byte) Extrusion.Flexible))
  2811. // note: this may have been changed above in the case of joints
  2812. {
  2813. AddFlag(PrimFlags.Phantom);
  2814. needsPhysicalRebuild = true; //Gotta rebuild now
  2815. }
  2816. else // Not phantom
  2817. {
  2818. if (wasPhantom)
  2819. {
  2820. RemFlag(PrimFlags.Phantom);
  2821. needsPhysicalRebuild = true; //Gotta rebuild now
  2822. }
  2823. }
  2824. if (IsVD && IsVD != VolumeDetectActive)
  2825. {
  2826. // If the above logic worked (this is urgent candidate to unit tests!)
  2827. // we now have a physicsactor.
  2828. // Defensive programming calls for a check here.
  2829. // Better would be throwing an exception that could be catched by a unit test as the internal
  2830. // logic should make sure, this Physactor is always here.
  2831. //FALSE, you can go from a phantom prim > VD -7/26
  2832. if (PhysActor != null)
  2833. PhysActor.VolumeDetect = true;
  2834. AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
  2835. VolumeDetectActive = true;
  2836. }
  2837. else
  2838. {
  2839. if (!IsVD)
  2840. {
  2841. // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
  2842. // (mumbles, well, at least if you have infinte CPU powers :-))
  2843. PhysicsObject pa = this.PhysActor;
  2844. if (pa != null)
  2845. PhysActor.VolumeDetect = false;
  2846. VolumeDetectActive = false;
  2847. }
  2848. }
  2849. if (IsTemporary)
  2850. AddFlag(PrimFlags.TemporaryOnRez);
  2851. else
  2852. RemFlag(PrimFlags.TemporaryOnRez);
  2853. if (UsePhysics != wasUsingPhysics) //Fire the event
  2854. ParentGroup.Scene.AuroraEventManager.FireGenericEventHandler("ObjectChangedPhysicalStatus", ParentGroup);
  2855. ParentGroup.HasGroupChanged = true;
  2856. ScheduleUpdate(PrimUpdateFlags.PrimFlags);
  2857. return needsPhysicalRebuild;
  2858. }
  2859. public void UpdateRotation(Quaternion rot)
  2860. {
  2861. if ((rot.X != GetRotationOffset().X) ||
  2862. (rot.Y != GetRotationOffset().Y) ||
  2863. (rot.Z != GetRotationOffset().Z) ||
  2864. (rot.W != GetRotationOffset().W))
  2865. {
  2866. SetRotationOffset(true, rot, true);
  2867. ValidpartOOB = false;
  2868. ScheduleTerseUpdate();
  2869. }
  2870. }
  2871. /// <summary>
  2872. /// Update the shape of this part.
  2873. /// </summary>
  2874. /// <param name="shapeBlock"></param>
  2875. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
  2876. {
  2877. UpdateShape(shapeBlock, true);
  2878. }
  2879. /// <summary>
  2880. /// Having this function because I found when scripts updated the shape.. over and over, it would fill up the memory
  2881. /// Having the extra paramater updatePhysics can prevent physics updates on the changes
  2882. /// The onlyplace this effects is if a script changes the shape
  2883. /// If the LocklessQueue gets updated this can be removed
  2884. /// </summary>
  2885. /// <param name="shapeBlock"></param>
  2886. /// <param name="UpdatePhysics"></param>
  2887. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, bool UpdatePhysics)
  2888. {
  2889. IOpenRegionSettingsModule module = ParentGroup.Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  2890. if (module != null)
  2891. {
  2892. if (shapeBlock.ProfileHollow > (module.MaximumHollowSize*500) &&
  2893. module.MaximumHollowSize != -1)
  2894. //This is so that it works correctly, since the packet sends (N * 500)
  2895. {
  2896. shapeBlock.ProfileHollow = (ushort) (module.MaximumHollowSize*500);
  2897. }
  2898. if (shapeBlock.PathScaleY > (200 - (module.MinimumHoleSize*100)) &&
  2899. module.MinimumHoleSize != -1 && shapeBlock.PathCurve == 32)
  2900. //This is how the packet is set up... so this is how we check for it...
  2901. {
  2902. shapeBlock.PathScaleY = Convert.ToByte((200 - (module.MinimumHoleSize*100)));
  2903. }
  2904. }
  2905. m_shape.PathBegin = shapeBlock.PathBegin;
  2906. m_shape.PathEnd = shapeBlock.PathEnd;
  2907. m_shape.PathScaleX = shapeBlock.PathScaleX;
  2908. m_shape.PathScaleY = shapeBlock.PathScaleY;
  2909. m_shape.PathShearX = shapeBlock.PathShearX;
  2910. m_shape.PathShearY = shapeBlock.PathShearY;
  2911. m_shape.PathSkew = shapeBlock.PathSkew;
  2912. m_shape.ProfileBegin = shapeBlock.ProfileBegin;
  2913. m_shape.ProfileEnd = shapeBlock.ProfileEnd;
  2914. m_shape.PathCurve = shapeBlock.PathCurve;
  2915. m_shape.ProfileCurve = shapeBlock.ProfileCurve;
  2916. m_shape.ProfileHollow = shapeBlock.ProfileHollow;
  2917. m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
  2918. m_shape.PathRevolutions = shapeBlock.PathRevolutions;
  2919. m_shape.PathTaperX = shapeBlock.PathTaperX;
  2920. m_shape.PathTaperY = shapeBlock.PathTaperY;
  2921. m_shape.PathTwist = shapeBlock.PathTwist;
  2922. m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
  2923. if (m_shape.SculptEntry && UpdatePhysics)
  2924. m_parentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), true, AssetReceived);
  2925. else
  2926. {
  2927. Shape = m_shape;
  2928. if ((UpdatePhysics) && (PhysActor != null))
  2929. PhysActor.Shape = m_shape;
  2930. }
  2931. // This is what makes vehicle trailers work
  2932. // A script in a child prim re-issues
  2933. // llSetPrimitiveParams(PRIM_TYPE) every few seconds. That
  2934. // prevents autoreturn. This also works in SL.
  2935. if (ParentGroup.RootPart != this)
  2936. ParentGroup.RootPart.Rezzed = DateTime.UtcNow;
  2937. ValidpartOOB = false;
  2938. ParentGroup.HasGroupChanged = true;
  2939. ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  2940. }
  2941. /// <summary>
  2942. /// Update the textures on the part.
  2943. /// </summary>
  2944. /// Added to handle bug in libsecondlife's TextureEntry.ToBytes()
  2945. /// not handling RGBA properly. Cycles through, and "fixes" the color
  2946. /// info
  2947. /// <param name="tex"></param>
  2948. /// <param name="sendChangedEvent"></param>
  2949. public void UpdateTexture(Primitive.TextureEntry tex, bool sendChangedEvent)
  2950. {
  2951. //Color4 tmpcolor;
  2952. //for (uint i = 0; i < 32; i++)
  2953. //{
  2954. // if (tex.FaceTextures[i] != null)
  2955. // {
  2956. // tmpcolor = tex.GetFace((uint) i).RGBA;
  2957. // tmpcolor.A = tmpcolor.A*255;
  2958. // tmpcolor.R = tmpcolor.R*255;
  2959. // tmpcolor.G = tmpcolor.G*255;
  2960. // tmpcolor.B = tmpcolor.B*255;
  2961. // tex.FaceTextures[i].RGBA = tmpcolor;
  2962. // }
  2963. //}
  2964. //tmpcolor = tex.DefaultTexture.RGBA;
  2965. //tmpcolor.A = tmpcolor.A*255;
  2966. //tmpcolor.R = tmpcolor.R*255;
  2967. //tmpcolor.G = tmpcolor.G*255;
  2968. //tmpcolor.B = tmpcolor.B*255;
  2969. //tex.DefaultTexture.RGBA = tmpcolor;
  2970. UpdateTextureEntry(tex.GetBytes(), sendChangedEvent);
  2971. }
  2972. public void aggregateScriptEvents()
  2973. {
  2974. AggregateScriptEvents = 0;
  2975. // Aggregate script events
  2976. lock (m_scriptEvents)
  2977. {
  2978. foreach (scriptEvents s in m_scriptEvents.Values)
  2979. {
  2980. AggregateScriptEvents |= s;
  2981. }
  2982. }
  2983. uint objectflagupdate = 0;
  2984. if (
  2985. ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
  2986. ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
  2987. ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
  2988. )
  2989. {
  2990. objectflagupdate |= (uint) PrimFlags.Touch;
  2991. }
  2992. if ((AggregateScriptEvents & scriptEvents.money) != 0)
  2993. {
  2994. objectflagupdate |= (uint) PrimFlags.Money;
  2995. }
  2996. if (AllowedDrop)
  2997. {
  2998. objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
  2999. }
  3000. // subscribe to physics updates.
  3001. //We subscribe by default now... so 'shouldn't' need this
  3002. if ((((AggregateScriptEvents & scriptEvents.collision) != 0) ||
  3003. ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
  3004. ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
  3005. ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
  3006. ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
  3007. ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0)
  3008. ) && PhysActor != null)
  3009. {
  3010. if (!m_hasSubscribedToCollisionEvent)
  3011. {
  3012. m_hasSubscribedToCollisionEvent = true;
  3013. PhysActor.OnCollisionUpdate += PhysicsCollision;
  3014. PhysActor.SubscribeEvents(1000);
  3015. }
  3016. }
  3017. else if (PhysActor != null)
  3018. {
  3019. if (m_hasSubscribedToCollisionEvent)
  3020. {
  3021. m_hasSubscribedToCollisionEvent = false;
  3022. PhysActor.OnCollisionUpdate -= PhysicsCollision;
  3023. }
  3024. }
  3025. LocalFlags = (PrimFlags) objectflagupdate;
  3026. if (m_parentGroup != null && m_parentGroup.RootPart == this)
  3027. {
  3028. m_parentGroup.aggregateScriptEvents();
  3029. }
  3030. else
  3031. {
  3032. // MainConsole.Instance.DebugFormat(
  3033. // "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
  3034. ScheduleUpdate(PrimUpdateFlags.PrimFlags);
  3035. }
  3036. }
  3037. public int registerTargetWaypoint(Vector3 target, float tolerance)
  3038. {
  3039. if (m_parentGroup != null)
  3040. {
  3041. return m_parentGroup.registerTargetWaypoint(target, tolerance);
  3042. }
  3043. return 0;
  3044. }
  3045. public void unregisterTargetWaypoint(int handle)
  3046. {
  3047. if (m_parentGroup != null)
  3048. {
  3049. m_parentGroup.unregisterTargetWaypoint(handle);
  3050. }
  3051. }
  3052. public int registerRotTargetWaypoint(Quaternion target, float tolerance)
  3053. {
  3054. if (m_parentGroup != null)
  3055. {
  3056. return m_parentGroup.registerRotTargetWaypoint(target, tolerance);
  3057. }
  3058. return 0;
  3059. }
  3060. public void unregisterRotTargetWaypoint(int handle)
  3061. {
  3062. if (m_parentGroup != null)
  3063. {
  3064. m_parentGroup.unregisterRotTargetWaypoint(handle);
  3065. }
  3066. }
  3067. #region Vehicle Params
  3068. private OSDArray m_VehicleFlags;
  3069. private OSDMap m_VehicleParams;
  3070. public int VehicleType { get; set; }
  3071. public OSDArray VehicleFlags
  3072. {
  3073. get
  3074. {
  3075. if (m_VehicleFlags == null)
  3076. m_VehicleFlags = new OSDArray();
  3077. return m_VehicleFlags;
  3078. }
  3079. set { m_VehicleFlags = value; }
  3080. }
  3081. public OSDMap VehicleParameters
  3082. {
  3083. get
  3084. {
  3085. if (m_VehicleParams == null)
  3086. m_VehicleParams = new OSDMap();
  3087. return m_VehicleParams;
  3088. }
  3089. set { m_VehicleParams = value; }
  3090. }
  3091. #endregion
  3092. public void SetRotationOffset(bool UpdatePrimActor, Quaternion value, bool single)
  3093. {
  3094. if (ParentGroup != null)
  3095. ParentGroup.HasGroupChanged = true;
  3096. ValidpartOOB = false;
  3097. RotationOffset = value;
  3098. PhysicsObject actor = PhysActor;
  3099. if (actor != null)
  3100. {
  3101. if (value.W == 0) //We have an issue here... try to normalize it
  3102. value.Normalize();
  3103. if (actor.PhysicsActorType != (int) ActorTypes.Prim) // for now let other times get updates
  3104. {
  3105. UpdatePrimActor = true;
  3106. single = false;
  3107. }
  3108. if (UpdatePrimActor)
  3109. {
  3110. try
  3111. {
  3112. // Root prim gets value directly
  3113. if (_parentID == 0)
  3114. {
  3115. actor.Orientation = value;
  3116. //MainConsole.Instance.Info("[PART]: RO1:" + actor.Orientation.ToString());
  3117. }
  3118. else if (single || !actor.IsPhysical)
  3119. {
  3120. // Child prim we have to calculate it's world rotationwel
  3121. Quaternion resultingrotation = GetWorldRotation();
  3122. actor.Orientation = resultingrotation;
  3123. //MainConsole.Instance.Info("[PART]: RO2:" + actor.Orientation.ToString());
  3124. }
  3125. }
  3126. catch (Exception ex)
  3127. {
  3128. MainConsole.Instance.Error("[SCENEOBJECTPART]: ROTATIONOFFSET" + ex.Message);
  3129. }
  3130. }
  3131. }
  3132. }
  3133. public void SetOffsetPosition(Vector3 value)
  3134. {
  3135. m_offsetPosition = value;
  3136. ValidpartOOB = false;
  3137. }
  3138. public void SetGroupPosition(Vector3 value)
  3139. {
  3140. m_groupPosition = new Vector3(value.X, value.Y, value.Z);
  3141. }
  3142. public void FixGroupPosition(Vector3 value, bool single)
  3143. {
  3144. FixGroupPositionComum(true, value, single);
  3145. }
  3146. public void FixGroupPositionComum(bool UpdatePrimActor, Vector3 value, bool single)
  3147. {
  3148. bool TriggerMoving_End = false;
  3149. if (m_groupPosition != value)
  3150. {
  3151. if (ParentGroup != null)
  3152. ParentGroup.HasGroupChanged = true;
  3153. TriggerMoving_End = true;
  3154. TriggerScriptMovingStartEvent();
  3155. }
  3156. m_groupPosition = value;
  3157. PhysicsObject actor = PhysActor;
  3158. if (actor != null)
  3159. {
  3160. if (actor.PhysicsActorType != (int) ActorTypes.Prim) // for now let other times get updates
  3161. {
  3162. UpdatePrimActor = true;
  3163. single = false;
  3164. }
  3165. if (UpdatePrimActor)
  3166. {
  3167. try
  3168. {
  3169. // Root prim actually goes at Position
  3170. if (_parentID == 0)
  3171. {
  3172. actor.Position = value;
  3173. }
  3174. else if (single || !actor.IsPhysical)
  3175. {
  3176. // To move the child prim in respect to the group position and rotation we have to calculate
  3177. actor.Position = GetWorldPosition();
  3178. actor.Orientation = GetWorldRotation();
  3179. }
  3180. // Tell the physics engines that this prim changed.
  3181. }
  3182. catch (Exception e)
  3183. {
  3184. MainConsole.Instance.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
  3185. }
  3186. }
  3187. }
  3188. lock (SitTargetAvatar)
  3189. {
  3190. if (SitTargetAvatar.Count != 0)
  3191. {
  3192. foreach (UUID avID in SitTargetAvatar.Where(avID => m_parentGroup != null))
  3193. {
  3194. IScenePresence avatar;
  3195. if (m_parentGroup.Scene.TryGetScenePresence(avID, out avatar))
  3196. {
  3197. avatar.ParentPosition = GetWorldPosition();
  3198. }
  3199. }
  3200. }
  3201. }
  3202. if (TriggerMoving_End)
  3203. TriggerScriptMovingEndEvent();
  3204. }
  3205. public void ResetExpire()
  3206. {
  3207. Expires = DateTime.Now + new TimeSpan(TimeSpan.TicksPerMinute);
  3208. }
  3209. public event AddPhysics OnAddPhysics;
  3210. public event RemovePhysics OnRemovePhysics;
  3211. public void FireOnAddedPhysics()
  3212. {
  3213. if (OnAddPhysics != null)
  3214. OnAddPhysics();
  3215. }
  3216. public void FireOnRemovedPhysics()
  3217. {
  3218. if (OnRemovePhysics != null)
  3219. OnRemovePhysics();
  3220. }
  3221. public void ClearUndoState()
  3222. {
  3223. lock (m_undo)
  3224. {
  3225. m_undo = new UndoStack<UndoState>(5);
  3226. }
  3227. lock (m_redo)
  3228. {
  3229. m_redo = new UndoStack<UndoState>(5);
  3230. }
  3231. StoreUndoState();
  3232. }
  3233. public byte ConvertScriptUintToByte(uint indata)
  3234. {
  3235. byte outdata = (byte) TextureAnimFlags.NONE;
  3236. if ((indata & 1) != 0) outdata |= (byte) TextureAnimFlags.ANIM_ON;
  3237. if ((indata & 2) != 0) outdata |= (byte) TextureAnimFlags.LOOP;
  3238. if ((indata & 4) != 0) outdata |= (byte) TextureAnimFlags.REVERSE;
  3239. if ((indata & 8) != 0) outdata |= (byte) TextureAnimFlags.PING_PONG;
  3240. if ((indata & 16) != 0) outdata |= (byte) TextureAnimFlags.SMOOTH;
  3241. if ((indata & 32) != 0) outdata |= (byte) TextureAnimFlags.ROTATE;
  3242. if ((indata & 64) != 0) outdata |= (byte) TextureAnimFlags.SCALE;
  3243. return outdata;
  3244. }
  3245. /// <summary>
  3246. /// Duplicates this part.
  3247. /// </summary>
  3248. /// <param name="parent"></param>
  3249. /// <param name="clonePhys"></param>
  3250. /// <returns></returns>
  3251. public SceneObjectPart Copy(SceneObjectGroup parent, bool clonePhys)
  3252. {
  3253. SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone();
  3254. dupe.m_parentGroup = parent;
  3255. dupe.m_shape = m_shape.Copy();
  3256. dupe.m_partOOBsize = m_partOOBsize;
  3257. dupe.m_partOOBoffset = m_partOOBoffset;
  3258. dupe.m_partBSphereRadiusSQ = m_partBSphereRadiusSQ;
  3259. dupe.m_regionHandle = m_regionHandle;
  3260. //memberwiseclone means it also clones the physics actor reference
  3261. // This will make physical prim 'bounce' if not set to null.
  3262. if (!clonePhys)
  3263. dupe.PhysActor = null;
  3264. dupe._groupID = GroupID;
  3265. dupe.m_groupPosition = m_groupPosition;
  3266. dupe.m_offsetPosition = m_offsetPosition;
  3267. dupe.RotationOffset = RotationOffset;
  3268. dupe.Velocity = new Vector3(0, 0, 0);
  3269. dupe.Acceleration = new Vector3(0, 0, 0);
  3270. dupe.AngularVelocity = new Vector3(0, 0, 0);
  3271. dupe.Flags = Flags;
  3272. dupe.LinkNum = LinkNum;
  3273. dupe.SitTargetAvatar = new List<UUID>();
  3274. dupe.m_LoopSoundSlavePrims = new List<SceneObjectPart>();
  3275. dupe.m_PlaySoundSlavePrims = new List<SceneObjectPart>();
  3276. dupe.m_ValidpartOOB = false;
  3277. dupe._ownershipCost = _ownershipCost;
  3278. dupe._objectSaleType = _objectSaleType;
  3279. dupe._salePrice = _salePrice;
  3280. dupe._category = _category;
  3281. dupe.Rezzed = Rezzed;
  3282. dupe.m_inventory = new SceneObjectPartInventory(dupe)
  3283. {
  3284. Items = (TaskInventoryDictionary) m_inventory.Items.Clone(),
  3285. HasInventoryChanged = m_inventory.HasInventoryChanged
  3286. };
  3287. byte[] extraP = new byte[Shape.ExtraParams.Length];
  3288. Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
  3289. dupe.Shape.ExtraParams = extraP;
  3290. dupe.m_scriptEvents = new Dictionary<UUID, scriptEvents>();
  3291. dupe.Shape.SculptData = this.Shape.SculptData;
  3292. dupe.GenerateRotationalVelocityFromOmega();
  3293. return dupe;
  3294. }
  3295. public void AssetReceived(string id, Object sender, AssetBase asset)
  3296. {
  3297. if (asset != null)
  3298. {
  3299. this.Shape.SculptEntry = true;
  3300. this.Shape.SculptData = asset.Data; //Set the asset data
  3301. }
  3302. bool isMesh = asset == null ? false : (asset.Type == (int) AssetType.Mesh);
  3303. if (isMesh)
  3304. this.Shape.SculptType = (byte) SculptType.Mesh;
  3305. PrimitiveBaseShape shape = Shape.Copy();
  3306. if ((bool) sender && this.PhysActor != null &&
  3307. (asset != null || (this.Shape.SculptData != null && this.Shape.SculptData.Length != 0)))
  3308. //Update physics
  3309. {
  3310. //Get physics to update in a hackish way
  3311. this.PhysActor.Shape = shape;
  3312. }
  3313. this.Shape = shape;
  3314. }
  3315. public double GetDistanceTo(Vector3 a, Vector3 b)
  3316. {
  3317. float dx = a.X - b.X;
  3318. float dy = a.Y - b.Y;
  3319. float dz = a.Z - b.Z;
  3320. return Math.Sqrt(dx*dx + dy*dy + dz*dz);
  3321. }
  3322. public UUID GetRootPartUUID()
  3323. {
  3324. if (m_parentGroup != null)
  3325. {
  3326. return m_parentGroup.UUID;
  3327. }
  3328. return UUID.Zero;
  3329. }
  3330. public void SetMoveToTarget(bool Enabled, Vector3 target, float tau)
  3331. {
  3332. if (Enabled)
  3333. {
  3334. m_initialPIDLocation = AbsolutePosition;
  3335. PIDTarget = target;
  3336. PIDTau = tau;
  3337. PIDActive = true;
  3338. }
  3339. else
  3340. {
  3341. PIDActive = false;
  3342. m_initialPIDLocation = Vector3.Zero;
  3343. }
  3344. }
  3345. public void StopHover()
  3346. {
  3347. m_parentGroup.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
  3348. }
  3349. public virtual void OnGrab(Vector3 offsetPos, IClientAPI remoteClient)
  3350. {
  3351. }
  3352. public void PhysicsCollision(EventArgs e)
  3353. {
  3354. // single threaded here
  3355. if (e == null)
  3356. return;
  3357. CollisionEventUpdate a = (CollisionEventUpdate) e;
  3358. Dictionary<uint, ContactPoint> collissionswith = a.GetCollisionEvents();
  3359. List<uint> thisHitColliders = new List<uint>();
  3360. List<uint> startedColliders = new List<uint>();
  3361. ContactPoint startedCollider = new ContactPoint();
  3362. // calculate things that started colliding this time
  3363. // and build up list of colliders this time
  3364. foreach (uint localID in collissionswith.Keys)
  3365. {
  3366. thisHitColliders.Add(localID);
  3367. if (!m_lastColliders.Contains(localID))
  3368. {
  3369. startedCollider = collissionswith[localID];
  3370. startedColliders.Add(localID);
  3371. }
  3372. //MainConsole.Instance.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
  3373. }
  3374. // calculate things that ended colliding
  3375. #if (!ISWIN)
  3376. List<uint> endedColliders = new List<uint>();
  3377. foreach (uint localId in m_lastColliders)
  3378. {
  3379. if (!thisHitColliders.Contains(localId)) endedColliders.Add(localId);
  3380. }
  3381. #else
  3382. List<uint> endedColliders = m_lastColliders.Where(localID => !thisHitColliders.Contains(localID)).ToList();
  3383. #endif
  3384. //add the items that started colliding this time to the last colliders list.
  3385. m_lastColliders.AddRange(startedColliders);
  3386. // remove things that ended colliding from the last colliders list
  3387. foreach (uint localID in endedColliders)
  3388. m_lastColliders.Remove(localID);
  3389. if (m_parentGroup == null)
  3390. return;
  3391. if (m_parentGroup.IsDeleted)
  3392. return;
  3393. const string SoundGlassCollision = "6a45ba0b-5775-4ea8-8513-26008a17f873";
  3394. const string SoundMetalCollision = "9e5c1297-6eed-40c0-825a-d9bcd86e3193";
  3395. const string SoundStoneCollision = "9538f37c-456e-4047-81be-6435045608d4";
  3396. const string SoundFleshCollision = "dce5fdd4-afe4-4ea1-822f-dd52cac46b08";
  3397. const string SoundPlasticCollision = "0e24a717-b97e-4b77-9c94-b59a5a88b2da";
  3398. const string SoundRubberCollision = "153c8bf7-fb89-4d89-b263-47e58b1b4774";
  3399. const string SoundWoodCollision = "063c97d3-033a-4e9b-98d8-05c8074922cb";
  3400. // play the sound.
  3401. if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f)
  3402. {
  3403. SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, 0, 0, false, false);
  3404. }
  3405. else if (startedColliders.Count > 0)
  3406. {
  3407. switch (startedCollider.Type)
  3408. {
  3409. case ActorTypes.Agent:
  3410. break; // Agents will play the sound so we don't
  3411. case ActorTypes.Ground:
  3412. SendSound(SoundWoodCollision, 1, true, 0, 0, false, false);
  3413. break; //Always play the click or thump sound when hitting ground
  3414. case ActorTypes.Prim:
  3415. switch (Material)
  3416. {
  3417. case (int) OpenMetaverse.Material.Flesh:
  3418. SendSound(SoundFleshCollision, 1, true, 0, 0, false, false);
  3419. break;
  3420. case (int) OpenMetaverse.Material.Glass:
  3421. SendSound(SoundGlassCollision, 1, true, 0, 0, false, false);
  3422. break;
  3423. case (int) OpenMetaverse.Material.Metal:
  3424. SendSound(SoundMetalCollision, 1, true, 0, 0, false, false);
  3425. break;
  3426. case (int) OpenMetaverse.Material.Plastic:
  3427. SendSound(SoundPlasticCollision, 1, true, 0, 0, false, false);
  3428. break;
  3429. case (int) OpenMetaverse.Material.Rubber:
  3430. SendSound(SoundRubberCollision, 1, true, 0, 0, false, false);
  3431. break;
  3432. case (int) OpenMetaverse.Material.Stone:
  3433. SendSound(SoundStoneCollision, 1, true, 0, 0, false, false);
  3434. break;
  3435. case (int) OpenMetaverse.Material.Wood:
  3436. SendSound(SoundWoodCollision, 1, true, 0, 0, false, false);
  3437. break;
  3438. }
  3439. break; //Play based on material type in prim2prim collisions
  3440. default:
  3441. break; //Unclear of what this object is, no sounds
  3442. }
  3443. }
  3444. if (CollisionSprite != UUID.Zero && CollisionSoundVolume > 0.0f)
  3445. // The collision volume isn't a mistake, its an SL feature/bug
  3446. {
  3447. // TODO: make a sprite!
  3448. }
  3449. if (((AggregateScriptEvents & scriptEvents.collision) != 0) ||
  3450. ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
  3451. ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
  3452. ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
  3453. ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
  3454. ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
  3455. (CollisionSound != UUID.Zero) ||
  3456. PassCollisions != 2)
  3457. {
  3458. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0 ||
  3459. (m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
  3460. {
  3461. // do event notification
  3462. if (startedColliders.Count > 0)
  3463. {
  3464. ColliderArgs StartCollidingMessage = new ColliderArgs();
  3465. List<DetectedObject> colliding = new List<DetectedObject>();
  3466. foreach (uint localId in startedColliders)
  3467. {
  3468. if (localId != 0)
  3469. {
  3470. // always running this check because if the user deletes the object it would return a null reference.
  3471. if (m_parentGroup == null)
  3472. return;
  3473. if (m_parentGroup.Scene == null)
  3474. return;
  3475. ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
  3476. string data = "";
  3477. if (obj != null)
  3478. {
  3479. if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  3480. m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
  3481. {
  3482. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3483. //If it is 1, it is to accept ONLY collisions from this object
  3484. if (found)
  3485. {
  3486. DetectedObject detobj = new DetectedObject
  3487. {
  3488. keyUUID = obj.UUID,
  3489. nameStr = obj.Name,
  3490. ownerUUID = obj.OwnerID,
  3491. posVector = obj.AbsolutePosition,
  3492. rotQuat = obj.GetWorldRotation(),
  3493. velVector = obj.Velocity,
  3494. colliderType = 0,
  3495. groupUUID = obj.GroupID
  3496. };
  3497. colliding.Add(detobj);
  3498. }
  3499. //If it is 0, it is to not accept collisions from this object
  3500. else
  3501. {
  3502. }
  3503. }
  3504. else
  3505. {
  3506. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3507. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  3508. if (!found)
  3509. {
  3510. DetectedObject detobj = new DetectedObject
  3511. {
  3512. keyUUID = obj.UUID,
  3513. nameStr = obj.Name,
  3514. ownerUUID = obj.OwnerID,
  3515. posVector = obj.AbsolutePosition,
  3516. rotQuat = obj.GetWorldRotation(),
  3517. velVector = obj.Velocity,
  3518. colliderType = 0,
  3519. groupUUID = obj.GroupID
  3520. };
  3521. colliding.Add(detobj);
  3522. }
  3523. }
  3524. }
  3525. else
  3526. {
  3527. IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
  3528. if (av != null)
  3529. {
  3530. if (av.LocalId == localId)
  3531. {
  3532. if (
  3533. m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  3534. m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
  3535. {
  3536. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
  3537. out data);
  3538. //If it is 1, it is to accept ONLY collisions from this avatar
  3539. if (found)
  3540. {
  3541. DetectedObject detobj = new DetectedObject
  3542. {
  3543. keyUUID = av.UUID,
  3544. nameStr = av.ControllingClient.Name,
  3545. ownerUUID = av.UUID,
  3546. posVector = av.AbsolutePosition,
  3547. rotQuat = av.Rotation,
  3548. velVector = av.Velocity,
  3549. colliderType = 0,
  3550. groupUUID =
  3551. av.ControllingClient
  3552. .ActiveGroupId
  3553. };
  3554. colliding.Add(detobj);
  3555. }
  3556. //If it is 0, it is to not accept collisions from this avatar
  3557. else
  3558. {
  3559. }
  3560. }
  3561. else
  3562. {
  3563. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
  3564. out data);
  3565. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  3566. if (!found)
  3567. {
  3568. DetectedObject detobj = new DetectedObject
  3569. {
  3570. keyUUID = av.UUID,
  3571. nameStr = av.ControllingClient.Name,
  3572. ownerUUID = av.UUID,
  3573. posVector = av.AbsolutePosition,
  3574. rotQuat = av.Rotation,
  3575. velVector = av.Velocity,
  3576. colliderType = 0,
  3577. groupUUID =
  3578. av.ControllingClient
  3579. .ActiveGroupId
  3580. };
  3581. colliding.Add(detobj);
  3582. }
  3583. }
  3584. }
  3585. }
  3586. }
  3587. }
  3588. }
  3589. if (colliding.Count > 0)
  3590. {
  3591. StartCollidingMessage.Colliders = colliding;
  3592. // always running this check because if the user deletes the object it would return a null reference.
  3593. if (m_parentGroup == null)
  3594. return;
  3595. if (m_parentGroup.Scene == null)
  3596. return;
  3597. //Always send to the prim it is occuring to
  3598. m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(this, StartCollidingMessage);
  3599. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  3600. {
  3601. const int PASS_IF_NOT_HANDLED = 0;
  3602. const int PASS_ALWAYS = 1;
  3603. const int PASS_NEVER = 2;
  3604. if (this.PassCollisions == PASS_NEVER)
  3605. {
  3606. }
  3607. if (this.PassCollisions == PASS_ALWAYS)
  3608. {
  3609. m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
  3610. this.ParentGroup.RootPart, StartCollidingMessage);
  3611. }
  3612. else if (((this.ScriptEvents & scriptEvents.collision_start) == 0) &&
  3613. this.PassCollisions == PASS_IF_NOT_HANDLED)
  3614. //If no event in this prim, pass to parent
  3615. {
  3616. m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(
  3617. this.ParentGroup.RootPart, StartCollidingMessage);
  3618. }
  3619. }
  3620. }
  3621. }
  3622. }
  3623. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
  3624. {
  3625. if (m_lastColliders.Count > 0)
  3626. {
  3627. ColliderArgs CollidingMessage = new ColliderArgs();
  3628. List<DetectedObject> colliding = new List<DetectedObject>();
  3629. foreach (uint localId in m_lastColliders)
  3630. {
  3631. if (localId != 0)
  3632. {
  3633. if (m_parentGroup == null)
  3634. return;
  3635. if (m_parentGroup.Scene == null)
  3636. return;
  3637. ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
  3638. string data = "";
  3639. if (obj != null)
  3640. {
  3641. if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  3642. m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
  3643. {
  3644. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3645. //If it is 1, it is to accept ONLY collisions from this object
  3646. if (found)
  3647. {
  3648. DetectedObject detobj = new DetectedObject
  3649. {
  3650. keyUUID = obj.UUID,
  3651. nameStr = obj.Name,
  3652. ownerUUID = obj.OwnerID,
  3653. posVector = obj.AbsolutePosition,
  3654. rotQuat = obj.GetWorldRotation(),
  3655. velVector = obj.Velocity,
  3656. colliderType = 0,
  3657. groupUUID = obj.GroupID
  3658. };
  3659. colliding.Add(detobj);
  3660. }
  3661. //If it is 0, it is to not accept collisions from this object
  3662. else
  3663. {
  3664. }
  3665. }
  3666. else
  3667. {
  3668. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3669. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  3670. if (!found)
  3671. {
  3672. DetectedObject detobj = new DetectedObject
  3673. {
  3674. keyUUID = obj.UUID,
  3675. nameStr = obj.Name,
  3676. ownerUUID = obj.OwnerID,
  3677. posVector = obj.AbsolutePosition,
  3678. rotQuat = obj.GetWorldRotation(),
  3679. velVector = obj.Velocity,
  3680. colliderType = 0,
  3681. groupUUID = obj.GroupID
  3682. };
  3683. colliding.Add(detobj);
  3684. }
  3685. }
  3686. }
  3687. else
  3688. {
  3689. IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
  3690. if (av != null)
  3691. {
  3692. if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  3693. m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
  3694. {
  3695. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3696. //If it is 1, it is to accept ONLY collisions from this avatar
  3697. if (found)
  3698. {
  3699. DetectedObject detobj = new DetectedObject
  3700. {
  3701. keyUUID = av.UUID,
  3702. nameStr = av.ControllingClient.Name,
  3703. ownerUUID = av.UUID,
  3704. posVector = av.AbsolutePosition,
  3705. rotQuat = av.Rotation,
  3706. velVector = av.Velocity,
  3707. colliderType = 0,
  3708. groupUUID =
  3709. av.ControllingClient.ActiveGroupId
  3710. };
  3711. colliding.Add(detobj);
  3712. }
  3713. //If it is 0, it is to not accept collisions from this avatar
  3714. else
  3715. {
  3716. }
  3717. }
  3718. else
  3719. {
  3720. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3721. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  3722. if (!found)
  3723. {
  3724. DetectedObject detobj = new DetectedObject
  3725. {
  3726. keyUUID = av.UUID,
  3727. nameStr = av.ControllingClient.Name,
  3728. ownerUUID = av.UUID,
  3729. posVector = av.AbsolutePosition,
  3730. rotQuat = av.Rotation,
  3731. velVector = av.Velocity,
  3732. colliderType = 0,
  3733. groupUUID =
  3734. av.ControllingClient.ActiveGroupId
  3735. };
  3736. colliding.Add(detobj);
  3737. }
  3738. }
  3739. }
  3740. }
  3741. }
  3742. }
  3743. if (colliding.Count > 0)
  3744. {
  3745. CollidingMessage.Colliders = colliding;
  3746. // always running this check because if the user deletes the object it would return a null reference.
  3747. if (m_parentGroup == null)
  3748. return;
  3749. if (m_parentGroup.Scene == null)
  3750. return;
  3751. m_parentGroup.Scene.EventManager.TriggerScriptColliding(this, CollidingMessage);
  3752. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  3753. {
  3754. const int PASS_IF_NOT_HANDLED = 0;
  3755. const int PASS_ALWAYS = 1;
  3756. const int PASS_NEVER = 2;
  3757. if (this.PassCollisions == PASS_NEVER)
  3758. {
  3759. }
  3760. if (this.PassCollisions == PASS_ALWAYS)
  3761. {
  3762. m_parentGroup.Scene.EventManager.TriggerScriptColliding(this.ParentGroup.RootPart,
  3763. CollidingMessage);
  3764. }
  3765. else if (((this.ScriptEvents & scriptEvents.collision) == 0) &&
  3766. this.PassCollisions == PASS_IF_NOT_HANDLED)
  3767. //If no event in this prim, pass to parent
  3768. {
  3769. m_parentGroup.Scene.EventManager.TriggerScriptColliding(
  3770. this.ParentGroup.RootPart, CollidingMessage);
  3771. }
  3772. }
  3773. }
  3774. }
  3775. }
  3776. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
  3777. {
  3778. if (endedColliders.Count > 0)
  3779. {
  3780. ColliderArgs EndCollidingMessage = new ColliderArgs();
  3781. List<DetectedObject> colliding = new List<DetectedObject>();
  3782. foreach (uint localId in endedColliders)
  3783. {
  3784. if (localId != 0)
  3785. {
  3786. // always running this check because if the user deletes the object it would return a null reference.
  3787. if (m_parentGroup == null)
  3788. return;
  3789. if (m_parentGroup.Scene == null)
  3790. return;
  3791. ISceneChildEntity obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
  3792. string data = "";
  3793. if (obj != null)
  3794. {
  3795. if (m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.UUID.ToString()) ||
  3796. m_parentGroup.RootPart.CollisionFilter.ContainsValue(obj.Name))
  3797. {
  3798. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3799. //If it is 1, it is to accept ONLY collisions from this object
  3800. if (found)
  3801. {
  3802. DetectedObject detobj = new DetectedObject
  3803. {
  3804. keyUUID = obj.UUID,
  3805. nameStr = obj.Name,
  3806. ownerUUID = obj.OwnerID,
  3807. posVector = obj.AbsolutePosition,
  3808. rotQuat = obj.GetWorldRotation(),
  3809. velVector = obj.Velocity,
  3810. colliderType = 0,
  3811. groupUUID = obj.GroupID
  3812. };
  3813. colliding.Add(detobj);
  3814. }
  3815. //If it is 0, it is to not accept collisions from this object
  3816. else
  3817. {
  3818. }
  3819. }
  3820. else
  3821. {
  3822. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1, out data);
  3823. //If it is 1, it is to accept ONLY collisions from this object, so this other object will not work
  3824. if (!found)
  3825. {
  3826. DetectedObject detobj = new DetectedObject
  3827. {
  3828. keyUUID = obj.UUID,
  3829. nameStr = obj.Name,
  3830. ownerUUID = obj.OwnerID,
  3831. posVector = obj.AbsolutePosition,
  3832. rotQuat = obj.GetWorldRotation(),
  3833. velVector = obj.Velocity,
  3834. colliderType = 0,
  3835. groupUUID = obj.GroupID
  3836. };
  3837. colliding.Add(detobj);
  3838. }
  3839. }
  3840. }
  3841. else
  3842. {
  3843. IScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
  3844. if (av != null)
  3845. {
  3846. if (av.LocalId == localId)
  3847. {
  3848. if (
  3849. m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.UUID.ToString()) ||
  3850. m_parentGroup.RootPart.CollisionFilter.ContainsValue(av.Name))
  3851. {
  3852. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
  3853. out data);
  3854. //If it is 1, it is to accept ONLY collisions from this avatar
  3855. if (found)
  3856. {
  3857. DetectedObject detobj = new DetectedObject
  3858. {
  3859. keyUUID = av.UUID,
  3860. nameStr = av.ControllingClient.Name,
  3861. ownerUUID = av.UUID,
  3862. posVector = av.AbsolutePosition,
  3863. rotQuat = av.Rotation,
  3864. velVector = av.Velocity,
  3865. colliderType = 0,
  3866. groupUUID =
  3867. av.ControllingClient
  3868. .ActiveGroupId
  3869. };
  3870. colliding.Add(detobj);
  3871. }
  3872. //If it is 0, it is to not accept collisions from this avatar
  3873. else
  3874. {
  3875. }
  3876. }
  3877. else
  3878. {
  3879. bool found = m_parentGroup.RootPart.CollisionFilter.TryGetValue(1,
  3880. out data);
  3881. //If it is 1, it is to accept ONLY collisions from this avatar, so this other avatar will not work
  3882. if (!found)
  3883. {
  3884. DetectedObject detobj = new DetectedObject
  3885. {
  3886. keyUUID = av.UUID,
  3887. nameStr = av.ControllingClient.Name,
  3888. ownerUUID = av.UUID,
  3889. posVector = av.AbsolutePosition,
  3890. rotQuat = av.Rotation,
  3891. velVector = av.Velocity,
  3892. colliderType = 0,
  3893. groupUUID =
  3894. av.ControllingClient
  3895. .ActiveGroupId
  3896. };
  3897. colliding.Add(detobj);
  3898. }
  3899. }
  3900. }
  3901. }
  3902. }
  3903. }
  3904. }
  3905. if (colliding.Count > 0)
  3906. {
  3907. EndCollidingMessage.Colliders = colliding;
  3908. // always running this check because if the user deletes the object it would return a null reference.
  3909. if (m_parentGroup == null)
  3910. return;
  3911. if (m_parentGroup.Scene == null)
  3912. return;
  3913. m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(this, EndCollidingMessage);
  3914. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  3915. {
  3916. const int PASS_IF_NOT_HANDLED = 0;
  3917. const int PASS_ALWAYS = 1;
  3918. const int PASS_NEVER = 2;
  3919. if (this.PassCollisions == PASS_NEVER)
  3920. {
  3921. }
  3922. if (this.PassCollisions == PASS_ALWAYS)
  3923. {
  3924. m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
  3925. this.ParentGroup.RootPart, EndCollidingMessage);
  3926. }
  3927. else if (((this.ScriptEvents & scriptEvents.collision_end) == 0) &&
  3928. this.PassCollisions == PASS_IF_NOT_HANDLED)
  3929. //If no event in this prim, pass to parent
  3930. {
  3931. m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(
  3932. this.ParentGroup.RootPart, EndCollidingMessage);
  3933. }
  3934. }
  3935. }
  3936. }
  3937. }
  3938. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision_start) != 0 ||
  3939. (m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision) != 0)
  3940. {
  3941. if (startedColliders.Count > 0)
  3942. {
  3943. ColliderArgs LandStartCollidingMessage = new ColliderArgs();
  3944. List<DetectedObject> colliding = (from localId in startedColliders
  3945. where localId == 0
  3946. select new DetectedObject
  3947. {
  3948. keyUUID = UUID.Zero,
  3949. nameStr = "",
  3950. ownerUUID = UUID.Zero,
  3951. posVector =
  3952. m_parentGroup.RootPart.AbsolutePosition,
  3953. rotQuat = Quaternion.Identity,
  3954. velVector = Vector3.Zero,
  3955. colliderType = 0,
  3956. groupUUID = UUID.Zero
  3957. }).ToList();
  3958. if (colliding.Count > 0)
  3959. {
  3960. LandStartCollidingMessage.Colliders = colliding;
  3961. // always running this check because if the user deletes the object it would return a null reference.
  3962. if (m_parentGroup == null)
  3963. return;
  3964. if (m_parentGroup.Scene == null)
  3965. return;
  3966. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(this,
  3967. LandStartCollidingMessage);
  3968. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  3969. {
  3970. const int PASS_IF_NOT_HANDLED = 0;
  3971. const int PASS_ALWAYS = 1;
  3972. const int PASS_NEVER = 2;
  3973. if (this.PassCollisions == PASS_NEVER)
  3974. {
  3975. }
  3976. if (this.PassCollisions == PASS_ALWAYS)
  3977. {
  3978. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
  3979. this.ParentGroup.RootPart, LandStartCollidingMessage);
  3980. }
  3981. else if (((this.ScriptEvents & scriptEvents.land_collision_start) == 0) &&
  3982. this.PassCollisions == PASS_IF_NOT_HANDLED)
  3983. //If no event in this prim, pass to parent
  3984. {
  3985. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingStart(
  3986. this.ParentGroup.RootPart, LandStartCollidingMessage);
  3987. }
  3988. }
  3989. }
  3990. }
  3991. }
  3992. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision) != 0)
  3993. {
  3994. if (m_lastColliders.Count > 0)
  3995. {
  3996. ColliderArgs LandCollidingMessage = new ColliderArgs();
  3997. List<DetectedObject> colliding = new List<DetectedObject>();
  3998. foreach (uint localId in m_lastColliders)
  3999. {
  4000. if (localId == 0)
  4001. {
  4002. //Hope that all is left is ground!
  4003. DetectedObject detobj = new DetectedObject
  4004. {
  4005. keyUUID = UUID.Zero,
  4006. nameStr = "",
  4007. ownerUUID = UUID.Zero,
  4008. posVector = m_parentGroup.RootPart.AbsolutePosition,
  4009. rotQuat = Quaternion.Identity,
  4010. velVector = Vector3.Zero,
  4011. colliderType = 0,
  4012. groupUUID = UUID.Zero
  4013. };
  4014. colliding.Add(detobj);
  4015. }
  4016. }
  4017. if (colliding.Count > 0)
  4018. {
  4019. LandCollidingMessage.Colliders = colliding;
  4020. // always running this check because if the user deletes the object it would return a null reference.
  4021. if (m_parentGroup == null)
  4022. return;
  4023. if (m_parentGroup.Scene == null)
  4024. return;
  4025. m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(this, LandCollidingMessage);
  4026. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  4027. {
  4028. const int PASS_IF_NOT_HANDLED = 0;
  4029. const int PASS_ALWAYS = 1;
  4030. const int PASS_NEVER = 2;
  4031. if (this.PassCollisions == PASS_NEVER)
  4032. {
  4033. }
  4034. if (this.PassCollisions == PASS_ALWAYS)
  4035. {
  4036. m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(
  4037. this.ParentGroup.RootPart,
  4038. LandCollidingMessage);
  4039. }
  4040. else if (((this.ScriptEvents & scriptEvents.land_collision) == 0) &&
  4041. this.PassCollisions == PASS_IF_NOT_HANDLED)
  4042. //If no event in this prim, pass to parent
  4043. {
  4044. m_parentGroup.Scene.EventManager.TriggerScriptLandColliding(
  4045. this.ParentGroup.RootPart, LandCollidingMessage);
  4046. }
  4047. }
  4048. }
  4049. }
  4050. }
  4051. if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.land_collision_end) != 0)
  4052. {
  4053. if (endedColliders.Count > 0)
  4054. {
  4055. ColliderArgs LandEndCollidingMessage = new ColliderArgs();
  4056. List<DetectedObject> colliding = (from localId in startedColliders
  4057. where localId == 0
  4058. select new DetectedObject
  4059. {
  4060. keyUUID = UUID.Zero,
  4061. nameStr = "",
  4062. ownerUUID = UUID.Zero,
  4063. posVector =
  4064. m_parentGroup.RootPart.AbsolutePosition,
  4065. rotQuat = Quaternion.Identity,
  4066. velVector = Vector3.Zero,
  4067. colliderType = 0,
  4068. groupUUID = UUID.Zero
  4069. }).ToList();
  4070. if (colliding.Count > 0)
  4071. {
  4072. LandEndCollidingMessage.Colliders = colliding;
  4073. // always running this check because if the user deletes the object it would return a null reference.
  4074. if (m_parentGroup == null)
  4075. return;
  4076. if (m_parentGroup.Scene == null)
  4077. return;
  4078. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(this, LandEndCollidingMessage);
  4079. if ((this.UUID != this.ParentGroup.RootPart.UUID))
  4080. {
  4081. const int PASS_IF_NOT_HANDLED = 0;
  4082. const int PASS_ALWAYS = 1;
  4083. const int PASS_NEVER = 2;
  4084. if (this.PassCollisions == PASS_NEVER)
  4085. {
  4086. }
  4087. if (this.PassCollisions == PASS_ALWAYS)
  4088. {
  4089. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
  4090. this.ParentGroup.RootPart, LandEndCollidingMessage);
  4091. }
  4092. else if (((this.ScriptEvents & scriptEvents.land_collision_end) == 0) &&
  4093. this.PassCollisions == PASS_IF_NOT_HANDLED)
  4094. //If no event in this prim, pass to parent
  4095. {
  4096. m_parentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd(
  4097. this.ParentGroup.RootPart, LandEndCollidingMessage);
  4098. }
  4099. }
  4100. }
  4101. }
  4102. }
  4103. }
  4104. }
  4105. public void PhysicsOutOfBounds(Vector3 pos)
  4106. {
  4107. MainConsole.Instance.Error("[Physics]: Physical object " + Name + ", localID " + LocalId +
  4108. " went out of bounds at " + pos + ". Stopping at " + AbsolutePosition +
  4109. " and making non-physical.");
  4110. lock (ParentGroup.Scene.PhysicsReturns)
  4111. {
  4112. if (!ParentGroup.Scene.PhysicsReturns.Contains(ParentGroup))
  4113. ParentGroup.Scene.PhysicsReturns.Add(ParentGroup);
  4114. }
  4115. }
  4116. public virtual void PhysicsRequestingTerseUpdate()
  4117. {
  4118. if (PhysActor != null)
  4119. {
  4120. // Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0);
  4121. m_parentGroup.SetAbsolutePosition(false, PhysActor.Position);
  4122. //m_parentGroup.RootPart.m_groupPosition = newpos;
  4123. }
  4124. ScheduleUpdate(PrimUpdateFlags.TerseUpdate);
  4125. }
  4126. public void RemoveScriptEvents(UUID scriptid)
  4127. {
  4128. lock (m_scriptEvents)
  4129. {
  4130. if (m_scriptEvents.ContainsKey(scriptid))
  4131. {
  4132. scriptEvents oldparts = scriptEvents.None;
  4133. oldparts = m_scriptEvents[scriptid];
  4134. // remove values from aggregated script events
  4135. AggregateScriptEvents &= ~oldparts;
  4136. m_scriptEvents.Remove(scriptid);
  4137. aggregateScriptEvents();
  4138. }
  4139. }
  4140. }
  4141. /// <summary>
  4142. /// Resize this part.
  4143. /// </summary>
  4144. /// <param name="scale"></param>
  4145. public void Resize(Vector3 scale)
  4146. {
  4147. Scale = scale;
  4148. ParentGroup.HasGroupChanged = true;
  4149. ScheduleUpdate(PrimUpdateFlags.Shape);
  4150. }
  4151. public void stopLookAt()
  4152. {
  4153. APIDEnabled = false;
  4154. }
  4155. /// <summary>
  4156. /// Check to see whether the given flags make it a terse update
  4157. /// </summary>
  4158. /// <param name="flags"></param>
  4159. /// <returns></returns>
  4160. private bool IsTerse(PrimUpdateFlags flags)
  4161. {
  4162. return flags.HasFlag((PrimUpdateFlags.TerseUpdate))
  4163. && !flags.HasFlag((PrimUpdateFlags.AttachmentPoint | PrimUpdateFlags.ClickAction |
  4164. PrimUpdateFlags.CollisionPlane | PrimUpdateFlags.ExtraData |
  4165. PrimUpdateFlags.FindBest | PrimUpdateFlags.FullUpdate |
  4166. PrimUpdateFlags.Joint | PrimUpdateFlags.Material | PrimUpdateFlags.MediaURL |
  4167. PrimUpdateFlags.NameValue |
  4168. PrimUpdateFlags.ParentID | PrimUpdateFlags.Particles | PrimUpdateFlags.PrimData |
  4169. PrimUpdateFlags.PrimFlags |
  4170. PrimUpdateFlags.ScratchPad | PrimUpdateFlags.Shape | PrimUpdateFlags.Sound |
  4171. PrimUpdateFlags.Text |
  4172. PrimUpdateFlags.TextureAnim | PrimUpdateFlags.Textures)) &&
  4173. !flags.HasFlag(PrimUpdateFlags.ForcedFullUpdate);
  4174. }
  4175. public void SetAttachmentPoint(int AttachmentPoint)
  4176. {
  4177. //Update the saved if needed
  4178. if (AttachmentPoint == 0 && this.AttachmentPoint != 0)
  4179. {
  4180. this.SavedAttachedPos = this.AttachedPos;
  4181. this.SavedAttachmentPoint = this.AttachmentPoint;
  4182. }
  4183. this.AttachmentPoint = AttachmentPoint;
  4184. IsAttachment = AttachmentPoint != 0;
  4185. // save the attachment point.
  4186. //if (AttachmentPoint != 0)
  4187. //{
  4188. m_shape.State = (byte) AttachmentPoint;
  4189. //}
  4190. }
  4191. public void SetPhysActorCameraPos(Quaternion CameraRotation)
  4192. {
  4193. if (PhysActor != null)
  4194. {
  4195. PhysActor.SetCameraPos(CameraRotation);
  4196. }
  4197. }
  4198. /// <summary>
  4199. /// Tell us if this object has cut, hollow, dimple, and other factors affecting the number of faces
  4200. /// </summary>
  4201. /// <param name="primType"></param>
  4202. /// <param name="shape"></param>
  4203. /// <param name="hasCut"></param>
  4204. /// <param name="hasHollow"></param>
  4205. /// <param name="hasDimple"></param>
  4206. /// <param name="hasProfileCut"></param>
  4207. protected static void HasCutHollowDimpleProfileCut(PrimType primType, PrimitiveBaseShape shape, out bool hasCut,
  4208. out bool hasHollow,
  4209. out bool hasDimple, out bool hasProfileCut)
  4210. {
  4211. if (primType == PrimType.BOX
  4212. ||
  4213. primType == PrimType.CYLINDER
  4214. ||
  4215. primType == PrimType.PRISM)
  4216. hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
  4217. else
  4218. hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
  4219. hasHollow = shape.ProfileHollow > 0;
  4220. hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
  4221. hasProfileCut = hasDimple; // is it the same thing?
  4222. }
  4223. public void SetGroup(UUID groupID)
  4224. {
  4225. _groupID = groupID;
  4226. }
  4227. public void SetPhysicsAxisRotation()
  4228. {
  4229. if (PhysActor != null)
  4230. PhysActor.LockAngularMotion(RotationAxis);
  4231. }
  4232. /// <summary>
  4233. /// Serialize this part to xml.
  4234. /// </summary>
  4235. /// <param name="xmlWriter"></param>
  4236. public void ToXml(XmlTextWriter xmlWriter)
  4237. {
  4238. SceneEntitySerializer.SceneObjectSerializer.ToXmlFormat(this, xmlWriter);
  4239. }
  4240. public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
  4241. {
  4242. m_shape.ReadInUpdateExtraParam(type, inUse, data);
  4243. if (type == 0x30)
  4244. {
  4245. if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
  4246. m_parentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), true, AssetReceived);
  4247. }
  4248. ValidpartOOB = false;
  4249. ParentGroup.HasGroupChanged = true;
  4250. ScheduleUpdate(PrimUpdateFlags.Shape);
  4251. }
  4252. public void UpdateGroupPosition(Vector3 pos)
  4253. {
  4254. if ((pos.X != GroupPosition.X) ||
  4255. (pos.Y != GroupPosition.Y) ||
  4256. (pos.Z != GroupPosition.Z))
  4257. {
  4258. // Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
  4259. FixGroupPosition(pos, false);
  4260. ScheduleTerseUpdate();
  4261. }
  4262. }
  4263. public void UpdatePermissions(UUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
  4264. {
  4265. bool set = addRemTF == 1;
  4266. bool god = m_parentGroup.Scene.Permissions.IsGod(AgentID);
  4267. uint baseMask = _baseMask;
  4268. if (god)
  4269. baseMask = 0x7ffffff0;
  4270. // Are we the owner?
  4271. if (m_parentGroup.Scene.Permissions.CanEditObject(this.UUID, AgentID))
  4272. {
  4273. uint exportPermission = (1 << 30);
  4274. if ((mask & exportPermission) == exportPermission)
  4275. {
  4276. //Only the creator can set export permissions
  4277. if (CreatorID != AgentID)
  4278. mask &= exportPermission;
  4279. }
  4280. switch (field)
  4281. {
  4282. case 1:
  4283. if (god)
  4284. {
  4285. _baseMask = ApplyMask(_baseMask, set, mask);
  4286. Inventory.ApplyGodPermissions(_baseMask);
  4287. }
  4288. break;
  4289. case 2:
  4290. _ownerMask = ApplyMask(_ownerMask, set, mask) &
  4291. baseMask;
  4292. break;
  4293. case 4:
  4294. _groupMask = ApplyMask(_groupMask, set, mask) &
  4295. baseMask;
  4296. break;
  4297. case 8:
  4298. _everyoneMask = ApplyMask(_everyoneMask, set, mask) &
  4299. baseMask;
  4300. break;
  4301. case 16:
  4302. _nextOwnerMask = ApplyMask(_nextOwnerMask, set, mask) &
  4303. baseMask;
  4304. // Prevent the client from creating no mod, no copy
  4305. // objects
  4306. if ((_nextOwnerMask & (uint) PermissionMask.Copy) == 0)
  4307. _nextOwnerMask |= (uint) PermissionMask.Transfer;
  4308. _nextOwnerMask |= (uint) PermissionMask.Move;
  4309. break;
  4310. }
  4311. ParentGroup.ScheduleGroupUpdate(PrimUpdateFlags.PrimFlags);
  4312. SendObjectPropertiesToClient(AgentID);
  4313. }
  4314. }
  4315. /// <summary>
  4316. /// Update the texture entry for this part.
  4317. /// </summary>
  4318. /// <param name="textureEntry"></param>
  4319. /// <param name="sendChangedEvent"></param>
  4320. public void UpdateTextureEntry(byte[] textureEntry, bool sendChangedEvent)
  4321. {
  4322. bool same = true;
  4323. byte[] old = m_shape.TextureEntry;
  4324. if (old.Length == textureEntry.Length)
  4325. {
  4326. #if (!ISWIN)
  4327. for (int i = 0; i < textureEntry.Length; i++)
  4328. if (old[i] != textureEntry[i])
  4329. {
  4330. same = false;
  4331. break;
  4332. }
  4333. #else
  4334. if (textureEntry.Where((t, i) => old[i] != t).Any())
  4335. {
  4336. same = false;
  4337. }
  4338. #endif
  4339. }
  4340. else
  4341. same = false;
  4342. if (same)
  4343. return;
  4344. Primitive.TextureEntry oldEntry = m_shape.Textures;
  4345. m_shape.TextureEntry = textureEntry;
  4346. bool textureChanged = false;
  4347. bool colorChanged = false;
  4348. if (m_shape.Textures.DefaultTexture.RGBA.A != oldEntry.DefaultTexture.RGBA.A ||
  4349. m_shape.Textures.DefaultTexture.RGBA.R != oldEntry.DefaultTexture.RGBA.R ||
  4350. m_shape.Textures.DefaultTexture.RGBA.G != oldEntry.DefaultTexture.RGBA.G ||
  4351. m_shape.Textures.DefaultTexture.RGBA.B != oldEntry.DefaultTexture.RGBA.B)
  4352. {
  4353. colorChanged = true;
  4354. }
  4355. if (m_shape.Textures.DefaultTexture.TextureID != oldEntry.DefaultTexture.TextureID)
  4356. {
  4357. textureChanged = true;
  4358. }
  4359. if (!(colorChanged && textureChanged)) // if both already changed so don't bother checking further
  4360. {
  4361. for (int i = 0; i < GetNumberOfSides(); i++)
  4362. {
  4363. if (m_shape.Textures.FaceTextures[i] != null &&
  4364. oldEntry.FaceTextures[i] != null)
  4365. {
  4366. if (m_shape.Textures.FaceTextures[i].RGBA.A != oldEntry.FaceTextures[i].RGBA.A ||
  4367. m_shape.Textures.FaceTextures[i].RGBA.R != oldEntry.FaceTextures[i].RGBA.R ||
  4368. m_shape.Textures.FaceTextures[i].RGBA.G != oldEntry.FaceTextures[i].RGBA.G ||
  4369. m_shape.Textures.FaceTextures[i].RGBA.B != oldEntry.FaceTextures[i].RGBA.B)
  4370. {
  4371. colorChanged = true;
  4372. }
  4373. if (m_shape.Textures.FaceTextures[i].TextureID != oldEntry.FaceTextures[i].TextureID)
  4374. {
  4375. textureChanged = true;
  4376. }
  4377. }
  4378. }
  4379. }
  4380. if (colorChanged && sendChangedEvent) TriggerScriptChangedEvent(Changed.COLOR);
  4381. if (textureChanged && sendChangedEvent) TriggerScriptChangedEvent(Changed.TEXTURE);
  4382. ParentGroup.HasGroupChanged = true;
  4383. ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  4384. }
  4385. public override string ToString()
  4386. {
  4387. return String.Format("{0} {1} linkNum {3} (parent {2}))", Name, UUID, ParentGroup, LinkNum);
  4388. }
  4389. #endregion Public Methods
  4390. public void ApplyPermissions(uint permissions)
  4391. {
  4392. _ownerMask = permissions;
  4393. }
  4394. private void UpdateLookAt()
  4395. {
  4396. try
  4397. {
  4398. //PID movement
  4399. // Has to be physical (works with phantom too)
  4400. if (PIDActive && ((Flags & PrimFlags.Physics) != 0))
  4401. {
  4402. Vector3 _target_velocity =
  4403. new Vector3(
  4404. (PIDTarget.X - m_initialPIDLocation.X)*(PIDTau),
  4405. (PIDTarget.Y - m_initialPIDLocation.Y)*(PIDTau),
  4406. (PIDTarget.Z - m_initialPIDLocation.Z)*(PIDTau)
  4407. );
  4408. if (PIDTarget.ApproxEquals(AbsolutePosition, 0.1f))
  4409. {
  4410. ParentGroup.Velocity = Vector3.Zero;
  4411. ParentGroup.SetAbsolutePosition(true, PIDTarget);
  4412. this.ScheduleTerseUpdate();
  4413. //End the movement
  4414. //SetMoveToTarget(false, Vector3.Zero, 0);
  4415. }
  4416. else
  4417. {
  4418. //ParentGroup.SetAbsolutePosition(true, ParentGroup.AbsolutePosition + _target_velocity);
  4419. Velocity = _target_velocity;
  4420. this.ScheduleTerseUpdate();
  4421. }
  4422. }
  4423. else if (PIDHoverActive)
  4424. {
  4425. Vector3 _target_velocity;
  4426. ITerrainChannel terrain = ParentGroup.Scene.RequestModuleInterface<ITerrainChannel>();
  4427. if (terrain == null)
  4428. return;
  4429. float groundHeight =
  4430. terrain[(int) ParentGroup.AbsolutePosition.X, (int) ParentGroup.AbsolutePosition.Y];
  4431. switch (PIDHoverType)
  4432. {
  4433. case PIDHoverType.Ground:
  4434. _target_velocity =
  4435. new Vector3(
  4436. 0, 0, ((groundHeight + PIDHoverHeight) - m_initialPIDLocation.Z)*(PIDTau)
  4437. );
  4438. break;
  4439. case PIDHoverType.GroundAndWater:
  4440. if (ParentGroup.Scene.RegionInfo.RegionSettings.WaterHeight < groundHeight)
  4441. groundHeight = (float) ParentGroup.Scene.RegionInfo.RegionSettings.WaterHeight;
  4442. _target_velocity =
  4443. new Vector3(
  4444. 0, 0, ((groundHeight + PIDHoverHeight) - m_initialPIDLocation.Z)*(PIDTau)
  4445. );
  4446. break;
  4447. default:
  4448. return;
  4449. }
  4450. Velocity = _target_velocity;
  4451. this.ScheduleTerseUpdate();
  4452. }
  4453. if (APIDEnabled)
  4454. {
  4455. if (APIDIterations <= 1)
  4456. {
  4457. UpdateRotation(APIDTarget);
  4458. APIDTarget = Quaternion.Identity;
  4459. return;
  4460. }
  4461. Quaternion rot = Quaternion.Slerp(GetRotationOffset(), APIDTarget, 1.0f/(float) APIDIterations);
  4462. UpdateRotation(rot);
  4463. APIDIterations--;
  4464. // This ensures that we'll check this object on the next iteration
  4465. ParentGroup.ScheduleGroupTerseUpdate();
  4466. }
  4467. }
  4468. catch (Exception ex)
  4469. {
  4470. MainConsole.Instance.Error("[Physics] " + ex);
  4471. }
  4472. }
  4473. internal void TriggerScriptMovingStartEvent()
  4474. {
  4475. if ((AggregateScriptEvents & scriptEvents.moving_start) == 0)
  4476. return;
  4477. if (m_parentGroup != null && m_parentGroup.Scene != null && m_parentGroup.Scene.EventManager != null)
  4478. m_parentGroup.Scene.EventManager.TriggerOnScriptMovingStartEvent(this);
  4479. }
  4480. internal void TriggerScriptMovingEndEvent()
  4481. {
  4482. if ((AggregateScriptEvents & scriptEvents.moving_end) == 0)
  4483. return;
  4484. if (m_parentGroup != null && m_parentGroup.Scene != null && m_parentGroup.Scene.EventManager != null)
  4485. m_parentGroup.Scene.EventManager.TriggerOnScriptMovingEndEvent(this);
  4486. }
  4487. }
  4488. }