SceneObjectGroup.cs 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Drawing;
  30. using System.IO;
  31. using System.Text;
  32. using System.Xml;
  33. using Axiom.Math;
  34. using libsecondlife;
  35. using libsecondlife.Packets;
  36. using OpenSim.Framework;
  37. using OpenSim.Framework.Console;
  38. using OpenSim.Region.Environment.Interfaces;
  39. using OpenSim.Region.Physics.Manager;
  40. namespace OpenSim.Region.Environment.Scenes
  41. {
  42. public delegate void PrimCountTaintedDelegate();
  43. public partial class SceneObjectGroup : EntityBase
  44. {
  45. protected SceneObjectPart m_rootPart;
  46. /// <summary>
  47. /// The constituent parts of this group
  48. /// </summary>
  49. protected Dictionary<LLUUID, SceneObjectPart> m_parts = new Dictionary<LLUUID, SceneObjectPart>();
  50. protected ulong m_regionHandle;
  51. public event PrimCountTaintedDelegate OnPrimCountTainted;
  52. private PrimCountTaintedDelegate handlerPrimCountTainted = null;
  53. /// <summary>
  54. /// Signal whether the non-inventory attributes of any prims in the group have changed
  55. /// since the group's last persistent backup
  56. /// </summary>
  57. public bool HasGroupChanged = false;
  58. private LLVector3 lastPhysGroupPos;
  59. private LLQuaternion lastPhysGroupRot;
  60. #region Properties
  61. /// <summary>
  62. ///
  63. /// </summary>
  64. public int PrimCount
  65. {
  66. get { return m_parts.Count; }
  67. }
  68. public LLQuaternion GroupRotation
  69. {
  70. get { return m_rootPart.RotationOffset; }
  71. }
  72. public LLUUID GroupID
  73. {
  74. get { return m_rootPart.GroupID; }
  75. set { m_rootPart.GroupID = value; }
  76. }
  77. /// <summary>
  78. ///
  79. /// </summary>
  80. public LLVector3 GroupCentrePoint
  81. {
  82. get { return new LLVector3(0, 0, 0); }
  83. }
  84. public Dictionary<LLUUID, SceneObjectPart> Children
  85. {
  86. get { return m_parts; }
  87. set { m_parts = value; }
  88. }
  89. public SceneObjectPart RootPart
  90. {
  91. get { return m_rootPart; }
  92. set { m_rootPart = value; }
  93. }
  94. public ulong RegionHandle
  95. {
  96. get { return m_regionHandle; }
  97. set
  98. {
  99. m_regionHandle = value;
  100. lock (m_parts)
  101. {
  102. foreach (SceneObjectPart part in m_parts.Values)
  103. {
  104. part.RegionHandle = m_regionHandle;
  105. }
  106. }
  107. }
  108. }
  109. public override LLVector3 AbsolutePosition
  110. {
  111. get
  112. {
  113. if( m_rootPart == null )
  114. {
  115. throw new NullReferenceException(string.Format("Object {0} has no root part.", m_uuid));
  116. }
  117. return m_rootPart.GroupPosition;
  118. }
  119. set
  120. {
  121. LLVector3 val = value;
  122. if (val.X > 257f || val.X < -1f || val.Y > 257f || val.Y < -1f)
  123. {
  124. m_scene.CrossPrimGroupIntoNewRegion(val, this);
  125. }
  126. lock (m_parts)
  127. {
  128. foreach (SceneObjectPart part in m_parts.Values)
  129. {
  130. part.GroupPosition = val;
  131. }
  132. }
  133. //if (m_rootPart.PhysActor != null)
  134. //{
  135. //m_rootPart.PhysActor.Position =
  136. //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
  137. //m_rootPart.GroupPosition.Z);
  138. //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  139. //}
  140. }
  141. }
  142. public override uint LocalId
  143. {
  144. get {
  145. if (m_rootPart == null)
  146. {
  147. m_log.Error("[PRIMGROUP]: Unable to find the rootpart for a LocalId Request!");
  148. return 0;
  149. }
  150. return m_rootPart.LocalId; }
  151. set { m_rootPart.LocalId = value; }
  152. }
  153. public override LLUUID UUID
  154. {
  155. get { return m_rootPart.UUID; }
  156. set { m_rootPart.UUID = value; }
  157. }
  158. public LLUUID OwnerID
  159. {
  160. get {
  161. if (m_rootPart == null)
  162. return LLUUID.Zero;
  163. return m_rootPart.OwnerID;
  164. }
  165. set { m_rootPart.OwnerID = value; }
  166. }
  167. public Color Color
  168. {
  169. get { return m_rootPart.Color; }
  170. set { m_rootPart.Color = value; }
  171. }
  172. public string Text
  173. {
  174. get { return m_rootPart.Text; }
  175. set { m_rootPart.Text = value; }
  176. }
  177. /// <summary>
  178. /// Added because the Parcel code seems to use it
  179. /// but not sure a object should have this
  180. /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
  181. /// think really there should be a list (or whatever) in each scenepresence
  182. /// saying what prim(s) that user has selected.
  183. /// </summary>
  184. protected bool m_isSelected = false;
  185. protected virtual bool InSceneBackup
  186. {
  187. get { return true; }
  188. }
  189. public bool IsSelected
  190. {
  191. get { return m_isSelected; }
  192. set {
  193. m_isSelected = value;
  194. // Tell physics engine that group is selected
  195. if (m_rootPart.PhysActor != null)
  196. {
  197. m_rootPart.PhysActor.Selected = value;
  198. // Pass it on to the children.
  199. foreach (SceneObjectPart child in Children.Values)
  200. {
  201. if (child.PhysActor != null)
  202. {
  203. child.PhysActor.Selected = value;
  204. }
  205. }
  206. }
  207. }
  208. }
  209. // The UUID for the Region this Object is in.
  210. public LLUUID RegionUUID
  211. {
  212. get
  213. {
  214. if (m_scene != null)
  215. {
  216. return m_scene.RegionInfo.RegionID;
  217. }
  218. return LLUUID.Zero;
  219. }
  220. }
  221. #endregion
  222. #region Constructors
  223. /// <summary>
  224. ///
  225. /// </summary>
  226. public SceneObjectGroup()
  227. {
  228. }
  229. /// <summary>
  230. /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
  231. /// The original SceneObjectPart will be used rather than a copy, preserving
  232. /// its existing localID and UUID.
  233. /// </summary>
  234. public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
  235. {
  236. m_scene = scene;
  237. part.SetParent(this);
  238. part.ParentID = 0;
  239. part.LinkNum = 0;
  240. m_parts.Add(part.UUID, part);
  241. SetPartAsRoot(part);
  242. RegionHandle = regionHandle;
  243. AttachToBackup();
  244. ApplyPhysics(scene.m_physicalPrim);
  245. ScheduleGroupForFullUpdate();
  246. }
  247. /// <summary>
  248. ///
  249. /// </summary>
  250. public SceneObjectGroup(Scene scene, ulong regionHandle, string xmlData)
  251. {
  252. m_scene = scene;
  253. m_regionHandle = regionHandle;
  254. StringReader sr = new StringReader(xmlData);
  255. XmlTextReader reader = new XmlTextReader(sr);
  256. reader.Read();
  257. reader.ReadStartElement("SceneObjectGroup");
  258. reader.ReadStartElement("RootPart");
  259. m_rootPart = SceneObjectPart.FromXml(reader);
  260. AddPart(m_rootPart);
  261. reader.ReadEndElement();
  262. while (reader.Read())
  263. {
  264. switch (reader.NodeType)
  265. {
  266. case XmlNodeType.Element:
  267. if (reader.Name == "Part")
  268. {
  269. reader.Read();
  270. SceneObjectPart part = SceneObjectPart.FromXml(reader);
  271. part.LocalId = m_scene.PrimIDAllocate();
  272. AddPart(part);
  273. part.RegionHandle = m_regionHandle;
  274. part.TrimPermissions();
  275. }
  276. break;
  277. case XmlNodeType.EndElement:
  278. break;
  279. }
  280. }
  281. reader.Close();
  282. sr.Close();
  283. m_rootPart.LocalId = m_scene.PrimIDAllocate();
  284. m_rootPart.ParentID = 0;
  285. m_rootPart.RegionHandle = m_regionHandle;
  286. UpdateParentIDs();
  287. AttachToBackup();
  288. ApplyPhysics(scene.m_physicalPrim);
  289. ScheduleGroupForFullUpdate();
  290. }
  291. /// <summary>
  292. ///
  293. /// </summary>
  294. public SceneObjectGroup(string xmlData)
  295. {
  296. StringReader sr = new StringReader(xmlData);
  297. XmlTextReader reader = new XmlTextReader(sr);
  298. reader.Read();
  299. reader.ReadStartElement("SceneObjectGroup");
  300. m_rootPart = SceneObjectPart.FromXml(reader);
  301. m_rootPart.SetParent(this);
  302. m_parts.Add(m_rootPart.UUID, m_rootPart);
  303. m_rootPart.ParentID = 0;
  304. m_rootPart.LinkNum = 0;
  305. reader.Read();
  306. bool more = true;
  307. while (more)
  308. {
  309. switch (reader.NodeType)
  310. {
  311. case XmlNodeType.Element:
  312. if (reader.Name == "SceneObjectPart")
  313. {
  314. SceneObjectPart Part = SceneObjectPart.FromXml(reader);
  315. AddPart(Part);
  316. }
  317. else
  318. {
  319. Console.WriteLine("found unexpected element: " + reader.Name);
  320. reader.Read();
  321. }
  322. break;
  323. case XmlNodeType.EndElement:
  324. reader.Read();
  325. break;
  326. }
  327. more = !reader.EOF;
  328. }
  329. reader.Close();
  330. sr.Close();
  331. UpdateParentIDs();
  332. }
  333. private void AttachToBackup()
  334. {
  335. if (InSceneBackup)
  336. {
  337. m_scene.EventManager.OnBackup += ProcessBackup;
  338. }
  339. }
  340. public EntityIntersection TestIntersection(Ray hRay)
  341. {
  342. // We got a request from the inner_scene to raytrace along the Ray hRay
  343. // We're going to check all of the prim in this group for intersection with the ray
  344. // If we get a result, we're going to find the closest result to the origin of the ray
  345. // and send back the intersection information back to the innerscene.
  346. EntityIntersection returnresult = new EntityIntersection();
  347. lock (m_parts)
  348. {
  349. foreach (SceneObjectPart part in m_parts.Values)
  350. {
  351. // Temporary commented to stop compiler warning
  352. //Vector3 partPosition =
  353. // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
  354. Quaternion parentrotation =
  355. new Quaternion(GroupRotation.W, GroupRotation.X, GroupRotation.Y, GroupRotation.Z);
  356. // Telling the prim to raytrace.
  357. //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
  358. EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation);
  359. // This may need to be updated to the maximum draw distance possible..
  360. // We might (and probably will) be checking for prim creation from other sims
  361. // when the camera crosses the border.
  362. float idist = (float)Constants.RegionSize;
  363. if (inter.HitTF)
  364. {
  365. // We need to find the closest prim to return to the testcaller along the ray
  366. if (inter.distance < idist)
  367. {
  368. idist = inter.distance;
  369. returnresult.HitTF = true;
  370. returnresult.ipoint = inter.ipoint;
  371. returnresult.obj = part;
  372. returnresult.normal = inter.normal;
  373. returnresult.distance = inter.distance;
  374. }
  375. }
  376. }
  377. }
  378. return returnresult;
  379. }
  380. /// <summary>
  381. ///
  382. /// </summary>
  383. public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
  384. LLQuaternion rot, PrimitiveBaseShape shape)
  385. {
  386. m_regionHandle = regionHandle;
  387. m_scene = scene;
  388. // this.Pos = pos;
  389. LLVector3 rootOffset = new LLVector3(0, 0, 0);
  390. SceneObjectPart newPart =
  391. new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rot, rootOffset);
  392. newPart.LinkNum = m_parts.Count;
  393. m_parts.Add(newPart.UUID, newPart);
  394. SetPartAsRoot(newPart);
  395. AttachToBackup();
  396. //ApplyPhysics(scene.m_physicalPrim);
  397. }
  398. /// <summary>
  399. ///
  400. /// </summary>
  401. public SceneObjectGroup(Scene scene, ulong regionHandle, LLUUID ownerID, uint localID, LLVector3 pos,
  402. PrimitiveBaseShape shape)
  403. : this(scene, regionHandle, ownerID, localID, pos, LLQuaternion.Identity, shape)
  404. {
  405. }
  406. #endregion
  407. public string ToXmlString()
  408. {
  409. using (StringWriter sw = new StringWriter())
  410. {
  411. using (XmlTextWriter writer = new XmlTextWriter(sw))
  412. {
  413. ToXml(writer);
  414. }
  415. return sw.ToString();
  416. }
  417. }
  418. public void ToXml(XmlTextWriter writer)
  419. {
  420. writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
  421. writer.WriteStartElement(String.Empty, "RootPart", String.Empty);
  422. m_rootPart.ToXml(writer);
  423. writer.WriteEndElement();
  424. writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
  425. lock (m_parts)
  426. {
  427. foreach (SceneObjectPart part in m_parts.Values)
  428. {
  429. if (part.UUID != m_rootPart.UUID)
  430. {
  431. writer.WriteStartElement(String.Empty, "Part", String.Empty);
  432. part.ToXml(writer);
  433. writer.WriteEndElement();
  434. }
  435. }
  436. }
  437. writer.WriteEndElement();
  438. writer.WriteEndElement();
  439. }
  440. public string ToXmlString2()
  441. {
  442. using (StringWriter sw = new StringWriter())
  443. {
  444. using (XmlTextWriter writer = new XmlTextWriter(sw))
  445. {
  446. ToXml2(writer);
  447. }
  448. return sw.ToString();
  449. }
  450. }
  451. public void ToXml2(XmlTextWriter writer)
  452. {
  453. writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
  454. m_rootPart.ToXml(writer);
  455. writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
  456. lock (m_parts)
  457. {
  458. foreach (SceneObjectPart part in m_parts.Values)
  459. {
  460. if (part.UUID != m_rootPart.UUID)
  461. {
  462. part.ToXml(writer);
  463. }
  464. }
  465. }
  466. writer.WriteEndElement();
  467. writer.WriteEndElement();
  468. }
  469. #region Copying
  470. /// <summary>
  471. ///
  472. /// </summary>
  473. /// <returns></returns>
  474. public SceneObjectGroup Copy(LLUUID cAgentID, LLUUID cGroupID)
  475. {
  476. SceneObjectGroup dupe = (SceneObjectGroup) MemberwiseClone();
  477. dupe.m_parts = new Dictionary<LLUUID, SceneObjectPart>();
  478. dupe.m_parts.Clear();
  479. //dupe.OwnerID = AgentID;
  480. //dupe.GroupID = GroupID;
  481. dupe.AbsolutePosition = new LLVector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
  482. dupe.m_scene = m_scene;
  483. dupe.m_regionHandle = m_regionHandle;
  484. dupe.CopyRootPart(m_rootPart, OwnerID, GroupID);
  485. dupe.m_rootPart.TrimPermissions();
  486. /// may need to create a new Physics actor.
  487. if (dupe.RootPart.PhysActor != null)
  488. {
  489. PrimitiveBaseShape pbs = dupe.RootPart.Shape;
  490. dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
  491. dupe.RootPart.Name,
  492. pbs,
  493. new PhysicsVector(dupe.RootPart.AbsolutePosition.X, dupe.RootPart.AbsolutePosition.Y,
  494. dupe.RootPart.AbsolutePosition.Z),
  495. new PhysicsVector(dupe.RootPart.Scale.X, dupe.RootPart.Scale.Y, dupe.RootPart.Scale.Z),
  496. new Quaternion(dupe.RootPart.RotationOffset.W, dupe.RootPart.RotationOffset.X,
  497. dupe.RootPart.RotationOffset.Y, dupe.RootPart.RotationOffset.Z),
  498. dupe.RootPart.PhysActor.IsPhysical);
  499. dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
  500. dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
  501. }
  502. // Now we've made a copy that replaces this one, we need to
  503. // switch the owner to the person who did the copying
  504. // Second Life copies an object and duplicates the first one in it's place
  505. // So, we have to make a copy of this one, set it in it's place then set the owner on this one
  506. SetRootPartOwner(m_rootPart, cAgentID, cGroupID);
  507. m_rootPart.ScheduleFullUpdate();
  508. List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.Values);
  509. foreach (SceneObjectPart part in partList)
  510. {
  511. if (part.UUID != m_rootPart.UUID)
  512. {
  513. dupe.CopyPart(part, OwnerID, GroupID);
  514. SetPartOwner(part, cAgentID, cGroupID);
  515. part.ScheduleFullUpdate();
  516. }
  517. }
  518. dupe.UpdateParentIDs();
  519. dupe.AttachToBackup();
  520. ScheduleGroupForFullUpdate();
  521. return dupe;
  522. }
  523. /// <summary>
  524. ///
  525. /// </summary>
  526. /// <param name="part"></param>
  527. public void CopyRootPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
  528. {
  529. SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
  530. newPart.SetParent(this);
  531. lock (m_parts)
  532. {
  533. m_parts.Add(newPart.UUID, newPart);
  534. }
  535. SetPartAsRoot(newPart);
  536. }
  537. public void ScriptSetPhysicsStatus(bool UsePhysics)
  538. {
  539. if (m_scene.m_physicalPrim)
  540. {
  541. lock (m_parts)
  542. {
  543. foreach (SceneObjectPart part in m_parts.Values)
  544. {
  545. if (UsePhysics)
  546. part.AddFlag(LLObject.ObjectFlags.Physics);
  547. else
  548. part.RemFlag(LLObject.ObjectFlags.Physics);
  549. part.DoPhysicsPropertyUpdate(UsePhysics, false);
  550. IsSelected = false;
  551. }
  552. }
  553. }
  554. }
  555. public void ScriptSetPhantomStatus(bool PhantomStatus)
  556. {
  557. lock (m_parts)
  558. {
  559. foreach (SceneObjectPart part in m_parts.Values)
  560. {
  561. if (PhantomStatus)
  562. {
  563. part.AddFlag(LLObject.ObjectFlags.Phantom);
  564. if (part.PhysActor != null)
  565. {
  566. m_scene.PhysicsScene.RemovePrim(part.PhysActor);
  567. }
  568. }
  569. else
  570. {
  571. part.RemFlag(LLObject.ObjectFlags.Phantom);
  572. if ((part.ObjectFlags & (int)LLObject.ObjectFlags.Physics) != 0)
  573. {
  574. part.DoPhysicsPropertyUpdate(true, false);
  575. }
  576. }
  577. }
  578. }
  579. }
  580. public void applyImpulse(PhysicsVector impulse)
  581. {
  582. // We check if rootpart is null here because scripts don't delete if you delete the host.
  583. // This means that unfortunately, we can pass a null physics actor to Simulate!
  584. // Make sure we don't do that!
  585. SceneObjectPart rootpart = m_rootPart;
  586. if (rootpart != null)
  587. {
  588. if (rootpart.PhysActor != null)
  589. {
  590. rootpart.PhysActor.AddForce(impulse);
  591. m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
  592. }
  593. }
  594. }
  595. public void moveToTarget(LLVector3 target, float tau)
  596. {
  597. SceneObjectPart rootpart = m_rootPart;
  598. if (rootpart != null)
  599. {
  600. rootpart.PhysActor.PIDTarget = new PhysicsVector(target.X, target.Y, target.Z);
  601. rootpart.PhysActor.PIDTau = tau;
  602. rootpart.PhysActor.PIDActive = true;
  603. }
  604. }
  605. public void stopMoveToTarget()
  606. {
  607. SceneObjectPart rootpart = m_rootPart;
  608. if (rootpart != null)
  609. {
  610. rootpart.PhysActor.PIDActive = false;
  611. }
  612. }
  613. public void SetRootPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
  614. {
  615. part.LastOwnerID = part.OwnerID;
  616. part.OwnerID = cAgentID;
  617. part.GroupID = cGroupID;
  618. if (part.OwnerID != cAgentID)
  619. {
  620. // Apply Next Owner Permissions if we're not bypassing permissions
  621. if (!m_scene.PermissionsMngr.BypassPermissions)
  622. m_rootPart.ApplyNextOwnerPermissions();
  623. }
  624. part.ScheduleFullUpdate();
  625. }
  626. /// <summary>
  627. ///
  628. /// </summary>
  629. /// <param name="part"></param>
  630. public void CopyPart(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
  631. {
  632. SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count);
  633. newPart.SetParent(this);
  634. lock (m_parts)
  635. {
  636. m_parts.Add(newPart.UUID, newPart);
  637. }
  638. SetPartAsNonRoot(newPart);
  639. }
  640. /// <summary>
  641. /// Reset the LLUUIDs for all the prims that make up this group.
  642. ///
  643. /// This is called by methods which want to add a new group to an existing scene, in order
  644. /// to ensure that there are no clashes with groups already present.
  645. /// </summary>
  646. public void ResetIDs()
  647. {
  648. // As this is only ever called for prims which are not currently part of the scene (and hence
  649. // not accessible by clients), there should be no need to lock
  650. List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
  651. m_parts.Clear();
  652. foreach (SceneObjectPart part in partsList)
  653. {
  654. part.ResetIDs(m_parts.Count);
  655. m_parts.Add(part.UUID, part);
  656. }
  657. }
  658. /// <summary>
  659. ///
  660. /// </summary>
  661. /// <param name="part"></param>
  662. public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, LLUUID AgentID, uint RequestFlags)
  663. {
  664. //RootPart.ServiceObjectPropertiesFamilyRequest(remoteClient, AgentID, RequestFlags);
  665. ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket) PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
  666. // TODO: don't create new blocks if recycling an old packet
  667. ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
  668. objPropDB.RequestFlags = RequestFlags;
  669. objPropDB.ObjectID = RootPart.UUID;
  670. objPropDB.OwnerID = RootPart.ObjectOwner;
  671. objPropDB.GroupID = RootPart.GroupID;
  672. objPropDB.BaseMask = RootPart.BaseMask;
  673. objPropDB.OwnerMask = RootPart.OwnerMask;
  674. objPropDB.GroupMask = RootPart.GroupMask;
  675. objPropDB.EveryoneMask = RootPart.EveryoneMask;
  676. objPropDB.NextOwnerMask = RootPart.NextOwnerMask;
  677. // TODO: More properties are needed in SceneObjectPart!
  678. objPropDB.OwnershipCost = RootPart.OwnershipCost;
  679. objPropDB.SaleType = RootPart.ObjectSaleType;
  680. objPropDB.SalePrice = RootPart.SalePrice;
  681. objPropDB.Category = RootPart.Category;
  682. objPropDB.LastOwnerID = RootPart.CreatorID;
  683. objPropDB.Name = Helpers.StringToField(RootPart.Name);
  684. objPropDB.Description = Helpers.StringToField(RootPart.Description);
  685. objPropFamilyPack.ObjectData = objPropDB;
  686. remoteClient.OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
  687. }
  688. public void SetPartOwner(SceneObjectPart part, LLUUID cAgentID, LLUUID cGroupID)
  689. {
  690. part.OwnerID = cAgentID;
  691. part.GroupID = cGroupID;
  692. }
  693. #endregion
  694. #region Scheduling
  695. /// <summary>
  696. /// Examine this object's parts to see if they've changed sufficiently to warrant an update
  697. /// </summary>
  698. public override void Update()
  699. {
  700. lock (m_parts)
  701. {
  702. if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02)
  703. {
  704. foreach (SceneObjectPart part in m_parts.Values)
  705. {
  706. if (part.UpdateFlag == 0) part.UpdateFlag = 1;
  707. }
  708. lastPhysGroupPos = AbsolutePosition;
  709. }
  710. if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
  711. || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
  712. || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
  713. || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1))
  714. {
  715. foreach (SceneObjectPart part in m_parts.Values)
  716. {
  717. if (part.UpdateFlag == 0) part.UpdateFlag = 1;
  718. }
  719. lastPhysGroupRot = GroupRotation;
  720. }
  721. foreach (SceneObjectPart part in m_parts.Values)
  722. {
  723. part.SendScheduledUpdates();
  724. }
  725. }
  726. }
  727. public void ScheduleFullUpdateToAvatar(ScenePresence presence)
  728. {
  729. lock (m_parts)
  730. {
  731. foreach (SceneObjectPart part in m_parts.Values)
  732. {
  733. part.AddFullUpdateToAvatar(presence);
  734. }
  735. }
  736. }
  737. public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
  738. {
  739. lock (m_parts)
  740. {
  741. foreach (SceneObjectPart part in m_parts.Values)
  742. {
  743. part.AddTerseUpdateToAvatar(presence);
  744. }
  745. }
  746. }
  747. /// <summary>
  748. /// Schedule a full update for every part in this object
  749. /// </summary>
  750. public void ScheduleGroupForFullUpdate()
  751. {
  752. HasGroupChanged = true;
  753. lock (m_parts)
  754. {
  755. foreach (SceneObjectPart part in m_parts.Values)
  756. {
  757. part.ScheduleFullUpdate();
  758. }
  759. }
  760. }
  761. /// <summary>
  762. ///
  763. /// </summary>
  764. public void ScheduleGroupForTerseUpdate()
  765. {
  766. HasGroupChanged = true;
  767. lock (m_parts)
  768. {
  769. foreach (SceneObjectPart part in m_parts.Values)
  770. {
  771. part.ScheduleTerseUpdate();
  772. }
  773. }
  774. }
  775. /// <summary>
  776. ///
  777. /// </summary>
  778. public void SendGroupFullUpdate()
  779. {
  780. HasGroupChanged = true;
  781. lock (m_parts)
  782. {
  783. foreach (SceneObjectPart part in m_parts.Values)
  784. {
  785. part.SendFullUpdateToAllClients();
  786. }
  787. }
  788. }
  789. public void QueueForUpdateCheck()
  790. {
  791. m_scene.m_innerScene.AddToUpdateList(this);
  792. }
  793. /// <summary>
  794. ///
  795. /// </summary>
  796. public void SendGroupTerseUpdate()
  797. {
  798. HasGroupChanged = true;
  799. lock (m_parts)
  800. {
  801. foreach (SceneObjectPart part in m_parts.Values)
  802. {
  803. part.SendTerseUpdateToAllClients();
  804. }
  805. }
  806. }
  807. #endregion
  808. #region SceneGroupPart Methods
  809. /// <summary>
  810. /// Get the child part by LinkNum
  811. /// </summary>
  812. /// <param name="linknum"></param>
  813. /// <returns>null if no child part with that linknum or child part</returns>
  814. public SceneObjectPart GetLinkNumPart(int linknum)
  815. {
  816. lock (m_parts)
  817. {
  818. foreach (SceneObjectPart part in m_parts.Values)
  819. {
  820. if (part.LinkNum == linknum)
  821. {
  822. return part;
  823. }
  824. }
  825. }
  826. return null;
  827. }
  828. /// <summary>
  829. /// Get a child part with a given UUID
  830. /// </summary>
  831. /// <param name="primID"></param>
  832. /// <returns>null if a child part with the primID was not found</returns>
  833. public SceneObjectPart GetChildPart(LLUUID primID)
  834. {
  835. SceneObjectPart childPart = null;
  836. if (m_parts.ContainsKey(primID))
  837. {
  838. childPart = m_parts[primID];
  839. }
  840. return childPart;
  841. }
  842. /// <summary>
  843. /// Get a child part with a given local ID
  844. /// </summary>
  845. /// <param name="localID"></param>
  846. /// <returns>null if a child part with the local ID was not found</returns>
  847. public SceneObjectPart GetChildPart(uint localID)
  848. {
  849. lock (m_parts)
  850. {
  851. foreach (SceneObjectPart part in m_parts.Values)
  852. {
  853. if (part.LocalId == localID)
  854. {
  855. return part;
  856. }
  857. }
  858. }
  859. return null;
  860. }
  861. /// <summary>
  862. /// Does this group contain the child prim
  863. /// should be able to remove these methods once we have a entity index in scene
  864. /// </summary>
  865. /// <param name="primID"></param>
  866. /// <returns></returns>
  867. public bool HasChildPrim(LLUUID primID)
  868. {
  869. if (m_parts.ContainsKey(primID))
  870. {
  871. return true;
  872. }
  873. return false;
  874. }
  875. /// <summary>
  876. /// Does this group contain the child prim
  877. /// should be able to remove these methods once we have a entity index in scene
  878. /// </summary>
  879. /// <param name="localID"></param>
  880. /// <returns></returns>
  881. public bool HasChildPrim(uint localID)
  882. {
  883. lock (m_parts)
  884. {
  885. foreach (SceneObjectPart part in m_parts.Values)
  886. {
  887. if (part.LocalId == localID)
  888. {
  889. return true;
  890. }
  891. }
  892. }
  893. return false;
  894. }
  895. #endregion
  896. #region Packet Handlers
  897. /// <summary>
  898. /// Link the prims in a given group to this group
  899. /// </summary>
  900. /// <param name="objectGroup">The group of prims which should be linked to this group</param>
  901. public void LinkToGroup(SceneObjectGroup objectGroup)
  902. {
  903. if (objectGroup.RootPart.UpdateFlag > 0)
  904. {
  905. // I've never actually seen this happen, though I think it's theoretically possible
  906. m_log.WarnFormat(
  907. "[SCENE OBJECT GROUP]: Aborted linking {0}, {1} to {2}, {3} as it has yet to finish delinking",
  908. objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
  909. return;
  910. }
  911. // m_log.DebugFormat(
  912. // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
  913. // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
  914. SceneObjectPart linkPart = objectGroup.m_rootPart;
  915. Vector3 oldGroupPosition =
  916. new Vector3(linkPart.GroupPosition.X, linkPart.GroupPosition.Y, linkPart.GroupPosition.Z);
  917. Quaternion oldRootRotation =
  918. new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y,
  919. linkPart.RotationOffset.Z);
  920. linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
  921. linkPart.GroupPosition = AbsolutePosition;
  922. Vector3 axPos = new Vector3(linkPart.OffsetPosition.X, linkPart.OffsetPosition.Y, linkPart.OffsetPosition.Z);
  923. Quaternion parentRot =
  924. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  925. m_rootPart.RotationOffset.Z);
  926. axPos = parentRot.Inverse()*axPos;
  927. linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
  928. Quaternion oldRot =
  929. new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X, linkPart.RotationOffset.Y,
  930. linkPart.RotationOffset.Z);
  931. Quaternion newRot = parentRot.Inverse()*oldRot;
  932. linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
  933. linkPart.ParentID = m_rootPart.LocalId;
  934. linkPart.LinkNum = m_parts.Count;
  935. lock (m_parts)
  936. {
  937. m_parts.Add(linkPart.UUID, linkPart);
  938. }
  939. linkPart.SetParent(this);
  940. //if (linkPart.PhysActor != null)
  941. //{
  942. // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
  943. //linkPart.PhysActor = null;
  944. //}
  945. //TODO: rest of parts
  946. foreach (SceneObjectPart part in objectGroup.Children.Values)
  947. {
  948. if (part.UUID != objectGroup.m_rootPart.UUID)
  949. {
  950. LinkNonRootPart(part, oldGroupPosition, oldRootRotation);
  951. }
  952. }
  953. DetachFromBackup(objectGroup);
  954. m_scene.DeleteEntity(objectGroup.UUID);
  955. // TODO Deleting the parts may cause problems later on if they have already
  956. // made it into the update queue. However, sending out updates for those parts is now
  957. // spurious, so it would be good not to send them at some point.
  958. // The traffic caused is always going to be pretty minor, so it's not high priority
  959. //objectGroup.DeleteParts();
  960. ScheduleGroupForFullUpdate();
  961. }
  962. /// <summary>
  963. /// Delink the given prim from this group. The delinked prim is established as
  964. /// an independent SceneObjectGroup.
  965. /// </summary>
  966. /// <param name="partID"></param>
  967. public void DelinkFromGroup(uint partID)
  968. {
  969. SceneObjectPart linkPart = GetChildPart(partID);
  970. if (null != linkPart)
  971. {
  972. // m_log.DebugFormat(
  973. // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
  974. // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
  975. LLQuaternion worldRot = linkPart.GetWorldRotation();
  976. // Remove the part from this object
  977. lock (m_parts)
  978. {
  979. m_parts.Remove(linkPart.UUID);
  980. }
  981. linkPart.ParentID = 0;
  982. if (linkPart.PhysActor != null)
  983. {
  984. m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
  985. }
  986. // We need to reset the child part's position
  987. // ready for life as a separate object after being a part of another object
  988. Quaternion parentRot
  989. = new Quaternion(
  990. m_rootPart.RotationOffset.W,
  991. m_rootPart.RotationOffset.X,
  992. m_rootPart.RotationOffset.Y,
  993. m_rootPart.RotationOffset.Z);
  994. Vector3 axPos
  995. = new Vector3(
  996. linkPart.OffsetPosition.X,
  997. linkPart.OffsetPosition.Y,
  998. linkPart.OffsetPosition.Z);
  999. axPos = parentRot*axPos;
  1000. linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
  1001. linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
  1002. linkPart.OffsetPosition = new LLVector3(0, 0, 0);
  1003. linkPart.RotationOffset = worldRot;
  1004. // This chunk is probably unnecesary now - delete later on
  1005. /*
  1006. Quaternion oldRot
  1007. = new Quaternion(
  1008. linkPart.RotationOffset.W,
  1009. linkPart.RotationOffset.X,
  1010. linkPart.RotationOffset.Y,
  1011. linkPart.RotationOffset.Z);
  1012. Quaternion newRot = parentRot*oldRot;
  1013. linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
  1014. */
  1015. // Add physics information back to delinked part if appropriate
  1016. // XXX This is messy and should be refactorable with the similar section in
  1017. // SceneObjectPart.UpdatePrimFlags()
  1018. //if (m_rootPart.PhysActor != null)
  1019. //{
  1020. //linkPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
  1021. //linkPart.Name,
  1022. //linkPart.Shape,
  1023. //new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y,
  1024. //linkPart.AbsolutePosition.Z),
  1025. //new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z),
  1026. //new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X,
  1027. //linkPart.RotationOffset.Y, linkPart.RotationOffset.Z),
  1028. //m_rootPart.PhysActor.IsPhysical);
  1029. //m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true);
  1030. //}
  1031. SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
  1032. m_scene.AddEntity(objectGroup);
  1033. ScheduleGroupForFullUpdate();
  1034. }
  1035. else
  1036. {
  1037. m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
  1038. "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
  1039. partID, LocalId, UUID);
  1040. }
  1041. }
  1042. private void DetachFromBackup(SceneObjectGroup objectGroup)
  1043. {
  1044. m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup;
  1045. }
  1046. private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation)
  1047. {
  1048. part.SetParent(this);
  1049. part.ParentID = m_rootPart.LocalId;
  1050. part.LinkNum = m_parts.Count;
  1051. lock (m_parts)
  1052. {
  1053. m_parts.Add(part.UUID, part);
  1054. }
  1055. Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
  1056. axiomOldPos = oldGroupRotation*axiomOldPos;
  1057. axiomOldPos += oldGroupPosition;
  1058. LLVector3 oldAbsolutePosition = new LLVector3(axiomOldPos.x, axiomOldPos.y, axiomOldPos.z);
  1059. part.OffsetPosition = oldAbsolutePosition - AbsolutePosition;
  1060. Quaternion axiomRootRotation =
  1061. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1062. m_rootPart.RotationOffset.Z);
  1063. Vector3 axiomPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z);
  1064. axiomPos = axiomRootRotation.Inverse()*axiomPos;
  1065. part.OffsetPosition = new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z);
  1066. Quaternion axiomPartRotation =
  1067. new Quaternion(part.RotationOffset.W, part.RotationOffset.X, part.RotationOffset.Y,
  1068. part.RotationOffset.Z);
  1069. axiomPartRotation = oldGroupRotation*axiomPartRotation;
  1070. axiomPartRotation = axiomRootRotation.Inverse()*axiomPartRotation;
  1071. part.RotationOffset =
  1072. new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
  1073. }
  1074. /// <summary>
  1075. /// If object is physical, apply force to move it around
  1076. /// If object is not physical, just put it at the resulting location
  1077. /// </summary>
  1078. /// <param name="offset">Always seems to be 0,0,0, so ignoring</param>
  1079. /// <param name="pos">New position. We do the math here to turn it into a force</param>
  1080. /// <param name="remoteClient"></param>
  1081. public void GrabMovement(LLVector3 offset, LLVector3 pos, IClientAPI remoteClient)
  1082. {
  1083. if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
  1084. {
  1085. if (m_rootPart.PhysActor != null)
  1086. {
  1087. if (m_rootPart.PhysActor.IsPhysical)
  1088. {
  1089. LLVector3 llmoveforce = pos - AbsolutePosition;
  1090. PhysicsVector grabforce = new PhysicsVector(llmoveforce.X, llmoveforce.Y, llmoveforce.Z);
  1091. grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass;
  1092. m_rootPart.PhysActor.AddForce(grabforce);
  1093. m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  1094. }
  1095. else
  1096. {
  1097. NonPhysicalGrabMovement(pos);
  1098. }
  1099. }
  1100. else
  1101. {
  1102. NonPhysicalGrabMovement(pos);
  1103. }
  1104. }
  1105. }
  1106. public void NonPhysicalGrabMovement(LLVector3 pos)
  1107. {
  1108. AbsolutePosition = pos;
  1109. m_rootPart.SendTerseUpdateToAllClients();
  1110. }
  1111. /// <summary>
  1112. ///
  1113. /// </summary>
  1114. /// <param name="client"></param>
  1115. public void GetProperties(IClientAPI client)
  1116. {
  1117. ObjectPropertiesPacket proper = (ObjectPropertiesPacket) PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
  1118. // TODO: don't create new blocks if recycling an old packet
  1119. proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
  1120. proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
  1121. proper.ObjectData[0].ItemID = LLUUID.Zero;
  1122. proper.ObjectData[0].CreationDate = (ulong) m_rootPart.CreationDate;
  1123. proper.ObjectData[0].CreatorID = m_rootPart.CreatorID;
  1124. proper.ObjectData[0].FolderID = LLUUID.Zero;
  1125. proper.ObjectData[0].FromTaskID = LLUUID.Zero;
  1126. proper.ObjectData[0].GroupID = LLUUID.Zero;
  1127. proper.ObjectData[0].InventorySerial = (short) m_rootPart.InventorySerial;
  1128. proper.ObjectData[0].LastOwnerID = m_rootPart.LastOwnerID;
  1129. proper.ObjectData[0].ObjectID = UUID;
  1130. proper.ObjectData[0].OwnerID = m_rootPart.OwnerID;
  1131. proper.ObjectData[0].TouchName = Helpers.StringToField(m_rootPart.TouchName);
  1132. proper.ObjectData[0].TextureID = new byte[0];
  1133. proper.ObjectData[0].SitName = Helpers.StringToField(m_rootPart.SitName);
  1134. proper.ObjectData[0].Name = Helpers.StringToField(m_rootPart.Name);
  1135. proper.ObjectData[0].Description = Helpers.StringToField(m_rootPart.Description);
  1136. proper.ObjectData[0].OwnerMask = m_rootPart.OwnerMask;
  1137. proper.ObjectData[0].NextOwnerMask = m_rootPart.NextOwnerMask;
  1138. proper.ObjectData[0].GroupMask = m_rootPart.GroupMask;
  1139. proper.ObjectData[0].EveryoneMask = m_rootPart.EveryoneMask;
  1140. proper.ObjectData[0].BaseMask = m_rootPart.BaseMask;
  1141. client.OutPacket(proper, ThrottleOutPacketType.Task);
  1142. }
  1143. /// <summary>
  1144. /// Set the name of a prim
  1145. /// </summary>
  1146. /// <param name="name"></param>
  1147. /// <param name="localID"></param>
  1148. public void SetPartName(string name, uint localID)
  1149. {
  1150. SceneObjectPart part = GetChildPart(localID);
  1151. if (part != null)
  1152. {
  1153. part.Name = name;
  1154. }
  1155. }
  1156. public void SetPartDescription(string des, uint localID)
  1157. {
  1158. SceneObjectPart part = GetChildPart(localID);
  1159. if (part != null)
  1160. {
  1161. part.Description = des;
  1162. }
  1163. }
  1164. public void SetPartText(string text, uint localID)
  1165. {
  1166. SceneObjectPart part = GetChildPart(localID);
  1167. if (part != null)
  1168. {
  1169. part.SetText( text );
  1170. }
  1171. }
  1172. public void SetPartText(string text, LLUUID partID)
  1173. {
  1174. SceneObjectPart part = GetChildPart(partID);
  1175. if (part != null)
  1176. {
  1177. part.SetText( text );
  1178. }
  1179. }
  1180. public string GetPartName(uint localID)
  1181. {
  1182. SceneObjectPart part = GetChildPart(localID);
  1183. if (part != null)
  1184. {
  1185. return part.Name;
  1186. }
  1187. return String.Empty;
  1188. }
  1189. public string GetPartDescription(uint localID)
  1190. {
  1191. SceneObjectPart part = GetChildPart(localID);
  1192. if (part != null)
  1193. {
  1194. return part.Description;
  1195. }
  1196. return String.Empty;
  1197. }
  1198. /// <summary>
  1199. ///
  1200. /// </summary>
  1201. /// <param name="localID"></param>
  1202. /// <param name="type"></param>
  1203. /// <param name="inUse"></param>
  1204. /// <param name="data"></param>
  1205. ///
  1206. public void UpdatePrimFlags(uint localID, ushort type, bool inUse, byte[] data)
  1207. {
  1208. SceneObjectPart part = GetChildPart(localID);
  1209. if (part != null)
  1210. {
  1211. // If we have children
  1212. lock (m_parts)
  1213. {
  1214. if (m_parts.Count > 1)
  1215. {
  1216. foreach (SceneObjectPart parts in m_parts.Values)
  1217. {
  1218. parts.UpdatePrimFlags(type, inUse, data);
  1219. }
  1220. }
  1221. else
  1222. {
  1223. part.UpdatePrimFlags(type, inUse, data);
  1224. }
  1225. }
  1226. }
  1227. }
  1228. public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
  1229. {
  1230. SceneObjectPart part = GetChildPart(localID);
  1231. if (part != null)
  1232. {
  1233. part.UpdateExtraParam(type, inUse, data);
  1234. }
  1235. }
  1236. public SceneObjectPart[] GetParts()
  1237. {
  1238. int numParts = Children.Count;
  1239. SceneObjectPart[] partArray = new SceneObjectPart[numParts];
  1240. Children.Values.CopyTo(partArray, 0);
  1241. return partArray;
  1242. }
  1243. /// <summary>
  1244. ///
  1245. /// </summary>
  1246. /// <param name="localID"></param>
  1247. /// <param name="textureEntry"></param>
  1248. public void UpdateTextureEntry(uint localID, byte[] textureEntry)
  1249. {
  1250. SceneObjectPart part = GetChildPart(localID);
  1251. if (part != null)
  1252. {
  1253. part.UpdateTextureEntry(textureEntry);
  1254. }
  1255. }
  1256. public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
  1257. {
  1258. SceneObjectPart updatePart = GetChildPart(localID);
  1259. updatePart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
  1260. }
  1261. #endregion
  1262. #region Shape
  1263. /// <summary>
  1264. ///
  1265. /// </summary>
  1266. /// <param name="shapeBlock"></param>
  1267. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID)
  1268. {
  1269. SceneObjectPart part = GetChildPart(localID);
  1270. if (part != null)
  1271. {
  1272. part.UpdateShape(shapeBlock);
  1273. if (part.PhysActor != null)
  1274. m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
  1275. }
  1276. }
  1277. #endregion
  1278. #region Resize
  1279. /// <summary>
  1280. ///
  1281. /// </summary>
  1282. /// <param name="scale"></param>
  1283. /// <param name="localID"></param>
  1284. public void Resize(LLVector3 scale, uint localID)
  1285. {
  1286. SceneObjectPart part = GetChildPart(localID);
  1287. if (part != null)
  1288. {
  1289. part.Resize(scale);
  1290. if (part.PhysActor != null)
  1291. {
  1292. part.PhysActor.Size =
  1293. new PhysicsVector(scale.X, scale.Y, scale.Z);
  1294. m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
  1295. }
  1296. if (part.UUID != m_rootPart.UUID)
  1297. ScheduleGroupForFullUpdate();
  1298. //if (part.UUID == m_rootPart.UUID)
  1299. //{
  1300. //if (m_rootPart.PhysActor != null)
  1301. //{
  1302. //m_rootPart.PhysActor.Size =
  1303. //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
  1304. //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  1305. //}
  1306. //}
  1307. }
  1308. }
  1309. #endregion
  1310. #region Position
  1311. /// <summary>
  1312. ///
  1313. /// </summary>
  1314. /// <param name="pos"></param>
  1315. public void UpdateGroupPosition(LLVector3 pos)
  1316. {
  1317. if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
  1318. {
  1319. AbsolutePosition = pos;
  1320. }
  1321. //we need to do a terse update even if the move wasn't allowed
  1322. // so that the position is reset in the client (the object snaps back)
  1323. ScheduleGroupForTerseUpdate();
  1324. }
  1325. /// <summary>
  1326. ///
  1327. /// </summary>
  1328. /// <param name="pos"></param>
  1329. /// <param name="localID"></param>
  1330. public void UpdateSinglePosition(LLVector3 pos, uint localID)
  1331. {
  1332. SceneObjectPart part = GetChildPart(localID);
  1333. if (part != null)
  1334. {
  1335. if (part.UUID == m_rootPart.UUID)
  1336. {
  1337. UpdateRootPosition(pos);
  1338. }
  1339. else
  1340. {
  1341. part.UpdateOffSet(pos);
  1342. }
  1343. }
  1344. }
  1345. /// <summary>
  1346. ///
  1347. /// </summary>
  1348. /// <param name="pos"></param>
  1349. private void UpdateRootPosition(LLVector3 pos)
  1350. {
  1351. LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
  1352. LLVector3 oldPos =
  1353. new LLVector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
  1354. AbsolutePosition.Y + m_rootPart.OffsetPosition.Y,
  1355. AbsolutePosition.Z + m_rootPart.OffsetPosition.Z);
  1356. LLVector3 diff = oldPos - newPos;
  1357. Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
  1358. Quaternion partRotation =
  1359. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1360. m_rootPart.RotationOffset.Z);
  1361. axDiff = partRotation.Inverse()*axDiff;
  1362. diff.X = axDiff.x;
  1363. diff.Y = axDiff.y;
  1364. diff.Z = axDiff.z;
  1365. lock (m_parts)
  1366. {
  1367. foreach (SceneObjectPart obPart in m_parts.Values)
  1368. {
  1369. if (obPart.UUID != m_rootPart.UUID)
  1370. {
  1371. obPart.OffsetPosition = obPart.OffsetPosition + diff;
  1372. }
  1373. }
  1374. }
  1375. AbsolutePosition = newPos;
  1376. ScheduleGroupForTerseUpdate();
  1377. }
  1378. public void OffsetForNewRegion(LLVector3 offset)
  1379. {
  1380. m_rootPart.GroupPosition = offset;
  1381. }
  1382. #endregion
  1383. #region Rotation
  1384. /// <summary>
  1385. ///
  1386. /// </summary>
  1387. /// <param name="rot"></param>
  1388. public void UpdateGroupRotation(LLQuaternion rot)
  1389. {
  1390. m_rootPart.UpdateRotation(rot);
  1391. if (m_rootPart.PhysActor != null)
  1392. {
  1393. m_rootPart.PhysActor.Orientation =
  1394. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1395. m_rootPart.RotationOffset.Z);
  1396. m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  1397. }
  1398. ScheduleGroupForTerseUpdate();
  1399. }
  1400. /// <summary>
  1401. ///
  1402. /// </summary>
  1403. /// <param name="pos"></param>
  1404. /// <param name="rot"></param>
  1405. public void UpdateGroupRotation(LLVector3 pos, LLQuaternion rot)
  1406. {
  1407. m_rootPart.UpdateRotation(rot);
  1408. if (m_rootPart.PhysActor != null)
  1409. {
  1410. m_rootPart.PhysActor.Orientation =
  1411. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1412. m_rootPart.RotationOffset.Z);
  1413. m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  1414. }
  1415. AbsolutePosition = pos;
  1416. ScheduleGroupForTerseUpdate();
  1417. }
  1418. /// <summary>
  1419. ///
  1420. /// </summary>
  1421. /// <param name="rot"></param>
  1422. /// <param name="localID"></param>
  1423. public void UpdateSingleRotation(LLQuaternion rot, uint localID)
  1424. {
  1425. SceneObjectPart part = GetChildPart(localID);
  1426. if (part != null)
  1427. {
  1428. if (part.UUID == m_rootPart.UUID)
  1429. {
  1430. UpdateRootRotation(rot);
  1431. }
  1432. else
  1433. {
  1434. part.UpdateRotation(rot);
  1435. }
  1436. }
  1437. }
  1438. /// <summary>
  1439. ///
  1440. /// </summary>
  1441. /// <param name="rot"></param>
  1442. private void UpdateRootRotation(LLQuaternion rot)
  1443. {
  1444. Quaternion axRot = new Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  1445. Quaternion oldParentRot =
  1446. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1447. m_rootPart.RotationOffset.Z);
  1448. m_rootPart.UpdateRotation(rot);
  1449. if (m_rootPart.PhysActor != null)
  1450. {
  1451. m_rootPart.PhysActor.Orientation =
  1452. new Quaternion(m_rootPart.RotationOffset.W, m_rootPart.RotationOffset.X, m_rootPart.RotationOffset.Y,
  1453. m_rootPart.RotationOffset.Z);
  1454. m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
  1455. }
  1456. lock (m_parts)
  1457. {
  1458. foreach (SceneObjectPart prim in m_parts.Values)
  1459. {
  1460. if (prim.UUID != m_rootPart.UUID)
  1461. {
  1462. Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z);
  1463. axPos = oldParentRot*axPos;
  1464. axPos = axRot.Inverse()*axPos;
  1465. prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
  1466. Quaternion primsRot =
  1467. new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y,
  1468. prim.RotationOffset.Z);
  1469. Quaternion newRot = oldParentRot*primsRot;
  1470. newRot = axRot.Inverse()*newRot;
  1471. prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
  1472. prim.ScheduleTerseUpdate();
  1473. }
  1474. }
  1475. }
  1476. m_rootPart.ScheduleTerseUpdate();
  1477. }
  1478. #endregion
  1479. /// <summary>
  1480. ///
  1481. /// </summary>
  1482. /// <param name="part"></param>
  1483. private void SetPartAsRoot(SceneObjectPart part)
  1484. {
  1485. m_rootPart = part;
  1486. }
  1487. /// <summary>
  1488. ///
  1489. /// </summary>
  1490. /// <param name="part"></param>
  1491. private void SetPartAsNonRoot(SceneObjectPart part)
  1492. {
  1493. part.ParentID = m_rootPart.LocalId;
  1494. }
  1495. /// <summary>
  1496. ///
  1497. /// </summary>
  1498. /// <returns></returns>
  1499. public List<ScenePresence> GetScenePresences()
  1500. {
  1501. return m_scene.GetScenePresences();
  1502. }
  1503. #region Events
  1504. /// <summary>
  1505. ///
  1506. /// </summary>
  1507. public void TriggerTainted()
  1508. {
  1509. handlerPrimCountTainted = OnPrimCountTainted;
  1510. if (handlerPrimCountTainted != null)
  1511. {
  1512. handlerPrimCountTainted();
  1513. }
  1514. }
  1515. /// <summary>
  1516. /// Processes backup
  1517. /// </summary>
  1518. /// <param name="datastore"></param>
  1519. public void ProcessBackup(IRegionDataStore datastore)
  1520. {
  1521. if (HasGroupChanged)
  1522. {
  1523. datastore.StoreObject(this, m_scene.RegionInfo.RegionID);
  1524. HasGroupChanged = false;
  1525. }
  1526. ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); });
  1527. }
  1528. #endregion
  1529. #region Client Updating
  1530. public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientFlags)
  1531. {
  1532. lock (m_parts)
  1533. {
  1534. foreach (SceneObjectPart part in m_parts.Values)
  1535. {
  1536. SendPartFullUpdate(remoteClient, part, clientFlags);
  1537. }
  1538. }
  1539. }
  1540. /// <summary>
  1541. /// Send a full update to the client for the given part
  1542. /// </summary>
  1543. /// <param name="remoteClient"></param>
  1544. /// <param name="part"></param>
  1545. internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags)
  1546. {
  1547. if (m_rootPart.UUID == part.UUID)
  1548. {
  1549. part.SendFullUpdateToClient(remoteClient, AbsolutePosition, clientFlags);
  1550. }
  1551. else
  1552. {
  1553. part.SendFullUpdateToClient(remoteClient, clientFlags);
  1554. }
  1555. }
  1556. /// <summary>
  1557. /// Send a terse update to the client for the given part
  1558. /// </summary>
  1559. /// <param name="remoteClient"></param>
  1560. /// <param name="part"></param>
  1561. internal void SendPartTerseUpdate(IClientAPI remoteClient, SceneObjectPart part)
  1562. {
  1563. if (m_rootPart.UUID == part.UUID)
  1564. {
  1565. part.SendTerseUpdateToClient(remoteClient, AbsolutePosition);
  1566. }
  1567. else
  1568. {
  1569. part.SendTerseUpdateToClient(remoteClient);
  1570. }
  1571. }
  1572. #endregion
  1573. public override void UpdateMovement()
  1574. {
  1575. lock (m_parts)
  1576. {
  1577. foreach (SceneObjectPart part in m_parts.Values)
  1578. {
  1579. part.UpdateMovement();
  1580. }
  1581. }
  1582. }
  1583. public float GetTimeDilation()
  1584. {
  1585. return m_scene.TimeDilation;
  1586. }
  1587. /// <summary>
  1588. /// Added as a way for the storage provider to reset the scene,
  1589. /// most likely a better way to do this sort of thing but for now...
  1590. /// </summary>
  1591. /// <param name="scene"></param>
  1592. public void SetScene(Scene scene)
  1593. {
  1594. m_scene = scene;
  1595. AttachToBackup();
  1596. }
  1597. /// <summary>
  1598. ///
  1599. /// </summary>
  1600. /// <param name="part"></param>
  1601. public void AddPart(SceneObjectPart part)
  1602. {
  1603. lock (m_parts)
  1604. {
  1605. part.SetParent(this);
  1606. part.LinkNum = m_parts.Count;
  1607. try
  1608. {
  1609. m_parts.Add(part.UUID, part);
  1610. }
  1611. catch (Exception e)
  1612. {
  1613. m_log.Error("Failed to add scened object part", e);
  1614. }
  1615. }
  1616. }
  1617. /// <summary>
  1618. ///
  1619. /// </summary>
  1620. public void UpdateParentIDs()
  1621. {
  1622. lock (m_parts)
  1623. {
  1624. foreach (SceneObjectPart part in m_parts.Values)
  1625. {
  1626. if (part.UUID != m_rootPart.UUID)
  1627. {
  1628. part.ParentID = m_rootPart.LocalId;
  1629. }
  1630. }
  1631. }
  1632. }
  1633. public void RegenerateFullIDs()
  1634. {
  1635. lock (m_parts)
  1636. {
  1637. foreach (SceneObjectPart part in m_parts.Values)
  1638. {
  1639. part.UUID = LLUUID.Random();
  1640. }
  1641. }
  1642. }
  1643. public void ResetChildPrimPhysicsPositions()
  1644. {
  1645. AbsolutePosition = AbsolutePosition;
  1646. HasGroupChanged = false;
  1647. }
  1648. public LLUUID GetPartsFullID(uint localID)
  1649. {
  1650. SceneObjectPart part = GetChildPart(localID);
  1651. if (part != null)
  1652. {
  1653. return part.UUID;
  1654. }
  1655. return null;
  1656. }
  1657. public void ObjectGrabHandler(uint localId, LLVector3 offsetPos, IClientAPI remoteClient)
  1658. {
  1659. if (m_rootPart.LocalId == localId)
  1660. {
  1661. OnGrabGroup(offsetPos, remoteClient);
  1662. }
  1663. else
  1664. {
  1665. SceneObjectPart part = GetChildPart(localId);
  1666. OnGrabPart(part, offsetPos, remoteClient);
  1667. }
  1668. }
  1669. public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient)
  1670. {
  1671. part.OnGrab(offsetPos, remoteClient);
  1672. }
  1673. public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient)
  1674. {
  1675. m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
  1676. }
  1677. /// <summary>
  1678. /// Completely delete this group and tell all the scene presences about that deletion.
  1679. /// </summary>
  1680. public void DeleteGroup()
  1681. {
  1682. DetachFromBackup(this);
  1683. lock (m_parts)
  1684. {
  1685. foreach (SceneObjectPart part in m_parts.Values)
  1686. {
  1687. List<ScenePresence> avatars = GetScenePresences();
  1688. for (int i = 0; i < avatars.Count; i++)
  1689. {
  1690. if (avatars[i].ParentID == LocalId)
  1691. {
  1692. avatars[i].StandUp();
  1693. }
  1694. avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
  1695. }
  1696. }
  1697. }
  1698. }
  1699. /// <summary>
  1700. /// Delete all the parts in this group.
  1701. /// </summary>
  1702. public void DeleteParts()
  1703. {
  1704. lock (m_parts)
  1705. {
  1706. foreach (SceneObjectPart part in m_parts.Values)
  1707. {
  1708. part.StopScripts();
  1709. }
  1710. m_rootPart = null;
  1711. m_parts.Clear();
  1712. }
  1713. }
  1714. public void AddScriptLPS(int count)
  1715. {
  1716. InnerScene d = m_scene.m_innerScene;
  1717. d.AddToScriptLPS(count);
  1718. }
  1719. public void AddActiveScriptCount(int count)
  1720. {
  1721. InnerScene d = m_scene.m_innerScene;
  1722. d.AddActiveScripts(count);
  1723. }
  1724. public override void SetText(string text, Vector3 color, double alpha)
  1725. {
  1726. Color = Color.FromArgb(0xff - (int) (alpha*0xff),
  1727. (int) (color.x*0xff),
  1728. (int) (color.y*0xff),
  1729. (int) (color.z*0xff));
  1730. Text = text;
  1731. m_rootPart.ScheduleFullUpdate();
  1732. }
  1733. public void ApplyPhysics(bool m_physicalPrim)
  1734. {
  1735. lock (m_parts)
  1736. {
  1737. if (m_parts.Count > 1)
  1738. {
  1739. m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
  1740. foreach (SceneObjectPart part in m_parts.Values)
  1741. {
  1742. if (part.LocalId != m_rootPart.LocalId)
  1743. {
  1744. part.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
  1745. }
  1746. // Hack to get the physics scene geometries in the right spot
  1747. ResetChildPrimPhysicsPositions();
  1748. }
  1749. }
  1750. else
  1751. {
  1752. m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim);
  1753. }
  1754. }
  1755. }
  1756. public void SetOwnerId(LLUUID userId)
  1757. {
  1758. ForEachPart(delegate(SceneObjectPart part)
  1759. { part.OwnerID = userId; });
  1760. }
  1761. public void ForEachPart(Action<SceneObjectPart> whatToDo)
  1762. {
  1763. lock (m_parts)
  1764. {
  1765. foreach (SceneObjectPart part in m_parts.Values)
  1766. {
  1767. whatToDo(part);
  1768. }
  1769. }
  1770. }
  1771. }
  1772. }