aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs150
1 files changed, 90 insertions, 60 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 2c3c481..6621d39 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -256,14 +256,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
256 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 256 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
257 257
258 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 258 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
259 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 259 World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
260 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 260 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
261 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), 261 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
262 m_DebugLogCallbackHandle); 262 m_DebugLogCallbackHandle));
263
264 // Initialization to support the transition to a new API which puts most of the logic
265 // into the C# code so it is easier to modify and add to.
266 World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
267 263
268 Constraints = new BSConstraintCollection(World); 264 Constraints = new BSConstraintCollection(World);
269 265
@@ -360,7 +356,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
360 } 356 }
361 357
362 // Anything left in the unmanaged code should be cleaned out 358 // Anything left in the unmanaged code should be cleaned out
363 BulletSimAPI.Shutdown(WorldID); 359 BulletSimAPI.Shutdown2(World.ptr);
364 360
365 // Not logging any more 361 // Not logging any more
366 PhysicsLogging.Close(); 362 PhysicsLogging.Close();
@@ -498,7 +494,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
498 { 494 {
499 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 495 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
500 496
501 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 497 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
502 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 498 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
503 499
504 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 500 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
@@ -536,26 +532,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
536 } 532 }
537 } 533 }
538 534
539 // This is a kludge to get avatar movement updates.
540 // the simulator expects collisions for avatars even if there are have been no collisions. This updates
541 // avatar animations and stuff.
542 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
543 foreach (BSPhysObject bsp in m_avatars)
544 bsp.SendCollisions();
545
546 // The above SendCollision's batch up the collisions on the objects. 535 // The above SendCollision's batch up the collisions on the objects.
547 // Now push the collisions into the simulator. 536 // Now push the collisions into the simulator.
548 if (ObjectsWithCollisions.Count > 0) 537 if (ObjectsWithCollisions.Count > 0)
549 { 538 {
550 foreach (BSPhysObject bsp in ObjectsWithCollisions) 539 foreach (BSPhysObject bsp in ObjectsWithCollisions)
551 if (!m_avatars.Contains(bsp)) // don't call avatars twice 540 if (!bsp.SendCollisions())
552 if (!bsp.SendCollisions()) 541 {
553 { 542 // If the object is done colliding, see that it's removed from the colliding list
554 // If the object is done colliding, see that it's removed from the colliding list 543 ObjectsWithNoMoreCollisions.Add(bsp);
555 ObjectsWithNoMoreCollisions.Add(bsp); 544 }
556 }
557 } 545 }
558 546
547 // This is a kludge to get avatar movement updates.
548 // The simulator expects collisions for avatars even if there are have been no collisions.
549 // The event updates avatar animations and stuff.
550 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
551 foreach (BSPhysObject bsp in m_avatars)
552 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
553 bsp.SendCollisions();
554
559 // Objects that are done colliding are removed from the ObjectsWithCollisions list. 555 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
560 // Not done above because it is inside an iteration of ObjectWithCollisions. 556 // Not done above because it is inside an iteration of ObjectWithCollisions.
561 if (ObjectsWithNoMoreCollisions.Count > 0) 557 if (ObjectsWithNoMoreCollisions.Count > 0)
@@ -579,11 +575,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
579 } 575 }
580 } 576 }
581 577
578 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world.
579 // Only enable this in a limited test world with few objects.
580 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
581
582 // The physics engine returns the number of milliseconds it simulated this call. 582 // The physics engine returns the number of milliseconds it simulated this call.
583 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 583 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
584 // We multiply by 45 to give a recognizable running rate (45 or less). 584 // We multiply by 55 to give a recognizable running rate (55 or less).
585 return numSubSteps * m_fixedTimeStep * 1000 * 45; 585 return numSubSteps * m_fixedTimeStep * 1000 * 55;
586 // return timeStep * 1000 * 45; 586 // return timeStep * 1000 * 55;
587 } 587 }
588 588
589 // Something has collided 589 // Something has collided
@@ -800,6 +800,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
800 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 800 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
801 delegate float ParamGet(BSScene scene); 801 delegate float ParamGet(BSScene scene);
802 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); 802 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
803 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
803 804
804 private struct ParameterDefn 805 private struct ParameterDefn
805 { 806 {
@@ -809,6 +810,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
809 public ParamUser userParam; // get the value from the configuration file 810 public ParamUser userParam; // get the value from the configuration file
810 public ParamGet getter; // return the current value stored for this parameter 811 public ParamGet getter; // return the current value stored for this parameter
811 public ParamSet setter; // set the current value for this parameter 812 public ParamSet setter; // set the current value for this parameter
813 public SetOnObject onObject; // set the value on an object in the physical domain
812 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 814 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
813 { 815 {
814 name = n; 816 name = n;
@@ -817,6 +819,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
817 userParam = u; 819 userParam = u;
818 getter = g; 820 getter = g;
819 setter = s; 821 setter = s;
822 onObject = null;
823 }
824 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
825 {
826 name = n;
827 desc = d;
828 defaultValue = v;
829 userParam = u;
830 getter = g;
831 setter = s;
832 onObject = o;
820 } 833 }
821 } 834 }
822 835
@@ -838,6 +851,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
838 // 851 //
839 // The single letter parameters for the delegates are: 852 // The single letter parameters for the delegates are:
840 // s = BSScene 853 // s = BSScene
854 // o = BSPhysObject
841 // p = string parameter name 855 // p = string parameter name
842 // l = localID of referenced object 856 // l = localID of referenced object
843 // v = float value 857 // v = float value
@@ -947,70 +961,84 @@ public class BSScene : PhysicsScene, IPhysicsParameters
947 -9.80665f, 961 -9.80665f,
948 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, 962 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
949 (s) => { return s.m_params[0].gravity; }, 963 (s) => { return s.m_params[0].gravity; },
950 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), 964 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
965 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
951 966
952 967
953 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 968 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
954 0f, 969 0f,
955 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 970 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
956 (s) => { return s.m_params[0].linearDamping; }, 971 (s) => { return s.m_params[0].linearDamping; },
957 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ), 972 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
973 (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
958 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 974 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
959 0f, 975 0f,
960 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 976 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
961 (s) => { return s.m_params[0].angularDamping; }, 977 (s) => { return s.m_params[0].angularDamping; },
962 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ), 978 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
979 (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
963 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 980 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
964 0.2f, 981 0.2f,
965 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 982 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
966 (s) => { return s.m_params[0].deactivationTime; }, 983 (s) => { return s.m_params[0].deactivationTime; },
967 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ), 984 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
985 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ),
968 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 986 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
969 0.8f, 987 0.8f,
970 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 988 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].linearSleepingThreshold; }, 989 (s) => { return s.m_params[0].linearSleepingThreshold; },
972 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 990 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
991 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
973 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 992 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
974 1.0f, 993 1.0f,
975 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 994 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
976 (s) => { return s.m_params[0].angularSleepingThreshold; }, 995 (s) => { return s.m_params[0].angularSleepingThreshold; },
977 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 996 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
997 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
978 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 998 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
979 0f, // set to zero to disable 999 0f, // set to zero to disable
980 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1000 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
981 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1001 (s) => { return s.m_params[0].ccdMotionThreshold; },
982 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 1002 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1003 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ),
983 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1004 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
984 0f, 1005 0f,
985 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1006 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
986 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1007 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
987 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 1008 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1009 (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ),
988 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
989 0.1f, 1011 0.1f,
990 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
991 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1013 (s) => { return s.m_params[0].contactProcessingThreshold; },
992 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 1014 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1015 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ),
993 1016
994 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1017 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
995 0.5f, 1018 0.5f,
996 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1019 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
997 (s) => { return s.m_params[0].terrainFriction; }, 1020 (s) => { return s.m_params[0].terrainFriction; },
998 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), 1021 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
999 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 1022 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1000 0.8f, 1023 0.8f,
1001 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, 1024 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1002 (s) => { return s.m_params[0].terrainHitFraction; }, 1025 (s) => { return s.m_params[0].terrainHitFraction; },
1003 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), 1026 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1004 new ParameterDefn("TerrainRestitution", "Bouncyness" , 1027 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1005 0f, 1028 0f,
1006 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1029 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1007 (s) => { return s.m_params[0].terrainRestitution; }, 1030 (s) => { return s.m_params[0].terrainRestitution; },
1008 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1031 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1009 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1032 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1010 0.2f, 1033 0.2f,
1011 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1034 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1012 (s) => { return s.m_params[0].avatarFriction; }, 1035 (s) => { return s.m_params[0].avatarFriction; },
1013 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), 1036 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1037 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1038 10f,
1039 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1040 (s) => { return s.m_params[0].avatarStandingFriction; },
1041 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1014 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1042 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1015 60f, 1043 60f,
1016 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1044 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
@@ -1227,52 +1255,54 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1227 return ret; 1255 return ret;
1228 } 1256 }
1229 1257
1230 // check to see if we are updating a parameter for a particular or all of the prims
1231 protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
1232 {
1233 List<uint> operateOn;
1234 lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
1235 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1236 }
1237
1238 // update all the localIDs specified 1258 // update all the localIDs specified
1239 // If the local ID is APPLY_TO_NONE, just change the default value 1259 // If the local ID is APPLY_TO_NONE, just change the default value
1240 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1260 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1241 // If the localID is a specific object, apply the parameter change to only that object 1261 // If the localID is a specific object, apply the parameter change to only that object
1242 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1262 protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
1243 { 1263 {
1264 List<uint> objectIDs = new List<uint>();
1244 switch (localID) 1265 switch (localID)
1245 { 1266 {
1246 case PhysParameterEntry.APPLY_TO_NONE: 1267 case PhysParameterEntry.APPLY_TO_NONE:
1247 defaultLoc = val; // setting only the default value 1268 defaultLoc = val; // setting only the default value
1269 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1270 objectIDs.Add(TERRAIN_ID);
1271 TaintedUpdateParameter(parm, objectIDs, val);
1248 break; 1272 break;
1249 case PhysParameterEntry.APPLY_TO_ALL: 1273 case PhysParameterEntry.APPLY_TO_ALL:
1250 defaultLoc = val; // setting ALL also sets the default value 1274 defaultLoc = val; // setting ALL also sets the default value
1251 List<uint> objectIDs = lIDs; 1275 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1252 string xparm = parm.ToLower(); 1276 TaintedUpdateParameter(parm, objectIDs, val);
1253 float xval = val;
1254 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1255 foreach (uint lID in objectIDs)
1256 {
1257 BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
1258 }
1259 });
1260 break; 1277 break;
1261 default: 1278 default:
1262 // setting only one localID 1279 // setting only one localID
1263 TaintedUpdateParameter(parm, localID, val); 1280 objectIDs.Add(localID);
1281 TaintedUpdateParameter(parm, objectIDs, val);
1264 break; 1282 break;
1265 } 1283 }
1266 } 1284 }
1267 1285
1268 // schedule the actual updating of the paramter to when the phys engine is not busy 1286 // schedule the actual updating of the paramter to when the phys engine is not busy
1269 protected void TaintedUpdateParameter(string parm, uint localID, float val) 1287 protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
1270 { 1288 {
1271 uint xlocalID = localID;
1272 string xparm = parm.ToLower();
1273 float xval = val; 1289 float xval = val;
1274 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1290 List<uint> xlIDs = lIDs;
1275 BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); 1291 string xparm = parm;
1292 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1293 ParameterDefn thisParam;
1294 if (TryGetParameter(xparm, out thisParam))
1295 {
1296 if (thisParam.onObject != null)
1297 {
1298 foreach (uint lID in xlIDs)
1299 {
1300 BSPhysObject theObject = null;
1301 PhysObjects.TryGetValue(lID, out theObject);
1302 thisParam.onObject(this, theObject, xval);
1303 }
1304 }
1305 }
1276 }); 1306 });
1277 } 1307 }
1278 1308