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