ExtendedPhysics.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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 copyrightD
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Linq;
  30. using System.Reflection;
  31. using System.Text;
  32. using System.Threading;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Framework;
  35. using OpenSim.Region.Framework.Interfaces;
  36. using OpenSim.Region.Framework.Scenes;
  37. using OpenSim.Region.PhysicsModules.SharedBase;
  38. using Mono.Addins;
  39. using Nini.Config;
  40. using log4net;
  41. using OpenMetaverse;
  42. namespace OpenSim.Region.PhysicsModule.BulletS
  43. {
  44. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
  45. public class ExtendedPhysics : INonSharedRegionModule
  46. {
  47. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  48. private static string LogHeader = "[EXTENDED PHYSICS]";
  49. // =============================================================
  50. // Since BulletSim is a plugin, this these values aren't defined easily in one place.
  51. // This table must correspond to an identical table in BSScene.
  52. // Per scene functions. See BSScene.
  53. // Per avatar functions. See BSCharacter.
  54. // Per prim functions. See BSPrim.
  55. public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
  56. public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
  57. public const string PhysFunctChangeLinkFixed = "BulletSim.ChangeLinkFixed";
  58. public const string PhysFunctChangeLinkType = "BulletSim.ChangeLinkType";
  59. public const string PhysFunctGetLinkType = "BulletSim.GetLinkType";
  60. public const string PhysFunctChangeLinkParams = "BulletSim.ChangeLinkParams";
  61. public const string PhysFunctAxisLockLimits = "BulletSim.AxisLockLimits";
  62. // =============================================================
  63. private IConfig Configuration { get; set; }
  64. private bool Enabled { get; set; }
  65. private Scene BaseScene { get; set; }
  66. private IScriptModuleComms Comms { get; set; }
  67. #region INonSharedRegionModule
  68. public string Name { get { return this.GetType().Name; } }
  69. public void Initialise(IConfigSource config)
  70. {
  71. BaseScene = null;
  72. Enabled = false;
  73. Configuration = null;
  74. Comms = null;
  75. try
  76. {
  77. if ((Configuration = config.Configs["ExtendedPhysics"]) != null)
  78. {
  79. Enabled = Configuration.GetBoolean("Enabled", Enabled);
  80. }
  81. }
  82. catch (Exception e)
  83. {
  84. m_log.ErrorFormat("{0} Initialization error: {0}", LogHeader, e);
  85. }
  86. m_log.InfoFormat("{0} module {1} enabled", LogHeader, (Enabled ? "is" : "is not"));
  87. }
  88. public void Close()
  89. {
  90. if (BaseScene != null)
  91. {
  92. BaseScene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
  93. BaseScene.EventManager.OnSceneObjectPartUpdated -= EventManager_OnSceneObjectPartUpdated;
  94. BaseScene = null;
  95. }
  96. }
  97. public void AddRegion(Scene scene)
  98. {
  99. }
  100. public void RemoveRegion(Scene scene)
  101. {
  102. if (BaseScene != null && BaseScene == scene)
  103. {
  104. Close();
  105. }
  106. }
  107. public void RegionLoaded(Scene scene)
  108. {
  109. if (!Enabled) return;
  110. BaseScene = scene;
  111. Comms = BaseScene.RequestModuleInterface<IScriptModuleComms>();
  112. if (Comms == null)
  113. {
  114. m_log.WarnFormat("{0} ScriptModuleComms interface not defined", LogHeader);
  115. Enabled = false;
  116. return;
  117. }
  118. // Register as LSL functions all the [ScriptInvocation] marked methods.
  119. Comms.RegisterScriptInvocations(this);
  120. Comms.RegisterConstants(this);
  121. // When an object is modified, we might need to update its extended physics parameters
  122. BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
  123. BaseScene.EventManager.OnSceneObjectPartUpdated += EventManager_OnSceneObjectPartUpdated;
  124. }
  125. public Type ReplaceableInterface { get { return null; } }
  126. #endregion // INonSharedRegionModule
  127. private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
  128. {
  129. }
  130. // Event generated when some property of a prim changes.
  131. private void EventManager_OnSceneObjectPartUpdated(SceneObjectPart sop, bool isFullUpdate)
  132. {
  133. }
  134. [ScriptConstant]
  135. public const int PHYS_CENTER_OF_MASS = 1 << 0;
  136. [ScriptInvocation]
  137. public string physGetEngineType(UUID hostID, UUID scriptID)
  138. {
  139. string ret = string.Empty;
  140. if (BaseScene.PhysicsScene != null)
  141. {
  142. ret = BaseScene.PhysicsScene.EngineType;
  143. }
  144. return ret;
  145. }
  146. // Code for specifying params.
  147. // The choice if 14700 is arbitrary and only serves to catch parameter code misuse.
  148. [ScriptConstant]
  149. public const int PHYS_AXIS_LOCK_LINEAR = 14700;
  150. [ScriptConstant]
  151. public const int PHYS_AXIS_LOCK_LINEAR_X = 14701;
  152. [ScriptConstant]
  153. public const int PHYS_AXIS_LIMIT_LINEAR_X = 14702;
  154. [ScriptConstant]
  155. public const int PHYS_AXIS_LOCK_LINEAR_Y = 14703;
  156. [ScriptConstant]
  157. public const int PHYS_AXIS_LIMIT_LINEAR_Y = 14704;
  158. [ScriptConstant]
  159. public const int PHYS_AXIS_LOCK_LINEAR_Z = 14705;
  160. [ScriptConstant]
  161. public const int PHYS_AXIS_LIMIT_LINEAR_Z = 14706;
  162. [ScriptConstant]
  163. public const int PHYS_AXIS_LOCK_ANGULAR = 14707;
  164. [ScriptConstant]
  165. public const int PHYS_AXIS_LOCK_ANGULAR_X = 14708;
  166. [ScriptConstant]
  167. public const int PHYS_AXIS_LIMIT_ANGULAR_X = 14709;
  168. [ScriptConstant]
  169. public const int PHYS_AXIS_LOCK_ANGULAR_Y = 14710;
  170. [ScriptConstant]
  171. public const int PHYS_AXIS_LIMIT_ANGULAR_Y = 14711;
  172. [ScriptConstant]
  173. public const int PHYS_AXIS_LOCK_ANGULAR_Z = 14712;
  174. [ScriptConstant]
  175. public const int PHYS_AXIS_LIMIT_ANGULAR_Z = 14713;
  176. [ScriptConstant]
  177. public const int PHYS_AXIS_UNLOCK_LINEAR = 14714;
  178. [ScriptConstant]
  179. public const int PHYS_AXIS_UNLOCK_LINEAR_X = 14715;
  180. [ScriptConstant]
  181. public const int PHYS_AXIS_UNLOCK_LINEAR_Y = 14716;
  182. [ScriptConstant]
  183. public const int PHYS_AXIS_UNLOCK_LINEAR_Z = 14717;
  184. [ScriptConstant]
  185. public const int PHYS_AXIS_UNLOCK_ANGULAR = 14718;
  186. [ScriptConstant]
  187. public const int PHYS_AXIS_UNLOCK_ANGULAR_X = 14719;
  188. [ScriptConstant]
  189. public const int PHYS_AXIS_UNLOCK_ANGULAR_Y = 14720;
  190. [ScriptConstant]
  191. public const int PHYS_AXIS_UNLOCK_ANGULAR_Z = 14721;
  192. [ScriptConstant]
  193. public const int PHYS_AXIS_UNLOCK = 14722;
  194. // physAxisLockLimits()
  195. [ScriptInvocation]
  196. public int physAxisLock(UUID hostID, UUID scriptID, object[] parms)
  197. {
  198. int ret = -1;
  199. if (!Enabled) return ret;
  200. PhysicsActor rootPhysActor;
  201. if (GetRootPhysActor(hostID, out rootPhysActor))
  202. {
  203. object[] parms2 = AddToBeginningOfArray(rootPhysActor, null, parms);
  204. ret = MakeIntError(rootPhysActor.Extension(PhysFunctAxisLockLimits, parms2));
  205. }
  206. return ret;
  207. }
  208. [ScriptConstant]
  209. public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
  210. [ScriptConstant]
  211. public const int PHYS_LINKSET_TYPE_COMPOUND = 1;
  212. [ScriptConstant]
  213. public const int PHYS_LINKSET_TYPE_MANUAL = 2;
  214. [ScriptInvocation]
  215. public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
  216. {
  217. int ret = -1;
  218. if (!Enabled) return ret;
  219. // The part that is requesting the change.
  220. SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
  221. if (requestingPart != null)
  222. {
  223. // The change is always made to the root of a linkset.
  224. SceneObjectGroup containingGroup = requestingPart.ParentGroup;
  225. SceneObjectPart rootPart = containingGroup.RootPart;
  226. if (rootPart != null)
  227. {
  228. PhysicsActor rootPhysActor = rootPart.PhysActor;
  229. if (rootPhysActor != null)
  230. {
  231. if (rootPhysActor.IsPhysical)
  232. {
  233. // Change a physical linkset by making non-physical, waiting for one heartbeat so all
  234. // the prim and linkset state is updated, changing the type and making the
  235. // linkset physical again.
  236. containingGroup.ScriptSetPhysicsStatus(false);
  237. Thread.Sleep(150); // longer than one heartbeat tick
  238. // A kludge for the moment.
  239. // Since compound linksets move the children but don't generate position updates to the
  240. // simulator, it is possible for compound linkset children to have out-of-sync simulator
  241. // and physical positions. The following causes the simulator to push the real child positions
  242. // down into the physics engine to get everything synced.
  243. containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition);
  244. containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation);
  245. object[] parms2 = { rootPhysActor, null, linksetType };
  246. ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
  247. Thread.Sleep(150); // longer than one heartbeat tick
  248. containingGroup.ScriptSetPhysicsStatus(true);
  249. }
  250. else
  251. {
  252. // Non-physical linksets don't have a physical instantiation so there is no state to
  253. // worry about being updated.
  254. object[] parms2 = { rootPhysActor, null, linksetType };
  255. ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
  256. }
  257. }
  258. else
  259. {
  260. m_log.WarnFormat("{0} physSetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
  261. LogHeader, rootPart.Name, hostID);
  262. }
  263. }
  264. else
  265. {
  266. m_log.WarnFormat("{0} physSetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
  267. LogHeader, requestingPart.Name, hostID);
  268. }
  269. }
  270. else
  271. {
  272. m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
  273. }
  274. return ret;
  275. }
  276. [ScriptInvocation]
  277. public int physGetLinksetType(UUID hostID, UUID scriptID)
  278. {
  279. int ret = -1;
  280. if (!Enabled) return ret;
  281. PhysicsActor rootPhysActor;
  282. if (GetRootPhysActor(hostID, out rootPhysActor))
  283. {
  284. object[] parms2 = { rootPhysActor, null };
  285. ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
  286. }
  287. else
  288. {
  289. m_log.WarnFormat("{0} physGetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
  290. }
  291. return ret;
  292. }
  293. [ScriptConstant]
  294. public const int PHYS_LINK_TYPE_FIXED = 1234;
  295. [ScriptConstant]
  296. public const int PHYS_LINK_TYPE_HINGE = 4;
  297. [ScriptConstant]
  298. public const int PHYS_LINK_TYPE_SPRING = 9;
  299. [ScriptConstant]
  300. public const int PHYS_LINK_TYPE_6DOF = 6;
  301. [ScriptConstant]
  302. public const int PHYS_LINK_TYPE_SLIDER = 7;
  303. // physChangeLinkType(integer linkNum, integer typeCode)
  304. [ScriptInvocation]
  305. public int physChangeLinkType(UUID hostID, UUID scriptID, int linkNum, int typeCode)
  306. {
  307. int ret = -1;
  308. if (!Enabled) return ret;
  309. PhysicsActor rootPhysActor;
  310. PhysicsActor childPhysActor;
  311. if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
  312. {
  313. object[] parms2 = { rootPhysActor, childPhysActor, typeCode };
  314. ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
  315. }
  316. return ret;
  317. }
  318. // physGetLinkType(integer linkNum)
  319. [ScriptInvocation]
  320. public int physGetLinkType(UUID hostID, UUID scriptID, int linkNum)
  321. {
  322. int ret = -1;
  323. if (!Enabled) return ret;
  324. PhysicsActor rootPhysActor;
  325. PhysicsActor childPhysActor;
  326. if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
  327. {
  328. object[] parms2 = { rootPhysActor, childPhysActor };
  329. ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinkType, parms2));
  330. }
  331. return ret;
  332. }
  333. // physChangeLinkFixed(integer linkNum)
  334. // Change the link between the root and the linkNum into a fixed, static physical connection.
  335. [ScriptInvocation]
  336. public int physChangeLinkFixed(UUID hostID, UUID scriptID, int linkNum)
  337. {
  338. int ret = -1;
  339. if (!Enabled) return ret;
  340. PhysicsActor rootPhysActor;
  341. PhysicsActor childPhysActor;
  342. if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
  343. {
  344. object[] parms2 = { rootPhysActor, childPhysActor , PHYS_LINK_TYPE_FIXED };
  345. ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
  346. }
  347. return ret;
  348. }
  349. // Code for specifying params.
  350. // The choice if 14400 is arbitrary and only serves to catch parameter code misuse.
  351. public const int PHYS_PARAM_MIN = 14401;
  352. [ScriptConstant]
  353. public const int PHYS_PARAM_FRAMEINA_LOC = 14401;
  354. [ScriptConstant]
  355. public const int PHYS_PARAM_FRAMEINA_ROT = 14402;
  356. [ScriptConstant]
  357. public const int PHYS_PARAM_FRAMEINB_LOC = 14403;
  358. [ScriptConstant]
  359. public const int PHYS_PARAM_FRAMEINB_ROT = 14404;
  360. [ScriptConstant]
  361. public const int PHYS_PARAM_LINEAR_LIMIT_LOW = 14405;
  362. [ScriptConstant]
  363. public const int PHYS_PARAM_LINEAR_LIMIT_HIGH = 14406;
  364. [ScriptConstant]
  365. public const int PHYS_PARAM_ANGULAR_LIMIT_LOW = 14407;
  366. [ScriptConstant]
  367. public const int PHYS_PARAM_ANGULAR_LIMIT_HIGH = 14408;
  368. [ScriptConstant]
  369. public const int PHYS_PARAM_USE_FRAME_OFFSET = 14409;
  370. [ScriptConstant]
  371. public const int PHYS_PARAM_ENABLE_TRANSMOTOR = 14410;
  372. [ScriptConstant]
  373. public const int PHYS_PARAM_TRANSMOTOR_MAXVEL = 14411;
  374. [ScriptConstant]
  375. public const int PHYS_PARAM_TRANSMOTOR_MAXFORCE = 14412;
  376. [ScriptConstant]
  377. public const int PHYS_PARAM_CFM = 14413;
  378. [ScriptConstant]
  379. public const int PHYS_PARAM_ERP = 14414;
  380. [ScriptConstant]
  381. public const int PHYS_PARAM_SOLVER_ITERATIONS = 14415;
  382. [ScriptConstant]
  383. public const int PHYS_PARAM_SPRING_AXIS_ENABLE = 14416;
  384. [ScriptConstant]
  385. public const int PHYS_PARAM_SPRING_DAMPING = 14417;
  386. [ScriptConstant]
  387. public const int PHYS_PARAM_SPRING_STIFFNESS = 14418;
  388. [ScriptConstant]
  389. public const int PHYS_PARAM_LINK_TYPE = 14419;
  390. [ScriptConstant]
  391. public const int PHYS_PARAM_USE_LINEAR_FRAMEA = 14420;
  392. [ScriptConstant]
  393. public const int PHYS_PARAM_SPRING_EQUILIBRIUM_POINT = 14421;
  394. public const int PHYS_PARAM_MAX = 14421;
  395. // Used when specifying a parameter that has settings for the three linear and three angular axis
  396. [ScriptConstant]
  397. public const int PHYS_AXIS_ALL = -1;
  398. [ScriptConstant]
  399. public const int PHYS_AXIS_LINEAR_ALL = -2;
  400. [ScriptConstant]
  401. public const int PHYS_AXIS_ANGULAR_ALL = -3;
  402. [ScriptConstant]
  403. public const int PHYS_AXIS_LINEAR_X = 0;
  404. [ScriptConstant]
  405. public const int PHYS_AXIS_LINEAR_Y = 1;
  406. [ScriptConstant]
  407. public const int PHYS_AXIS_LINEAR_Z = 2;
  408. [ScriptConstant]
  409. public const int PHYS_AXIS_ANGULAR_X = 3;
  410. [ScriptConstant]
  411. public const int PHYS_AXIS_ANGULAR_Y = 4;
  412. [ScriptConstant]
  413. public const int PHYS_AXIS_ANGULAR_Z = 5;
  414. // physChangeLinkParams(integer linkNum, [ PHYS_PARAM_*, value, PHYS_PARAM_*, value, ...])
  415. [ScriptInvocation]
  416. public int physChangeLinkParams(UUID hostID, UUID scriptID, int linkNum, object[] parms)
  417. {
  418. int ret = -1;
  419. if (!Enabled) return ret;
  420. PhysicsActor rootPhysActor;
  421. PhysicsActor childPhysActor;
  422. if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
  423. {
  424. object[] parms2 = AddToBeginningOfArray(rootPhysActor, childPhysActor, parms);
  425. ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkParams, parms2));
  426. }
  427. return ret;
  428. }
  429. private bool GetRootPhysActor(UUID hostID, out PhysicsActor rootPhysActor)
  430. {
  431. SceneObjectGroup containingGroup;
  432. SceneObjectPart rootPart;
  433. return GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor);
  434. }
  435. private bool GetRootPhysActor(UUID hostID, out SceneObjectGroup containingGroup, out SceneObjectPart rootPart, out PhysicsActor rootPhysActor)
  436. {
  437. bool ret = false;
  438. rootPhysActor = null;
  439. containingGroup = null;
  440. rootPart = null;
  441. SceneObjectPart requestingPart;
  442. requestingPart = BaseScene.GetSceneObjectPart(hostID);
  443. if (requestingPart != null)
  444. {
  445. // The type is is always on the root of a linkset.
  446. containingGroup = requestingPart.ParentGroup;
  447. if (containingGroup != null && !containingGroup.IsDeleted)
  448. {
  449. rootPart = containingGroup.RootPart;
  450. if (rootPart != null)
  451. {
  452. rootPhysActor = rootPart.PhysActor;
  453. if (rootPhysActor != null)
  454. {
  455. ret = true;
  456. }
  457. else
  458. {
  459. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
  460. LogHeader, rootPart.Name, hostID);
  461. }
  462. }
  463. else
  464. {
  465. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not exist. RequestingPartName={1}, hostID={2}",
  466. LogHeader, requestingPart.Name, hostID);
  467. }
  468. }
  469. else
  470. {
  471. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Containing group missing or deleted. hostID={1}", LogHeader, hostID);
  472. }
  473. }
  474. else
  475. {
  476. m_log.WarnFormat("{0} GetRootAndChildPhysActors: cannot find script object in scene. hostID={1}", LogHeader, hostID);
  477. }
  478. return ret;
  479. }
  480. // Find the root and child PhysActors based on the linkNum.
  481. // Return 'true' if both are found and returned.
  482. private bool GetRootAndChildPhysActors(UUID hostID, int linkNum, out PhysicsActor rootPhysActor, out PhysicsActor childPhysActor)
  483. {
  484. bool ret = false;
  485. rootPhysActor = null;
  486. childPhysActor = null;
  487. SceneObjectGroup containingGroup;
  488. SceneObjectPart rootPart;
  489. if (GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor))
  490. {
  491. SceneObjectPart linkPart = containingGroup.GetLinkNumPart(linkNum);
  492. if (linkPart != null)
  493. {
  494. childPhysActor = linkPart.PhysActor;
  495. if (childPhysActor != null)
  496. {
  497. ret = true;
  498. }
  499. else
  500. {
  501. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Link part has no physical actor. rootName={1}, hostID={2}, linknum={3}",
  502. LogHeader, rootPart.Name, hostID, linkNum);
  503. }
  504. }
  505. else
  506. {
  507. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Could not find linknum part. rootName={1}, hostID={2}, linknum={3}",
  508. LogHeader, rootPart.Name, hostID, linkNum);
  509. }
  510. }
  511. else
  512. {
  513. m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
  514. LogHeader, rootPart.Name, hostID);
  515. }
  516. return ret;
  517. }
  518. // Return an array of objects with the passed object as the first object of a new array
  519. private object[] AddToBeginningOfArray(object firstOne, object secondOne, object[] prevArray)
  520. {
  521. object[] newArray = new object[2 + prevArray.Length];
  522. newArray[0] = firstOne;
  523. newArray[1] = secondOne;
  524. prevArray.CopyTo(newArray, 2);
  525. return newArray;
  526. }
  527. // Extension() returns an object. Convert that object into the integer error we expect to return.
  528. private int MakeIntError(object extensionRet)
  529. {
  530. int ret = -1;
  531. if (extensionRet != null)
  532. {
  533. try
  534. {
  535. ret = (int)extensionRet;
  536. }
  537. catch
  538. {
  539. ret = -1;
  540. }
  541. }
  542. return ret;
  543. }
  544. }
  545. }