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